特征工程之连续/离散特征的处理


离散特征:

1.无序离散特征:one-hot encoding,比如所属国家、城市 
        (1)无序离散特征:one-hot encoding,比如所属国家,城市。(1)如果one-hot之后unique值不多可以不用做Embedding, (2)但是如果该特征unique值过多,比如所属国家、城市,onehot产生的矩阵过宽,这种情况下,我们的通常做法就是将其转换为embedding。
         (2)也可以先做LabelEncoder将特征的不同取值区分开,然后再embedding 

2.有序离散特征:label encoding,比如年龄 (类似分桶)

3.单值离散特征:做Embedding映射成1*K维向量,然后与其他特征拼接

4.多值离散特征:做Embedding映射成3*K维,然后MeanPooling 成1*K维,比如某人的爱好有3个这种特征。

总结:
- 特征用于FM一次项wi*xi:
    - 原值:比如1、2、3等级
    - Onehot:比如性别,省份,城市
    - LabelEncoder:有序离散特征 年龄
- 特征用于FM二次项的隐向量
    - OneHot --> Embedding 
    - LabelEncoder -->  

连续特征:

- 1.归一化:去除不同维度数据的量纲以及量纲单位 服从均匀分布
- 2.标准化:  标准化成正态分布之后,可以更加容易地得出最优参数目标函数的最小值,从而达到加速收敛的效果。服从高斯分布,一般数据服从高斯分布,所以标准化用的比较多。

区别:两者都可以对特征做幅度缩放,两者的效果差不多,选择其中一个即可。

- 分桶:
    - (1)连续特征可以通过分桶实现离散化成[0,1,2,3,..9]
    - (2)大量离散特征比如 每个用户观看的视频数,也可以分桶

应用于FM一次项时:先通过标准化/分桶 --> 乘以权重系数wi*xi 再与其他特征拼接。  例如1个连续特征先通过Dense(1) (wi*xi)得到1个数,再与其他特征拼接。   
应用于FM二次项时:先通过标准化/分桶 -->Embedding得到K个数,在通过RepeatVector 得到1*K维向量,再与其他特征相乘。例如1个连续特征先通过Dense(1)(类似一个Embedding) 得到K个数,在通过RepeatVector 得到1*K维向量,再与其他特征相乘。(Ref: DeepFM-keras 实现中FM二次项)

## 离散/连续特征 总结:
- 第一步:原值,标准化,OneHot,LabelEncoder,分桶
- 第二步:如果需要得到隐向量的话 就再做Embedding


# 正则化:
- 常见的有正则项有 L1 正则 和 L2 正则 以及 Dropout 


