【精通特征工程】学习笔记(四)

【精通特征工程】学习笔记Day4&2.22&D5章&P65-81页

5、分类变量:自动化时代的数据计数

  • 分类变量是用来表示类别或标记的,又称为无序变量
  • 大型分类变量,分箱计数

5.1 分类变量的编码

分类变量中的类别通常不是数值型的。例如,眼睛的颜色可以是“黑色”“蓝色”和“褐 色”,等等。因此,需要一种编码方法来将非数值型的类别转换为数值。如果简单地为 k 个可能类别中的每个类别分配一个整数,如从 1 到 k,但这样做的结果是 使类别彼此之间有了顺序,这在分类变量中是不允许的。

  • 三个不同城市的公寓价格数据集
5.1.1 one-hot 编码

使用一组比特位,每个比特位表示一种可能的类别。如果变量不能同时属于 多个类别,那么这组值中就只有一个比特位是“开”的。这就是 one-hot 编码,它可以通 过scikit-learn中 的 sklearn.preprocessing.OneHotEncoder 实 现。 每 个 比 特 位 表 示 一 个 特 征,因此,一个可能有 k 个类别的分类变量就可以编码为一个长度为 k 的特征向量。

  • 对3个城市的类别进行独热编码
5.1.2 虚拟编码

one-hot 编码的问题是它允许有 k 个自由度,而变量本身只需要 k-1 个自由度。虚拟编码在进行表示时只使用 k-1 个特征,除去了额外的自由度。没有被使用的那个特征通过一个全零向量来表示,它称为参照类。虚拟编码和 one-hot 编码都可以通过 Pandas 包中的pandas.get_dummies 来实现。

  • 对3个城市的类别进行dummy编码
  • eg:在独热编码上的线性回归

>>> import pandas
>>> from sklearn import linear_model

# 定义一个模拟数据集,表示纽约、旧金山和西雅图的公寓租金
>>> df = pd.DataFrame({'City': ['SF', 'SF', 'SF', 'NYC', 'NYC', 'NYC','Seattle', 'Seattle', 'Seattle'],
                       'Rent': [3999, 4000, 4001, 3499, 3500, 3501, 2499, 2500, 2501]})
>>> df['Rent'].mean()
3333.3333333333335

# 将数据框中的分类变量转换为one-hot编码并拟合一个线性回归模型 
>>> one_hot_df = pd.get_dummies(df, prefix=['city'])
>>> one_hot_df
   Rent  city_NYC  city_SF  city_Seattle
0  3999         0        1             0
1  4000         0        1             0
2  4001         0        1             0
3  3499         1        0             0
4  3500         1        0             0
5  3501         1        0             0
6  2499         0        0             1
7  2500         0        0             1
8  2501         0        0             1

model = linear_model.LinearRegression()
model.fit(one_hot_df[['city_NYC', 'city_SF', 'city_Seattle']],
         one_hot_df[['Rent']])
>>> model.coef_
array([[ 166.66666667,  666.66666667, -833.33333333]])
>>> model.intercept_
array([ 3333.33333333])


  • eg:在虚拟变量上进行线性回归
dummy_df = pd.get_dummies(df, prefix=['city'], drop_first=True)

>>> dummy_df
   Rent  city_SF  city_Seattle
0  3999        1             0
1  4000        1             0
2  4001        1             0
3  3499        0             0
4  3500        0             0
5  3501        0             0
6  2499        0             1
7  2500        0             1
8  2501        0             1

>>> model.fit(dummy_df[['city_SF', 'city_Seattle']], dummy_df['Rent'])
>>> model.coef_
array([  500., -1000.])
>>> model.intercept_
3500.0

使用 one-hot 编码时,截距项表示目标变量 Rent 的整体均值,每个线性系数表示相应城市的租金均值与整体均值有多大差别。

使用虚拟编码时,偏差系数表示响应变量 y 对于参照类的均值,本例中参照类是纽约。第 i个特征的系数等于第 i 个类别的均值与参照类均值的差。

  • 线性回归系数差距
5.1.3 效果编码

分类变量编码的另一种变体称为Effect编码。 Effect编码与虚拟编码非常相似,区别在于参考类别现在由所有-1的向量表示。

  • Effect编码表示3个城市

