【发布时间】:2022-11-14 20:12:59
【问题描述】:
我需要找到一种计算有效的方法来识别和匹配句子中的单词。我知道有各种字符串相似度包,它们使用 Levenshtein 距离、Jaccard 距离、余弦等方法,如stringdist。但是这些在近似两个长度大致相同的字符串的相似度方面是有效的。基本上我必须将短字符串与长字符串进行比较。
我认为最好通过一个例子来说明,我有描述SPECIAL JOS VALEY CHOCK COOKIES 10X550GR,我想确定它是否属于JOE'S VALLEY品牌产品。例如,在这两个字符串之间进行 Levenshteins 相似性将产生较差的相似性。但是,如果我决定使用子字符串并仅使用 JOS VALEY 作为描述,则相似度得分会更高并且可以匹配。
library(stringdist)
# Decription we want to search
sku <- "SPECIAL JOS VALEY CHOCK COOKIES 10X550GR"
# An established brand in our database
br <- "JOE'S VALLEY"
# For comparison below, this is the misspelled brand in the actual description above
sku_br <- "JOS VALEY"
# Similarity measures
methods <- c("osa", "lv", "dl", "hamming", "lcs", "qgram", "cosine", "jaccard", "jw", "soundex")
# Test similarity scores methods
for(i in 1:length(methods)){
cat(paste0(methods[i],":\n"))
cat(paste0(sku," <-> ",br," ====> ",stringsim(sku,br,method = methods[i]),"\n"))
cat(paste0(sku_br ," <-> ",br," ====> ",stringsim(sku_br,br,method = methods[i]),"\n"))
cat(paste0("\n"))
}
如果你不能运行上面的代码,这里是输出:
osa:
SPECIAL JOS VALEY CHOCK COOKIES 10X550GR <-> JOE'S VALLEY ====> 0.175
JOS VALEY <-> JOE'S VALLEY ====> 0.75
lv:
SPECIAL JOS VALEY CHOCK COOKIES 10X550GR <-> JOE'S VALLEY ====> 0.175
JOS VALEY <-> JOE'S VALLEY ====> 0.75
dl:
SPECIAL JOS VALEY CHOCK COOKIES 10X550GR <-> JOE'S VALLEY ====> 0.175
JOS VALEY <-> JOE'S VALLEY ====> 0.75
hamming:
SPECIAL JOS VALEY CHOCK COOKIES 10X550GR <-> JOE'S VALLEY ====> 0
JOS VALEY <-> JOE'S VALLEY ====> 0
lcs:
SPECIAL JOS VALEY CHOCK COOKIES 10X550GR <-> JOE'S VALLEY ====> 0.346153846153846
JOS VALEY <-> JOE'S VALLEY ====> 0.857142857142857
qgram:
SPECIAL JOS VALEY CHOCK COOKIES 10X550GR <-> JOE'S VALLEY ====> 0.423076923076923
JOS VALEY <-> JOE'S VALLEY ====> 0.857142857142857
cosine:
SPECIAL JOS VALEY CHOCK COOKIES 10X550GR <-> JOE'S VALLEY ====> 0.649519052838329
JOS VALEY <-> JOE'S VALLEY ====> 0.916666666666667
jaccard:
SPECIAL JOS VALEY CHOCK COOKIES 10X550GR <-> JOE'S VALLEY ====> 0.428571428571429
JOS VALEY <-> JOE'S VALLEY ====> 0.9
jw:
SPECIAL JOS VALEY CHOCK COOKIES 10X550GR <-> JOE'S VALLEY ====> 0.624494949494949
JOS VALEY <-> JOE'S VALLEY ====> 0.805555555555555
soundex:
SPECIAL JOS VALEY CHOCK COOKIES 10X550GR <-> JOE'S VALLEY ====> 0
JOS VALEY <-> JOE'S VALLEY ====> 1
从上面的结果我们可以看出,完整的 sku 描述与比较品牌的匹配度并不高。但是,如果我们对拼写错误的品牌进行子串化,它会获得可接受的匹配分数。
所以我有一个解决方案是创建一个“搜索窗口”,它遍历整个完整描述(搜索窗口长度等于品牌字符串的长度)。例如,它将首先计算以下之间的相似性:
-
SPECIAL JOS和JOE'S VALLEY然后如果分数小于容差,它会将窗口增加一个字符。 -
PECIAL JOS V比较JOE'S VALLEY然后如果分数更少...... -
ECIAL JOS VA比较JOE'S VALLEY然后如果分数更少... 直到它获得的分数超过所需的容差为止,它将返回一个匹配项。这在计算上非常昂贵,并且由于我们数据库中的品牌数量而加剧。所以我的问题是,有没有更有效的方法来做到这一点?
感谢您阅读。
【问题讨论】:
标签: r text text-mining similarity