什么是分类变量?
- 通常来说,分类变量是用来表示类别或标记的。小型分类变量例如:一年中的四季,行业(银行、保险、券商、科技......),一线城市“北上广深”等等;大型分类变量例如:IP地址,用户ID,语料库的词汇表等等
- 不管类别的大小,分类变量有2个显而易见的特点:数量有限且无序。因此在很多涉及到数值度量的模型中,如:LR,SVM等,我们不能像处理数值型变量那样来处理分类变量。
-
所以今天我们来讲讲小型分类变量的常见处理方式:one-hot编码,虚拟编码和效果编码,以及通过虚构的“城市&租金”数据来看看,三者之间的联系与差异。
one-hot编码(one-hot encoding)
- 在虚构的“城市&租金”数据中,“CITY”特征有BJ, SH, SZ三种值,我们可以简单地为其标注为0,1,2,但是这样做的结果是使类别彼此之间有了顺序和大小关系。所以更好地方法是使用一组比特位,每个比特位表示一种可能的类别,因此k个类别的分类变量就可以编码为长度为k的特征向量。one-hot encoding可以用scikit-learn中的sklearn.proprocessing.OneHotEncoder来实现,在这里我们用pandas.get_dummies实现。
pd.get_dummies(df, columns=["CITY"])
虚拟编码(dummy encoding)
- 在one-hot编码中,我们看到分类变量有k个类别,就用了长度为k的特征向量来表示。而在虚拟编码中,我们只使用长度为(k-1)的特征向量来表示,被去掉的特征被一个全零向量所替代,它被称为参照类。
pd.get_dummies(df, columns=["CITY"], drop_first=True)
效果编码(effect coding)
- 另一种编码是效果编码,与虚拟编码非常相似,区别在于效果编码的参照类由全零向量变成了全部由-1组成的向量来表示。
#先进行虚拟编码
dummyDF = pd.get_dummies(df, columns=["CITY"], drop_first=True)
#对编码过后的DF进行效果编码形式的转换
dummy2effect(dummyDF, columns)
#虚拟编码转为效果编码的函数
def dummy2effect(dummyDF, columns):
"""将经过虚拟编码的DF转变为效果编码的形式"""
dummyColumns = dummyDF.columns.tolist()
effectCols = [[newCol for newCol in dummyColumns if newCol.split("_")[0]==col] for col in columns ]
effectDF = dummyDF.copy()
for pairCols in effectCols:
featureidx = [dummyColumns.index(c) for c in pairCols]
sampleidx = np.nonzero(dummyDF[effectCols[0]].sum(axis=1).values == 0)[0]
effectDF.iloc[sampleidx, featureidx] = -1.
return effectDF
三种编码的解释性
- 对编码后的数据分别进行线性回归,再依次进行解释。
if __name__ == "__main__":
df = pd.DataFrame({'CITY':['BJ','BJ','BJ','SH','SH','SH','SZ','SZ','SZ'],
'RENT':[3999,4000,4001,3499,3500,3501,2999,3000,3001]})
#分别进行编码
onehot_df = coding(df, ["CITY"], "one-hot")
dummy_df = coding(df, ["CITY"], "dummy")
effect_df = coding(df, ["CITY"], "effect")
#分别进行线性回归
from sklearn import linear_model
clf_onehot = linear_model.LinearRegression()
clf_onehot.fit(onehot_df.drop("RENT", axis=1), onehot_df["RENT"])
clf_dummy = linear_model.LinearRegression()
clf_dummy.fit(dummy_df.drop("RENT", axis=1), dummy_df["RENT"])
clf_effect = linear_model.LinearRegression()
clf_effect.fit(effect_df.drop("RENT", axis=1), effect_df["RENT"])
- 我们可以发现,在one-hot编码中,截距代表了整体Y值(租金)的均值,每个线性系数代表了相应城市的租金均值与整体租金均值有多大差别。
- 在虚拟编码中,截距代表了参照类Y值(租金)的均值,本例中的参照类是BJ,第i个特征的系数等于第i个类别的租金均值与参照类均值的差异。
- 在效果编码中,截距代表了整体Y值(租金)的均值,各个系数表示了各个类别的均值与整体均值之间的差,此处BJ的均值当且仅当"CITY_SH=CITY_SZ=-1"时所取到的值。
以上就是one-hot, 虚拟编码, 效果编码的简单介绍,谢谢阅读。
全部代码可前往以下地址下载:
https://github.com/shoucangjia1qu/ML_gzh/tree/master/FeatureEngineer
*本文知识点参考了Alice Zheng 的《Mastering Feature Engineering Principles and Techniques for Data Scientists》一书。
学无止境,欢迎关注笔者公众号,互相学习!