一. 数据源
根据类目型号采集3C产品的标题。品牌,型号,和标题均做分词处理,英文转小写,数据如下:
二. 训练
word2vec的java实现包:deeplearning4j,python实现包:gensim。工程结构是使用gensim训练每个类目的模型,线上环境初始化时候把这些模型载入,使用deeplearning4j计算相似度获取匹配结果。原因如下:
- deeplearning4j 训练时间非常长,要加速的话可以的,Windows要用Vistual Studio的C++编译器,还要配置蛮多东西,我就没来搞了。
- 相同数据:手机类目100507个标题,python版本训练时间1分钟,java版本7分钟,这导致了deeplearning4j的训练参数调节不方便。
- 最关键的问题是出来的精度堪忧啊(应该是训练参数问题),看下图相同训练集,:
调参
model = Word2Vec(LineSentence("./brand_title/title_token_%s.txt"%(cid)), size=400, window=5, min_count=5, workers=multiprocessing.cpu_count(), sg=0)
默认sg=1是skip-gram算法,对低频词敏感,如果要多近似词就要选择CBOW(sg=0);size是词向量的维数;window是前后看词的单位,5表示在目标词前看5-b个词,后面看b个词(b在0-5之间随机);因为语料(title)太短,设置过大的window会导致结果并不那么理想,最后CBOW用的3;mini_count=5是忽略出现次数小于5的极低频词。
三. 匹配
- 检索title获得品牌型号gid
- 获得该gid的match_words:
- title分词,读word2vec产生的模型,计算title中每个词与match_words的相似距离。
- match_words中分别有一个词与title分词结果近似。任务solr检索结果正确。
原先问题在于验证过程,粗暴的使用match_words是否在title分词结果中存在,忽略了语义的联系,如iphone <-> 苹果,可以说明该title分词(苹果)和match_word(iphone)有较强联系。现在使用两两词向量的cos距离表示词语间的近似关系,可以表现语义联系。
规则:词与match_word的相似度大于0.35即可认为有联系;词与match_words相似度总和大于0.35*match_word个数可认为词语与品牌型号有强关联。
例如title:国行现货【送膜+壳】Apple/苹果iPhone5s移动联通4G手机分期购
Apple <-> iphone 0.96
Apple <-> 5s 0.48
Apple <-> iphone5s 0.76
0.96 + 0.48 + 0.76 > 3 * 0.35 说明Apple与iPhone5S有强关联。
联通 <-> iphone 0.06
联通 <-> 5s 0.20
联通 <-> iphone5s 0.01
说明“联通”和iPhone5s没啥关系。
在Title的分词结果中,有1个词语与品牌型号关键词有强联系,可认为Solr检索结果正确,返回品牌型号。
四. 代码结构:
计算词与品牌型号关键词的相似度代码:
double sim = word2vecConfig.getCidVectors().get(categoryCode).similarity(word.toLowerCase(), matchModelList.get(i));