更详细内容请参考:[ML 入门:归一化、标准化和正则化](https://zhuanlan.zhihu.com/p/29957294)

关于FM 的数据输入格式:

- libsvm数据格式:libsvm 格式的数据 一行中只有有数据的才会写上 比如5.0 1:1 5:1 10:5.1 11193:1  就表示预测值y=5.0,其中特征1(表示这条样本的userid=1),其中特征5(表示这条样本性别男特征=1),特征10(比如score表示分数连续值),特征11193(表示这条样本的itemid=11193)。
- 比如 userid有8千个,itemid 有3万个,连续,离散以及onehot之后的特征有2千个,那么共有4万个特征。这4万个特征依次排开形成 field_1,field_2....field_40000,

field:index:value
连续: filed_index:0:得分:表示一条样本的filed_score 这个特征 只有一个取值,大小就是实际分数比如5.1分
离散:field_index:9:1:表示这个特征被分了0~9十个桶,这条样本的filed_score取值位于第9个桶范围内,比如实际分数在(90,100)之间 
field_index:0:1:表示这个特征被分了0~9十个桶,这条样本的filed_score取值位于第1个桶范围内,比如实际分数在(90,100)之间

下表是一条样本的libsvm数据:其中231、10005都是特征索引,表示第几个特征。

label单值离散单值离散(少)单值离散(多)连续(范围小)连续(范围大)多值离散单值离散
样本1y=5.0userid=231user_level=2action_statis=121score1=5.1score2=51hobby=[0,3,4]itemid=11193
libsvm5.0231:18005:1100021:1:1

10010:0:5.1

或10010:5.1

10010:5:1

10210:0:1

10210:3:1

10210:4:1

11193:1
样本2y=4.1userid=241user_level=3action_statis=522score1=7.1score2=71hobby=[1,3]itemid=13241
libsvm4.1241:18006:1100022:5:1

10010:0:7.1

或10010:7.1

10010:7:1

10210:1:1

10210:3:1

13241:1
做分桶当做连续值当做离散值 做分桶

FM 一次项输入的是:

具体数值(如下图的0.5,5.1等);onehot值[0,1,0,0]; 还可以是[0,1,0,1,0] *W得到的值。

原理图,和实际物理实现方式之间的区别,
连续特征: 输入到Input中的是 原值(归一化)/分桶之后的离散值
    - 原值输入,#取值范围较小的   对一次项的贡献等于自身数值乘以权值w,可以用Dense(1)层实现
    - 可以通过归一化/标准化 做幅度缩放 直接作为FM的输入     #取值范围较大的做幅度缩放   对一次项的贡献等于缩放后数值乘以权值w,可以用Dense(1)层实现
    - 也可以 通过分桶,然后再onehot  作为输入 

in_score = Input(shape=[1], name="score") # None*1
emb_score = Dense(1)(in_score) # None*1    wi*xi
# or
in_score = Input(shape=[1], name="score") # None*1
numeric = Concatenate()([in_score, in_sales]) # None*2
dense_numeric = Dense(1)(numeric) # None*1


单值离散特征:输入到Input中的是 原值/分桶之后的离散值
    - onthot 之后作为输入                             # 取值个数较少
    - labelEncoder之后再 onehot作为输入。# 取值个数较多的

in_age = Input(shape=[1], name="age") # None*1
emb_age_1d = Reshape([1])(Embedding(10, 1)(in_age)) # None*1, 年龄取值10种


多值离散特征:输入到Input中的是 [2,3]  
    - 先做padding补成相同长度的,就得到了[0,1,0,1,1,0..0] 然后做Embedding(10,1) 即(w31*x1+w32*x2+...+w310*x10)/10

in_topic = Input(shape=[4], name="topic") # None*4, 最长长度4
emb_topic_1d = Embedding(22, 1, mask_zero=True)(in_topic) # None*4*1
emb_topic_1d = MyMeanPool(axis=1)(emb_topic_1d) # None*1

    首先,连续型field对一次项的贡献等于自身数值乘以权值w,可以用Dense(1)层实现,任意个连续型field输入到同一个Dense层即可,因此在数据处理时,可以先将所有连续型field拼成一个大矩阵,同时如上所述,ID可以省略。
    其次,单值离散型field根据样本特征取值的index,从w中取出对应权值(标量),由于离散型特征值为1,故它对一次项的贡献即取出的权值本身。取出权值的过程称为 table-lookup,可以用Embedding(n,1)层实现(n为该field特征取值个数)。若将所有单值离散型field的特征值联合编码,则可使用同一个Embedding Table进行lookup,不需要对每个field单独声明Embedding层。因此在数据处理时,可以先将所有单值离散型field拼起来并联合编码,同时如上所述,Value可以省略,只关心lookup出来的权值ww即可。
 最后,多值离散型field可以同时取多个特征值,为了batch training,必须对样本进行补零padding。相似地可用Embedding层实现,Value并不是必要的,但Value可以作为mask来使用,当然也可以在Embedding中设置mask_zero=True。Ref:https://blog.csdn.net/songbinxu/article/details/80151814

注意区别:word2vec和Embedding

word2vec是基于上下文的共现学习来学习词向量的;一般的embedding,就相当于是网络里的一层,是跟着任务端到端优化网络学习到权重参数,从而得到隐向量的。

word embedding是指词向量,是一个将词向量化的概念,word2vec则是将词映射成词向量的一种具体的技术。几个比较有名的word embedding方法包括: word2vec (Google), GloVe, wordRank, FastText (Facebook)。区别的话,就是一个是概念,一个是实现手段。

word2vec 的实现:先将离散特征(比如一句话中的每个词表示成onehot形式, 然后输入到CBOW或者Skip-Gram模型中得到 某一个单词的词向量。其中 CBOW的输入是好几个onehot向量,而Skip-Gram 输入的事一个onehot值。

FM二次项输入都是K维的隐向量:

  • 1.连续值 输入到Input中的是 连续值/分桶之后的离散值

比如特征score=2.5,直接输入到Input神经元,分别乘以不同权重,得到隐向量score*(w_{01},w_{02},w_{03}) 然后输入到下一层神经元。而在实际训练中是,来了一个样本score=2.5,去lookup table表中查找score这个特征应的隐向量,取出来然后再乘以score,就可以了。

in_score = Input(shape=[1], name="score") # None*1
emb_score_Kd = RepeatVector(1)(Dense(latent)(in_score)) # None * 1 * K
  • 2.单值离散  输入到Input中的是  原值/分桶之后的离散值

参考用keras实现一个DeepFM 画出对于单值离散的embedding图1 . 直接将年龄分桶之后的值(age=2)作为神经元的输入,然后得到1个3维隐向量,这是将Embedding视做黑盒子得到的结构图,可以看成是 keras层级图。

图1. 是Embedding 内部网络结构图,直接将年龄分桶之后的值(age=2)作为Embedding的输入,然后embedding内部将age=2 映射成一个1*5的向量[0,0,1,0,0] 通过全连接网络得到 3维隐向量。假设 年龄分桶之后取值(0,5),0对应(0~20)岁,4对应(80,100)岁,先将每样样本的年龄进行onehot,然后将onehot映射成一个3维向量,比如这三维向量是身高,体重,阅历。显然w01 要小于w21;w11>w21>w41,因为人的身高先增大,后减小,20-40岁之间最大。

Embedding 实际物理实现方式:age=23 分桶之后变成 age=2 输入--> embedding --> 输出age=2的一个8维隐向量,也就是embedding内部去将age=2  onehot成 [0,0,1,0..0] 然后乘以lookup table表 取出隐向量。也就是我们输入到Input层的事age=2 而不是age=[0,0,1,0...0] ,因此不需要我们自己在特征工程时将age=2 变成onehot形式

in_age = Input(shape=[1], name="age") # None*1    
emb_age_Kd = Embedding(10, 8)(in_age) # None*1, 年龄取值10种
图3 Embedding 实际物理实现
  • 3. 多值离散 输入到Input中的是   原值[2,3]

比如爱好特征共有22个不同取值而一个人爱好最多是4个,其中一个人有2个爱好[1,3]  那么我们直接将[1,3]补零后[1,3,0,0]作为Input层输入,embedding会逐个进行onehot 然后乘以权重矩阵得到对应的一个4*8的隐向量矩阵。

in_topic = Input(shape=[4], name="topic") # None*4, 最长长度4
emb_topic_Kd = Embedding(22, 8, mask_zero=True)(in_topic) # None * 4 * K  
# (22,8) 表示Embedding lookup table 是22*8的,也就是topic 共有22中不同取值0~21

总结:

连续特征的分桶

常用的分桶方式:

  • 等距分桶、等频分桶、
  • 直接对数做离散化如: 
  • 利用树模型做离散化:如使用GBDT+LR来将连续特征分到不同的节点,利用节点分裂的值作为分桶依据。

离散化方法的缺点:

  • 无法与CTR模型进行一起优化,即无法做到端到端训练
  • 两个相近的取值由于被分到了不同的桶中,导致其embedding可能相差很远
  • 两边的取值可能相差很远,但由于在同一桶中,其对应的embedding是完全相同的

AutoDis框架,具有高模型容量端到端训练每个特征取值具有独立表示的特点

三个步骤:

  • 1、Meta-Embeddings

  • 2、Automatic Discretization 对连续特征进行自动的离散化,实现了离散化过程的端到端训练。可以看作是一种软离散化(soft discretization)。对于温度系数 ,当其接近于0时,得到的分桶概率分布接近于one-hot,当其接近于无穷时,得到的分桶概率分布近似于均匀分布。这种方式也称为softargmax。
  • 3、Aggregation Function  将每个桶的embedding进行整合

KDD2021 | 华为AutoDis:连续特征的Embedding学习框架 - 知乎

autodis:一种新的连续特征embedding框架 - 知乎

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值