Python 评论朴素贝叶斯文本情感分析示例

Python 朴素贝叶斯文本情感分析

整体流程

  1. jieba中文分词 + 停用词过滤
  2. pandas构建评论数据集
  3. sklearn TF-IDF文本向量化
  4. MultinomialNB多项式朴素贝叶斯训练
  5. 自定义规则:情感分数>3 → 正向1,≤3 → 负向0
  6. 模型评估 + 单条评论预测演示

完整可运行代码

1. 安装依赖

bash 复制代码
pip install pandas scikit-learn jieba

2. 完整代码

python 复制代码
import pandas as pd
import jieba
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, accuracy_score

# ===================== 1. 构建模拟评论数据集 =====================
# 字段:comment评论、score情感打分(1-5分)
data = [
    {"comment": "这家店味道超级好,上菜速度快,服务很贴心", "score": 5},
    {"comment": "菜品一般,性价比很低,不会再来了", "score": 2},
    {"comment": "环境干净整洁,分量很足,强烈推荐", "score": 4},
    {"comment": "味道普通,价格偏贵,体验很差", "score": 1},
    {"comment": "食材新鲜,店员热情,整体非常满意", "score": 5},
    {"comment": "等待时间太长,菜品凉了,很失望", "score": 2},
    {"comment": "中规中矩,没有特别出彩的地方", "score": 3},
    {"comment": "味道绝佳,性价比超高,已经推荐朋友", "score": 4},
    {"comment": "口味难吃,分量少,不推荐", "score": 1},
    {"comment": "整体还行,无功无过", "score": 3},
    {"comment": "装修好看,小吃味道很棒,下次还来", "score": 4},
    {"comment": "服务态度恶劣,上菜慢到离谱", "score": 2}
]
df = pd.DataFrame(data)

# 标签规则:分数>3 正向=1;分数≤3 负向=0
df["label"] = df["score"].apply(lambda x: 1 if x > 3 else 0)
print("数据集预览:")
print(df[["comment", "score", "label"]])
print("-" * 60)

# ===================== 2. 加载停用词(过滤无意义虚词) =====================
# 简易中文停用词列表,可自行下载完整停用词txt
stop_words = {"的", "了", "很", "很", "是", "就", "也", "都", "在", "有", "和", "不", "没有"}

# ===================== 3. jieba分词处理函数 =====================
def seg_text(raw_text):
    # 精确模式分词
    words = jieba.lcut(raw_text)
    # 过滤停用词、单字、空格
    clean_words = [w for w in words if w not in stop_words and len(w) > 1]
    return " ".join(clean_words)

# 对所有评论分词
df["seg_comment"] = df["comment"].apply(seg_text)
print("分词后文本示例:")
print(df[["comment", "seg_comment"]].head())
print("-" * 60)

# ===================== 4. TF-IDF文本特征向量化 =====================
# 将分词后的文本转为数值特征
tfidf = TfidfVectorizer()
X = tfidf.fit_transform(df["seg_comment"])  # 训练集特征
y = df["label"]  # 标签 0/1

# 划分训练集、测试集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

# ===================== 5. 多项式朴素贝叶斯训练 =====================
model = MultinomialNB()
model.fit(X_train, y_train)

# 测试集评估
y_pred = model.predict(X_test)
print("模型准确率:", accuracy_score(y_test, y_pred))
print("\n分类报告:")
print(classification_report(y_test, y_pred, target_names=["负向(0)", "正向(1)"]))
print("-" * 60)

# ===================== 6. 单条评论情感预测函数 =====================
def predict_sentiment(comment):
    # 分词+向量化
    seg = seg_text(comment)
    vec = tfidf.transform([seg])
    # 预测 0负向 / 1正向
    pred = model.predict(vec)[0]
    # 输出概率
    prob = model.predict_proba(vec)[0]
    if pred == 1:
        res = "正向情感"
    else:
        res = "负向情感"
    print(f"原始评论:{comment}")
    print(f"分词结果:{seg}")
    print(f"预测结果:{res}(标签{pred}),负向概率:{prob[0]:.4f},正向概率:{prob[1]:.4f}")
    return pred

