【深度学习】 Attention机制的几种实现方法总结(基于Keras框架)

说明

  在讲解了Dense+Attention以及LSTM+Attention时,还是使用了别人的代码,因此很多同学对一些地方仍有不够清晰的认识,在这里分享下自己的经验,并基于实践重新设计了实验。这是本人在Attention实践后的经验之谈,所讲不一定完全正确,欢迎讨论。

1 前情提要

  我们的实验思路还是借鉴于前两篇,随机生成数据,并指定某一个特征为标签。这样,我们就期望Attention机制能够很好地捕捉到这个特征,即给这个特征分配的权重较高。
  为了方便理解,这一次我们的数据集最初都由int型表示,实际上,很多实际问题的特征都是以编号ID的形式出现,这样做符合实际。我们的数据集期望设计成如下形式,特征:[5,2,1,9,2],标签始终为第个3特征 [1];特征:[7,2,9,5,3],标签[9]…以此类推。
  首先先看下整个实验所需要的一些参数,这里假设有12个特征,每个特征大小假设都在区间[0,999]内,通过Embedding进行嵌入进行后续的训练,嵌入维度为32。我们选定第3个特征为标签,期望Attention机制捕捉到。数据集大小设置为10000,即有10000个[特征,标签]数据,数据集太小了容易欠拟合或过拟合,太大了容易一下就学到,不方便比较。经测试10000这个值比较适中,因此就选择了它。将数据集8:2分为训练集和测试集,训练的轮数为10次。
  注意,这里做了简化,在实际中,每个特征的最大值和最小值是大概率不相同的,比如年龄{0,1,…,100}和性别{0,1},因此,每种特征的嵌入维度也应不一致(范围大种类多的应嵌入维度更高,需要更多的隐层特征进行表示)。

1.1 参数设定

datasize = 10000 #数据规模
feature_cnt = 12 #特征数量
feature_key = 3 #人为设得的重要特征,期望注意力机制能正确捕捉到。feature_key<=feature_cnt
    
feature_range = 1000 #特征的值域
feature_min = 0 #特征最小值
feature_max = feature_range-1 #特征最大值

data_split = 0.8 #数据集划分比例
epochs = 10 #训练轮数
dim = 32 #嵌入维度

1.2 数据集生成

  这里可以直接输出来看,为了方便调试,我们将随机种子固定,多次实验时随机结果相同,便于调试。同时,我们的问题视为多分类问题,因此将标签由ID的形式转化为one-hot形式。

def generate_data(datasize,feature_cnt,feature_key,feature_min,feature_max,data_split):
    np.random.seed(1327) #有预见的随机,方便调试

    data_split = int(datasize*data_split)
    
    data = np.random.randint(low = feature_min,high = feature_max+1,size=(datasize,feature_cnt)) #值在[low,high)
    #print(data)
    
    label = data[:,feature_key-1].reshape(len(data),1) #让标签与数据的某一维特征相同。 feature_key<=feature_cnt
    #print(label)
    label = [to_categorical(lab[0],feature_max+1) for lab in label] #将标签由数值转化为one-hot形式,用于多分类
    label = np.array(label)
        
    #print(label)

    train_x = data[:data_split]
    train_y = label[:data_split]
    test_x = data[data_split:]
    test_y = label[data_split:]
    
    '''
    print('-------------train datasize:',len(train_x))
    print('train_x:\n',train_x)
    print('train_y:\n',train_y)
    print()
    print('-------------test datasize:',len(test_x))
    print('test_x:\n',test_x)
    print('test_y:\n',test_y)
    '''
    return train_x,train_y,test_x,test_y

2 模型构建

2.1 总体构建

  总体的框架是一个多分类模型,本文一共实现了3种不同思路的Attention机制,每一类Attention最后的应用又可以按平均或拼接进行划分。因此,一共有6种不同的组合,再加上不用Attention进行的实验对比,总共7种。注意,在这里,实现注意力时,我们总是给每一个输入的特征分配一个注意力,总体框架的代码如下:

2.1.1 搭建模型

def build_model(feature_cnt,feature_max,model_type,merge_type,dim):
    K.clear_session() #清除之前的模型,省得压满内存
    inputs = Input(shape=(feature_cnt,), dtype='int32')
    
    embd = Embedding(feature_max+1,dim)(inputs)
    embd = BatchNormalization()(embd)
    Dropout(0.25)
    if model_type != 'basic':  
        if model_type == 'att1':
            hidden = attention_block_1(embd,feature_cnt,dim) 
        elif model_type == 'att2':
            hidden = attention_block_2(embd,feature_cnt,dim)
        elif model_type == 'att3':
            hidden = attention_block_3(embd,feature_cnt,dim)
        
        if merge_type == 'avg':
            #hidden = GlobalAveragePooling1D()(hidden) 
            hidden = Lambda(lambda x:K.mean(x,axis = 1))(hidden)
        else:
            hidden = Flatten()(hidden)
    else:
        hidden = Flatten()(embd)
    outputs = Dense(feature_max+1,activation='softmax')(hidden)
    model = Model(inputs=inputs, outputs=outputs)
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    model.summary()
    return model

2.1.2 获取注意力

def get_layer_output
  • 31
    点赞
  • 171
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lechuan_dafo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值