hi各位大佬好,我是探花小明哥,之前的博文中提及的one-hot可能与常见的one-hot不太一样,针对叶子节点中的one-hot,这个肯定是多个0,1的组合,最终的结果就是直接LabelEncoder的拼接,我失算了,我以为有啥高深的玩意,发现并没有。
For Recommendation in Deep learning QQ Group 102948747
For Visual in deep learning QQ Group 629530787
I'm here waiting for you
我之前提到过lightgbm中的确只需0~k编码即可,无需one-hot,计算结果前者更好,而且节省时空,这是lightgbm独有的快速处理方式。
LightGBM can use categorical features as input directly. It doesn’t need to convert to one-hot coding, and is much faster than one-hot coding (about 8x speed-up).
而对于LR则不可,必然需要(对于类别特征),而经过随机森林及树模型的处理得到的是新特征,即类别特征——落在每个叶子的索引,如代码,和paper中的类似吧
>>> X_train_lr.shape
(20000, 20)
>>> X_train_lr
array([[ 1.16872922, -0.12326182, -1.5484857 , ..., 0.67940014,
0.52846206, 0.83227156],
[-1.00731753, -0.13562786, 0.6830177 , ..., -1.38317951,
-0.34762768, -0.05636781],
[ 0.1071118 , 0.12562994, -2.57552698, ..., 0.52352653,
0.22234559, 0.02766531],
...,
[ 0.65539074, -0.0093059 , -0.29745059, ..., 0.221068 ,
0.10400257, 0.7163802 ],
[ 1.74374594, 0.04608131, 0.97697367, ..., -1.74149946,
-1.90247471, -0.29741195],
[-0.52465285, -0.16638788, 0.61640846, ..., 0.41042506,
-1.32117369, 0.59130764]])
>>> rf_enc.transform(rf.apply(X_train_lr)).toarray()
array([[0., 0., 1., ..., 0., 0., 0.],
[0., 0., 1., ..., 0., 0., 0.],
[0., 0., 1., ..., 0., 0., 0.],
...,
[0., 0., 1., ..., 0., 0., 0.],
[0., 0., 1., ..., 0., 0., 0.],
[0., 0., 1., ..., 0., 0., 0.]])
>>> rf_enc.transform(rf.apply(X_train_lr)).toarray()[0]
array([0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0.,
0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0.,
0., 1., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0.,
1., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.])
>>> rf_enc.transform(rf.apply(X_train_lr)).shape
(20000, 80)
分析:LabelEncoder只是对任何形式的特征做0~k编码,而OneHotEncoder则是真正的0~1编码,比如下面代码得到的k只是0~k的编码,但不知道它到底是哪个特征的编码,这一点LR是不知道的,它可能会误认为是一个特征的编码。【注:一般默认每列为一个特征】OneHotEncoder可对特征进行编码0~k,也就是说包含了LabelEncoder,而且知道最终的特征的编码个数,这也是表示0-1的编码的根本所在,如下注释:
enc = OneHotEncoder(categories='auto')
arr=np.array([[0, 0, 4],
[1, 1, 0],
[0, 2, 1],
[1, 0, 2]])
enc.fit(arr,)
b=np.array([[0, 1, 4]])
ans = enc.transform(b).toarray()
print(ans)
for i in range(arr.shape[1]):
lbe=LabelEncoder()
arr[:,i]=lbe.fit_transform(arr[:,i])
k=lbe.transform(b[:,i])
print(k)
print("coding order",lbe.classes_)
print("feature number",len(lbe.classes_))
[[1. 0. 0. 1. 0. 0. 0. 0. 1.]]
[0]
coding order [0 1]
feature number 2
[1]
coding order [0 1 2]
feature number 3
[3]
coding order [0 1 2 4]
feature number 4
前者的结果与后者是统一的,只不过不知道特征个数时无法得到最终的编码形式。知道后,第一特征0-1编码则为[1,0],就是第0个位置为1,特征个数为2,那么是2维;第二个则为[0,1,0],即第1个位置为1,特征个数是3维;第三个则为[0,0,0,1],第3个位置为1,特征个数是4维度。
而下面的两个编码则需要注意,第一个是对特征内的编码,也就是说对单个特征的编码,当然也可多个特征,但第一次见这个的人可能会蒙圈,因为它不对整型的特征编码,只对原始的类别特征编码。如下。第二则是keras中one-hot,它是对单个特征的编码,目前不知道多特征是否有类似的函数。
>>> df = pd.DataFrame({'A': ['a', 'b', 'a'], 'B': ['b', 'a', 'c'],
'C': [1, 2, 3]})
>>> df
A B C
0 a b 1
1 b a 2
2 a c 3
>>> pd.get_dummies(df)
C A_a A_b B_a B_b B_c
0 1 1 0 0 1 0
1 2 0 1 1 0 0
2 3 1 0 0 0 1
#直接输入会默认为单个特征,然后进行0~k及one-hot编码,因为它不知道每个特征的编码个数
>>> pd.get_dummies([0, 1, 4])
0 1 4
0 1 0 0
1 0 1 0
2 0 0 1
>>> to_categorical([0, 1, 4])
array([[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 0., 0., 1.]], dtype=float32)
>>> to_categorical([[0, 1, 4]])
array([[[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 0., 0., 1.]]], dtype=float32)
#无间隔的认为已经0~k编码过了
这也算是一个总结吧,拜拜。