嗨,昨天语料库模型建好了,下一步要如何使用呢? 我们要如何比对输入的句子与语料库中的哪一句最相似呢?
计算两个点之间存在的差异大小,主要有两种方式,欧式距离与余弦相似度。
详细的介绍参考: 欧氏距离与余弦相似度的比较
主要计算空间中点与点之间的距离。
距离越大,相似性越低,反之亦然。
主要计算向量间的夹角大小。
夹角越大,相似性越低,反之亦然。
而余弦相似度的公式由「内积公式」推导而来。
余弦相似度无关乎向量大小,重点是向量之间的方向。
此段参考 机器是这样理解语言 - 词向量 | 莫烦Python
大部分时候,我们注重的不一定是点与点之间的距离,更重要的是两个向量的方向是否接近。这时候,余弦相似度就比欧式距离适合。
莫烦 Python 的程序码: https://github.com/MorvanZhou/NLP-Tutorials
我修改过的版本: https://gitlab.com/graduate_lab415/nlp/-/blob/master/main.py
"""test"""
q = sys.argv[1]
# q = "拐杖去哪里申请"
# q = "I like kitty"
if CUT_METHOD == "ckip":
tmp_q = [q]
q = tmp_q
scores = docs_score(q)
d_ids = scores.argsort()[-3:][::-1]
if LOG:
print("\n[{}] top 3 docs for '{}':\n{}".format(CUT_METHOD, (q if CUT_METHOD != "ckip" else q[0]), [docs[i] for i in d_ids]))
第一句 q
是读入要比较的句子,sys.argv[1]
就是用来读取执行程序码时输入的参数,过几天的文章会写到。我如果还记得,再回来补连结...
第一个 if 那边是因为 CKIP 和 Jieba 转换完的格式不一样,需要做个转换,统一一下。
docs_score(q)
计算 q
和其他所有句子的余弦相似性。
Python List 操作方式
a = [1, 2, 3, 4, 5] a[::-1] #[::-1] 是倒置,输出: [5, 4, 3, 2, 1] a[-3] #[-3] 是倒数第 3 个,输出: 3 a[-3:] #[-3:] 是从倒数第三个到最後一个,输出: [3, 4, 5] a[-3:][::-1] #输出: [5, 4, 3]
def docs_score(query, len_norm=False):
"""断词"""
if CUT_METHOD == "jieba":
q_words = CutSentence.cut_jeiba(re.sub('[??()()「」,,、。::_“”→]', ' ', query), log=LOG) # use jieba
elif CUT_METHOD == "ckip":
q_words = CutSentence.cut_ckip(query, log=LOG) # use ckip
temp_arr = np.array(q_words)
temp_arr = temp_arr.reshape(len(q_words[0]))
q_words = temp_arr
else:
q_words = query.replace(",", "").split(" ")
"""label"""
if LABEL:
q_words = add_label(q_words)
"""add unknown words"""
unknown_v = 0
for v in set(q_words):
if v not in v2i:
v2i[v] = len(v2i)
i2v[len(v2i) - 1] = v
unknown_v += 1
if unknown_v > 0:
_idf = np.concatenate((idf, np.zeros((unknown_v, 1), dtype=np.float)), axis=0)
_tf_idf = np.concatenate((tf_idf, np.zeros((unknown_v, tf_idf.shape[1]), dtype=np.float)), axis=0)
else:
_idf, _tf_idf = idf, tf_idf
counter = Counter(q_words)
q_tf = np.zeros((len(_idf), 1), dtype=np.float) # [n_vocab, 1]
for v in counter.keys():
q_tf[v2i[v], 0] = counter[v]
q_vec = q_tf * _idf # [n_vocab, 1]
q_scores = cosine_similarity(q_vec, _tf_idf) # 拿q的向量和所有向量比对
if len_norm:
len_docs = [len(d) for d in docs_words]
q_scores = q_scores / np.array(len_docs)
return q_scores
一个新拿到的 q
(这个 function 中叫 query
),进行比较前,也要经过段词、加 label,再检查 query
有没有新的词,有的话就要加到 v2i
和 i2v
里面。将 query
转换成向量 q_vec
後才能算相似性唷。
最後 q_scores = cosine_similarity(q_vec, _tf_idf)
计算 query 与每个句子的相似性。
终於写完了,这篇应该本系列是最难的一篇了,我早上还先复习了数学呢。
>>: EP 25: Validation by Data Annotation Validators in TopStore App
本篇重点 每日下载及更新Kbar资料 每日产生观察名单 结论 每日下载及更新Kbar资料 每天下载及...
Fragments在Navigation中的参数传递 - SafeArgs 继上篇我们得知如何运用N...
Linux 因为之後会部署在 Linux 上 所以要先大概了解一下档案结构 鸟哥的 Linux 私房...
今天我们正式开始聊聊AI作曲相关方面的话题~ AI作曲历史 如果要追朔到最早的自动作曲 ,大家可以猜...
昨天介绍完硬碟管理,来实作吧~ TIPS: Array在unRaid指的是资料池,并非POOL(在u...