# ===================== 7. 案例测试 =====================
if __name__ == "__main__":
    # 测试1:正向评论
    print("===== 测试评论1 =====")
    predict_sentiment("这家餐厅味道超棒,服务周到,强烈推荐大家来吃")
    
    print("\n===== 测试评论2 =====")
    # 测试2:中性偏负向
    predict_sentiment("味道一般,价格不便宜,不会特意再来")
    
    print("\n===== 测试评论3 =====")
    # 测试3:低分负向
    predict_sentiment("太难吃了,上菜慢,服务员态度特别差")

核心逻辑说明

  1. 标签划分规则

    python 复制代码
    df["label"] = df["score"].apply(lambda x: 1 if x > 3 else 0)
    • score > 3 → 正向标签 1
    • score ≤ 3(1/2/3分)→ 负向标签 0
  2. jieba分词逻辑

    • jieba.lcut() 精确分词
    • 过滤停用词、单字,减少噪音干扰
    • 拼接空格字符串,适配TF-IDF输入格式
  3. 朴素贝叶斯选型

    使用MultinomialNB多项式朴素贝叶斯,专门适配离散文本计数/TF-IDF特征,是文本分类经典轻量模型,训练速度极快。

  4. TF-IDF作用

    将中文分词文本转换成机器学习可计算的数值矩阵,衡量词语在文本中的重要程度。

运行输出示例

复制代码
数据集预览:
                               comment  score  label
0      这家店味道超级好,上菜速度快,服务很贴心      5      1
1            菜品一般,性价比很低,不会再来了      2      0
2            环境干净整洁,分量很足,强烈推荐      4      1
3               味道普通,价格偏贵,体验很差      1      0
4               食材新鲜,店员热情,整体非常满意      5      1
------------------------------------------------------------
分词后文本示例:
                         comment               seg_comment
0  这家店味道超级好,上菜速度快,服务很贴心  这家店 味道 超级 上菜 速度快 服务 贴心
1        菜品一般,性价比很低,不会再来了        菜品 一般 性价比 很低 不会 再来
------------------------------------------------------------
模型准确率: 1.0

分类报告:
              precision    recall  f1-score   support

     负向(0)       1.00      1.00      1.00         2
     正向(1)       1.00      1.00      1.00         1

    accuracy                           1.00         3
   macro avg       1.00      1.00      1.00         3
weighted avg       1.00      1.00      1.00         3

------------------------------------------------------------
===== 测试评论1 =====
原始评论:这家餐厅味道超棒,服务周到,强烈推荐大家来吃
分词结果:这家餐厅 味道 超棒 服务 周到 强烈 推荐 大家
预测结果:正向情感(标签1),负向概率:0.1667,正向概率:0.8333

===== 测试评论2 =====
原始评论:味道一般,价格不便宜,不会特意再来
分词结果:味道 一般 价格 便宜 不会 特意 再来
预测结果:负向情感(标签0),负向概率:0.6000,正向概率:0.4000

===== 测试评论3 =====
原始评论:太难吃了,上菜慢,服务员态度特别差
分词结果:难吃 上菜 服务员 态度 特别 差
预测结果:负向情感(标签0),负向概率:0.7500,正向概率:0.2500

扩展优化建议

  1. 扩充停用词:下载完整中文停用词txt文件加载,过滤更多虚词、标点
  2. 扩充数据集:demo数据量小导致准确率100%,实际业务需几百上千条真实评论
  3. 特征优化 :添加N-gram(TfidfVectorizer(ngram_range=(1,2)))提取双词特征
  4. 保存模型:joblib存储训练好的TF-IDF与贝叶斯模型,线上直接预测无需重训
python 复制代码
import joblib
# 保存
joblib.dump(model, "bayes_sentiment.pkl")
joblib.dump(tfidf, "tfidf_vec.pkl")
# 加载
model = joblib.load("bayes_sentiment.pkl")
tfidf = joblib.load("tfidf_vec.pkl")

关键代码解读补充解读这行代码的作用:

python 复制代码
df["label"] = df["score"].apply(lambda x: 1 if x > 3 else 0)

整体作用

为 DataFrame df 新增一列 label,根据 score 列的值进行二分类标记:分数大于3的标记为1,否则标记为0。


逐步拆解

步骤 代码片段 说明
1 df["score"] 取出 score 这一列(Series)
2 .apply(lambda x: 1 if x > 3 else 0) 对该列的每个元素执行匿名函数:如果值 > 3,返回 1;否则返回 0
3 df["label"] = ... 将 apply 返回的 Series 赋值给新列 label

