什么是词向量
在自然语言处理(Natural Language Processing,NLP)任务中,文本是最基础也是最核心的数据形式。然而,计算机并不能像人类一样直接理解文字的含义,它只能对数字进行计算和建模。因此,如何将文本信息转化为数值形式,成为机器学习处理文本数据的首要问题。
词向量(Word Embedding)正是在这一背景下提出的一种重要表示方法
主流词向量模型
一、词袋模型
词袋模型(Bag of Words)是最早也是最基础的文本向量化方法之一。该方法将文本看作词语的集合,仅统计每个词在文档中出现的次数,而不考虑词语的顺序和语义关系。在词袋模型中,每个文档可以表示为一个高维向量,向量的每一维对应词表中的一个词,其取值表示该词在文档中的出现频率。
词袋模型实现简单、计算效率高,但其缺点也较为明显:一方面向量维度较高且稀疏,另一方面无法刻画词语之间的语义相似性,因此在复杂语义任务中的表现有限。
Python 示例代码:
fromsklearn.feature_extraction.textimportCountVectorizer texts=["这家餐厅的菜很好吃","服务态度非常好","这家店的菜太难吃了"]vectorizer=CountVectorizer()X=vectorizer.fit_transform(texts)print("词表:",vectorizer.get_feature_names_out())print("向量表示:\n",X.toarray())二、TF-IDF 模型
TF-IDF(Term Frequency–Inverse Document Frequency)是一种在词袋模型基础上引入权重机制的文本表示方法。其核心思想是:一个词在当前文档中出现得越频繁,同时在整个语料库中出现得越少,则该词对文档的区分能力越强。
与传统词频统计相比,TF-IDF 能有效降低“的、了、是”等高频但区分度较低词语的权重,从而突出文本中的关键词信息。因此,TF-IDF 被广泛应用于文本分类、信息检索和情感分析等任务中。
Python 示例代码:
fromsklearn.feature_extraction.textimportTfidfVectorizer texts=["这家餐厅的菜很好吃","服务态度非常好","这家店的菜太难吃了"]tfidf=TfidfVectorizer()X=tfidf.fit_transform(texts)print("词表:",tfidf.get_feature_names_out())print("TF-IDF 向量:\n",X.toarray())TF-IDF 在保证模型简单性的同时,显著提升了文本特征的区分能力,是传统机器学习情感分析中最常用的向量化方法。
三、Word2Vec
Word2Vec 是一种基于神经网络的词向量模型,其核心思想是通过上下文信息学习词语的语义表示。与传统基于词频的表示方法不同,Word2Vec 能够将词语映射为低维、稠密的向量,并使语义相近的词在向量空间中距离更近。
Word2Vec 主要包含两种训练模型:CBOW(通过上下文预测中心词)和 Skip-gram(通过中心词预测上下文)。该模型在捕捉词语语义相似性方面表现突出,是现代自然语言处理的重要基础方法之一。
Python 示例代码(gensim):
fromgensim.modelsimportWord2Vec sentences=[["这家","餐厅","的","菜","很好吃"],["服务","态度","非常","好"],["这家","店","的","菜","太","难吃","了"]]model=Word2Vec(sentences,vector_size=100,window=5,min_count=1,workers=4)查看某个词的词向量
print(model.wv["好"])计算相似词
print(model.wv.most_similar("好"))四、GloVe
GloVe(Global Vectors for Word Representation)是一种结合全局词频统计信息的词向量模型。与 Word2Vec 侧重局部上下文不同,GloVe 利用整个语料库中词与词的共现关系进行建模,从而学习词语的向量表示。
在实际应用中,GloVe 常以预训练词向量的形式使用,能够在多种自然语言处理任务中取得稳定效果。
词向量转化的小例子
下面通过一个简单示例,演示如何使用 CountVectorizer 将文本转化为词袋向量表示。
fromsklearn.feature_extraction.textimportCountVectorizer texts=["dog cat fish","dog cat cat","fish bird",'bird']cont=[]#实例化一个模型cv=CountVectorizer(max_features=6,ngram_range=(1,3))#,统计每篇文章中每个词出现的频率次数#训练此模型cv_fit=cv.fit_transform(texts)#每个词在这篇文章中出现的次数print(cv_fit)# 打印出模型的全部词库print(cv.get_feature_names())#打印出每个语句的词向量print(cv_fit.toarray())# #打印出所有数据求和结果# print(cv_fit.toarray().sum(axis=0))#输出结果
- 示例数据说明
texts=["dog cat fish","dog cat cat","fish bird","bird"]该示例中包含 4 条英文文本,每条文本可以看作一条简单的“评论”或“文档”。
这些文本由少量词语组成,适合用于演示词袋模型的基本原理。
- CountVectorizer 的作用
cv=CountVectorizer(max_features=6,ngram_range=(1,3))CountVectorizer 是 scikit-learn 中用于构建**词袋模型(Bag of Words)**的工具,其核心功能是:
建立词表(Vocabulary)
统计每个词或词组在文档中出现的次数
将文本转换为数值向量
参数说明:
max_features=6
表示只保留词频最高的前 6 个特征(词或词组),用于控制向量维度,防止特征过多。
ngram_range=(1, 3)
表示同时考虑:
1-gram(单词,如 dog)
2-gram(连续两个词,如 dog cat)
3-gram(连续三个词,如 dog cat fish)
这使得模型不仅能捕捉单个词,还能捕捉局部的词序信息。
- 模型训练与文本转换
cv_fit=cv.fit_transform(texts)该语句完成了两个步骤:
fit:从所有文本中学习词表(统计词频并筛选特征)
transform:将每条文本转换为词频向量
返回的 cv_fit 是一个稀疏矩阵,用于高效存储高维文本特征。
- 查看稀疏矩阵结果
print(cv_fit)输出结果为稀疏矩阵格式,只显示非零元素的位置和值,表示:
行索引:文本编号
列索引:词表中特征的索引
值:该特征在文本中出现的次数
这种表示方式可以节省大量内存,适合大规模文本数据。
- 查看模型词表
print(cv.get_feature_names())该语句用于输出模型最终保留的所有特征,即词袋模型的词表。
由于设置了 ngram_range=(1,3),词表中不仅包含单个词,还可能包含多个连续词组成的短语。例如:
单词:dog、cat
二元词组:dog cat
三元词组:dog cat fish
- 查看每条文本的词向量表示
print(cv_fit.toarray())该语句将稀疏矩阵转换为普通的二维数组,方便观察。
每一行表示一条文本
每一列对应词表中的一个特征
数值表示该特征在对应文本中出现的次数
例如,如果某一列对应特征 cat,那么数值为 2 表示该文本中 cat 出现了两次。
项目案例
为了训练一个能够自动判断评论情感倾向(好评或差评)的模型,本文选取苏宁易购商品评论数据作为实验数据来源。相关评论数据通过网络爬虫方式获取,并根据情感极性分为优质评价(好评)和差评两类,为后续的文本向量化和模型训练提供数据基础。
1. 数据读取与初步整理
实验中分别使用两个文本文件存储不同情感类别的评论数据,其中:
优质评价.txt:存储正向情感评论(好评)
差评.txt:存储负向情感评论(差评)
使用 Pandas 对文本数据进行读取,代码如下:
importpandasaspd cp_content=pd.read_table(r".\差评.txt",encoding='gbk')yzpj_content=pd.read_table(r".\优质评价.txt",encoding='gbk')中文评论的分词处理(jieba)
在中文文本处理中,词语之间不存在天然的空格分隔,因此在进行词向量构建之前,必须先对评论文本进行分词操作。本文采用 jieba 分词库对苏宁易购评论数据进行分词处理。
jieba 提供了两种常用分词接口:
jieba.cut():返回生成器,适合大规模数据
jieba.lcut():直接返回列表,使用更加方便
本实验中采用 jieba.lcut() 方法。
差评文本分词
importjiebaimportpandasaspd cp_segments=[]提取差评文本内容
contents=cp_content['content'].values.tolist()对每条评论进行分词
fortextincontents:words=jieba.lcut(text)iflen(words)>1:# 过滤分词结果过短的评论cp_segments.append(words)将分词结果保存为 DataFrame
cp_fc_results=pd.DataFrame({'content':cp_segments})cp_fc_results.to_excel('cp_fc_results.xlsx',index=False)好评文本分词
yzpj_segments=[]提取好评文本内容
contents=yzpj_content['content'].values.tolist()fortextincontents:words=jieba.lcut(text)iflen(words)>1:yzpj_segments.append(words)保存分词结果
yzpj_fc_results=pd.DataFrame({'content':yzpj_segments})yzpj_fc_results.to_excel('yzpj_fc_results.xlsx',index=False)至此,好评与差评的分词结果已分别存储,为后续文本清洗和特征提取做好准备。
停用词去除
分词完成后,文本中仍然包含大量无实际语义价值的词语,如“的”“了”“是”等。这类词被称为停用词,若不加处理,会对模型训练产生干扰,因此需要将其移除。
导入停用词表
stopwords_df=pd.read_csv(r'./StopwordsCN.txt',encoding='utf8',engine='python')stopwords=stopwords_df['stopword'].values.tolist()定义去停用词函数
defremove_stopwords(texts,stopwords):cleaned_texts=[]fortextintexts:clean_words=[wordforwordintextifwordnotinstopwords]cleaned_texts.append(clean_words)returncleaned_texts差评去停用词
cp_contents=cp_fc_results['content'].values.tolist()cp_clean=remove_stopwords(cp_contents,stopwords)好评去停用词
yzpj_contents=yzpj_fc_results['content'].values.tolist()yzpj_clean=remove_stopwords(yzpj_contents,stopwords)基于朴素贝叶斯的情感分类模型
构建训练数据集
为实现监督学习,需要为评论数据添加情感标签:
差评:1
好评:0
cp_train=pd.DataFrame({'segments_clean':cp_clean,'label':1})yzpj_train=pd.DataFrame({'segments_clean':yzpj_clean,'label':0})pj_train=pd.concat([cp_train,yzpj_train],axis=0)pj_train.to_excel('pj_train.xlsx',index=False)划分训练集与测试集
fromsklearn.model_selectionimporttrain_test_split x_train,x_test,y_train,y_test=train_test_split(pj_train['segments_clean'].values,pj_train['label'].values,random_state=0)文本向量化(CountVectorizer)
由于 CountVectorizer 接受的是字符串形式输入,因此需要先将分词列表重新拼接成字符串。
train_texts=[' '.join(words)forwordsinx_train]fromsklearn.feature_extraction.textimportCountVectorizer vectorizer=CountVectorizer(max_features=4000,lowercase=False,ngram_range=(1,3))vectorizer.fit(train_texts)训练朴素贝叶斯模型
fromsklearn.naive_bayesimportMultinomialNBfromsklearnimportmetrics classifier=MultinomialNB(alpha=0.1)classifier.fit(vectorizer.transform(train_texts),y_train)训练集评估
train_pred=classifier.predict(vectorizer.transform(train_texts))print(metrics.classification_report(y_train,train_pred))测试集评估
test_texts=[' '.join(words)forwordsinx_test]test_pred=classifier.predict(vectorizer.transform(test_texts))print(metrics.classification_report(y_test,test_pred))模型交互测试
训练完成后,可以通过命令行输入文本,实时测试模型的情感预测效果。
whileTrue:text=input('请输入一段评价(输入 exit 退出):')iftext=='exit':breakwords=jieba.lcut(text)words_clean=[wforwinwordsifwnotinstopwords]text_vec=vectorizer.transform([' '.join(words_clean)])result=classifier.predict(text_vec)ifresult[0]==1:print("预测结果:差评")else:print("预测结果:优质评价")