skip-gram模型介绍及代码
在自然语言处理中,首先要把文本转化为数据的形式,更确切地说,是把词转化为向量的形式,才可以用计算机通过各种算法处理自然语言问题。在词向量的表示方法中,One-hot编码是一个非常经典的表示方法,但是在这种编码方法中,词向量的维度等于词的总个数,且词向量中只有一个位置数为1,其他位置全为0,这就导致了词表构成的矩阵是一个稀疏矩阵,它会消耗相当大的计算资源。
word2vector模型是自然语言处理技术中的新方法,它通过学习文本来用词向量的方式表征词的语义信息,即通过一个嵌入空间使得语义上相似的单词在该空间内距离很近。embedding其实就是一个映射,将单词从原先所属的空间映射到新的低维空间中,这样就解决了向量稀疏问题。
word2vector主要有Skip-Gram和CBOW两种模型。
Skip-Gram模型分为两个部分,第一部分为建立模型,第二部分是通过模型获取嵌入词向量。首先基于训练数据构建一个神经网络,当这个模型训练好以后,并不会用这个训练好的模型处理新的任务,真正需要的是这个模型通过训练数据所学得的参数,即隐层的权重矩阵,这些权重在word2vector中实际上就是需要的“word vectors”。
Skip-Gram模型的基础形式如下图所示:(下面的部分均翻译自原文献,水平有限)
从上图可知,Skip-Gram是根据当前的词来预测上下文的词。
对softmax的改进:
上述的softmax函数并不实用,因为的计算成本与词汇表的大小成正比。
为了避免要计算所有词的softmax概率,word2vec采用了霍夫曼树来代替从隐藏层到输出softmax层的映射。和之前的神经网络语言模型相比,霍夫曼树的所有内部节点就类似之前神经网络隐藏层的神经元,其中,根节点的词向量对应投影后的词向量,而所有叶子节点就类似于之前神经网络softmax输出层的神经元,叶子节点的个数就是词汇表的大小。在霍夫曼树中,隐藏层到输出层的softmax映射不是一下子完成的,而是沿着霍夫曼树一步步完成的。(ps: 这段是翻译自原论文,本人英文水平实在有限)
skip-gram训练词向量代码:
# coding=utf-8
import jieba
import numpy as np
import tensorflow as tf
from tqdm import tqdm
from pprint import pprint
obj_path = r'E:\back_up\NLP\process_train.txt'
stop_word_file = r"E:\back_up\NLP\pro1\data\stop_word.txt"def get_stop_word(stop_word_file):"""加载停用词:param stop_word_file: :return: """stopwords = [x.strip() for x in open(stop_word_file, 'r', encoding='utf-8').readlines()]return stopwords + list("0123456789") + [r'\n', '\n']def get_data(file_path, windows_len, lines_number):""":param file_path: 数据的路径:param windows_len: 窗口长度:return:"""words = set() # 保存词sentences = [] # 保存句子stopwords = get_stop_word(stop_word_file)stopwords = set(stopwords)count = 0with open(file_path, 'r', encoding='utf-8') as fp:while True:line = fp.readline()count = count + 1if not line or count > lines_number:break# print(line)out_str = []result = jieba.cut(line, cut_all=False) # 精确模式for c in result:if c not in stopwords and len(c) > 1:out_str.append(c)words.add(c) # 保存所有的词else:continueout_str.append("EOS")sentences.append(out_str)word2id = {}words = list(words)for i in range(len(words)):word2id[words[i]] = i + 1word2id["EOS"] = len(words) + 1# 构造输入input和输出labelsinput = []labels = []# 构造训练数据和标签for sentence in sentences:for word_index in range(len(sentence)):start = max(0, word_index - windows_len)end = min(word_index + windows_len + 1, len(sentence))for index in range(start, end):if index == word_index:continueelse:input_word_id = word2id.get(sentence[word_index], None)label_word_id = word2id.get(sentence[index], None)if input_word_id is None or label_word_id is None:continueinput.append(int(input_word_id))labels.append(int(label_word_id))return words, word2id, sentences, input, labels, len(words)class TrainData:def __init__(self, inputs, labels, words, vocab_size, batch_size):""":param inputs: 输入:param labels: 输出:param words: 所有单词:param vocab_size:"""self.inputs = inputsself.labels = labelsself.words = wordsself.vocab_size = vocab_sizeself.batch_size = batch_sizeself.input_length = len(inputs)def get_batch_data(self, batch_count):""":param batch_count: batch计数:return:"""# 确定选取的batch大小start_position = batch_count * self.batch_sizeend_position = min((batch_count + 1) * self.batch_size, self.input_length)batch_input = self.inputs[start_position: end_position]batch_labels = self.labels[start_position: end_position]batch_input = np.array(batch_input, dtype=np.int32)batch_labels = np.array(batch_labels, dtype=np.int32)batch_labels = np.reshape(batch_labels, [len(batch_labels), 1]) # 转置return batch_input, batch_labelsdef get_batch_nums(self):"""获取数据的batch数:return:"""return self.input_length // self.batch_size + 1class Model:def __init__(self, vocab_size, embedding_size, batch_nums, num_sampled, learning_rate):self.vocab_size = vocab_sizeself.embedding_size = embedding_sizeself.batch_nums = batch_numsself.num_sampled = num_sampledself.lr = learning_rateself.batch_size = None# self.graph = tf.Graph()# 创建placeholderwith tf.name_scope("placeholders"):self.inputs = tf.placeholder(dtype=tf.int32, shape=[self.batch_size], name="train_inputs") # 输入self.labels = tf.placeholder(dtype=tf.int32, shape=[self.batch_size, 1], name="train_labels")self.test_word_id = tf.placeholder(dtype=tf.int32, shape=[None], name="test_word_id")# 创建词向量with tf.name_scope("word_embedding"):self.embedding_dict = tf.get_variable(name="embedding_dict", shape=[self.vocab_size, self.embedding_size],initializer=tf.random_uniform_initializer(-1, 1, seed=1))self.nce_weight = tf.get_variable(name="nce_weight", shape=[self.vocab_size, self.embedding_size],initializer=tf.random_uniform_initializer(-1, 1, seed=1))self.nce_bias = tf.get_variable(name="nce_bias", initializer=tf.zeros([self.vocab_size]))# 定义误差with tf.name_scope("creating_embedding"):embeded = tf.nn.embedding_lookup(self.embedding_dict, self.inputs)self.embeded = tf.layers.dense(inputs=embeded, units=self.embedding_size, activation=tf.nn.relu) # 激活函数# 定义误差with tf.name_scope("creating_loss"):self.loss = tf.reduce_mean(tf.nn.nce_loss(weights=self.nce_weight,biases=self.nce_bias,labels=self.labels,inputs=self.embeded,num_sampled=self.num_sampled,num_classes=self.vocab_size,# remove_accidental_hits=True))# 定义测试函数with tf.name_scope("evaluation"):norm = tf.sqrt(tf.reduce_sum(tf.square(self.embedding_dict), 1, keepdims=True))self.normed_embedding_dict = self.embedding_dict / normtest_embed = tf.nn.embedding_lookup(self.normed_embedding_dict, self.test_word_id)self.similarity = tf.matmul(test_embed, tf.transpose(self.normed_embedding_dict), name='similarity')self.optimizer = tf.train.AdamOptimizer(learning_rate=self.lr).minimize(self.loss)# tensorboard 显示数据with tf.name_scope("summaries"):tf.summary.scalar('loss', self.loss) # 在 tensorboard中显示信息self.summary_op = tf.summary.merge_all()def train(self, train_data, train_steps=1000):with tf.Session() as sess:# 初始化变量sess.run(tf.group(tf.local_variables_initializer(), tf.global_variables_initializer()))writer = tf.summary.FileWriter(r'E:\back_up\NLP\graph', sess.graph) initial_step = 0 # self.global_step.eval(session=sess)step = 0 # 记录总的训练次数saver = tf.train.Saver(tf.global_variables(), max_to_keep=2) # 保存模型for index in range(initial_step, train_steps):total_loss = 0.0 # 总的lossfor batch_count in tqdm(range(self.batch_nums)):batch_inputs, batch_labels = train_data.get_batch_data(batch_count)feed_dict = {self.inputs: batch_inputs,self.labels: batch_labels}sess.run(self.optimizer, feed_dict=feed_dict)batch_loss = sess.run(self.loss, feed_dict=feed_dict)summary = sess.run(self.summary_op, feed_dict=feed_dict)# batch_loss, summary = sess.run([self.loss, self.summary_op])total_loss += batch_lossstep += 1if step % 200 == 0:saver.save(sess=sess, save_path=r'E:\back_up\NLP\global_variables\global_variables', global_step=step)writer.add_summary(summary, global_step=step)print('Train Loss at step {}: {:5.6f}'.format(index, total_loss/self.batch_nums))word_embedding = sess.run(self.embedding_dict)np.save(r"E:\back_up\NLP\word_embedding\word_embedding", word_embedding) # 保存词向量def predict(test_word, word2id, top_k=4): # 测试训练的词向量""":param test_word: :param word2id: :param top_k: 与testword最相近的k个词 :return: """sess = tf.Session()check_point_file = tf.train.latest_checkpoint(r'E:\back_up\NLP\global_variables') # 加载模型saver = tf.train.import_meta_graph("{}.meta".format(check_point_file), clear_devices=True)saver.restore(sess, check_point_file)graph = sess.graph graph_test_word_id = graph.get_operation_by_name("placeholders/test_word_id").outputs[0]graph_similarity = graph.get_operation_by_name("evaluation/similarity").outputs[0]test_word_id = [word2id.get(x) for x in test_word]feed_dict = {graph_test_word_id: test_word_id}similarity = sess.run(graph_similarity, feed_dict)for index in range(len(test_word)):nearest = (-similarity[index, :]).argsort()[0:top_k] # argsort()默认按照从小大的顺序 最接近的词log_info = "Nearest to %s: " % test_word[index]for k in range(top_k):closest_word = [x for x, v in word2id.items() if v == nearest[k]]log_info = '%s %s,' % (log_info, closest_word)print(log_info)if __name__ == "__main__":batch_size = 40window_len = 4words, word2id, sentences, inputs, labels, vocab_size = get_data(obj_path, windows_len=window_len, lines_number=2000)train_data = TrainData(inputs, labels, words, vocab_size, batch_size)batch_nums = train_data.get_batch_nums()# print(words)print("vocab_size: ", vocab_size)print("batch_nums", batch_nums)model = Model(vocab_size=vocab_size, embedding_size=128, batch_nums=batch_nums, num_sampled=5, learning_rate=0.0001)model.train(train_data=train_data, train_steps=150)if __name__ == "__main__":batch_size = 200window_len = 4words, word2id, sentences, inputs, labels, vocab_size = get_data(obj_path, windows_len=window_len,lines_number=2000)test_word = []for count in range(50):test_word.append(np.random.choice(words))print(test_word)predict(test_word, word2id)
skip-gram论文
这篇翻译的水,论文中很多东西还是没有理解,代码可用。
skip-gram模型介绍及代码相关推荐
- Bert模型介绍及代码解析(pytorch)
Bert(预训练模型) 动机 基于微调的NLP模型 预训练的模型抽取了足够多的信息 新的任务只需要增加一个简单的输出层 注:bert相当于只有编码器的transformer 基于transformer ...
- GAT: 图注意力模型介绍及PyTorch代码分析
文章目录 GAT: 图注意力模型介绍及代码分析 原理 图注意力层(Graph Attentional Layer) 情境一:节点和它的一个邻居 情境二:节点和它的多个邻节点 聚合(Aggregatio ...
- 经典Wide Deep模型介绍及tensorflow 2代码实现
Wide & Deep模型介绍 目标: 内容: 一. 模型介绍 二. 推荐系统架构 三. Wide部分 四. Deep部分 五. Wide和Deep一起训练 六. 系统实现 (1)数据生成阶段 ...
- 【从零开始学习深度学习】25.卷积神经网络之LeNet模型介绍及其Pytorch实现【含完整代码】
目录 1. LeNet模型介绍与实现 2. 输入为Fashion-MNIST时各层输出形状 3. 获取Fashion-MNIST数据和并使用LeNet模型进行训练 4.完整代码 之前我们对Fashio ...
- DEMATEL-ISM模型的Python实现——方法介绍以及代码复现
DEMATEL-ISM模型的Python实现--方法介绍以及代码复现 前言 DEMATEL-ISM分析方法 方法简介 步骤 明确系统要素 确定直接影响矩阵 规范影响矩阵 计算综合影响矩阵 计算各个要素 ...
- 《自然语言处理学习之路》02 词向量模型Word2Vec,CBOW,Skip Gram
本文主要是学习参考莫烦老师的教学,对老师课程的学习,记忆笔记. 原文链接 文章目录 书山有路勤为径,学海无涯苦作舟. 零.吃水不忘挖井人 一.计算机如何实现对于词语的理解 1.1 万物数字化 1.2 ...
- [深度学习-总结]Deep learning中8大模型介绍与比较(LeNet5,AlexNet,VGG,Inception,MobileNets,ResNet,DenseNet,Senet)
深度学习 9中模型介绍与比较 0. CNN 结构演化 1. LeNet5 2. AlexNet 3. VGG 为什么使用2个3x3卷积核可以来代替5*5卷积核 4. 1*1卷积 5. Inceptio ...
- 基于Python的岭回归与LASSO回归模型介绍及实践
基于Python的岭回归与LASSO回归模型介绍及实践 这是一篇学习的总结笔记 参考自<从零开始学数据分析与挖掘> [中]刘顺祥 著 完整代码及实践所用数据集等资料放置于:Github 岭 ...
- 三维点云语义分割模型介绍
三维点云语义分割模型介绍 1 三维深度学习简介 1.1 三维数据表达方式 2 PointNet 2.1 点云的属性 2.1.1 无序性 2.1.2 关联性 2.1.3 不变性 2.2 key modu ...
最新文章
- Mysqli的批量CRUD数据
- OpenGL版本与硬件支持
- SQL语句的基本语法一
- springsecurity 认证之密码模式
- Android课程思维导图,Android实现思维导图
- 网页排序向量计算和改进
- android a20 i2c 通信,Android程序运行分析——中等复杂程度的NTAG I2C Demo为例(二)...
- 用计算机绘制工作表,《计算机操作基础Excel练习题答案.doc
- 梦断代码读后感 (一)
- English学习网址
- H5/C3基础(1)
- js生成8位随机字符串密码
- 自然语言处理基础技术之语义角色标注
- vim 常用功能大全
- [A*,启发式搜索] [SCOI2005] 骑士精神
- JavaScript走动的小人
- 微信小程序生成海报失败问题解决方法
- 2019计算机考研心得
- 进程(六):进程池(Pool)
- Android 字符串中数字替换为阿拉伯语或波斯语