菜品文本匹配
数据准备
- 原始数据:从网上爬虫得到的菜单数据,包含菜名,单价,销售量等
- 目标:将原始数据中的菜名分类,并划分菜谱类别(如粤菜、川菜、西餐等)
- 辅助:从网上搜索找到菜谱数据库,包含了5000多种菜的标准菜名、菜谱类型、做法等,但是需要修正菜谱类型至我们所规定的类别。
问题点
原始数据中的菜名千奇百怪,需要跟标准菜名进行匹配,而且一个菜名可能对应多个标准菜名,需要找出最相关的标准菜名。例如'虾仁小馄饨'、'大份馄饨'都对应了''馄饨'',但是也有可能对应'虾仁炒饭'。
<aside>
💡 注意
- 文本匹配的方法,相似性的算法
- 先分词在做相似性评价,可能效果更好
- 数据量大,匹配算法不能太慢
</aside>
解决思路(基于字符的匹配,忽略语义)
- 精准匹配+模糊匹配:
- 精准匹配: 用字符串查找函数来精确匹配原始数据菜名中是否包含标准菜名,只要包含就认为匹配成功
- 模糊匹配:调用fuzzywuzzy库,结果jieba中文分词提高匹配率
fuzzywuzzy的使用
fuzzywuzzy.token_sort_ratio或token_sort_ratio计算相似度时在中文字符串里需要用空格分词才有效
fuzz.ratio("番茄炒蛋","鸡蛋拌番茄")#单纯匹配文本的编辑距离,考虑总字符数
44
fuzz.partial_ratio("番茄炒蛋","鸡蛋拌番茄")#单纯匹配文本的编辑距离,考虑最短文本的字符数
50
fuzz.token_sort_ratio("番茄炒蛋","鸡蛋拌番茄")#忽略分词顺序的相似度,需要空格间隔分词才有效
44
fuzz.token_set_ratio("番茄炒蛋","鸡蛋拌番茄")#忽略分词重复的相似度,需要空格间隔分词才有效
44
fuzz.partial_ratio("番茄 炒 蛋","鸡蛋 拌 番茄")
33
fuzz.token_sort_ratio("番茄 炒 蛋","鸡蛋 拌 番茄")#加空格分词后显著提高相似性
77
fuzz.token_set_ratio("番茄 炒 蛋","鸡蛋 拌 番茄")#加空格分词后显著提高相似性
77
fuzz.token_set_ratio("番茄 炒 蛋","鸡蛋 蛋 拌 番茄")#分词时用全匹配的方式似乎可以提高相似性
80
fuzz.token_sort_ratio("番茄 炒 蛋","鸡蛋 蛋 拌 番茄")
67
#综合表现来说,中文分词后用fuzzywuzzy.token_set_ratio最合适
fuzzywuzzy.extractOne或者extract提取候选集合中相似性最大的一个或多个选项,输出(匹配文本,相似度)
matchname = process.extractOne(row['匹配菜名'], choices, scorer=fuzz.token_set_ratio)
#scorer用于指定相似度计算器,默认是Wratio,它的编码方式是utf-8,不能用于中文,但指定scorer后可用
jieba中文分词包
jieba.lcut("紫菜蛋花汤")#精确模式,精确分词不冗余
['紫菜', '蛋花汤']
jieba.lcut("紫菜蛋花汤",cut_all=True)#全模式,所有可能的词组
['紫菜', '蛋花', '蛋花汤', '花汤']
jieba.lcut_for_search("紫菜蛋花汤")#精确模式的基础上对长文本进一步分词
['紫菜', '蛋花', '花汤', '蛋花汤']
jieba.lcut("丰化芋艿头")
['丰化', '芋艿', '头']
jieba.lcut("丰化芋艿头",cut_all=True)
['丰', '化', '芋艿', '头']
jieba.lcut_for_search("丰化芋艿头")
['丰化', '芋艿', '头']
#lcut分词过于简单,忽略了类似'蛋花汤'中的'蛋花'信息,cut_all又过于细,反而不利于后续的相似度计算
#个人感觉lcut_for_search最合适
实验结果
第一阶段实验:
-
精确匹配结果:
匹配成功次数 225
尝试匹配次数 1000
匹配成功率
循环运行时间: -
模糊匹配结果:(不包括分词)
ratio≥0.6
匹配成功次数 239
尝试匹配次数 775
匹配成功率 0.30838709677419357
循环运行时间:100.00秒 -
模糊匹配结果:(包括分词)
ratio≥0.6
匹配成功次数 503
尝试匹配次数 775
匹配成功率 0.6490322580645161
循环运行时间:106.94秒ratio≥0.8
匹配成功次数 134
尝试匹配次数 775
匹配成功率 0.17290322580645162
循环运行时间:61.48秒
<aside>
💡 采用分词后,同样的模糊匹配模式和ratio阈值,匹配的“门槛”变低,匹配成功率提高,但结果不够准确。 提高ratio阈值,会降低匹配成功率,但提高准确性
</aside>