BI-LSTM+Attention 的 tensorflow-1.14 实现

这里只是用简单例子演示关于 self-attention 的逻辑,判断一句话的情感是正面或者是负面,具体原理自己百度即可。

import tensorflow as tf
import numpy as np
tf.reset_default_graph()

# 词向量维度
dim = 2
# 隐层大小
hidden = 5
# 时间步大小
step = 3
# 情感类别 正面或者负面
N = 2

sentences = ["i love mengjun","i like peipei","she likes damao","she hates wangda","wangda is good","mengjun is bad"]
labels = [1,1,1,0,1,0]

words = list(set(" ".join(sentences).split()))
# 词典大小
V = len(words)
# 单词和索引互相映射
word2idx = {v:k for k,v in enumerate(words)}
idx2word = {k:v for k,v in enumerate(words)}

# 处理输入数据
input_batch = []
for sentence in sentences:
    input_batch.append([word2idx[word] for word in sentence.split()])

# 处理输出目标数据
target_batch = []
for label in labels:
    target_batch.append(np.eye(N)[label]) # 这里要进行独热编码,后面计算损失会用到
    
# 初始化词向量
embedding = tf.Variable(tf.random_normal([V, dim]))
# 输出分类时使用到的向量矩阵
out = tf.Variable(tf.random_normal([hidden * 2, N]))

X = tf.placeholder(tf.int32, [None, step])
# 对输入进行词嵌入
X_embedding = tf.nn.embedding_lookup(embedding, X)
Y = tf.placeholder(tf.int32, [None, N])

# 定义正向和反向的 lstm 
lstm_fw_cell = tf.nn.rnn_cell.LSTMCell(hidden)
lstm_bw_cell = tf.nn.rnn_cell.LSTMCell(hidden)

# 经过双向 lstm 的计算得到结果 
# output : ([batch_size, step, hidden],[batch_size, step, hidden])  
# final_state : (fw:(c:[batch_size, hidden], h:[batch_size, hidden]), bw:(c:[batch_size, hidden], h:[batch_size, hidden]))
output, final_state = tf.nn.bidirectional_dynamic_rnn(lstm_fw_cell, lstm_bw_cell, X_embedding, dtype=tf.float32)
# 将 output 根据 hidden 维度拼接起来,[batch_size, step, hidden*2]
output = tf.concat([output[0], output[1]], 2)

# 将 final_state 的反方向的 c 和 h 根据 hidden 维度拼接起来, [batch_size, hidden*2]
final_hidden_state = tf.concat([final_state[1][0], final_state[1][1]], 1)
# 增加第三个维度,方便计算 [batch_size, hidden*2, 1]
final_hidden_state = tf.expand_dims(final_hidden_state, 2)

# 计算每个时间步的输出与最后输出状态的相似度 
# [batch_size, step, hidden*2] * [batch_size, hidden*2, 1] = squeeze([batch_size, step, 1]) = [batch_size, step]
attn_weights = tf.squeeze(tf.matmul(output, final_hidden_state), 2)
# 在时间步维度上进行 softmax 得到权重向量
soft_attn_weights = tf.nn.softmax(attn_weights, 1)

# 各时间步输出和对应的权重想成得到上下文矩阵 [batch_size, hidden*2, step] * [batch_size, step, 1] = [batch_size, hidden*2, 1]
context = tf.matmul(tf.transpose(output, [0, 2, 1]), tf.expand_dims(soft_attn_weights, 2))
# squeeze([batch_size, hidden*2, 1]) = [batch_size, hidden*2]
context = tf.squeeze(context, 2)

# 输出概率矩阵 [batch_size, hidden*2] * [hidden*2, N] = [batch_size, N]
model = tf.matmul(context, out)
# 计算损失并优化
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=model ,labels=Y))
optimizer = tf.train.AdamOptimizer(0.001).minimize(cost)
# 预测
hypothesis = tf.nn.softmax(model)
prediction = tf.argmax(hypothesis, 1)

sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)
for epoch in range(5000):
    _, loss = sess.run([optimizer, cost], feed_dict={X:input_batch, Y:target_batch})
    if (epoch+1) % 1000 == 0:
        print('epoch ','%06d'%(epoch+1), ' loss ', '%08f'%loss)
        
test_text = [[word2idx[word] for word in 'she hates wangda'.split()]]
predict = sess.run([prediction], feed_dict={X: test_text})
print('she hates wangda', '-->', predict[0][0])

结果打印:

epoch  001000  loss  0.001645
epoch  002000  loss  0.000279
epoch  003000  loss  0.000106
epoch  004000  loss  0.000052
epoch  005000  loss  0.000029
she hates wangda --> 0  
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Dual-CNN+Bi-LSTM (DCNN+Bi-LSTM)是一种结合了Dual-CNN和Bi-LSTM的网络模型,用于文本分类任务。它的结构包括两个主要部分:Dual-CNN和Bi-LSTM。 Dual-CNN是一种使用两个不同大小的卷积核进行卷积操作的模型。它的目的是捕捉不同大小的语义信息。通过使用不同大小的卷积核,Dual-CNN可以同时捕捉局部和全局的语义特征。 Bi-LSTM是一种双向长短期记忆网络,用于学习文本中的上下文信息。Bi-LSTM通过同时考虑前向和后向的上下文信息,可以更好地理解文本的语义。 下面是一个示例代码,演示了如何实现Dual-CNN+Bi-LSTM模型: ```python import tensorflow as tf from tensorflow.keras.layers import Input, Embedding, Conv1D, MaxPooling1D, Bidirectional, LSTM, Dense # 定义输入层 input_layer = Input(shape=(max_length,)) # 定义嵌入层 embedding_layer = Embedding(vocab_size, embedding_dim)(input_layer) # 定义Dual-CNN层 conv1 = Conv1D(filters=32, kernel_size=3, activation='relu')(embedding_layer) conv2 = Conv1D(filters=32, kernel_size=5, activation='relu')(embedding_layer) pool1 = MaxPooling1D(pool_size=2)(conv1) pool2 = MaxPooling1D(pool_size=2)(conv2) # 将Dual-CNN层的输出拼接起来 concat = tf.keras.layers.concatenate([pool1, pool2], axis=1) # 定义Bi-LSTMlstm = Bidirectional(LSTM(64))(concat) # 定义输出层 output_layer = Dense(num_classes, activation='softmax')(lstm) # 定义模型 model = tf.keras.Model(inputs=input_layer, outputs=output_layer) # 编译模型 model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) # 训练模型 model.fit(X_train, y_train, epochs=10, batch_size=32) # 使用模型进行预测 predictions = model.predict(X_test) ``` 请注意,上述代码中的`max_length`是输入文本的最大长度,`vocab_size`是词汇表的大小,`embedding_dim`是嵌入层的维度,`num_classes`是分类的类别数。你需要根据你的具体任务进行相应的调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

王大丫丫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值