tensorflow用skipgram+nce模型实现中文word2vec

TensorFlow用skipgram实现中文word2vec
摘要由CSDN通过智能技术生成
这是第一个自己学习并实现的tensorflow程序,用了两天,基本弄懂,但还是有些问题,比如现在还没有弄懂如何保存并重新加载使用训练好的模型,在整个流程上有时候还是会混乱,超参的设置也没太走心。路漫漫其修远兮啊~~~同样,感谢网上的各种大神,完成这个主要参考了4篇内容(文章最后有链接)。若以下出现任何错误,热烈欢迎大家在评论区指正,因为我也是新手,难免会犯错~程序中出现的逻辑错误也希望大家指出~

下面先说一下整个流程,什么都不是一蹴而就的,当初理清楚要做什么还是用了一些时间的。

1. 获取中文语料,并分词。
说明:分词工具使用的结巴分词工具,网上有使用方法。我的语料是每一行是一句,词与词之间我用空格分隔的,这些和后面统计词频的部分有点关系。总之,我觉得是语料中的每一句话应该能够区分出边界,即能够判断出 sentence1,sentence2,… 这样。
语料举例:
我们 是 祖国 的 花朵
你 今天 吃 饭 了 吗
今天 真 开心 啊

2.将语料的中所有word存成一个list
说明:这一步的原因,我认为是为了方便后序由此构建词频统计、词典和反转词典。
格式描述:
[‘我们’,’是’,’祖国’,’的’,…]

3.构建词频统计、词典和反转词典
说明:这一步我分成了两个函数来写,写在一个函数中也行,和上一步都写在一个函数中都行,随意。我之所以分开写,是因为新手练习,方便调试和测试。
词频统计结果格式:
[(‘unk’,-1),(‘的’,20),(‘你’,10),…],词频统计的是TopN的词和其在语料中出现的次数,除了‘unk’这一项,后面的项按照词频降序排序
词典格式:
{word1:num1,word2:num2,…},num就是词在词频表(countlist)中对应的序号(位序)
反转词典格式:
{num1:word1,…},就是将词典中的键与值对调

4.构建训练数据
skipgram模型是有监督的,而原始语料是无监督的,所以要从分好词的语料中构建训练数据。本实验中的窗口大小为1,即取中心词左右两边各一个词与中心词构成训练语料,举例说明:
语料格式:
我们 是 祖国 的 花朵
你 今天 吃 饭 了 吗
今天 真 开心 啊
用第一句话构建训练数据(shipgram模型是用中心词预测上下文词汇)
[(‘我们’,’是’),(‘是’,’我们’),(‘是’,’祖国’),…]
当‘我们’作为中心词时,它的上下文词只有‘是’,所以组成一个pair,‘我们’就是输入数据,‘是’就是对应的label;当‘是’作为中心词时,它的上下文词有‘我们’和‘祖国’,所以组成两个pair,这样可以把语料都转换为训练数据。但是在本实验中,需要将数据数据与标签数据分开,所以最终的训练数据有两部分,一个是输入list,一个是输出list,两部分要对应,举例说明:
input:[‘我们’,’是’,’是’,…]
label:[‘是’,’我们’,’祖国’,…]

5.构建skipgram模型
这里我把模型的定义和训练都写在一起了。

完整程序如下:

import tensorflow as tf
import numpy as np
from collections import Counter  #用于统计词频

data_path = "6-15.txt"  #语料路径
embedding_save_path = "embeddings.txt"  #把最后的emdeddings保存的路径
vocabulary_size = 8000  #词典大小
win_len = 1   #窗口长度,即取中心词左右两边各一个词

batch_size = 500  #一个batch中的训练数据的个数
embedding_size = 128  #生成的词向量的长度
num_sampled = 
  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
