小言_互联网的博客

注意力机制的本质

273人阅读  评论(0)


如图所示,一般描述注意力机制都是这样的图这样的图其实就是
序列元素之间彼此建立一种关系,那么看此图可以知道元素自己和自己建立了关系,这个人觉得是浪费权重的表现,其实要建立元素和元素之间的关系
其实可以这样看上图
竖着的一侧作为输入,横着的每个作为输出这样就能建立关系。但是有一个疑问就是无论输出是什么输入都是一样的,所以我们不能这样输入
我们要将输入一个输出建立一种对应关系,这个关系就是无论输入是多长输入不能存在输出,但是又不能没有关系(我们规定输出只有一个元素)那么我们可以使输入必须使用一个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
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场