如何按含义比较两个字符串?
Posted
技术标签:
【中文标题】如何按含义比较两个字符串?【英文标题】:how to compare two strings by meaning? 【发布时间】:2020-04-12 07:13:24 【问题描述】:我希望我的 node.js 应用程序的用户写下想法,然后将其存储在数据库中。 到目前为止一切顺利,但我不希望该表中有多余的条目,所以我决定使用这个来检查相似性: https://www.npmjs.com/package/string-similarity-js
你知道一种方法,我可以按含义比较两个字符串吗?就像在“使用公共交通工具”与“乘坐火车”的相似度得分很高,而在上述得分中表现很差。
【问题讨论】:
你刚才描述的是一个涉及人工智能的博士级问题。 事实证明,自然语言理解是并且一直是计算领域最困难的问题之一。 这是一个很好的问题 - 欢迎来到社区。很抱歉圣诞节期间所有孤独的人都花时间投票否决了问题。这不再是一个博士级别的问题——这是一个解决了所有实际目的的问题。使用 JxCode 的答案以及 Google Universal Sentence 嵌入等更轻量级的模型,使用余弦相似度对相似文本进行分组 【参考方案1】:比较两个字符串的含义仍然是一项正在进行的研究。如果你真的想解决这个问题(或者想获得真正好的语言模态性能),你应该考虑攻读博士学位。
对于当时的开箱即用解决方案:我发现这个 Github repo 实现了 google 的 BERT 模态并使用它来获取两个句子的嵌入。理论上,如果嵌入相似,则两个句子具有相同的含义。
https://github.com/UKPLab/sentence-transformers
# the following is simplified from their README.md
embedder = SentenceTransformer('bert-base-nli-mean-tokens')
# Corpus with example sentences
S1 = ['A man is eating a food.']
S2 = ['A man is eating pasta.']
s1_embedding = embedder.encode(S1)
s2_embedding = embedder.encode(S2)
dist = scipy.spatial.distance.cdist([s1_embedding], [s2_embedding], "cosine")[0]
Example output (copied from their README.md)
Query: A man is eating pasta.
Top 5 most similar sentences in corpus:
A man is eating a piece of bread. (Score: 0.8518)
A man is eating a food. (Score: 0.8020)
A monkey is playing drums. (Score: 0.4167)
A man is riding a horse. (Score: 0.2621)
A man is riding a white horse on an enclosed ground. (Score: 0.2379)
【讨论】:
【参考方案2】:要按含义比较两个字符串,首先需要将字符串转换为张量,然后评估张量之间的距离或相似性。许多算法可用于将字符串转换为张量——所有这些都与感兴趣的领域相关。但是通用句子编码器是一个宽泛的句子编码器,它将把所有单词投射在一维空间中。余弦相似度可用于查看某些单词的含义有多接近。
示例
虽然king
和kind
在汉明距离上是封闭的(只有一个字符的差异),但它们是非常不同的。而queen
和king
尽管它们似乎不相关(因为所有字符都不同),但它们的含义很接近。因此king
和queen
之间的距离(在含义上)应该小于king
和kind
之间的距离,如下面的sn-p 所示。
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/universal-sentence-encoder"></script>
<script>
(async() =>
const model = await use.load();
const embeddings = (await model.embed(['queen', 'king', 'kind'])).unstack()
tf.losses.cosineDistance(embeddings[0], embeddings[1], 0).print() // 0.39812755584716797
tf.losses.cosineDistance(embeddings[1], embeddings[2], 0).print() // 0.5585797429084778
)()
</script>
【讨论】:
以上是关于如何按含义比较两个字符串?的主要内容,如果未能解决你的问题,请参考以下文章