具有 string/categorical 个特征(变量)的线性回归分析?
Linear regression analysis with string/categorical features (variables)?
回归算法似乎适用于以数字表示的特征。
例如:
此数据集不包含分类 features/variables。很清楚如何对这些数据进行回归并预测价格。
但现在我想对包含分类特征的数据做回归分析:
有5个特征:District
、Condition
、Material
、Security
、Type
如何对这些数据进行回归?我是否必须手动将所有 string/categorical 数据转换为数字?我的意思是如果我必须创建一些编码规则并根据该规则将所有数据转换为数值。
有没有什么简单的方法可以将字符串数据转换为数字,而无需手动创建我自己的编码规则?也许 Python 中有一些库可以用于此目的?由于 "bad encoding"?
,回归模型是否存在某种不正确的风险?
在这种情况下,您可以使用 "Dummy Coding"。
有 Python 个库可以进行虚拟编码,您有几个选择:
- 您可以使用
scikit-learn
库。看看here。
- 或者,如果您正在使用
pandas
,它有一个内置函数 create dummy variables。
pandas 的示例如下:
import pandas as pd
sample_data = [[1,2,'a'],[3,4,'b'],[5,6,'c'],[7,8,'b']]
df = pd.DataFrame(sample_data, columns=['numeric1','numeric2','categorical'])
dummies = pd.get_dummies(df.categorical)
df.join(dummies)
是的,您必须将所有内容都转换为数字。这需要考虑这些属性代表什么。
通常有三种可能:
- 分类数据的单热编码
- 序数数据的任意数字
- 对分类数据使用类似于组均值的方法(例如市区的平均价格)。
您必须小心,不要在申请案例中注入您没有的信息。
一个热编码
如果您有分类数据,您可以为每个可能的值创建 0/1 值的虚拟变量。
E. g.
idx color
0 blue
1 green
2 green
3 red
至
idx blue green red
0 1 0 0
1 0 1 0
2 0 1 0
3 0 0 1
这可以通过 pandas 轻松完成:
import pandas as pd
data = pd.DataFrame({'color': ['blue', 'green', 'green', 'red']})
print(pd.get_dummies(data))
将导致:
color_blue color_green color_red
0 1 0 0
1 0 1 0
2 0 1 0
3 0 0 1
序数数据
创建可排序类别的映射,例如。 G。
旧 < 翻新 < 新 → 0, 1, 2
这也可以用 pandas:
data = pd.DataFrame({'q': ['old', 'new', 'new', 'ren']})
data['q'] = data['q'].astype('category')
data['q'] = data['q'].cat.reorder_categories(['old', 'ren', 'new'], ordered=True)
data['q'] = data['q'].cat.codes
print(data['q'])
结果:
0 0
1 2
2 2
3 1
Name: q, dtype: int8
使用分类数据进行 groupby 操作
您可以使用过去(已知事件)每个类别的平均值。
假设您有一个包含城市最新已知平均价格的 DataFrame:
prices = pd.DataFrame({
'city': ['A', 'A', 'A', 'B', 'B', 'C'],
'price': [1, 1, 1, 2, 2, 3],
})
mean_price = prices.groupby('city').mean()
data = pd.DataFrame({'city': ['A', 'B', 'C', 'A', 'B', 'A']})
print(data.merge(mean_price, on='city', how='left'))
结果:
city price
0 A 1
1 B 2
2 C 3
3 A 1
4 B 2
5 A 1
在使用分类变量的线性回归中,您应该小心虚拟变量陷阱。虚拟变量陷阱是自变量多重共线性的场景——两个或多个变量高度相关的场景;简单来说,一个变量可以从其他变量中预测出来。这会产生模型的奇异性,这意味着您的模型将无法正常工作。 Read about it here
想法是使用 drop_first=True
的虚拟变量编码,这将在将分类变量转换为 dummy/indicator 变量后从每个类别中省略一列。这样做你 不会 丢失任何相关信息,因为你在数据集中的所有点都可以用其余特征完全解释。
这是有关如何为您的住房数据集执行此操作的完整代码
所以你有分类特征:
District, Condition, Material, Security, Type
以及您要预测的一项数值特征:
Price
首先,您需要根据输入变量和预测拆分初始数据集,假设其 pandas 数据框如下所示:
输入变量:
X = housing[['District','Condition','Material','Security','Type']]
预测:
Y = housing['Price']
将分类变量转换为 dummy/indicator 个变量并在每个类别中删除一个:
X = pd.get_dummies(data=X, drop_first=True)
所以现在,如果您使用 drop_first=True
检查 X 的形状,您会发现它少了 4 列 - 每个分类变量一列。
您现在可以继续在您的线性模型中使用它们。对于 scikit-learn 实现,它可能如下所示:
from sklearn import linear_model
from sklearn.model_selection import train_test_split
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size = .20, random_state = 40)
regr = linear_model.LinearRegression() # Do not use fit_intercept = False if you have removed 1 column after dummy encoding
regr.fit(X_train, Y_train)
predicted = regr.predict(X_test)
用分类变量作为自变量实现回归的一种方法就是上面提到的——使用编码。
另一种方法是使用 R 之类的统计公式,使用 statmodels 库。这是一个代码片段
from statsmodels.formula.api import ols
tips = sns.load_dataset("tips")
model = ols('tip ~ total_bill + C(sex) + C(day) + C(day) + size', data=tips)
fitted_model = model.fit()
fitted_model.summary()
数据集
total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.50 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4
回归总结
回归算法似乎适用于以数字表示的特征。 例如:
此数据集不包含分类 features/variables。很清楚如何对这些数据进行回归并预测价格。
但现在我想对包含分类特征的数据做回归分析:
有5个特征:District
、Condition
、Material
、Security
、Type
如何对这些数据进行回归?我是否必须手动将所有 string/categorical 数据转换为数字?我的意思是如果我必须创建一些编码规则并根据该规则将所有数据转换为数值。
有没有什么简单的方法可以将字符串数据转换为数字,而无需手动创建我自己的编码规则?也许 Python 中有一些库可以用于此目的?由于 "bad encoding"?
,回归模型是否存在某种不正确的风险?在这种情况下,您可以使用 "Dummy Coding"。 有 Python 个库可以进行虚拟编码,您有几个选择:
- 您可以使用
scikit-learn
库。看看here。 - 或者,如果您正在使用
pandas
,它有一个内置函数 create dummy variables。
pandas 的示例如下:
import pandas as pd
sample_data = [[1,2,'a'],[3,4,'b'],[5,6,'c'],[7,8,'b']]
df = pd.DataFrame(sample_data, columns=['numeric1','numeric2','categorical'])
dummies = pd.get_dummies(df.categorical)
df.join(dummies)
是的,您必须将所有内容都转换为数字。这需要考虑这些属性代表什么。
通常有三种可能:
- 分类数据的单热编码
- 序数数据的任意数字
- 对分类数据使用类似于组均值的方法(例如市区的平均价格)。
您必须小心,不要在申请案例中注入您没有的信息。
一个热编码
如果您有分类数据,您可以为每个可能的值创建 0/1 值的虚拟变量。
E. g.
idx color
0 blue
1 green
2 green
3 red
至
idx blue green red
0 1 0 0
1 0 1 0
2 0 1 0
3 0 0 1
这可以通过 pandas 轻松完成:
import pandas as pd
data = pd.DataFrame({'color': ['blue', 'green', 'green', 'red']})
print(pd.get_dummies(data))
将导致:
color_blue color_green color_red
0 1 0 0
1 0 1 0
2 0 1 0
3 0 0 1
序数数据
创建可排序类别的映射,例如。 G。 旧 < 翻新 < 新 → 0, 1, 2
这也可以用 pandas:
data = pd.DataFrame({'q': ['old', 'new', 'new', 'ren']})
data['q'] = data['q'].astype('category')
data['q'] = data['q'].cat.reorder_categories(['old', 'ren', 'new'], ordered=True)
data['q'] = data['q'].cat.codes
print(data['q'])
结果:
0 0
1 2
2 2
3 1
Name: q, dtype: int8
使用分类数据进行 groupby 操作
您可以使用过去(已知事件)每个类别的平均值。
假设您有一个包含城市最新已知平均价格的 DataFrame:
prices = pd.DataFrame({
'city': ['A', 'A', 'A', 'B', 'B', 'C'],
'price': [1, 1, 1, 2, 2, 3],
})
mean_price = prices.groupby('city').mean()
data = pd.DataFrame({'city': ['A', 'B', 'C', 'A', 'B', 'A']})
print(data.merge(mean_price, on='city', how='left'))
结果:
city price
0 A 1
1 B 2
2 C 3
3 A 1
4 B 2
5 A 1
在使用分类变量的线性回归中,您应该小心虚拟变量陷阱。虚拟变量陷阱是自变量多重共线性的场景——两个或多个变量高度相关的场景;简单来说,一个变量可以从其他变量中预测出来。这会产生模型的奇异性,这意味着您的模型将无法正常工作。 Read about it here
想法是使用 drop_first=True
的虚拟变量编码,这将在将分类变量转换为 dummy/indicator 变量后从每个类别中省略一列。这样做你 不会 丢失任何相关信息,因为你在数据集中的所有点都可以用其余特征完全解释。
这是有关如何为您的住房数据集执行此操作的完整代码
所以你有分类特征:
District, Condition, Material, Security, Type
以及您要预测的一项数值特征:
Price
首先,您需要根据输入变量和预测拆分初始数据集,假设其 pandas 数据框如下所示:
输入变量:
X = housing[['District','Condition','Material','Security','Type']]
预测:
Y = housing['Price']
将分类变量转换为 dummy/indicator 个变量并在每个类别中删除一个:
X = pd.get_dummies(data=X, drop_first=True)
所以现在,如果您使用 drop_first=True
检查 X 的形状,您会发现它少了 4 列 - 每个分类变量一列。
您现在可以继续在您的线性模型中使用它们。对于 scikit-learn 实现,它可能如下所示:
from sklearn import linear_model
from sklearn.model_selection import train_test_split
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size = .20, random_state = 40)
regr = linear_model.LinearRegression() # Do not use fit_intercept = False if you have removed 1 column after dummy encoding
regr.fit(X_train, Y_train)
predicted = regr.predict(X_test)
用分类变量作为自变量实现回归的一种方法就是上面提到的——使用编码。 另一种方法是使用 R 之类的统计公式,使用 statmodels 库。这是一个代码片段
from statsmodels.formula.api import ols
tips = sns.load_dataset("tips")
model = ols('tip ~ total_bill + C(sex) + C(day) + C(day) + size', data=tips)
fitted_model = model.fit()
fitted_model.summary()
数据集
total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.50 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4
回归总结