Skip-gram 是一种常用的词向量训练方法,它通过预测一个词周围的词来学习每个词的向量表示。下面是使用 Python 实现 Skip-gram 训练的简单示例。 首先,我们需要导入必要的库: ```python import numpy as np import tensorflow as tf from collections import Counter import random ``` 然后,我们需要定义一些参数: ```python # 语料库文件路径 corpus_file = 'corpus.txt' # 词向量维度 embedding_size = 128 # 跳跃窗口大小 window_size = 5 # 负样本数 num_neg_samples = 64 # 学习率 learning_rate = 0.1 # 迭代次数 num_iterations = 10000 # 每隔多少步输出一次日志 log_interval = 1000 ``` 接下来,我们需要读取语料库文件,并将其中的词转换成数字编码: ```python with open(corpus_file, 'r', encoding='utf-8') as f: corpus = f.read().split() # 统计词频并按照词频从高到低排序 word_counts = Counter(corpus) sorted_vocab = sorted(word_counts, key=word_counts.get, reverse=True) # 生成词汇表和词汇表的反向映射表 vocab_to_int = {word: idx for idx, word in enumerate(sorted_vocab)} int_to_vocab = {idx: word for idx, word in enumerate(sorted_vocab)} # 将语料库中的词转换成数字编码 corpus_int = [vocab_to_int[word] for word in corpus] ``` 之后,我们需要定义 Skip-gram 模型的输入和输出: ```python inputs = tf.placeholder(tf.int32, [None], name='inputs') labels = tf.placeholder(tf.int32, [None, 1], name='labels') ``` 然后,我们需要定义词向量矩阵,这个矩阵的维度是词汇表大小 × 词向量维度: ```python vocab_size = len(vocab_to_int) embedding = tf.Variable(tf.random_uniform([vocab_size, embedding_size], -1.0, 1.0)) ``` 接下来,我们需要定义损失函数。具体来说,我们用负对数似然损失函数来最小化预测概率和真实值之间的距离,同时使用负样本来训练模型: ```python nce_weights = tf.Variable(tf.truncated_normal([vocab_size, embedding_size], stddev=1.0 / np.sqrt(embedding_size))) nce_biases = tf.Variable(tf.zeros([vocab_size])) embed = tf.nn.embedding_lookup(embedding, inputs) loss = tf.reduce_mean(tf.nn.nce_loss(nce_weights, nce_biases, labels, embed, num_neg_samples, vocab_size)) ``` 最后,我们需要使用梯度下降优化器来最小化损失函数,并在训练过程中输出日志: ```python optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) for i in range(num_iterations): # 生成训练样本 batch_inputs, batch_labels = generate_batch(corpus_int, window_size, num_neg_samples) # 训练模型 feed_dict = {inputs: batch_inputs, labels: batch_labels} _, loss_val = sess.run([optimizer, loss], feed_dict=feed_dict) # 输出日志 if (i + 1) % log_interval == 0: print('Iteration {}: Loss = {:.4f}'.format(i + 1, loss_val)) ``` 完整代码如下: ```python import numpy as np import tensorflow as tf from collections import Counter import random # 语料库文件路径 corpus_file = 'corpus.txt' # 词向量维度 embedding_size = 128 # 跳跃窗口大小 window_size = 5 # 负样本数 num_neg_samples = 64 # 学习率 learning_rate = 0.1 # 迭代次数 num_iterations = 10000 # 每隔多少步输出一次日志 log_interval = 1000 def generate_batch(corpus, window_size, num_neg_samples): # 遍历整个语料库 for i in range(window_size, len(corpus) - window_size): # 输入词 center_word = corpus[i] # 输出词 context_words = [] for j in range(i - window_size, i + window_size + 1): if j != i: context_words.append(corpus[j]) # 负样本 neg_samples = [] while len(neg_samples) < num_neg_samples: samp = random.randint(0, len(corpus) - 1) if samp != center_word and samp not in context_words: neg_samples.append(samp) yield center_word, context_words + neg_samples with open(corpus_file, 'r', encoding='utf-8') as f: corpus = f.read().split() # 统计词频并按照词频从高到低排序 word_counts = Counter(corpus) sorted_vocab = sorted(word_counts, key=word_counts.get, reverse=True) # 生成词汇表和词汇表的反向映射表 vocab_to_int = {word: idx for idx, word in enumerate(sorted_vocab)} int_to_vocab = {idx: word for idx, word in enumerate(sorted_vocab)} # 将语料库中的词转换成数字编码 corpus_int = [vocab_to_int[word] for word in corpus] inputs = tf.placeholder(tf.int32, [None], name='inputs') labels = tf.placeholder(tf.int32, [None, 1], name='labels') vocab_size = len(vocab_to_int) embedding = tf.Variable(tf.random_uniform([vocab_size, embedding_size], -1.0, 1.0)) nce_weights = tf.Variable(tf.truncated_normal([vocab_size, embedding_size], stddev=1.0 / np.sqrt(embedding_size))) nce_biases = tf.Variable(tf.zeros([vocab_size])) embed = tf.nn.embedding_lookup(embedding, inputs) loss = tf.reduce_mean(tf.nn.nce_loss(nce_weights, nce_biases, labels, embed, num_neg_samples, vocab_size)) optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) for i in range(num_iterations): # 生成训练样本 batch_inputs, batch_labels = generate_batch(corpus_int, window_size, num_neg_samples) # 训练模型 feed_dict = {inputs: batch_inputs, labels: batch_labels} _, loss_val = sess.run([optimizer, loss], feed_dict=feed_dict) # 输出日志 if (i + 1) % log_interval == 0: print('Iteration {}: Loss = {:.4f}'.format(i + 1, loss_val)) ``` 注意,这只是一个简单的示例,实际上 Skip-gram 模型中还可以加入很多其他的优化和技巧。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值