词向量技术原理及应用详解(一)

文本表示是自然语言处理中的基础工作,文本表示的好坏直接影响到整个自然语言处理系统的性能。在自然语言处理研究领域,文本向量化是文本表示的一种重要方式。顾名思义,文本向量化就是将文本表示成一系列能够表达文本语义的向量。无论中文还是英文,词语都是表达文本处理的最基本单元。当前阶段,对文本向量化都是通过词向量化实现的。当然也有将文章或者句子作为文本处理的基本单元,像doc2vec和str2vec技术。

接下来主要是讨论以词语作为基本单元的word2vec技术,将先从onehot编码到word2vec,再从glove词向量到fasttext。本文主要是用于学习工作的个人笔记,备以后温习之。

1、什么是one hot编码

one-hot编码,又称独热编码、一位有效编码。其方法是使用N位状态寄存器来对N个状态进行编码,每个状态都有它独立的寄存器位,并且在任意时候,其中只有一位有效。举个例子,假设我们有四个样本(行),每个样本有三个特征(列),如下图:

  Feature_1 Feature_2 Feature_3
Sample1 1 4 3
Sample2 2 3 2
Sample3 1 2 2
Sample4 2 1 1

上图中我们已经对每个特征进行了普通的数字编码:我们的feature_1有两种可能的取值,比如是男/女,这里男用1表示,女用2表示。

那么one-hot编码是怎么搞的呢?我们再拿feature_2来说明:这里feature_2 有4种取值(状态),我们就用4个状态位来表示这个特
征,one-hot编码就是保证每个样本中的单个特征只有1位处于状态1,其他的都是0。

           1 -> 0001;  2 -> 0010;   3 -> 0100;   4 -> 1000;

对于2种状态、3种状态、甚至更多状态都可以这样表示,所以我们可以得到这些样本特征的新表示,入下图:

  Feature_1 Feature_2 Feature_3
Sample1 01 1000 100
Sample2 10 0100 010
Sample3 01 0010 010
Sample4 10 0001 001

one-hot编码将每个状态位都看成一个特征。对于前两个样本我们可以得到它的特征向量分别为:

Sample1  ->[0,1,1,0,0,0,1,0,0]               Sample2  ->[1,0,0,1,0,0,0,1,0]

2、one-hot在提取文本特征中的应用

one hot在特征提取上属于词袋模型(bag of words)。关于如何使用one-hot抽取文本特征向量我们通过以下例子来说明。假设我们的语料库中有三段话:

  • 我爱中国
  • 爸爸妈妈爱我
  • 爸爸妈妈爱中国

我们首先对上面语料进行分词,并获取其中的所有的词,然后对每个词进行编号:

              1 我;    2 爱;   3 爸爸;   4 妈妈;   5 中国

然后使用one-hot对每段话提取特征向量:

词向量技术原理及应用详解(一)_第1张图片

 

因此我们得到了最终的特征向量为:
                   我爱中国 -> ( 1,1,0,0,1 )
                   爸爸妈妈爱我 ->( 1,1,1,1,0 )
                   爸爸妈妈爱中国 ->( 0,1,1,1,1 )

在实际应用过程中,我们对多篇文本进行分词,并统计词频,生成的词典中词数有几万,十几万,甚至更多,如果都进行one-hot进行编码肯定是行不通的,这时一般会根据词频选取前5K或50K的词进行向量化,摒弃写低频词,提高效率。当然5K或50K对于one-hot编码已经很大了,后面会用word2vec对其进行处理。

优缺点分析:

优点:

      一是解决了分类器不好处理离散数据的问题;

     二是在一定程度上也起到了扩充特征的作用(上面样本特征数从3扩展到了9)。

缺点:

      1.  它是一个词袋模型,不考虑词与词之间的顺序,无法保留词序信息;

      2.  它假设词与词相互独立,存在语义鸿沟问题(在大多数情况下,词与词是相互影响的);

      3.  它得到的特征是离散稀疏的;

      4.  维度灾难:很显然,如果上述例子词典中包含10K个单词,那么每个需要用10000维的向量表示,采用one-hot编码,对角线元素均设为1,其余为0,也就是说除了文本中出现的词语位置不为0,其余9000多的位置均为0,如此高纬度的向量会严重影响计算速度。

3、one-hot编程实现

1、手动实现one-hot编码

import numpy as np
contents = ['我 毕业 于 **大学','我 就职 于 **公司']
dict = { }
for content in contents:
    for word in content.split():
        if word not in dict:
            dict[word] = len(dict) + 1

results = np.zeros(shape=(len(contents),len(dict) + 1,max(dict.values()) + 1))
#创建 2 个7*7的矩阵
print(dict)
for i,content in enumerate(contents):
    for j,word in list(enumerate(content.split())):
        index = dict.get(word)
        results[i,j,index] = 1
# print(results)
results2 = np.zeros(shape=(len(contents), max(dict.values())+1))

for i, content in enumerate(contents):
    for _,word in list(enumerate(content.split())):
        index = dict.get(word)
        results2[i,index] = 1
print(results2)
结果:
{'我': 1, '毕业': 2, '于': 3, '**大学': 4, '就职': 5, '**公司': 6}
[[0. 1. 1. 1. 1. 0. 0.]
 [0. 1. 0. 1. 0. 1. 1.]]

2、Keras中one-hot编码的实现

from keras.preprocessing.text import Tokenizer
contents = ['我 毕业 于 **大学','我 就职 于 **公司']

#构建单词索引

tokenizer =Tokenizer()
tokenizer.fit_on_texts(contents)

word_index = tokenizer.word_index
print(word_index)
# print(len(word_index))

sequences = tokenizer.texts_to_sequences(contents)
# print(sequences)

one_hot_result = tokenizer.texts_to_matrix(contents)
print(one_hot_result)

参考资料:

微信公众号:AI壹号堂

你可能感兴趣的:(NLP,one-hot,词向量)