莫烦nlp——词向量—CBOW
由于不是第一次接触,本文只摘录莫烦关于词向量的观点。更多的关注代码。
上一次系统学习莫烦教程已经一年半了,时间过得太快了。
转载:https://mofanpy.com/tutorials/machine-learning/nlp/intro-w2v/
自然语言处理
学会语言,往往是从学会词语的意思开始,将词组成话,才让语言有了意义。
计算机识别图片就是在这些图片背后的数字上寻找规律。那么在语言上怎样用数字表达呢?
答:计算机之所以能看懂字里行间的感情,理解文字,处理文字,并不是因为它理解的我们普罗万象的人类语言,而是它将语言或者词汇归类到了一个正确的位置上。计算机对词语的理解,其实是计算机对空间及位置的理解。
只要是能被数值化,被投射到某个空间中,计算机都能把它们按相似度聚集起来。
相似度标准:如果只想测量两个词的相似度,角度信息也足够了。
另外: 频率太高,和很多字都能混搭的词算是之中机器认为的“中性词”,越有区分力的词可能越远离中心地带,因为他们和其他词都不像,而越通用,在每种场景都有的词,就可能越靠近原点。这时,点与点的距离就能告诉我们词的频率性特征。
词向量技术
步骤:
训练时,我们取一小段文本,取出这些词的向量表示,比如取出除了“一”字以外的词向量,然后整合到一起,表示这些文字的整体向量,用这个整体向量预测最中间那个“一”。接下来在开始下一段文字的训练。
将这个窗口挪动一格,用前后文预测“段”字,接着将窗口依次这样扫过所有文字,用所有的前后文预测中间词,这样计算机就能将前后文的关系搞清楚,挨得近的词他们的关系越亲密 总出现在类似的上下文中间的词关系越亲密。向量在一定程度上也越相近。除了用前后文预测中间词,我们还能换一个思路,用中间词预测前后文也行。
原理:
假设是,在某个词的周围,应该都是和这个词有关系的词,所以当我们预测关联词的时候也就会拉近这些关联词的距离,把相近的词聚集到一起,从而得到所有的词向量。
用途:
词向量是一种预训练特征。用word2vec 的方法预先训练好了词语的特征表达,然后在其他场景中拿着预训练结果直接使用。
continuous bag of words(CBOW)
这里是手写实现(不长)。之前李宏毅的homework4——感情分类,用的是gensim库实现word2vec。学习时间有限,没必要自己亲手实现,而且还没有预处理,优化的例子。使用的是TensorFlow2.+,那我还是来欣赏一下吧,我也没用过tf2.+
挑一个要预测的词,来学习这个词前后文中词语和预测词的关系。
sum的不合理之处: 句子是由词语组成的,那么有一种理解句子的方式,就是将这个句子中所有词语的词向量都加起来,然后就变成了句子的理解。 不过这种空间上的向量相加,从直观上理解,就不是特别成立,因为它加出来以后,还是在这个词汇空间中的某个点, 你说它是句向量吧,好像也不行,说它是一个词的理解吧,好像也不对。
所以更常用的方式是将这些训练好的词向量当做预训练模型,然后放入另一个神经网络(比如RNN)当成输入,使用另一个神经网络加工后,训练句向量。
莫烦视频:为了汇总前后文的信息,把前后文的词向量相加变成前后文向量。相加的过程:这个操作还是处于词向量的空间,并非是用另外一个前后文向量的空间去表示前后文信息。另一种词向量训练方法Skip-Gram,我个人更喜欢后者, 因为后者没有我觉得说不太通的词向量相加过程。
Loss——tf.nn.nce_loss
噪声对比估计(NCE, Noise Contrastive Estimation)
使用nce_loss能够大大加速softmax求loss的方式,它不关心所有词汇loss, 而是抽样选取几个词汇用来传递loss,因为如果考虑所有词汇,那么当词汇量大的时候,会很慢。
如果不关心词汇量大导致softmax的计算量大,则用softmax-cross-entropy代替。
tf.nn.embedding原理
nce_loss原理
tf.nn.nce_loss参考链接
下面第一句话是重点
==假设nce_loss之前的输入数据是K维的,一共有N个类,==
那么
weight.shape = (N, K)
bias.shape = (N)
inputs.shape = (batch_size, K)
labels.shape = (batch_size, num_true)
num_true : 实际的正样本个数
num_sampled: 采样出多少个负样本
num_classes = N
nce_loss的实现逻辑如下:
_compute_sampled_logits: 通过这个函数计算出正样本和采样出的负样本对应的output和label
sigmoid_cross_entropy_with_logits: 通过 sigmoid cross entropy来计算output和label的loss,从而进行反向传播。这个函数把最后的问题转化为了num_sampled+num_real个两类分类问题,然后每个分类问题用了交叉熵的损伤函数,也就是logistic regression常用的损失函数。TF里还提供了一个softmax_cross_entropy_with_logits的函数,和这个有所区别。——这个我是懂的,不知道读者
log_uniform_candidate_sampler是怎么采样的呢?
k越大,被采样到的概率越小。
TF的word2vec实现里,词频越大,词的类别编号也就越大 越小 。因此,在TF的word2vec里,负采样的过程其实就是优先采词频高的词作为负样本。
还有一篇解释参数的
使用nce_loss训练mnist数据集会更好理解nce_loss这一层是干嘛的
nce_weights = tf.Variable(tf.truncated_normal([vocabulary_size, embedding_size],stddev=1.0/math.sqrt(embedding_size)),name="embed")tf.nn.nce_loss(weights=nce_weights,biases=nce_biases,labels=y_idx,inputs=fc1_drop,num_sampled=num_sampled,num_classes=vocabulary_size),)
output = tf.matmul(fc1_drop, tf.transpose(nce_weights)) + nce_biase
最后的tf.matmul说明,tf.nn.nce_loss的作用与其相似。
例子,找出卧底数字‘9’
# -*- coding: utf-8 -*-
"""
Created on Thu Jan 7 15:44:39 2021@author: Administrator
"""
import matplotlib.pyplot as plt
import numpy as np
import itertoolsclass Dataset:def __init__(self, x, y, v2i, i2v):self.x, self.y = x, yself.v2i, self.i2v = v2i, i2vself.vocab = v2i.keys()def sample(self, n):b_idx = np.random.randint(0, len(self.x), n)bx, by = self.x[b_idx], self.y[b_idx]return bx, by@propertydef num_word(self):return len(self.v2i)def show_w2v_word_embedding(model, data: Dataset, path):word_emb = model.embeddings.get_weights()[0]for i in range(data.num_word):c = "blue"try:int(data.i2v[i])except ValueError:c = "red"plt.text(word_emb[i, 0], word_emb[i, 1], s=data.i2v[i], color=c, weight="bold")plt.xlim(word_emb[:, 0].min() - .5, word_emb[:, 0].max() + .5)plt.ylim(word_emb[:, 1].min() - .5, word_emb[:, 1].max() + .5)plt.xticks(())plt.yticks(())plt.xlabel("embedding dim1")plt.ylabel("embedding dim2")plt.savefig(path, dpi=300, format="png")plt.show()def process_w2v_data(corpus, skip_window=2, method="skip_gram"):all_words = [sentence.split(" ") for sentence in corpus]all_words = np.array(list(itertools.chain(*all_words)))# vocab sort by decreasing frequency for the negative sampling below (nce_loss).#eturn the number of times each unique item appears in ar.vocab, v_count = np.unique(all_words, return_counts=True)vocab = vocab[np.argsort(v_count)[::-1]]print("all vocabularies sorted from more frequent to less frequent:\n", vocab)v2i = {v: i for i, v in enumerate(vocab)}i2v = {i: v for v, i in v2i.items()}# pair datapairs = []js = [i for i in range(-skip_window, skip_window + 1) if i != 0]for c in corpus:words = c.split(" ")w_idx = [v2i[w] for w in words]if method == "skip_gram":for i in range(len(w_idx)):for j in js:if i + j < 0 or i + j >= len(w_idx):continuepairs.append((w_idx[i], w_idx[i + j])) # (center, context) or (feature, target)elif method.lower() == "cbow":for i in range(skip_window, len(w_idx) - skip_window):context = []for j in js:context.append(w_idx[i + j])pairs.append(context + [w_idx[i]]) # (contexts, center) or (feature, target)else:raise ValueErrorpairs = np.array(pairs)print("5 example pairs:\n", pairs[:5])if method.lower() == "skip_gram":x, y = pairs[:, 0], pairs[:, 1]elif method.lower() == "cbow":x, y = pairs[:, :-1], pairs[:, -1]else:raise ValueErrorreturn Dataset(x, y, v2i, i2v)from tensorflow import keras
import tensorflow as tfcorpus = [# numbers"5 2 4 8 6 2 3 6 4","4 8 5 6 9 5 5 6","1 1 5 2 3 3 8","3 6 9 6 8 7 4 6 3","8 9 9 6 1 4 3 4","1 0 2 0 2 1 3 3 3 3 3","9 3 3 0 1 4 7 8","9 9 8 5 6 7 1 2 3 0 1 0",# alphabets, expecting that 9 is close to letters"a t g q e h 9 u f","e q y u o i p s","q o 9 p l k j o k k o p","h g y i u t t a e q","i k d q r e 9 e a d","o p d g 9 s a f g a","i u y g h k l a s w","o l u y a o g f s","o p i u y g d a s j d l","u k i l o 9 l j s","y g i s h k j l f r f","i o h n 9 9 d 9 f a 9",
]class CBOW(keras.Model):def __init__(self, v_dim, emb_dim): #emb_dim=2,特征大小super().__init__()self.v_dim = v_dimself.embeddings = keras.layers.Embedding(input_dim=v_dim, output_dim=emb_dim, # [n_vocab, emb_dim]embeddings_initializer=keras.initializers.RandomNormal(0., 0.1),)# noise-contrastive estimationself.nce_w = self.add_weight(name="nce_w", shape=[v_dim, emb_dim],initializer=keras.initializers.TruncatedNormal(0., 0.1)) # [n_vocab, emb_dim]self.nce_b = self.add_weight(name="nce_b", shape=(v_dim,),initializer=keras.initializers.Constant(0.1)) # [n_vocab, ]self.opt = keras.optimizers.Adam(0.01)def call(self, x, training=None, mask=None):# x.shape = [n, skip_window*2]o = self.embeddings(x) # [n, skip_window*2, emb_dim]o = tf.reduce_mean(o, axis=1) # [n, emb_dim]return o# negative sampling: take one positive label and num_sampled negative labels to compute the loss# in order to reduce the computation of full softmaxdef loss(self, x, y, training=None):embedded = self.call(x, training) # [batch,emb_dim]return tf.reduce_mean(tf.nn.nce_loss(weights=self.nce_w, biases=self.nce_b, labels=tf.expand_dims(y, axis=1), #labels=[batch,1]inputs=embedded, num_sampled=5, num_classes=self.v_dim))def step(self, x, y):with tf.GradientTape() as tape:loss = self.loss(x, y, True)grads = tape.gradient(loss, self.trainable_variables)self.opt.apply_gradients(zip(grads, self.trainable_variables))return loss.numpy()def train(model, data):for t in range(2500):bx, by = data.sample(8)loss = model.step(bx, by)if t % 200 == 0:print("step: {} | loss: {}".format(t, loss))if __name__ == "__main__":d = process_w2v_data(corpus, skip_window=2, method="cbow") #return Dataset(x, y, v2i, i2v)m = CBOW(d.num_word, 2)train(m, d)# plottingshow_w2v_word_embedding(m, d, "./result/cbow.png")
莫烦nlp——词向量—CBOW相关推荐
- 莫烦nlp——ELMO一词多义
李宏毅介绍过ELMO,但我已经忘记它是个啥东西了.说明不看代码,是无法牢固地记住一样东西的.我的笔记>> 莫烦简洁地介绍了该模型,结合之前笔记效果更佳.莫烦视频>> 预训练的作 ...
- NLP:词向量与ELMo模型笔记
目录: 基础部分回顾(词向量.语言模型) NLP的核心:学习不同语境下的语义表示 基于LSTM的词向量学习 深度学习中的层次表示以及Deep BI-LSTM ELMo模型 总结 1. 基础部分回顾(词 ...
- NLP(词向量、word2vec和word embedding)
最近在做一些文本处理相关的任务,虽然对于相关知识有所了解,而且根据相关开源代码也可以完成相应任务:但是具有有些细节,尤其是细节之间的相互关系,感觉有些模糊而似懂非懂,所以找到相关知识整理介绍,分享如下 ...
- NLP词向量模型总结:从Elmo到GPT,再到Bert
词向量历史概述 提到NLP,总离开不了词向量,也就是我们经常说的embedding,因为我们需要把文字符号转化为模型输入可接受的数字向量,进而输入模型,完成训练任务.这就不得不说这个转化的历史了. 起 ...
- PGL 系列(四)词向量 CBOW
环境 python 3.6.8 paddlepaddle-gpu 2.3.0 numpy 1.19.5 pgl 2.2.4 学习路线 一.CBOW 概念 CBOW:通过上下文的词向量推理中心词 在CB ...
- 深度学习与自然语言处理教程(1) - 词向量、SVD分解与Word2Vec(NLP通关指南·完结)
作者:韩信子@ShowMeAI 教程地址:https://www.showmeai.tech/tutorials/36 本文地址:https://www.showmeai.tech/article-d ...
- 词向量介绍以及Word2Vec的pytorch实现
词向量 在自然语言处理任务中,首先需要考虑字.词如何在计算机中表示.通常,有两种表示方式:one-hot表示和分布式表示 one-hot表示 把每个词表示为一个长向量.这个向量的维度是词表大小,向量中 ...
- word2vec预训练词向量+通俗理解word2vec+CountVectorizer+TfidfVectorizer+tf-idf公式及sklearn中TfidfVectorizer
文章目录 文分类实(一) word2vec预训练词向量 2 数据集 3 数据预处理 4 预训练word2vec模型 canci 通俗理解word2vec 独热编码 word2vec (Continuo ...
- 【莫烦Python】机器要说话 NLP 自然语言处理教程 W2V Transformer BERT Seq2Seq GPT 笔记
[莫烦Python]机器要说话 NLP 自然语言处理教程 W2V Transformer BERT Seq2Seq GPT 笔记 教程与代码地址 P1 NLP行业大佬采访 P2 NLP简介 P3 1. ...
最新文章
- python的pandas库内的函数_python 中NumPy和Pandas工具包中的函数使用笔记(方便自己查找)...
- fzyzojP3372 -- [校内训练20171124]博弈问题
- Programe_Of_Beauty :3.9 重建二叉树
- 65. Leetcode 153. 寻找旋转排序数组中的最小值 (二分查找-局部有序)
- Map与Set的经典OJ题
- 【CyberSecurityLearning 28】批处理与简单病毒
- shiro的登录 subject.login(token)中执行逻辑和流程
- oracle顺序读发散读,Oracle 拼音排序
- html5 注册协议弹出层,js制作带有遮罩弹出层实现登录注册表单特效代码分享
- WPJAM网址导航:最轻便快捷的WordPress网址导航插件
- Redis 5种数据结构使用及注意事项
- c语言修改内存字节,要开学了,小白给大家一个C语言修改dnf内存的示范代码
- linux 下的绘图软件Visio
- UML常用图--类图,用例图,序列图(时序图),协作图(通信图),状态图,活动图
- sql语句之多表查询
- 电容屏物体识别_浅谈多点电容屏物体识别,实物识别技术
- Ansible中的jinjia2模板
- Git clean简介
- Android点9图的使用与制作工具推荐
- android QQ分享、QQ空间分享