前言

在自然语言处理(NLP)中,词向量是将文本转换为数值型数据的重要手段,也是后续进行文本分类、情感分析等任务的基础。今天我们将通过两个案例,系统地学习词向量转换的原理及实际应用,并在此基础上完成一个基于朴素贝叶斯的评论情感分类任务。

一、词向量转换基础:CountVectorizer

1.1 什么是词向量?

计算机无法直接理解文本,我们需要将文本转化为数字向量。词向量就是将文本中的词语映射为数值特征的一种表示方式。最基础的方法是词袋模型(Bag of Words),统计每个词在文档中出现的次数。

1.2 基础案例

from sklearn.feature_extraction.text import CountVectorizer

texts = ["dog cat fish", "dog cat cat", "fish bird", "bird"]

# 建立模型,ngram_range=(1,1) 表示只考虑单个词
cv = CountVectorizer(ngram_range=(1, 1))

# 训练模型
cv_fit = cv.fit_transform(texts)

# 打印词频矩阵(稀疏格式)
print(cv_fit)

# 打印词库
print(cv.get_feature_names_out())

# 打印每个句子的完整词向量
print(cv_fit.toarray())

运行结果解析

cv_fit 输出的是稀疏矩阵,只记录非零值的位置和数量,节省内存。

get_feature_names_out() 输出词库,例如:['bird', 'cat', 'dog', 'fish']

toarray() 转换为二维数组,每行对应一个句子,每列对应一个词,值为该词在句子中出现的次数。

句子birdcatdogfish
dog cat fish0111
dog cat cat0210
fish bird1001
bird1000

核心理解:CountVectorizer 将文本变成了计算机可识别的“词频矩阵”。

二、综合实战:评论情感分类

2.1 环境准备与数据读取

# -*- coding: utf-8 -*-
import pandas as pd
import jieba

cp_content = pd.read_table(r".\差评.txt", encoding='gbk')
yzpj_content = pd.read_table(r".\优质评价.txt", encoding='gbk')

注意中文编码问题,文件首行加 # -*- coding: utf-8 -*-,并根据文件实际编码指定 encoding(如 gbk、utf-8)。

2.2 中文分词(使用 jieba)

def segment_text(contents):
    segments = []
    for content in contents:
        results = jieba.lcut(content)
        if len(results) > 1:
            segments.append(results)
    return segments
  • jieba.lcut() 返回分词列表
  • 过滤掉长度为 1 的结果(通常是标点或单个无意义词)
  • 分词结果保存为 Excel,方便后续查看。

2.3 去除停用词

stopwords = pd.read_csv(r".\StopwordsCN.txt", encoding='utf-8', engine='python', index_col=False)

def drop_stopwords(contents, stopwords):
    segments_clean = []
    for content in contents:
        line_clean = [word for word in content if word not in stopwords]
        segments_clean.append(line_clean)
    return segments_clean

停用词表(StopwordsCN.txt)可从网上下载,包含“的、了、是”等常见无意义词,去除后可以减少噪声,提高分类准确率。

2.4 构建训练集并切分

cp_train = pd.DataFrame({'segments_clean': cp_fc_contents_clean_s, 'label': 1})
yzpj_train = pd.DataFrame({'segments_clean': yzpj_fc_content_clean_s, 'label': 0})
pj_train = pd.concat([cp_train, yzpj_train])

from sklearn.model_selection import train_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)
  • 标签定义:差评 = 1,优质评价 = 0
  • 训练集/测试集默认按 75% / 25% 切分

2.5 词向量转换(关键步骤)

# 将分词列表拼接成空格分隔的字符串
words = [' '.join(seg) for seg in x_train]

vec = CountVectorizer(max_features=4000, lowercase=False, ngram_range=(1, 3))
vec.fit(words)
x_train_vec = vec.transform(words)

参数解读:

  • max_features=4000:只保留出现频率最高的 4000 个词,防止维度爆炸
  • lowercase=False:中文无需小写转换
  • ngram_range=(1, 3):保留 1~3 个连续词的组合(如“不喜欢”、“非常不好”),能捕捉更多语义信息

2.6 朴素贝叶斯分类

from sklearn.naive_bayes import MultinomialNB

classifier = MultinomialNB(alpha=0.1)
classifier.fit(x_train_vec, y_train)
  • MultinomialNB 适用于多项式分布数据,适合文本分类
  • alpha=0.1 是平滑参数,防止概率为 0

2.7 模型评估

from sklearn import metrics

train_pr = classifier.predict(x_train_vec)
print(metrics.classification_report(y_train, train_pr))

test_words = [' '.join(seg) for seg in x_test]
test_pr = classifier.predict(vec.transform(test_words))
print(metrics.classification_report(y_test, test_pr))

输出包括精确率、召回率、F1-score,可以直观看到模型在训练集和测试集上的表现。

如果测试集准确率明显低于训练集,可能存在过拟合,可尝试减少特征数或增大训练数据。

2.8 预测新评论

s = "这个手机超好,我很喜欢"
s_seg = jieba.lcut(s)
s_clean = [w for w in s_seg if w not in stopwords]
s_vec = vec.transform([' '.join(s_clean)])
pred = classifier.predict(s_vec)
print("好评" if pred[0] == 0 else "差评")

最终可以判断该评论为 好评。

三、总结

模块技术点
词向量转换CountVectorizer 基本用法、ngram 参数
中文处理jieba 分词、停用词过滤
分类模型朴素贝叶斯(MultinomialNB)
数据预处理pandas 读取、DataFrame 操作
模型评估classification_report 详解

更多推荐