文本表示

文本表示 对于自然语言处理各类应用,最基础的任务是文本表示。文本是不能直接作为模型的输入的,都是要转化成向量的形式再导入到模型中训练。所谓文本的表示就是研究如何将文本表示成向量或者矩阵的形式。
文本表示的最小单元是单词,其次是短语、句子、段落。我们需要懂得把这些都表示成向量的形式,其中,单词的表示法是最基础的,对于句子或者更长的文本说,其向量表示都依赖于单词的表示。单词的表示可以有多重方法,如独热编码、TF-IDF等等。
单词的表示
独热编码是可以用来表示一个词向量。首先我们需要根据文本构建自己的词库,词库的大小决定向量矩阵的大小,每个单词都有自己独特的向量表示,每个向量只有一个位置表示为1,其余全为0,列如词库的大小是5,某个单词向量可以表示为\( [0,0,1,0,0] \)。词库中所包含的单词的先后顺序并不影响后续任务。
独热编码虽然简单,但是也存在许多问题:

  • 由于大量0存在,极度稀疏
  • 每个单词表示成长度为|V|,|V|是词库的大小
  • 无法比较语义相似度
句子的表示
知道了单词的表示就可以知道句子的表示,一个句子由多个单词组成。记录一下句子中单词是否出现,我们就可以表示这个句子的向量,当然,某些时候也需要记录单词出现的次数。
但这种表示法也存在一些问题,例如:
  • 没有考虑到一个单词的重要性
    没有记录单词出现个数的表示法叫Boolean function,记录单词出现个数的表示法叫作Count vectorizer
from sklearn.feature_extraction.text import CountVectorizer #corpus 语料库 corpus = ['I like this course,', 'I like this game,', 'I like this course,but I also like that game' ] #构建countvectorizer object vectorizer = CountVectorizer() #得到每个文档的count向量,X为稀疏矩阵 X = vectorizer.fit_transform(corpus) #打印词典 print(vectorizer.get_feature_names())#['also', 'but', 'course', 'game', 'like', 'that', 'this'] #打印每个文档的向量 print(X.toarray()) [[0 0 1 0 1 0 1] [0 0 0 1 1 0 1] [1 1 1 1 2 1 1]] print(X) (0, 4)1 (0, 6)1 (0, 2)1 (1, 4)1 (1, 6)1 (1, 3)1 (2, 4)2 (2, 6)1 (2, 2)1 (2, 3)1 (2, 1)1 (2, 0)1 (2, 5)1

文档表示 TF-IDF
TF-IDF表示考虑了单词的权重,也可以认为是质量。但并不是出现的越多就越重要,也并不是出现的越少就越不重要。具体表示法请看下式(1):
$$ tfidf(w) = tf(d,w)*idf(w)\tag{1} $$
\( w \)表示词语, \( tf(d,w) \)表示文档\( d \)中\( w \)的词频,\( idf(w) =log\frac {N}{N(w)}\),\( N \)表示语料库中的文档总数,\( N(w) \)表示词语\( w \)出现在了多少个文档
TF-IDF的应用非常广泛,即使放在眼前也是表示文本的最核心的技术之一。TF-IDF是文本表示领域最有效的基准。
文本相似度 两个文本之间的相似度可以认为是计算两个向量之间的相似度。下面涉及到的相似度计算公式适合任何向量化的场景,不仅仅局限于文本之间的相似度。两种常见的相似度计算方法分别基于欧氏距离的计算和基于余弦相似度的计算。
计算欧式距离
$$ d = |s_1 - s_2|\tag{2} $$
向量之间的相似度实际上要考虑到向量的方向,因为向量最重要的特性为它的方向性。如果两个向量相似,那也需要它俩的方向也比较相似。然而,计算欧式距离的过程并没有把方向考虑进去,这是欧式距离的最大的问题。
计算余弦相似度
【文本表示】通过余弦相似度事实上我们计算的是两个向量之间的夹角大小。两个向量的方向上越一致就说明它俩的相似度就越高。
$$ d =\frac{ s_1\cdot s_2} {|s_1|* |s_2| }\tag{3} $$
\( s_1\cdot s_2 \)是向量内积,\( |s_1| \)表示长度
关余弦相似度:
  • 在分母上除以向量大小是为了消除两个向量大小所带来的影响
  • 内积可用来计算向量之间的相似度
  • 余弦相似度考虑到了方向,欧式距离则没有
  • 在向量之间相似度计算上,余弦相似度的应用相比欧式距离更广泛一些
#计算句子余弦形似度 '''向量a,b''' def cos_sim(a,b): dot_product = sum([i[0]*i[1] for i in zip(a,b)]) norm_a = np.sqrt(sum([x*x for x in a])) norm_b = np.sqrt(sum([y*y for y in b])) return dot_product / (norm_a*norm_b)

小结
对于独热编码表示的单词,基于欧式距离计算相似度结果均是\( \sqrt2 \),基于余弦计算相似度结果均是0,所以词向量的表示我们需要考虑其他的方式。
未完待续...

    推荐阅读