计算机处理图像的时候,本质上利用了图像的像素数值信息。对自然语言来说,本身并没有包含计算机擅长处理的数值信息,因此,需要通过一定的手段将“自然语言”量化,进而利用已有的机器学习方法对自然语言进行处理、分析和预测。
独热编码也称One-hot编码(一位有效码),其方法是使用N位状态寄存器来对N个状态进行编码,每个状态都有它独立的寄存器位,并且在任意时候,其中只有一位有效。比如有下面的状态表:
indicator-1indicator-2sample-sample-sample-转化为独热编码为(注意:这里容易和数字电路中的真值表编号相混淆,请务必区分)
indicator-1indicator-2sample-sample-sample-如果上面的indicator不是数值量,而是文本,则可以表示为:
indicator-1indicator-2sample-1"male""fromEurope"sample-2"female""fromUS"sample-3"female""fromRussia"对应的独热编码可以编号为:
indicator-1indicator-2sample-sample-sample-这样处理的优缺点在哪?
首先是优点,很显然,将一个word映射为一个数学向量,这便于我们后续进行各种机器学习算法的输入处理。
缺点也很明显:
它是一个词袋模型,不考虑词与词之间的顺序(文本中词的顺序信息也是很重要的)
它假设词与词相互独立(在大多数情况下,词与词是相互影响的)
它得到的特征是离散稀疏的
在线性代数中,有稀疏矩阵的概念——大部分矩阵元素都为0.上面的独热编码正是特殊的1xn维的稀疏矩阵,这样就非常浪费空间,并且容易造成维度灾难。因此,我们急切需要一种可以降低维度的方法。
DristributedrepresentationDristributedrepresentation的思路是通过训练,将每个词都映射到一个较短的词向量上来。所有的这些词向量就构成了向量空间,用普通的统计学的方法来研究词与词之间的关系。词向量维度一般在训练时指定。下图说明了一个简单示例:
词汇表里的词用"Royalty","Masculinity","Femininity"和"Age"4个维度来表示,King这个词对应的词向量可能是(0.99,0.99,0.05,0.7),此处,king这个词从一个可能非常稀疏的向量空间,映射到现在这个四维向量所在的空间,这个过程就是词嵌入(wordembedding).
假如我们将词的维度降低到2D,有研究表明:
国王-男性+是女性=女王,挺有道理的。
出现这种现象的原因是,我们得到最后的词向量的训练过程中引入了词的上下文。
Word2Vec(一个神经网络模型)输入是One-HotVector,HiddenLayer没有激活函数,也就是线性的单元。OutputLayer维度跟InputLayer的维度一样,用的是Softmax回归。当这个模型训练好以后,我们并不会用这个训练好的模型处理新的任务,真正需要的是这个模型通过训练数据所学得的参数,如隐藏层的权重矩阵。
这个模型是如何定义数据的输入和输出?一般分为CBOW(ContinuousBag-of-Words与Skip-Gram两种模型。
CBOW模型的训练输入是某一个特征词的上下文相关的词对应的词向量,而输出就是这特定的一个词的词向量。 Skip-Gram模型和CBOW的思路是反着来的,即输入是特定一个词的词向量,而输出是特定词对应的上下文词向量。CBOW对小型数据库比较合适,而Skip-Gram在大型语料中表现更好。
通俗一点,CBOW解决的是这样的问题:
而Skip-gram解决的是这样的问题:
CBOW的训练模型处理步骤:
输入:上下文单词的onehot编码,每个onehot编码是1xV的向量
每个onehot向量乘以VxN的权重矩阵
全部向量相加求平均得到隐藏层的特征向量,这个向量是1xN维的
隐藏层的特征向量乘以NxV维的输出权重矩阵,得到1xV维的输出向量
输出向量通过激活函数处理,得到概率分布
概率最大的index所指示的单词为预测出的中间词
训练完毕后,输入层的每个单词与矩阵W相乘得到的向量的就是我们想要的词向量(wordembedding).
下面是一个简单例子:
Skip-Gram的训练模型假如有一个句子“Thedogbarkedatthemailman”。首先选句子中间的一个词作为输入词,例如选取“dog”作为inputword.
有了inputword以后,再定义一个叫做skipwindow的参数,它代表着从当前inputword的一侧(左边或右边)选取词的数量。如果设置skipwindow=2,那么最终获得窗口中的词(包括inputword在内)就是[The,dog,barked,at]。skipwindow=2代表着选取左inputword左侧2个词和右侧2个词进入窗口,所以整个窗口大小span=2x2=4。
另一个参数叫numskips,它代表着从整个窗口中选取多少个不同的词作为outputword,当skipwindow=2,numskips=2时,将会得到两组(inputword,outputword)形式的训练数据,即(dog,barked),(dog,the)。
神经网络基于这些训练数据将会输出一个概率分布,这个概率代表词典中的每个词是outputword的可能性。例如,先拿一组数据(dog,barked)来训练神经网络,那么模型通过学习这个训练样本,会告诉我们词汇表中每个单词是“barked”的概率大小。模型的输出概率代表着到词典中每个词有多大可能性跟inputword同时出现。
Word2Vec的优缺点优点由于Word2vec会考虑上下文,跟之前的Embedding方法相比,效果要更好
比之前的Embedding方法维度更少,所以速度更快
通用性很强,可以用在各种NLP任务中
缺点由于词和向量是一对一的关系,所以多义词的问题无法解决。
Word2vec是一种静态的方式,虽然通用性强,但是无法针对特定任务做动态优化
Word2Vec中文语料实战环境win10+python3依赖包:gensim与jieba(通过pipinstall安装)
语料库《诛仙》小说(部分)
文本预处理去除文本中可能存在的空白等,防止对训练造成干扰。
#文本预处理
file=open(text.txt,w,encoding=utf-8)
withopen(诛仙.txt,r,encoding=utf-8)asorigin_file:
forlineinorigin_file:
line=line.strip()
file.write(line+\n)
file.close()
中文分词将停顿词放在一个stop.txt文件中,这里选取了部分停顿词如下:
调用jieba库进行词语划分.
#分词
importjieba
stop_words_file=stop.txt
stop_words=[]
withopen(stop_words_file,r,encoding=utf-8)asorigin_stop_words_file:
text=origin_stop_words_file.readlines()
forlineintext:
line=line.strip()
stop_words.append(line)
origin_txt_file=text.txt
target_file=open(text_cut.txt,w,encoding=utf-8)
withopen(origin_txt_file,r,encoding=utf-8)asorigin_file:
text=origin_file.readlines()
forlineintext:
line=line.strip()
out_str=
word_list=jieba.cut(line,cut_all=False)
forwordinword_list:
ifwordnotinstop_words:
ifword!=\t:
out_str+=word
out_str+=
target_file.write(out_str.rstrip()+\n)
target_file.close()
分词结果:
训练word2vec模型#coding:utf8
importgensim.models.word2vecasw2v
model_file_name=model
#模型训练,生成词向量
sentences=w2v.LineSentence(text_cut.txt)
#训练参数:输出词的向量维数为20,训练窗口为5,截断频次在5次以下的词,4个并行任务
model=w2v.Word2Vec(sentences,size=,window=5,min_count=5,workers=4)
model.save(model_file_name)
模型测试importgensim
importwarnings
warnings.filterwarnings(action=ignore,category=UserWarning,module=gensim)
model=gensim.models.Word2Vec.load("model")
word=金瓶儿
result=model.similar_by_word(word)
print("跟"+word+"最相近的词:")
foriinresult:
print(i)
模型结果参考文献[1]Muwen.().[NLP]UnderstandingtheessenceofWord2vec.Retrievedfrom