【问题标题】:Linear regression analysis with string/categorical features (variables)?具有字符串/分类特征(变量)的线性回归分析?
【发布时间】:2016-03-04 14:27:59
【问题描述】:

回归算法似乎正在处理以数字表示的特征。 例如:

此数据集不包含分类特征/变量。很清楚如何对这些数据进行回归并预测价格。


但现在我想对包含分类特征的数据进行回归分析:

5个特征:DistrictConditionMaterialSecurityType


如何对这些数据进行回归?我是否必须手动将所有字符串/分类数据转换为数字?我的意思是如果我必须创建一些编码规则并根据这些规则将所有数据转换为数值。

是否有任何简单的方法可以将字符串数据转换为数字,而无需手动创建自己的编码规则?也许 Python 中有一些库可以用于此目的?是否存在由于“错误编码”而导致回归模型不正确的风险?

【问题讨论】:

标签: python machine-learning regression linear-regression feature-selection


【解决方案1】:

在这种情况下,您可以使用“虚拟编码”。 有 Python 库可以进行虚拟编码,您有几个选择:

  • 您可以使用scikit-learn 库。看看here
  • 或者,如果您正在使用pandas,它具有create dummy variables 的内置函数。

下面是熊猫的一个例子:

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)

【讨论】:

    【解决方案2】:

    是的,您必须将所有内容都转换为数字。这需要考虑这些属性代表什么。

    通常有三种可能:

    1. 分类数据的 One-Hot 编码
    2. 序数数据的任意数字
    3. 对分类数据使用诸如组均值之类的方法(例如,市区的平均价格)。

    您必须小心,不要注入您在申请案例中没有的信息。

    一种热编码

    如果您有分类数据,您可以为每个可能的值创建具有 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。 旧

    熊猫也可以做到这一点:

    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
    

    使用分类数据进行分组操作

    您可以使用过去(已知事件)中每个类别的平均值。

    假设您有一个 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
    

    【讨论】:

    • 但是当您尝试预测一种新颜色时,热编码如何帮助您?也许在您的情况下,您必须重新训练模型。你有什么解决办法吗?
    【解决方案3】:

    在使用分类变量的线性回归中,您应该小心虚拟变量陷阱。虚拟变量陷阱是自变量是多重共线性的场景——两个或多个变量高度相关的场景;简单来说,一个变量可以从其他变量中预测出来。这会产生模型的奇异性,这意味着您的模型将无法正常工作。 Read about it here

    想法是使用带有drop_first=True 的虚拟变量编码,这将在将分类变量转换为虚拟/指标变量后从每个类别中省略一列。您不会这样做会丢失任何相关信息,因为您在数据集中的所有点都可以通过其余功能完全解释。

    这里是关于如何为您的住房数据集执行此操作的完整代码

    所以你有分类特征:

    District, Condition, Material, Security, Type
    

    还有一个你试图预测的数字特征:

    Price
    

    首先,您需要根据输入变量和预测拆分初始数据集,假设它的 pandas 数据框如下所示:

    输入变量:

    X = housing[['District','Condition','Material','Security','Type']]
    

    预测:

    Y = housing['Price']
    

    将分类变量转换为虚拟/指标变量,并在每个类别中删除一个:

    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)
    

    【讨论】:

    • “少了 4 列 - 每个分类变量一个”是什么意思?
    • 想法是使用带有 drop_first=True 的虚拟变量编码,这将在将分类变量转换为虚拟/指示变量后从每个类别中省略一列。因此,对于 4 个分类变量,您将省略所有 4 列。
    • 我们怎样才能把这个模型转换成coremltools
    【解决方案4】:

    使用分类变量作为自变量实现回归的一种方法如上所述 - 使用编码。 另一种方法是使用 statmodels 库使用类似 R 的统计公式。这是一个代码sn-p

    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
    

    回归总结

    【讨论】:

    • 优雅的解决方案,让您免于编码!
    • C(sex) 或 C(day) 做什么?
    • 他们将性别和日期视为分类变量,并且大多在后台创建虚拟变量
    • 上述输出中的T.Fri 是什么意思?
    猜你喜欢
    • 2020-05-27
    • 2019-04-07
    • 2020-08-08
    • 2019-02-27
    • 2015-04-27
    • 2020-09-20
    • 2018-01-02
    相关资源
    最近更新 更多