【NLP】word2vec词向量模型训练——基于tensorflow

前言

  维基百科中文数据训练word2vec词向量模型——基于gensim库

  上文我们使用了 gensim 库中的 Word2vec 模块训练词向量模型,本篇我们通过 tensorflow 自己手写代码来训练词向量模型,并测试词与词之间的相似度,主要步骤大体如下:

  • 数据准备(数据这部分我们使用了某部小说)
  • tensorflow 训练模型的构建、训练(图的构建、初始化操作、会话开启、训练模型)
  • 模型测试(计算词与词之间的相似度)

准备环境:

  • Windows10 64位
  • tensorflow-gpu-1.9.0(我电脑使用的这个,不过本篇cpu版本的即可,安装方式自行百度,gpu版本安装比较麻烦)
  • jieba
  • Python3.6(我用的是 Anaconda
  • Pycharm

本篇代码可见: Github

一、数据准备

  本篇我们使用的数据是小说《斗破苍穹》,通过对《斗破苍穹》文本数据的训练,我们希望从中找出指定词最相似的 n 个词,此外我们还有一个停用词文本文件。

为了模型可以快速训练,所以这里这是使用了一部小说,如果模型的效果要更好,可以扩大数据量。

1、数据查看

在这里插入图片描述

在这里插入图片描述

当然,看到这些文本数据,我们自然而然会想到,分词、去停用词

2、读取停用词构建 set 集合

代码如下:

# step 1 读取停用词,构建停用词set集合
stop_words = []
with open('stop_words.txt', encoding='utf-8') as f:  # 读取stop_words.txt,每行为一个词
    line = f.readline()  # 按行读取
    while line:
        stop_words.append(line[:-1])  # 去除每行后面的换行符并添加到stop_words中
        line = f.readline()
stop_words = set(stop_words)  # 通过set函数去除重复词
print('停用词读取完毕,共{n}个单词'.format(n=len(stop_words)))
3、文本处理,分词、去停用词,得到词典

代码如下:

# step2 读取文本,预处理,分词,得到词典
all_word_list = []  # 用于记录所有的词,即词典
sentence_list = []  # 用于记录所有样本的样本list,如:[["今天","天气","不错"],["我","是","谁"],...,["","",""]]
line_sum = 1
with open('wiki_zh_jian.txt', encoding='utf-8') as f:
    line = f.readline()  # 按行读取
    while line:  # 判断有没有读取到文件末尾,没有就执行循环语句
        print("正在处理第", line_sum, "行")
        while '\n' in line:
            line = line.replace('\n', '')  # 将'\n'替换为''
        while ' ' in line:
            line = line.replace(' ', '')  # 将' '替换为''
        if len(line) > 0:  # 如果句子非空
            raw_words = list(jieba.cut(line, cut_all=False))  # 使用jieba分词
            dealed_words = []  # 用于记录去除停用词以及规定词后的词
            for word in raw_words:
                # 如果词不属于停用词且不是['qingkan520', 'www', 'com', 'http']中的词
                if word not in stop_words and word not in ['qingkan520', 'www', 'com', 'http']:
                    all_word_list.append(word)  # 将该词添加到样本的词list中
                    dealed_words.append(word)  # 将该词添加到处理后的词list中
            sentence_list.append(dealed_words)  # 每行为一个样本,并将处理过的词list添加到样本list
        line = f.readline()  # 读取下一行
        line_sum += 1
word_count = collections.Counter(all_word_list)  # 计数器,返回dict类型,{"单词1":15,"单词2":5,"单词3":2}
# 表示单词1出现了15次,单词2出现了5次,单词3出现了2次,依次类推
print('文本中总共有{n1}个单词,不重复单词数{n2},选取前30000个单词进入词典'
      .format(n1=len(all_word_list), n2=len(word_count)))
word_count = word_count.most_common(30000)  # 返回一个TopN列表,如:[("单词1",15),("单词2",5),("单词3",2)]
word_list = [x[0] for x in word_count]  # 取出TopN列表中的单词,放到word_list中,构成["单词1","单词2","单词3"]
print(word_list[:100])

二、tensorflow 训练模型的构建、训练

  本节通过 word2vec 类来实现,主要包括:

1. 初始化参数 __init__

  • vocab_list=None, 词典默认为None,需用户传入
  • embedding_size=200, 词向量维度,默认为200
  • win_len=3, 单边窗口长,也就是上下文,考虑某个词的前面3个词,后面3个词
  • num_sampled=1000, 负采样个数,默认1000
  • learning_rate=1.0, 学习率
  • logdir='/tmp/simple_word2vec', tensorboard记录地址
  • model_path=None 模型路径,用于训练好后加载模型用

程序执行到此类时,先执行 __init__ 。根据模型训练时传入的参数, __init__进行:参数的获取、词的映射(词典)、图的定义、操作初始化(会话创建、会话开启、记录摘要)

2. 图的定义 build_graph

  • 图的声明:所有的变量和操作都定义在该声明的图上
  • 定义变量:词向量、权值、偏置
  • 构建损失函数:NCE损失
  • 优化损失函数:以随机梯度下降的方式
  • 计算与指定若干单词的相似度

3. 操作初始化 init_op

  • 创建会话
  • 执行会话
  • 记录摘要

4. 训练模型 train_by_sentence

  • 模型需传入的输入数据
  • 开启会话,并传入数据
  • 训练损失

5. 计算相似度概率

6. 模型保存

7. 模型加载

具体内容可看代码部分,其中有大量的注释

三、模型测试

  主要是从词典选择两个词,然后计算出它们之间的相似度。结果如下:

0 sentences dealed, loss: 392.29644775390625
1000 sentences dealed, loss: 246.87802124023438
2000 sentences dealed, loss: 185.36923217773438
3000 sentences dealed, loss: 109.7376708984375
4000 sentences dealed, loss: 102.31909942626953
5000 sentences dealed, loss: 87.00853729248047
6000 sentences dealed, loss: 92.63105773925781
7000 sentences dealed, loss: 60.69317626953125
8000 sentences dealed, loss: 47.703128814697266
9000 sentences dealed, loss: 51.7804069519043
['天地', '级别']
[['片刻', '一笑', '笑', '实力', '斗之气', '斗技', '挥手', '实在', '少年', '这位'], 
 ['萧战', '摇头', '时', '薰', '点头', '一口气', '小医仙', '笑', '少年', '心头']] 
0.049292885 0.011192114

从上面结果中,我们好像也看不出什么,主要是因为数据量比较小,训练出来的模型效果不是很好,我们可以自己找一个大点的数据集进行训练。但是整个过程还是能够很好的完成的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值