文章目录

  • 1. one-hot
  • 2. tfidf
  • 3. n-gram
  • 4. NNLM
  • 5. word2vec



在NLP的处理中,我们需要讲文本输入到模型中处理,实现分类识别,文本生成或者翻译等工作。而模型是无法知道一个纯粹的文本是什么意思的,模型的输入只能是数字,比如连续型的小数或则离散的整数。而对于文本之类的无法直接用数字表示的数据可以通过一下几种方式处理。

1. one-hot

在机器学习中,我们经常使用该方法处理一些类别型的数据。比方说,在预测放假的时候,有一微特征表示几线城市,有“一线”,“新一线”,“二线”,“三线”,“四线”,“其他”等,那么当某一个特征的值为“二线”的时候,就可以表示为[0, 0, 1, 0, 0, 0]。在实现的时候,可使用sklearn进行one-hot编码。

# 例子来自sklearn的官方例子,https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html
>>> from sklearn.preprocessing import OneHotEncoder
>>> enc = OneHotEncoder(handle_unknown='ignore')
>>> X = [['Male', 1], ['Female', 3], ['Female', 2]]
>>> enc.fit(X)
OneHotEncoder(handle_unknown='ignore')
>>> enc.categories_
[array(['Female', 'Male'], dtype=object), array([1, 2, 3], dtype=object)]
>>> enc.transform([['Female', 1], ['Male', 4]]).toarray()
array([[1., 0., 1., 0., 0.],
       [0., 1., 0., 0., 0.]])

在文本处理中,可以以此表vocab中的所有词作为类别集合,按照文本所需处理的词进行one-hot编码,用于one-hot处理。

2. tfidf

然而,使用one-hot编码无法表示词的重要性。比如一个文本嗯,我是程序员中,经过分词之后是["嗯",“我”,“是”, "程序员"], 显然这句话中,程序员这几个词比重要,但是在经过one-hot处理之后,是看不出来这几个词之间的区别的。而使用tfidf方式就能够表示词的重要性。
tfidf的方法,是根据一个词在一篇文本中出现的次数,以及该词在所有文本中出现的次数来计算的,用于表示一个词的重要程度。比如某词的ifidf的计算公式如下langchainembedding文本向量化 文本向量化模型_nlp
langchainembedding文本向量化 文本向量化模型_nlp_02
langchainembedding文本向量化 文本向量化模型_语言模型_03直观的理解就是,一个词在某个文本中出现的次数越多,那么该词在该文本中就越重要(即langchainembedding文本向量化 文本向量化模型_词向量_04),但是如果一个词在语料的所有文本中都出现过,那么该词就不那么重要了,比如,之类的词可能在语料的很多文本中出现过,但是这些词是不重要的(即langchainembedding文本向量化 文本向量化模型_语言模型_05),于是就可以使用langchainembedding文本向量化 文本向量化模型_人工智能_06来表示一个词在所在文本中的重要新。
而理论上对于每一个文本,都可以计算词表vocab中所有词在该文本中的langchainembedding文本向量化 文本向量化模型_语言模型_07(如果某次在该文本中没出现过,那么就可以直接以0表示重要性),那么对于每一个文本,就可以用一个词表长度的向量来表示。计算一个文本的tfidf值,同样可以调用sklearn。

# 例子来自sklearn的官方例子,https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfVectorizer.html
>>> from sklearn.feature_extraction.text import TfidfVectorizer
>>> corpus = [
...     'This is the first document.',
...     'This document is the second document.',
...     'And this is the third one.',
...     'Is this the first document?',
... ]
>>> vectorizer = TfidfVectorizer()
>>> X = vectorizer.fit_transform(corpus)
>>> print(vectorizer.get_feature_names())
['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']
>>> print(X.shape)
(4, 9)

3. n-gram

使用langchainembedding文本向量化 文本向量化模型_语言模型_07虽然能够表示一个词在文本中的重要程度,但是却无法表示词的先后顺序。比如鸣人喜欢雏田雏田喜欢鸣人,这是两句不一样的话,但是在langchainembedding文本向量化 文本向量化模型_语言模型_07的表示方法中,这两句话却会被表示成一样的向量。如果我们能够在文本表示中添加词的先后顺序的信息,就能一定程度的解决这个问题。
因此,我们可以使用n-gram来表示文本。n-gram,就是把文本分词之后,以n个词为一个单元来进行处理。比如,以bi-gram(即n=2)为例,在上述的两句话中,经过分词之后,得到的均是[鸣人,喜欢, 雏田],而第一句使用bi-gram表示结果为[鸣人喜欢,喜欢雏田],第二句的表示结果为[雏田喜欢,喜欢鸣人],这样两句话的表示结果就不一样了。
但是,使用n-gram表示方法,每一个文本档的表示结果就不是词表的大小,而是词表大小vocab_size的n次方。这就使得每一个文本的表示结果非常长,且非常稀疏。

4. NNLM

后来,一些大牛们就想到了使用神经网络来训练表示文本的向量,于是就有了NNLM(Feedforward Neural Net Language Mode)。NNLM的网络结构如下:

langchainembedding文本向量化 文本向量化模型_词向量_10


NNLM,Feedforward Neural Net Language Mode,翻译过来就是“前向神经网络语言模型”,这是一个语言模型,文本的词向量表示是其中间产物。

如上图所示,NNLM是使用文本中的某一个词的前N-1个词来预测该词。NNLM的预测流程如下:

  1. 获取当前词的前N-1个词,将这N-1个词经过shape=vocab_size*embedding_size的矩阵langchainembedding文本向量化 文本向量化模型_词向量_11转化伟相应词的向量,有N-1个词,于是就得到了N-1个向量
  2. 将这N-1个向量进行concat拼接,将拼接后的向量经过tanh的非线性变化之后,在经过一个全连接的隐藏层
  3. 然后再经过一个softmax层输出结果。输出概率最大的神经元对应的词,即为预测的当前词。

NNLM为语言模型,而我们取其中的矩阵langchainembedding文本向量化 文本向量化模型_人工智能_12作为我们的词向量矩阵,矩阵中第langchainembedding文本向量化 文本向量化模型_nlp_13行的向量,就是词表中第langchainembedding文本向量化 文本向量化模型_nlp_13个词的向量化结果。
在NNLM的训练过程中,时间复杂度为langchainembedding文本向量化 文本向量化模型_语言模型_15其中N为上述过程中的N,D为词向量的大小,即为上述过程中的embedding_size,H为隐藏层的大小,V为词表大小。

5. word2vec

上述的计算的时间复杂度也比较大,尤其是在隐藏层中消耗比较大的计算资源,为此,langchainembedding文本向量化 文本向量化模型_nlp_16提出了新的词向量训练模型wor2vec用于简化计算,word2vec有CBOW和n-gram两种形式,并且针对词表比较大的情况又提出了hierarchical softmax和nagative sampling两种优化方法。

langchainembedding文本向量化 文本向量化模型_深度学习_17


上图即为word2vec的两种形式,具体对于这两种形式的介绍,待下一篇再进行介绍。