如何在Word2Vec中处理词汇表外词语的相似度计算?
解决Word2Vec未登录词的产品-分类映射方案
问题核心
用杂货店产品名训练的Word2Vec模型,在计算长产品名(如"salty potato chips with cheese and onion")与分类名的相似度时,因长产品名不在词汇表中报错,需突破词汇表限制完成映射。
可行解决方案
1. 拆分未登录词,计算平均向量
将长文本拆分为短语/词汇,过滤出模型词汇表内的部分,取这些词汇向量的平均值作为整个文本的向量,再与分类名向量计算相似度。
代码实现:
import numpy as np from sklearn.metrics.pairwise import cosine_similarity def get_average_vector(text, w2v_model, bigram_model): # 用训练好的bigram工具处理文本 tokens = bigram_model[text.lower().split()] # 筛选出词汇表内的有效词 valid_tokens = [token for token in tokens if token in w2v_model.wv.key_to_index] if not valid_tokens: return None # 计算有效词向量的平均值 vecs = [w2v_model.wv[token] for token in valid_tokens] return np.mean(vecs, axis=0) def assign_category(products, categories, w2v_model, bigram_model): for product in products: product_name = Product.get_name(product).lower() product_vec = get_average_vector(product_name, w2v_model, bigram_model) if not product_vec: product.set_category("未分类") product.set_match_rate(0) continue max_sim = -1 best_cat = None for category in categories: cat_name = Category.get_name(category).lower() cat_vec = get_average_vector(cat_name, w2v_model, bigram_model) if not cat_vec: continue current_sim = cosine_similarity([product_vec], [cat_vec])[0][0] if current_sim > max_sim: max_sim = current_sim best_cat = category if best_cat: product.set_category(best_cat) product.set_match_rate(max_sim) else: product.set_category("未分类") product.set_match_rate(0)
2. 调整短语生成参数,扩大词汇表
之前的Phrases设置了min_count=30,阈值较高,导致很多低频短语未被收录。调低参数可以捕获更多短语,减少未登录词:
# 降低min_count和threshold,生成更多短语 phrases = Phrases(product_list, min_count=10, threshold=5.0, progress_per=10000) bigram = Phraser(phrases)
调整后重新训练Word2Vec模型,词汇表会包含更多产品相关短语,降低未登录词出现概率。
3. 提取文本中已登录的核心词做匹配
如果长文本中包含词汇表内的核心词(比如示例中的"potato chips"),可以直接提取这些核心词,用核心词与分类名计算相似度:
def extract_valid_tokens(text, w2v_model, bigram_model): tokens = bigram_model[text.lower().split()] return [token for token in tokens if token in w2v_model.wv.key_to_index] def assign_category(products, categories, w2v_model, bigram_model): for product in products: product_name = Product.get_name(product).lower() valid_tokens = extract_valid_tokens(product_name, w2v_model, bigram_model) if not valid_tokens: product.set_category("未分类") product.set_match_rate(0) continue max_sim = -1 best_cat = None for category in categories: cat_name = Category.get_name(category).lower() # 分类名如果是短语,先检查是否在词汇表 if cat_name in w2v_model.wv.key_to_index: cat_token = cat_name else: cat_tokens = extract_valid_tokens(cat_name, w2v_model, bigram_model) if not cat_tokens: continue cat_token = cat_tokens[0] # 取第一个有效分类词,或取平均向量 # 计算产品所有有效词与分类词的相似度最大值 for token in valid_tokens: current_sim = w2v_model.wv.similarity(token, cat_token) if current_sim > max_sim: max_sim = current_sim best_cat = category if best_cat: product.set_category(best_cat) product.set_match_rate(max_sim) else: product.set_category("未分类") product.set_match_rate(0)
4. 替代方案:使用预训练语言模型
如果Word2Vec的词汇表限制难以突破,可以用基于子词的预训练模型(如BERT、RoBERTa)提取文本向量,这类模型天然支持未登录词,能更好地处理长文本语义。只需将产品名和分类名输入模型得到向量,再计算余弦相似度即可完成映射。
内容的提问来源于stack exchange,提问作者lurenia
相关产品推荐
相关产品推荐

