如图所示,一般描述注意力机制都是这样的图这样的图其实就是
序列元素之间彼此建立一种关系,那么看此图可以知道元素自己和自己建立了关系,这个人觉得是浪费权重的表现,其实要建立元素和元素之间的关系
其实可以这样看上图
竖着的一侧作为输入,横着的每个作为输出这样就能建立关系。但是有一个疑问就是无论输出是什么输入都是一样的,所以我们不能这样输入
我们要将输入一个输出建立一种对应关系,这个关系就是无论输入是多长输入不能存在输出,但是又不能没有关系(我们规定输出只有一个元素)那么我们可以使输入必须使用一个cls 占位输出的位置(也即是输入的序列必须包含输出但是不能表示为输出,只是使用一个其他用来占位,这个占位可以帮助任何的元素占位,也就是未知数,输入只能由一个未知数),这样输入和输出就存在必然关系,且网络也能建立元素之间的位置关系。
其实这个和bert的mask 差不多只不过bert是采用多对多的机制,我们力求将问题简化,也就是说我们的输出的结果只有元素个类别。
举例说明
数据 三体文明
输入 cls 体文明
输出 三
输入 三cls文明
输出 体
输入 三体cls明
输出 文
输入 三体文cls
输出 明
例子代码
import torch
from torch import nn
import matplotlib.pyplot as plt
from torch.utils.data import DataLoader
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
class autoencoder(nn.Module):
def __init__(self,seq_len,num_class):
super(autoencoder, self).__init__()
self.liner_1=nn.Linear(seq_len,100,bias=True)
self.relu=nn.ReLU(True)
self.bn=nn.BatchNorm1d(100)
self.liner_2=nn.Linear(100,num_class)
def forward(self,x):
x=self.liner_1(x)
x = self.relu(x)
x = self.bn(x)
x=self.liner_2(x)
return x
data="ABCDEFGHIGKLMNOPQRSTUVWXYZ"
seq_len=10
data_list=[]
for j in data:
for i in range(0,len(data[data.index(j):]),seq_len):
res=data[data.index(j):][i:i+seq_len]
if len(res)==seq_len:
#制作label 使用27代表cls
for z in res:
res_num = [0]*seq_len
label=data.index(z)
res_num[res.index(z)]=len(data)+1
for z_ in res:
if z_==z:
continue
else:
res_num[res.index(z_)] =data.index(z_)
data_list.append([res_num,label])
train_data = DataLoader(dataset=data_list, batch_size=10, shuffle=True)
model=autoencoder(seq_len,len(data))
loss_f=torch.nn.CrossEntropyLoss()
opt=torch.optim.Adam(model.parameters(),0.001,weight_decay=0.0001)
# 绘图设置
#定义两个数组
Loss_list = []
Accuracy_list = []
for epoch in range(200):
loss_list=[]
for i,data_ in enumerate(train_data):
input_data=torch.Tensor([i.numpy().tolist() for i in data_[0]]).permute(1,0)
output=model(input_data)
loss=loss_f(output,data_[1])
loss_list.append(loss.data.numpy().tolist())
opt.zero_grad()
loss.backward()
opt.step()
Loss_list.append(sum(loss_list)/len(loss_list))
#我这里迭代了200次,所以x的取值范围为(0,200),然后再将每次相对应的准确率以及损失率附在x上
x2 = range(len(Loss_list))
y2 = Loss_list
plt.subplot(1, 1, 1)
plt.plot(x2, y2, '-')
plt.xlabel('Train loss vs. epoches')
plt.ylabel('Train loss')
plt.show()
# plt.savefig("accuracy_loss.jpg")
if __name__ == '__main__':
pass
看下图可以知道这是一个盆地。说明这样的设计数据集和标签学到了东西并且收敛了,可以调节seq_len 的长度
转载:https://blog.csdn.net/weixin_32759777/article/details/116389080
查看评论