Effect编码与虚拟编码非常相似,但是在线性回归中更容易被拟合。截距项表示目标变量的整体均值,各个系数表示了各个类别的均值与整体均值之间的差。one-hot 编码实际上也可以得到同样的截距和系数,但它的每个城市都有一个线性系数。在 效果编码中,没有单独的特征来表示参照类,所以参照类的效果需要单独计算,它是所有其他类别的系数的相反数之和。

  • 使用效果编码的线性回归
>>> effect_df = dummy_df.copy()
>>> effect_df.ix[3:5, ['city_SF', 'city_Seattle']] = -1.0
>>> effect_df
   Rent  city_SF  city_Seattle
0  3999      1.0           0.0
1  4000      1.0           0.0
2  4001      1.0           0.0
3  3499     -1.0          -1.0
4  3500     -1.0          -1.0
5  3501     -1.0          -1.0
6  2499      0.0           1.0
7  2500      0.0           1.0
8  2501      0.0           1.0
>>> model.fit(effect_df[['city_SF', 'city_Seattle']], effect_df['Rent'])
>>> model.coef_
array([ 666.66666667, -833.33333333])
>>> model.intercept_
3333.3333333333335
5.1.4 各种分类变量编码的优缺点

one-hot 编码、虚拟编码和效果编码彼此之间非常相似,它们都有各自的优缺点。one-hot 编码有冗余,这会使得同一个问题有多个有效模型,这种非唯一性有时候比较难以解释。 它的优点是每个特征都明确对应一个类别,而且可以把缺失数据编码为全零向量,模型输 出也是目标变量的总体均值。

虚拟编码和效果编码没有冗余,它们可以生成唯一的可解释的模型。虚拟编码的缺点是不 太容易处理缺失数据,因为全零向量已经映射为参照类了。它还会将每个类别的效果表示 为与参照类的相对值,这看上去有点不直观。

效果编码使用另外一种编码表示参照类,从而避免了这个问题,但是全由 -1 组成的向量 是个密集向量,计算和存储的成本都比较高。正是因为这个原因,像 Pandas 和 scikit-learn 这样的常用机器学习软件包更喜欢使用虚拟编码或 one-hot 编码,而不是效果编码。

当类别的数量变得非常大时,这 3 种编码方式都会出现问题,所以需要另外的策略来处理 超大型分类变量。

5.2 处理大型分类变量

5.2.1 特征散列化
  • demo : 使用 scikit-learnFeatureHasher 函数
 >>> from sklearn.feature_extraction import FeatureHasher
 >>> h = FeatureHasher(n_features=m, input_type='string')
 >>> f = h.transform(review_df['business_id'])
5.2.2 分箱计数

分箱计数它不使用分类变量的值作为特征,而是使用目标变量取这 个值的条件概率。换句话说,我们不对分类变量的值进行编码,而是要计算分类变量值与 要预测的目标变量之间的相关统计量。

小结

one-hot encoding

空间使用:O(n) 时间复杂度:O(nk)

优点:

  • 容易实现
  • 更高的精度
  • 在线学习特别容易扩展

缺点

  • 计算不足
  • 如果类别增加则不能够使用
  • 对线性模型以外的任何其他方法都不可行
  • 对于大数据集需要分布式训练

特征散列化 Feature hashing

空间使用:O(n) 时间复杂度:O(nm)

优点:

  • 容易实现
  • 容易训练
  • 容易扩展到新类别
  • 容易处理稀有类别
  • 在线学习容易扩展

缺点

  • 只能够使用线性或核模型
  • 哈希编码很难解释
  • 精度有争议

分箱计数 Bin-counting

空间使用:O(n+k) 时间复杂度:O(n)

优点:

  • 训练快
  • 能够使用树模型
  • 容易扩展到新列类别
  • 容易处理稀有类别
  • 可解释

缺点

  • 需要利用历史信息
  • 对于在线学习有困难
  • 会有数据泄露

参考:《精通特征工程》爱丽丝·郑·阿曼达·卡萨丽

面向机器学习的特征工程学习笔记:
【精通特征工程】学习笔记(一)
【精通特征工程】学习笔记(二)
【精通特征工程】学习笔记(三)

你可能感兴趣的:(【精通特征工程】学习笔记(四))