文本示意
对于自然语言解决各类利用,最根底的工作是文本示意。文本是不能间接作为模型的输出的,都是要转化成向量的模式再导入到模型中训练。所谓文本的示意就是钻研如何将文本示意成向量或者矩阵的模式。
文本示意的最小单元是单词,其次是短语、句子、段落。咱们须要懂得把这些都示意成向量的模式,其中,单词的表示法是最根底的,对于句子或者更长的文本说,其向量示意都依赖于单词的示意。单词的示意能够有多重办法,如独热编码、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,所以词向量的示意咱们须要思考其余的形式。
未完待续 …