基于Word2Vec计算句子与目标词相似度并实现文本归类的方法咨询
基于Word2Vec计算句子与目标词相似度并实现文本归类的方法咨询
嘿,你的思路其实挺靠谱的!针对你要把1000条投诉文本归类到4个核心词的需求,我来一步步帮你实现你想的方法,再给你补充几个更实用的替代方案。
一、实现你提出的「取TopN相似词求平均」方法
你的思路是对的:先算句子里每个词和目标词的相似度,取TopN最高的求平均,作为句子和目标词的匹配度。下面是具体的代码实现,结合你的示例数据:
1. 预处理与模型训练(先把基础工作做扎实)
先做些文本预处理(转小写、去标点),这能让模型效果更好:
import pandas as pd from gensim.models import Word2Vec import numpy as np # 你的示例数据 data = { 'text': [ "The king sat on the throne with wisdom.", "A queen ruled the kingdom alongside the king.", "Knights were loyal to their king.", "The empire prospered under the rule of a wise monarch." ] } df = pd.DataFrame(data) # 文本预处理:转小写、去标点、分词 df['text'] = df['text'].str.lower().str.replace('[^\w\s]', '').str.split() # 训练Word2Vec模型,这里可以根据你的数据调整参数 model = Word2Vec(df['text'], vector_size=100, window=2, min_count=1, workers=4)
2. 编写相似度计算函数
写一个通用函数,用来计算句子和目标词的TopN相似度平均值:
def calculate_topn_similarity(sentence_words, target_word, model, top_n=3): # 过滤掉模型不认识的词 valid_words = [word for word in sentence_words if word in model.wv.key_to_index] if not valid_words: return 0.0 # 句子里没有模型识别的词时返回0 # 计算每个有效词和目标词的相似度 similarities = [model.wv.similarity(word, target_word.lower()) for word in valid_words] # 取TopN最高的相似度并求平均 top_similarities = sorted(similarities, reverse=True)[:top_n] return np.mean(top_similarities)
3. 应用到DataFrame并归类
假设你的4个核心词是['king', 'castle', 'queen', 'monarch'],直接批量计算并找出每个句子最匹配的词:
target_words = ['king', 'castle', 'queen', 'monarch'] # 给每个目标词创建对应的相似度列 for word in target_words: df[word] = df['text'].apply(lambda x: calculate_topn_similarity(x, word, model, top_n=3)) # 找出每个句子最匹配的核心词 df['most_representative'] = df[target_words].idxmax(axis=1)
运行后你就能看到每个句子和4个核心词的匹配度,以及它最对应的类别啦。
二、更常用的替代方案:句子向量直接求相似度
其实还有一种更简洁的思路:先把整个句子转换成向量(用所有词向量的平均值),再和目标词的向量求余弦相似度,这样能更直接反映整个句子的语义和目标词的关联:
1. 编写句子向量与相似度计算函数
def get_sentence_vector(sentence_words, model): valid_vectors = [model.wv[word] for word in sentence_words if word in model.wv.key_to_index] if not valid_vectors: return np.zeros(model.vector_size) # 无有效词时返回全0向量 return np.mean(valid_vectors, axis=0) # 计算每个句子的向量 df['sentence_vector'] = df['text'].apply(lambda x: get_sentence_vector(x, model)) # 用余弦相似度计算句子向量与目标词向量的匹配度 from sklearn.metrics.pairwise import cosine_similarity for word in target_words: if word in model.wv.key_to_index: target_vec = model.wv[word].reshape(1, -1) df[f'{word}_vec_sim'] = df['sentence_vector'].apply(lambda x: cosine_similarity(x.reshape(1, -1), target_vec)[0][0]) else: df[f'{word}_vec_sim'] = 0.0 # 找出最匹配的核心词 df['most_representative_vec'] = df[[f'{word}_vec_sim' for word in target_words]].idxmax(axis=1).str.replace('_vec_sim', '')
这种方法的优势是不需要手动选TopN,避免了个别极端相似词的干扰,结果更稳定。
三、一些优化小建议
- 预处理要到位:除了转小写、去标点,还可以去掉停用词(比如the、on这类无意义的词),用
nltk的停用词库就能轻松实现,能大幅提升模型效果。 - 模型参数调整:如果你的数据量有1000条,可以把
vector_size调到150-300,window调到5-10,min_count设为2-5,过滤掉出现极少的冷门词。 - 处理OOV词:对于模型不认识的词(比如一些行业专属术语),可以用随机向量或者忽略,上面的函数已经处理了这种情况。
备注:内容来源于stack exchange,提问作者rafine




