如何在Tflearn的DNN分类器中添加词嵌入层实现答案匹配评分预测?
嘿,我来帮你搞定这个问题!在Tflearn里给DNN模型加词嵌入层来做答案匹配评分预测,其实可以分几个清晰的步骤来走,我给你详细拆解,附代码示例:
1. 先搞定数据预处理与词汇表构建
首先得把你的问答对数据转换成模型能认的格式,第一步就是构建词汇表——把所有问题和答案里的词都收集起来,给每个词分配唯一索引,再把句子转成索引序列。
举个实际代码例子:
import tflearn import numpy as np from collections import Counter # 假设我们有样例问答对数据,每个样本是(问题, 答案, 匹配评分) data = [ ("如何学习Python", "看官方文档和做项目", 0.9), ("Python入门方法", "从基础语法开始练习", 0.85), ("怎么提高编程能力", "多写代码多调试", 0.92), # 这里可以加更多你的真实样本 ] # 收集所有出现的词汇 all_words = [] for q, a, _ in data: all_words.extend(q.split()) all_words.extend(a.split()) # 构建词汇表,保留出现频率最高的10000个词(可根据数据量调整) vocab = Counter(all_words).most_common(10000) word2idx = {word: idx+1 for idx, (word, _) in enumerate(vocab)} # 留0给padding补位 idx2word = {idx: word for word, idx in word2idx.items()} vocab_size = len(word2idx) + 1 # 加上padding的0索引 # 把句子转成固定长度的词索引序列 def sentence_to_indices(sentence, max_len=20): indices = [word2idx.get(word, 0) for word in sentence.split()] # 补位或截断到指定长度 if len(indices) < max_len: indices += [0]*(max_len - len(indices)) else: indices = indices[:max_len] return np.array(indices) # 处理所有数据,得到模型输入 X_q = np.array([sentence_to_indices(q) for q, a, _ in data]) X_a = np.array([sentence_to_indices(a) for q, a, _ in data]) Y = np.array([[score] for q, a, score in data]) # 评分是回归任务,用一维输出
2. 构建带词嵌入层的DNN模型
这里核心是给问题和答案分别做词嵌入,然后把两个句向量合并(拼接、相加都可以),再接入全连接层做评分预测。推荐共享词嵌入层,这样模型能学到更通用的语义表示:
# 定义输入层,问题和答案的输入都是固定长度的词索引序列 input_q = tflearn.input_data(shape=[None, 20], name='question_input') input_a = tflearn.input_data(shape=[None, 20], name='answer_input') # 共享词嵌入层(问题和答案用同一个词汇表时,共享嵌入效果更好) embedding_layer = tflearn.embedding(input_q, input_dim=vocab_size, output_dim=128, name='embedding') # 答案输入复用同一个嵌入层 embedding_a = tflearn.embedding(input_a, input_dim=vocab_size, output_dim=128, name='embedding', reuse=True) # 把词嵌入转换成句向量,这里用平均池化(也可以用max池化或LSTM) sentence_vec_q = tflearn.global_avg_pool(embedding_layer, name='q_avg_pool') sentence_vec_a = tflearn.global_avg_pool(embedding_a, name='a_avg_pool') # 合并两个句向量,这里用拼接方式 combined_vec = tflearn.concat([sentence_vec_q, sentence_vec_a], axis=1) # 接入全连接层,加 dropout 防止过拟合 dense1 = tflearn.fully_connected(combined_vec, 256, activation='relu') dropout1 = tflearn.dropout(dense1, 0.5) dense2 = tflearn.fully_connected(dropout1, 128, activation='relu') dropout2 = tflearn.dropout(dense2, 0.5) # 输出层:因为是评分预测(回归任务),用线性激活函数 output = tflearn.fully_connected(dropout2, 1, activation='linear') # 定义回归模型,用均方误差做损失,Adam优化器 regression = tflearn.regression(output, optimizer='adam', loss='mean_square', metric='R2') model = tflearn.DNN(regression)
3. 训练与预测
搞定模型结构后,就可以训练和测试了:
# 训练模型 model.fit({'question_input': X_q, 'answer_input': X_a}, Y, n_epoch=50, batch_size=8, show_metric=True) # 测试预测 test_q = sentence_to_indices("怎么学Python") test_a = sentence_to_indices("跟着教程写代码") predicted_score = model.predict({'question_input': [test_q], 'answer_input': [test_a]}) print(f"预测匹配评分:{predicted_score[0][0]:.4f}")
一些实用小技巧
- 如果你的评分是分类任务(比如高/中/低匹配度),把输出层激活改成
softmax,损失换成categorical_crossentropy,同时把Y转成one-hot编码。 - 词嵌入维度(
output_dim)可以根据数据规模调整,一般在50-300之间。 - 不想用平均池化的话,也可以用LSTM/GRU提取句向量,比如:
lstm_q = tflearn.lstm(embedding_layer, 128, return_seq=False) lstm_a = tflearn.lstm(embedding_a, 128, return_seq=False, reuse=True)
- 有预训练词嵌入(比如Word2Vec、GloVe)的话,可以加载预训练权重到嵌入层,能大幅提升效果:
# 假设你已经加载了预训练的嵌入矩阵embedding_matrix embedding_layer = tflearn.embedding(input_q, input_dim=vocab_size, output_dim=128, weights_init=embedding_matrix, trainable=True, name='embedding')
内容的提问来源于stack exchange,提问作者abhijit dalavi
相关产品推荐
相关产品推荐

