如何使用 Python 和 Scikit 进行线性回归学习使用一种热编码?
Posted
技术标签:
【中文标题】如何使用 Python 和 Scikit 进行线性回归学习使用一种热编码?【英文标题】:How to do linear regression using Python and Scikit learn using one hot encoding? 【发布时间】:2017-05-10 13:31:06 【问题描述】:我正在尝试将线性回归与 python 和 scikitlearn 结合使用来回答“可以根据用户人口统计信息预测用户会话长度吗?”
我使用线性回归,因为用户会话长度以毫秒为单位,这是连续的。我对我所有的分类变量进行了热编码,包括性别、国家和年龄范围。
我不确定如何考虑我的一个热编码,或者我什至需要。
输入数据:
我尝试在这里阅读:http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html
我知道输入主要是计算拟合截距、归一化、复制 x(全布尔值),然后是 n 个作业。
我不确定在决定这些输入时要考虑哪些因素。我还担心我对变量的一种热编码是否会产生影响。
【问题讨论】:
您的数据看起来已经正确编码。但是,如果可以的话,我会尝试在不合并年龄的情况下拟合模型。 你为什么使用线性回归作为特别的东西?例如,随机森林回归器也适用于连续值。 【参考方案1】:你可以这样做:
from sklearn.preprocessing import OneHotEncoder
from sklearn.linear_model import LinearRegression
# X is a numpy array with your features
# y is the label array
enc = OneHotEncoder(sparse=False)
X_transform = enc.fit_transform(X)
# apply your linear regression as you want
model = LinearRegression()
model.fit(X_transform, y)
print("Mean squared error: %.2f" % np.mean((model.predict(X_transform) - y) ** 2))
请注意,这个示例我使用相同的数据集进行训练和测试!这可能会导致您的模型过拟合。您应该避免拆分数据或进行交叉验证。
【讨论】:
您应该在LinearRegression
中设置fit_intercept=False
以避免dummy variable trap【参考方案2】:
我只是想用 sklearn 拟合线性回归,我将它用作其他非线性方法的基准,例如 MLPRegressor,以及线性回归的变体,例如 Ridge、Lasso 和 ElasticNet(请参阅此处了解本组:http://scikit-learn.org/stable/modules/linear_model.html)。
实际上对我来说,按照@silviomoreto 描述的相同方式(对所有其他模型都有效)导致了一个错误的模型(非常高的错误)。这很可能是由于所谓的虚拟变量陷阱,当您为分类变量的每个类别包含一个虚拟变量时,由于变量中的多重共线性而发生 - 这正是 OneHotEncoder 所做的!另请参阅以下关于 statsexchange 的讨论:https://stats.stackexchange.com/questions/224051/one-hot-vs-dummy-encoding-in-scikit-learn。
为了避免这种情况,我编写了一个简单的包装器,它排除了一个变量,然后作为默认值。
class DummyEncoder(BaseEstimator, TransformerMixin):
def __init__(self, n_values='auto'):
self.n_values = n_values
def transform(self, X):
ohe = OneHotEncoder(sparse=False, n_values=self.n_values)
return ohe.fit_transform(X)[:,:-1]
def fit(self, X, y=None, **fit_params):
return self
因此,基于@silviomoreto 的代码,您将更改第 6 行:
enc = DummyEncoder()
这解决了我的问题。请注意,OneHotEncoder 对所有其他模型(例如 Ridge、Lasso 和 ANN)都运行良好(并且更好)。
我选择了这种方式,因为我想将它包含在我的功能管道中。但是您似乎已经对数据进行了编码。在这里,您必须为每个类别删除一列(例如,男性/女性仅包括一列)。因此,例如,如果您使用 pandas.get_dummies(...),则可以使用参数 drop_first=True 来完成。
最后但同样重要的是,如果您真的需要更深入地研究 Python 中的线性回归,而不是将其仅用作基准,我会推荐 statsmodels 而不是 scikit-learn (https://pypi.python.org/pypi/statsmodels),因为它提供了更好的模型统计信息,例如每个变量的 p 值等。
【讨论】:
您可以在LinearRegression
中设置fit_intercept=False
,而不是使用虚拟编码,以避免dummy variable trap,同时仍然使用One-hot 编码【参考方案3】:
如何为 sklearn LinearRegression 准备数据
OneHotEncode 只能用于预期的列:具有分类变量或字符串的列,或者本质上是级别而不是数字的整数。
请勿将 OneHotEncode 应用于您的整个数据集,包括数值变量或布尔值。
为sklearn LinearRegression准备数据,数值和分类应该分开处理。
数值列:如果您的模型包含交互作用或多项式项,则进行标准化 分类列:通过 sklearn 或 pd.get_dummies 应用 OneHot。 pd.get_dummies 更加灵活,而 OneHotEncode 在使用 sklearn API 时更加一致。drop='first'
从 0.22 版开始,sklearn 中的OneHotEncoder
具有drop
选项。例如OneHotEncoder(drop='first').fit(X)
,类似于
pd.get_dummies(drop_first=True)
.
使用正则化线性回归
如果使用 Lasso 等正则化线性回归,多重共线性变量将受到惩罚和收缩。
p 值统计的限制
OLS 中的 p 值仅在 OLS 假设或多或少正确时才有效。虽然有一些方法可以处理 p 值不可信的情况,但一种可能的解决方案是使用交叉验证或留一法来获得对模型的信心。
【讨论】:
以上是关于如何使用 Python 和 Scikit 进行线性回归学习使用一种热编码?的主要内容,如果未能解决你的问题,请参考以下文章
使用 scikit-learn 训练线性回归模型后,如何对原始数据集中不存在的新数据点进行预测?
在 SciKit 线性回归中获取“ValueError:形状未对齐”