频道栏目
首页 > 网络 > 云计算 > 正文
Tensorflow实例-CNN处理句子相似度(上)
2017-04-08 09:19:11           
收藏   我要投稿

上一篇文章中,提到了在Tensorflow中关键的两个问题,第一对数据进行处理,转化为合适的tensor作为input输入到图中。第二使用tensorflow对神经网络进行构建。免费白菜网站大全2018上传至github上(https://github.com/Irvinglove/TF_Sentence_Similarity_CNN),感兴趣的同学可以下载并进行仿真,加深对tensorflow的理解。免费白菜网站大全2018较长,因此分为上下两篇对该实例进行讲解。上篇讲解句子相似度问题中数据处理的相关工作。

1、 读取glove词向量文件。

选用glove文件是google预先训练好的文件,因为是pretrained,所以我们直接进行读取。值得一提的是,这里新建了两个变量embedding_w,embedding_dic。因为我们在实际操作过程中发现,如果直接使用词向量作为input的话,那么placeholder中传入的shape就是[s_count,sentence_length,embedding_size],其中,s_count是数据集大小,sentence_length就是最大句子长度,embedding_length就是词向量的大小。那么placeholder的维度就太大,然后程序就变得特别卡顿。所以,参考Text Classification(CNN)(https://github.com/dennybritz/cnn-text-classification-tf)的方法,使用embedding层进行转换,即embedding_w的shape为[vocabulary_size,embedding_size],考虑这个矩阵纵坐标是glove的词汇大小,横坐标是词向量长度。placeholder的shape就变成了[s_count,sentence_length],以词汇在embedding_w的索引值代替词向量,这样就大大节省了placeholder的空间,embedding_dic就是将word转化为索引值的字典。

比如句子“cat sit on the mat”,一般的思路是用“cat”,”sit”,”on”,”the”,”mat”这五个单词的词向量表示这句话:

[[1,1,1],

[2,2,2],

def build_glove_dic():
无需申请自动送
无需申请自动送 从文件中读取pre-trained的glove文件,对应每个词的词向量
无需申请自动送
embedding_dic = {}
embedding_w = []
glove_dir = "glove.6B.50d.txt"
for i, line in enumerate(open(glove_dir, &无需申请自动送39;r&无需申请自动送39;)):
arr = line.split(" ")
embedding_dic[arr[0]] = i
embedding_w.append(np.array(arr[1:]).astype(float))
embedding_w = np.array(embedding_w, dtype=&无需申请自动送39;float32&无需申请自动送39;)
return embedding_w,embedding_dic

[3,3,3],

[4,4,4],

[5,5,5]]

那么整个数据集为9840行,placeholder就变成了9840*5*3大小的tensor,采用embedding_w以后呢,我们采用“cat”,”sit”,”on”,”the”,”mat”这五个词在embedding_w中的索引代替该词:

[1,2,3,4,5]

然后placeholder就变成了9840*5大小的tensor,然后在之后的操作中,根据索引查找embedding_w的词向量即可,当embedding_size为3时,影响不大,但是当embedding_size为50、100或者更大时,节省的时间就很可观了。

def build_glove_dic():
无需申请自动送
无需申请自动送 从文件中读取pre-trained的glove文件,对应每个词的词向量
无需申请自动送
embedding_dic = {}
embedding_w = []
glove_dir = "glove.6B.50d.txt"
for i, line in enumerate(open(glove_dir, &无需申请自动送39;r&无需申请自动送39;)):
arr = line.split(" ")
embedding_dic[arr[0]] = i
embedding_w.append(np.array(arr[1:]).astype(float))
embedding_w = np.array(embedding_w, dtype=&无需申请自动送39;float32&无需申请自动送39;)
return embedding_w,embedding_dic

2、读取数据集。本实例中数据集选取SICK(https://clic.cimec.unitn.it/composes/sick.html)。数据集主要包括两个句子和它们之间的相似度。整个函数的想法就是从数据集中提取数据,使用s1,s2,score存储两个句子和它们之间的相似度。然后对句子进行处理,记数据集中句子的最大长度sentence_length,不够该长度的使用‘unk’进行填充。

值得一提的是,这里的s1_image和s2_image的形状是[s_count,sentence_length

],label的形状是[s_count,1]。这里说道的s1_image和s2_image刚好和placeholder的input的形状保持一致,然后通过

def read_data_sets(train_dir):
无需申请自动送
无需申请自动送 s1代表数据集的句子1
无需申请自动送 s2代表数据集的句子2
无需申请自动送 score代表相似度
无需申请自动送 s_count代表数据总共有多少行
无需申请自动送
s1 = []
s2 = []
score = []
s_count = 0
SICK_DIR = "SICK_data/SICK.txt"
for line in open(SICK_DIR, &无需申请自动送39;r&无需申请自动送39;):
arr = line.split("\t")
s1.append(clean_str(arr[1]))
s2.append(clean_str(arr[2]))
score.append(arr[4])
s_count = s_count + 1
无需申请自动送 填充句子
s1, s2 = padding_sentence(s1, s2)
无需申请自动送 引入embedding矩阵和字典
embedding_w, embedding_dic = build_glove_dic()
无需申请自动送 将每个句子中的每个单词,转化为embedding矩阵的索引
无需申请自动送 如:s1_words表示s1中的单词,s1_vec表示s1的一个句子,s1_image代表所有s1中的句子
s1_image = []
s2_image = []
label = []
for i in range(s_count):
s1_words = s1[i].split(" ")
s2_words = s2[i].split(" ")
s1_vec = []
s2_vec = []
无需申请自动送 如果在embedding_dic中存在该词,那么就将该词的索引加入到s1的向量表示s1_vec中,不存在则用代替
for j,_ in enumerate(s1_words):
if embedding_dic.has_key(s1_words[j]):
s1_vec.append(embedding_dic[s1_words[j]])
else:
s1_vec.append(embedding_dic[&无需申请自动送39;&无需申请自动送39;])
if embedding_dic.has_key(s2_words[j]):
s2_vec.append(embedding_dic[s2_words[j]])
else:
s2_vec.append(embedding_dic[&无需申请自动送39;&无需申请自动送39;])
s1_image.append(np.array(s1_vec))
s2_image.append(np.array(s2_vec))
label.append(np.array(np.array([score[i]]).astype(float)))
无需申请自动送 求得训练集与测试集的tensor并返回
s1_image = np.array(s1_image)
s2_image = np.array(s2_image)
label = np.array(label,dtype=&无需申请自动送39;float32&无需申请自动送39;)
train_end = int(s_count*0.7)
return s1_image[0:train_end], s2_image[0:train_end], label[0:train_end],\
s1_image[train_end:s_count], s2_image[train_end:s_count], label[train_end:s_count],\
embedding_w

3、填充句子

def padding_sentence(s1, s2):
无需申请自动送
无需申请自动送 得到句子s1,s2以后,很直观地想法就是先找出数据集中的最大句子长度,
无需申请自动送 然后用对句子进行填充
无需申请自动送
s1_length_max = max([len(s.split(" ")) for s in s1])
s2_length_max = max([len(s.split(" ")) for s in s1])
sentence_length = max(s1_length_max, s2_length_max)
print "已经求得最大长度sentence_length"
for i,s in enumerate(s1):
sen_len_cur = len(s.split(" "))
if (sen_len_cur < sentence_length):
reduces = sentence_length - sen_len_cur
for reduce in range(reduces):
s += " "
s1[i] = s
for i,s in enumerate(s2):
sen_len_cur = len(s.split(" "))
if (sen_len_cur < sentence_length):
reduces = sentence_length - sen_len_cur
for reduce in range(reduces):
s += " "
s2[i] = s
print "9840个句子填充完毕"
return s1, s2

注意:在处理数据的过程中,要把列表转化成np数组,不然传入placeholder中会一直报错“setting an array element with a sequence”。np数组的转换也很简单,使用np.array()就可以进行转换,但是np数组在插入过程不是很熟练,因此也可以采用先对列表进行操作,在转换为np数组。但一定要注意,多维的列表的每一层都需要转化成np数组,可以在tensorflow的调试过程中慢慢处理。

点击复制链接 与好友分享!回本站首页
上一篇:大数据技术原理与引用—上机实验报告之一
下一篇:基于hadoop2.2.0分布式搭建
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑--致力于做实用的IT技术学习网站

无需申请自动送