壮阳秘方
招商咨询>二楼店面成功案例pytorch中,嵌⼊层bedding的计算⽅式
本⽂主要记录:
1. 离散特征如何预处理之后嵌⼊
2.使⽤pytorch怎么使⽤nn.embedding
以推荐系统中:考虑输⼊样本只有两个特征,⽤逻辑回归来预测点击率ctr
看图混个眼熟,后⾯再说明:
⼀、离散数据预处理怦然一震
假设⼀个样本有两个离散特征【职业,省份】,第⼀个特征种类有10种,第⼆个特征种类有20种。于是field_dims=[10, 20]
“职业”的取值为:[学⽣,⽼师,⽼板,司机……]共10种
“省份”的取值为:[⿊龙江、吉林、四川(第3个位置)、……、北京(第7个位置)、……、重庆(第19个位置)、……]
设原始数据部分样本是这样的(标签没写出来,点击就为1,未点击就为0):
[学⽣,四川],[学⽣,北京],[⽼师,重庆]
那么处理过后变为
[1, 3], [1, 7], [2, 19]
假设我们在torch嵌⼊⽅式为:所有特征同时⼀起嵌⼊(还有就是分别嵌⼊:就是每个特征分开嵌⼊,然后把所有特征的嵌⼊向量⽤torch.cat 拼接成⼀个向量):
field_dims=[10,20],取embed_dim=3
这个时候得到了⼀个索引字典index_dict,长度为sum(field_dims)=30, 每个索引对应⼀个嵌⼊维度为e
mbed_dim=3的向量(相当于字典的key为1到30,每个key对应⼀个嵌⼊的维度为embed_dim=3的向量)
现在,我们该怎么把[学⽣,四川],对应的[1, 3]数据嵌⼊进去,嵌⼊的结果是什么呢?
这个时候需要把[1, 3], [1, 7], [2, 19]变为[1, 13], [1, 17], [2, 29].
因为在one-hot编码的时候[1, 3]中的1对应“1,0,0,0,0,0,0,0,0,0”,3对应“0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0”,
最终形成的one-hot向量为“1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0”,1和3分别在第1位置和第13位置(我把这种操作简单叫做:变换处理)。
设batch_size=2,那么在定义模型的时候,def forward(lf, x)中的x的size就等于batch_size*特征数=2*2。
假如第⼀个batch读取的数据是[1, 3], [1, 7], 则x=[[1,3], [1,7]],经过“变换处理”变为了x_=[[1,13], [1,17]],
这个时候就可以把x_输⼊到嵌⼊层,embed_result = bed(x_)
得到的结果embed_result的size为:batch_size*特征数*嵌⼊维度=2*2*3。
设1,13,17对应的嵌⼊向量分为为[0.1, 0.2, 0.3], [0.3, 0.6, 0.2], [0.3, 0.9, 0.2],
那么embed_result结果为(还是⼀个tensor,这⼉只是展现了数据):
因为batch_size=2,是两个样本,所以最后需要得到两个输出。拉唑类药物
R1 = torch.sum(embed_result,1) # size=batch_size*嵌⼊维度=2*3
[0.1+0.7, 0.2+0.6, 0.3+0.2] = [0.8, 0.8, 0.5]
压强实验
R2 = torch.sum(R1,1) # size = batch_size=2
双鱼座金牛座(注意,如果还要在添加层的话,可以把R1作为下⼀层的输⼊,或者把embed_result每⼀个样本的特征拼接起来得到R3输⼊到下⼀层)
上⾯这个怎么和公式联系起来呢,感觉直接是把特征嵌⼊过后的向量直接相加求和得到输出y,公式前⾯的权重w怎么体现的呢?
因为特征x1有10个取值,x2有20个取值,one-hot编码过后,特征变成了30个,设新的特征为f:
原来的式⼦相当于变成了:
对于样本[学⽣,四川]—>[1,3]-变换处理->[1, 13],
只有x1,1⼀个为1,
其中也只有x2,3⼀个为1
然⽽实际上并没有采⽤one-hot存储,当⽤了embedding过后只是存储了⼀个索引字典,设嵌⼊的为度为3,式⼦相当于(设θ0=0)
这就与R2中的结果对应上了。所以直接把样本嵌⼊向量的元素值全部加起来,就是输出。
图解:
针对输⼊为[学⽣,四川]-->[1,3]-->[1, 13],
输⼊层one-hot编码第1个位置和第13个位置是1(蓝⾊),其余位置是0
(启⽰程序中并不是输⼊的one-hot编码,只是⼀个索引key=1和13,通过索引去得到嵌⼊过后的向量)
1.嵌⼊
embed_result = bed(x_)
2.每个特征的对应元素求和,得到embedding层第i个神经元的值
对应代码R1 = torch.sum(embed_result,1)。# size=batch_size*嵌⼊维度=2*3
⽐如,以输⼊[1,3]à[1,13]为例,
得到嵌⼊层三个神经元的值为:
同理计算得到[1,7]-->[1,17]对应的embedding层神经元的值
即:
3. 把每个样本embeding层所有神经元的值加起来。
对应代码R2 = torch.sum(R1, 1) # size = batch_size=2
补充说明
特征嵌⼊的两种⽅式
1.所有特征⼀起嵌⼊
field_dims=[10,20], emb_dim1=3, 设batch_size=2x1=[1, 3],x2=[1,7],
于是⼀个batch中 x=[[1, 3], [1, 7]],
Pytorch代码:
embed_1 = Embedding(sum(field_dims), emb_dim1)
x “变换处理”后,得到x_=[[1, 13], [1, 17]]
输⼊x_,输出embed_result1
embed_result1 = embed_1(x_)#size=batch_size*特征数*嵌⼊维度=2*2*3
此时需要⽤r1 = torch.sum(embed_result1, 1)得到的结果size=2*3
r2 = torch.sum(r1,1) # size = batch_size =2
ebd = nn.Embedding(30,3)
x_ = Variable(torch.LongTensor([[1, 13], [1, 17]]))
print(ebd(x_)) #2*2*3
r1 = torch.sum(ebd(x_),1)
print(r1) # 2*3
r2 = torch.sum(r1,1)
print(r2) #size = 2
输出;
tensor([[[ 2.2919, 0.2820, -0.0129],
[-0.1115, 2.2074, 0.1836]],
[[ 2.2919, 0.2820, -0.0129],
[ 1.0564, 0.4073, -1.7239]]], grad_fn=<EmbeddingBackward>)
tensor([[ 2.1804, 2.4893, 0.1707],
幼儿园招生宣传语[ 3.3483, 0.6892, -1.7368]], grad_fn=<SumBackward1>)
tensor([4.8404, 2.3007], grad_fn=<SumBackward1>)
2.特征分别嵌⼊,然后再cat。
(⽐如,模型准备把嵌⼊维度设为100,同时嵌⼊的嵌⼊维度直接为100,分别嵌⼊各个特征的嵌⼊维度之和为100)(同时嵌⼊的嵌⼊维度为3,为了保持⼀致,分别嵌⼊时候第⼀个特征嵌⼊维度设为1,第⼆个特征设嵌⼊维度为2)field_dims=[10,20], emb_dim2_1=1, emb_dim2_1=2
embed2_1 = Embedding(filed_dims[0], emb_dim2_1)
embed2_2 = Embedding(filed_dims[1], emb_dim2_2)
embed_result2_1 = embed2_1(x_[ : ,0]) #batch_size*emb_dim2_1=2*1
#相当于得到对[1, 1]嵌⼊的结果
embed_result2_2 = embed2_2(x_[ : ,1]) #batch_size*emb_dim2_1=2*2
#相当于得到对[13, 17]嵌⼊的结果
embed_result_list = embed_result2_1+ embed_result2_2
embed_result2 = torch.cat(embed_result_list, 1) #size=batch_size*( emb_dim2_1+ emb_dim2_2=2*
1*(1+2)=2*3
最后使⽤torch.sum(embed_result2, 1) # size=2
x_ = Variable(torch.LongTensor([[1, 13], [1, 17]]))
embed2_1 = nn.Embedding(10,1)
embed2_2 = nn.Embedding(20,2)
embed_result2_1 = embed2_1(x_[ : ,0])
embed_result2_2 = embed2_2(x_[ : ,1])
print(embed_result2_1) # batch_size*emb_dim2_1=2*1
print(embed_result2_2) #batch_size*emb_dim2_1=2*2
lisi_ebd2 = []
lisi_ebd2.append(embed_result2_1)
lisi_ebd2.append(embed_result2_2)
# lisi_ebd2长度为2,⼀个元素为2*1⼤⼩,⼀个元素为2*2
embed_result2 = torch.cat(lisi_ebd2,1)
print(embed_result2) #2*3
p = torch.sum(embed_result2, 1)