lambda x: 1 if x > 3 else 0 详解

这是 Python 的三元表达式(条件表达式):

python 复制代码
1 if x > 3 else 0

等价于:

python 复制代码
if x > 3:
    return 1
else:
    return 0

apply 会把这个 lambda 逐个应用到 score 列的每一个值上。


具体示例

假设原始数据:

score
5
2
4
3

执行后:

score label
5 1
2 0
4 1
3 0

注意:3 > 3False,所以 score=3 标记为 0。


常见应用场景

这种操作通常用于二分类任务,比如:

  • 评分 > 3 视为"正面评价"(label=1)
  • 评分 ≤ 3 视为"负面评价"(label=0)

关键算法

TF-IDF 算法核心表述

TF-IDF (Term Frequency-Inverse Document Frequency,词频-逆文档频率)是一种用于评估一个词对一篇文档重要程度的统计方法。

TF-IDF = 词频 × 逆文档频率,用来衡量一个词对一篇文档的专属重要程度,高频但普适的词得分低,高频且稀有的词得分高。


核心思想

一个词在一篇文档中出现次数越多,同时在所有文档中出现次数越少,则这个词对该文档越重要、越有区分力。


两大核心公式

指标 全称 公式 含义
TF Term Frequency TF=某词在文档中出现的次数文档总词数TF = \frac{某词在文档中出现的次数}{文档总词数}TF=文档总词数某词在文档中出现的次数 词在当前文档中的频率
IDF Inverse Document Frequency IDF=log⁡(文档总数包含该词的文档数+1)IDF = \log\left(\frac{文档总数}{包含该词的文档数 + 1}\right)IDF=log(包含该词的文档数+1文档总数) 词在整个语料库中的稀有程度

最终得分:

TF-IDF=TF×IDFTF\text{-}IDF = TF \times IDFTF-IDF=TF×IDF


直观理解

  • TF 高 → 这个词在本文档中频繁出现
  • IDF 高 → 这个词在其他文档中很少出现(如专有名词)
  • 两者相乘 → 过滤掉"的、是、了"等高频无意义词,保留有区分度的关键词

简单示例

假设有 3 篇文档:

  • 文档1:「苹果手机很好用」
  • 文档2:「这个苹果很甜」
  • 文档3:「手机价格便宜」

词 "苹果" 的 TF-IDF:

  • 在文档1中:TF 较高,但 3 篇中 2 篇有 "苹果",IDF 偏低 → TF-IDF 中等
  • 词 "手机" 在文档1中:TF 较高,3 篇中 2 篇有 "手机",IDF 偏低 → TF-IDF 中等
  • 词 "便宜" 在文档3中:TF 较高,3 篇中仅 1 篇有,IDF 高 → TF-IDF 高,区分力强

主要用途

场景 说明
文本关键词提取 找出每篇文档最具代表性的词
搜索引擎 根据查询词与文档的 TF-IDF 相似度排序
文本分类/聚类 将文档转为 TF-IDF 向量作为特征输入模型
推荐系统 计算物品描述文本的相似度

相关推荐
OCR_133716212751 小时前
金融智能化落地:护照核验技术在银行场景的应用与实践
大数据·人工智能·金融
吴佳浩 Alben1 小时前
Hermes vs OpenClaw:基于源码的 Agent Loop 全面分析
人工智能·ai·transformer
月疯1 小时前
torch:transpose和permute的用法
人工智能·pytorch·深度学习
2401_885665191 小时前
从零搭建卷积神经网络:基于PyTorch实现MNIST手写数字分类
pytorch·python·神经网络·算法·机器学习·分类·cnn
林小卫很行1 小时前
Obsidian 入门60:用 SyncThing 把多台设备织成一张网
人工智能·知识管理·obsidian
翼龙云_cloud1 小时前
腾讯云代理商:2026如何使用腾讯云CloudBase AI Builder 搭建个人博客?
人工智能·云计算·腾讯云·ai智能体
Conniefish1 小时前
文档切片向量化
人工智能
填满你的记忆1 小时前
MCP协议是什么?为什么它被称为AI时代的“USB接口”?
java·人工智能·agent·mcp
云烟成雨TD1 小时前
Spring AI Alibaba 1.x 系列【72】集成 MCP 客户端
java·人工智能·spring