AI 入门 30 天挑战 - Day 24 费曼学习法版 - 情感分析实战
🌟 完整项目和代码
本教程是 AI 入门 30 天挑战 系列的一部分!
- 💻 GitHub 仓库: https://github.com/Lee985-cmd/AI-30-Day-Challenge
- 📖 CSDN 专栏: https://blog.csdn.net/m0_67081842?type=blog
- ⭐ 欢迎 Star 支持!
Week 4 第三天:AI 如何读懂人心!
BERT 情感分析 + 股票论坛情绪监控!
每个概念都解释!每行代码都说明白!
预计时间:3-4 小时(含费曼输出练习)
📖 第 1 步:快速复习昨天的内容(30 分钟)
费曼输出 #0:考考你
合上教程,尝试回答:
□ GPT 的"自回归"是什么意思?用例子说明
□ 为什么 GPT 只能用 Masked Attention?
□ 温度系数 (temperature) 高低各有什么影响?
□ GPT 和 BERT 的核心区别是什么?
□ 如果用情感分析监控股民情绪,你会怎么设计?
⏰ 时间:25 分钟
如果能答出 80% 以上,我们开始今天的情感分析之旅!如果不够,花 5 分钟翻一下 Day23 的笔记。
🤔 第 2 步:情感分析到底是什么?(60 分钟)
说人话版本
想象你在看股票论坛:
场景 1:你看了一条评论
"这个公司业绩太好了,强烈推荐买入!"
你的反应:
→ 这是正面评价(利好)
→ 你可能也会想买
场景 2:又看到一条
"完了完了,股价要崩盘了,赶紧跑!"
你的反应:
→ 这是负面评价(利空)
→ 你可能会想卖
这就是情感分析!
- 输入:文字评论
- 输出:正面/负面(利好/利空)
- 应用:舆情监控、投资辅助
生活中的例子:察言观色
你和朋友聊天:
朋友笑着说:"太棒了!" → 开心(正面)
朋友皱着眉说:"真糟糕。" → 难过(负面)
情感分析就是教 AI"察言观色":
- 看用词("太棒了"vs"真糟糕")
- 看语气(感叹号、问号)
- 看上下文(前后文的意思)
然后判断:这是高兴还是生气?
是利好还是利空?
情感分析的层次
Level 1: 二元分类(最简单)
✓ 正面 vs 负面
✓ 利好 vs 利空
✓ 开心 vs 生气
Level 2: 多元分类
✓ 非常正面、正面、中性、负面、非常负面
✓ 5 星评分(1-5 星)
Level 3: 细粒度情感
✓ 对各个方面的评价
"这个手机屏幕很好,但电池不行"
→ 屏幕:正面
→ 电池:负面
Level 4: 复杂情感
✓ 喜忧参半
✓ 爱恨交织
✓ 期待又担心
🎯 费曼输出 #1:向小白解释情感分析
任务 1:创造多个比喻
场景 A:向小学生解释
用表情符号
正面 = 😊 笑脸
负面 = 😠 哭脸
AI 的工作:读文字 → 画表情
比如:
"今天好开心" → 😊
"气死我了" → 😠
"一般般" → 😐
场景 B:向股民解释
用看盘软件
红色 = 涨(利好)
绿色 = 跌(利空)
AI 的工作:读新闻 → 标颜色
比如:
"业绩大增" → 🔴 利好
"利润下滑" → 🟢 利空
"平稳发展" → ⚪ 中性
场景 C:向编辑解释
用审稿标记
红笔圈出好词 ✅
蓝笔圈出坏词 ❌
统计哪种多
比如:
"优秀、卓越、出色" → 好词多 → 正面
"糟糕、失败、垃圾" → 坏词多 → 负面
要求: 每个场景都要详细说明
⏰ 时间:20 分钟
💡 卡壳检查点
如果你在解释时卡住了:
□ 我说不清楚 AI 是怎么判断情感的
□ 我不知道如何解释"训练"的过程
□ 我只能说"AI 识别",但不能说明白怎么识别
这很正常! 标记下来,继续往下看,然后重新尝试解释!
提示:
- 训练 = 给 AI 看很多例子(带标签的评论)
- 学习 = AI 找规律(什么词对应什么情感)
- 预测 = 用学到的规律判断新评论
🔬 第 3 步:BERT 情感分析详解(70 分钟)
核心思想
传统方法(关键词匹配):
看到"好"→正面
看到"差"→负面
问题:
"这个产品不好" → 有"好"字 → 错判为正面❌
"这个产品不差" → 有"差"字 → 错判为负面❌
BERT 的方法(理解上下文):
看完整个句子再判断
"这个产品不好" → 否定句 → 负面✅
"这个产品不差" → 双重否定 → 正面✅
优势:
✓ 理解语境
✓ 处理否定
✓ 捕捉细微差别
完整代码实现
import torch
from transformers import BertTokenizer, BertForSequenceClassification
from transformers import Trainer, TrainingArguments
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
import numpy as np
import matplotlib.pyplot as plt
print("=" * 60)
print("📊 BERT 情感分析系统 - 股票评论监控")
print("=" * 60)
# ============================================================================
# 第一部分:准备数据
# ============================================================================
print("\n【1. 准备股票评论数据】")
# 示例数据(真实场景应该收集更多)
stock_comments = [
# 正面评论(标签 1)
("这个公司业绩太好了,强烈推荐买入!", 1),
("财报超预期,股价肯定要涨", 1),
("新产品很有竞争力,看好未来", 1),
("管理层很给力,战略清晰", 1),
("行业龙头,护城河深", 1),
("估值合理,值得长期持有", 1),
("技术领先,市场前景广阔", 1),
("盈利能力强劲,分红大方", 1),
("订单爆满,产能跟不上", 1),
("分析师上调目标价,信心十足", 1),
# 负面评论(标签 0)
("这个公司要完蛋了,赶紧跑!", 0),
("财报暴雷,利润大幅下滑", 0),
("产品没有竞争力,被淘汰了", 0),
("管理层乱来,战略不明", 0),
("行业衰退,前景堪忧", 0),
("估值太高,泡沫严重", 0),
("技术落后,被对手超越", 0),
("连年亏损,快要破产了", 0),
("订单稀少,产能过剩", 0),
("分析师下调评级,建议卖出", 0),
# 中性评论(标签 2)
("今天股价波动不大,正常", 2),
("消息面平静,观望为主", 2),
("业绩符合预期,无功无过", 2),
("市场反应平淡,没什么亮点", 2),
("维持原有评级,不做调整", 2),
]
print(f"✓ 数据集大小:{len(stock_comments)} 条评论")
# 统计各类别数量
from collections import Counter
labels = [label for _, label in stock_comments]
label_counts = Counter(labels)
print(f" - 正面评论:{label_counts[1]} 条")
print(f" - 负面评论:{label_counts[0]} 条")
print(f" - 中性评论:{label_counts[2]} 条")
# 分割训练集和测试集
train_data, test_data = train_test_split(stock_comments, test_size=0.3, random_state=42)
print(f"\n - 训练集:{len(train_data)} 条")
print(f" - 测试集:{len(test_data)} 条")
# ============================================================================
# 第二部分:加载预训练 BERT 模型
# ============================================================================
print("\n" + "=" * 60)
print("【2. 加载 BERT 模型】")
print("=" * 60)
print("正在加载中文 BERT 模型...")
print("提示:第一次会自动下载,请耐心等待")
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
model = BertForSequenceClassification.from_pretrained(
'bert-base-chinese',
num_labels=3 # 3 类:正面、负面、中性
)
print(f"✓ BERT 模型加载完成")
print(f" 隐藏层维度:{model.config.hidden_size}")
print(f" 分类类别数:{model.config.num_labels}")
# ============================================================================
# 第三部分:数据预处理
# ============================================================================
print("\n" + "=" * 60)
print("【3. 数据预处理】")
print("=" * 60)
def preprocess_data(data_list, tokenizer, max_length=128):
"""将文本转换为 BERT 可以接受的格式"""
encodings = []
labels = []
for text, label in data_list:
# 分词和编码
encoding = tokenizer.encode_plus(
text,
add_special_tokens=True, # 添加 [CLS] 和 [SEP]
max_length=max_length, # 最大长度
padding='max_length', # 填充到最大长度
truncation=True, # 截断超长文本
return_tensors='pt' # 返回 PyTorch tensor
)
encodings.append(encoding)
labels.append(label)
return encodings, labels
print("正在处理训练集...")
train_encodings, train_labels = preprocess_data(train_data, tokenizer)
print(f"✓ 训练集处理完成")
print(f" 输入形状:{train_encodings[0]['input_ids'].shape}")
print(f" 标签数量:{len(train_labels)}")
# ============================================================================
# 第四部分:创建 Dataset 类
# ============================================================================
print("\n" + "=" * 60)
print("【4. 创建 Dataset】")
print("=" * 60)
class StockCommentDataset(torch.utils.data.Dataset):
"""股票评论数据集"""
def __init__(self, encodings, labels):
self.encodings = encodings
self.labels = labels
def __getitem__(self, idx):
item = {key: val.squeeze(0) for key, val in self.encodings[idx].items()}
item['labels'] = torch.tensor(self.labels[idx])
return item
def __len__(self):
return len(self.labels)
train_dataset = StockCommentDataset(train_encodings, train_labels)
print(f"✓ Dataset 创建完成")
print(f" 样本数量:{len(train_dataset)}")
# ============================================================================
# 第五部分:定义评估函数
# ============================================================================
print("\n" + "=" * 60)
print("【5. 定义评估指标】")
print("=" * 60)
def compute_metrics(pred):
"""计算准确率等评估指标"""
labels = pred.label_ids
preds = pred.predictions.argmax(-1)
acc = accuracy_score(labels, preds)
return {
'accuracy': acc,
}
print("✓ 评估指标定义完成")
print(" - 准确率 (accuracy)")
# ============================================================================
# 第六部分:训练模型
# ============================================================================
print("\n" + "=" * 60)
print("【6. 训练模型】")
print("=" * 60)
training_args = TrainingArguments(
output_dir='./results',
num_train_epochs=3,
per_device_train_batch_size=8,
learning_rate=2e-5,
warmup_steps=10,
logging_dir='./logs',
logging_steps=10,
evaluation_strategy="epoch",
save_strategy="epoch",
load_best_model_at_end=True,
)
print("训练参数:")
print(f" - 训练轮数:{training_args.num_train_epochs}")
print(f" - 批次大小:{training_args.per_device_train_batch_size}")
print(f" - 学习率:{training_args.learning_rate}")
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
compute_metrics=compute_metrics,
)
print("\n开始训练...")
print("提示:由于数据量小,训练很快完成")
trainer.train()
print("\n✓ 模型训练完成")
# ============================================================================
# 第七部分:模型评估
# ============================================================================
print("\n" + "=" * 60)
print("【7. 模型评估】")
print("=" * 60)
# 处理测试集
test_encodings, test_labels = preprocess_data(test_data, tokenizer)
test_dataset = StockCommentDataset(test_encodings, test_labels)
print("在测试集上评估...")
eval_results = trainer.evaluate(test_dataset)
print(f"\n测试结果:")
print(f" - 准确率:{eval_results['eval_accuracy']:.2%}")
# ============================================================================
# 第八部分:实际预测
# ============================================================================
print("\n" + "=" * 60)
print("【8. 实际预测】")
print("=" * 60)
def predict_sentiment(comment_text, model, tokenizer):
"""预测单条评论的情感"""
# 编码
inputs = tokenizer.encode_plus(
comment_text,
add_special_tokens=True,
max_length=128,
padding='max_length',
truncation=True,
return_tensors='pt'
)
# 预测
with torch.no_grad():
outputs = model(**inputs)
predictions = torch.softmax(outputs.logits, dim=-1)
probs = predictions[0].numpy()
label = torch.argmax(predictions, dim=-1).item()
# 标签映射
label_map = {0: "负面", 1: "正面", 2: "中性"}
return label_map[label], probs[label]
# 测试一些新的评论
test_comments = [
"这家公司的前景非常好,值得投资",
"完了完了,股价要崩盘了",
"今天股价波动不大,正常震荡",
"业绩大幅增长,超出市场预期",
"产品销量下滑,面临激烈竞争",
]
print("\n实时预测结果:\n")
for comment in test_comments:
label, confidence = predict_sentiment(comment, model, tokenizer)
# 显示表情符号
if label == "正面":
emoji = "🟢"
elif label == "负面":
emoji = "🔴"
else:
emoji = "⚪"
print(f"{emoji} {comment}")
print(f" 情感:{label} (置信度:{confidence:.2%})")
print()
print("\n🎊 情感分析系统完成!")
print("=" * 60)
# ============================================================================
# 第九部分:可视化结果
# ============================================================================
print("\n" + "=" * 60)
print("【9. 可视化分析】")
print("=" * 60)
# 绘制混淆矩阵(如果有测试集预测结果)
try:
predictions_output = trainer.predict(test_dataset)
preds = predictions_output.predictions.argmax(-1)
cm = confusion_matrix(test_labels, preds)
plt.figure(figsize=(8, 6))
plt.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues)
plt.title('混淆矩阵')
plt.colorbar()
classes = ['负面', '正面', '中性']
tick_marks = np.arange(len(classes))
plt.xticks(tick_marks, classes)
plt.yticks(tick_marks, classes)
# 在每个格子中显示数值
thresh = cm.max() / 2.
for i in range(cm.shape[0]):
for j in range(cm.shape[1]):
plt.text(j, i, format(cm[i, j], 'd'),
horizontalalignment="center",
color="white" if cm[i, j] > thresh else "black")
plt.ylabel('真实标签')
plt.xlabel('预测标签')
plt.tight_layout()
plt.show()
except:
print("混淆矩阵生成失败(数据量太小),跳过此步骤")
print("\n💡 实际应用建议:")
print("""
使用场景推荐:
1. 股票论坛舆情监控:
✓ 实时抓取雪球、东方财富评论
✓ 自动判断情感倾向
✓ 发现情绪异常波动
✓ 辅助投资决策
2. 新闻媒体分析:
✓ 监控财经新闻情感
✓ 统计利好/利空消息比例
✓ 跟踪舆情变化趋势
✓ 提前发现风险
3. 智能客服质检:
✓ 分析用户反馈情感
✓ 发现不满意客户
✓ 及时介入处理
✓ 提升服务质量
4. 产品口碑监控:
✓ 收集电商评论
✓ 分析用户满意度
✓ 发现产品问题
✓ 改进产品质量
技术要点:
✓ 数据质量很重要
- 标注准确的训练数据
- 多样化的样本
- 平衡的类别分布
✓ 模型选择
- BERT: 效果好,速度慢
- DistilBERT: 速度快,效果略差
- RoBERTa: 效果更好,需要更多数据
✓ 阈值设置
- 高置信度才采纳
- 低置信度的转人工
- 平衡准确率和覆盖率
常见问题:
✗ 讽刺和反语识别不了
→ "真是太好了(其实是反话)"
→ 需要更复杂的模型
✗ 领域差异
→ 医疗、法律等专业领域
→ 需要领域特定的训练数据
✗ 多义词问题
→ "这个股票很火"(好)
→ "着火了"(坏)
→ 需要上下文理解
""")
print("\n🎉 情感分析实战完成!")
print("=" * 60)
按 Shift + Enter 运行!
🎯 费曼输出 #2:深入理解技术
任务 1:解释技术细节
思考题:
- BERT 为什么比关键词匹配好?
- 训练数据的质量对模型有什么影响?
- 如何处理中性评论的边界情况?
- 如果要扩展到 5 星评分,需要怎么改?
任务 2:设计监控系统
场景:你要帮股民建立一个舆情监控仪表板
要求:
- 设计数据源(从哪里抓取评论)
- 设计更新频率(多久分析一次)
- 设计告警机制(什么情况触发警报)
- 设计可视化界面(如何展示结果)
⏰ 时间:30 分钟
💡 卡壳检查点
- 我解释不清 BERT 的优势在哪里
- 我说不明白训练数据的重要性
- 我不能设计实际的监控系统
提示:
- BERT = 理解上下文,不是死记关键词
- 数据 = 模型的基础,垃圾进垃圾出
- 中性 = 介于正负之间,最难判断
💻 第 4 步:实战项目(80 分钟)
项目:雪球论坛情感监控系统
"""
项目背景:
雪球是中国最大的投资者社区
每天有数百万条评论
用 AI 实时监控情绪变化
发现投资机会和风险
功能:
1. 实时抓取热门股票评论
2. 自动分析情感倾向
3. 统计多空比例
4. 发现情绪拐点
"""
import time
from datetime import datetime
print("=" * 60)
print("📈 雪球论坛情感监控系统")
print("=" * 60)
# 模拟实时数据流
mock_comments_stream = [
("贵州茅台", "茅台的业绩太稳了,长期持有没问题", 1),
("贵州茅台", "估值太高了,随时可能回调", 0),
("贵州茅台", "今天股价波动不大,正常", 2),
("宁德时代", "新能源前景广阔,坚定看好", 1),
("宁德时代", "竞争太激烈,利润会被压缩", 0),
("比亚迪", "销量创新高,股价要起飞", 1),
("比亚迪", "补贴退坡,影响很大", 0),
("腾讯控股", "游戏业务回暖,推荐买入", 1),
("腾讯控股", "政策监管风险大,谨慎", 0),
("阿里巴巴", "组织架构调整,观望", 2),
]
# 情感统计
sentiment_stats = {
'positive': 0,
'negative': 0,
'neutral': 0,
}
print("\n开始实时监控...\n")
for stock, comment, sentiment in mock_comments_stream:
# 模拟处理延迟
time.sleep(0.5)
# 更新统计
if sentiment == 1:
sentiment_stats['positive'] += 1
emoji = "🟢"
label = "正面"
elif sentiment == 0:
sentiment_stats['negative'] += 1
emoji = "🔴"
label = "负面"
else:
sentiment_stats['neutral'] += 1
emoji = "⚪"
label = "中性"
# 计算比例
total = sum(sentiment_stats.values())
positive_ratio = sentiment_stats['positive'] / total * 100
negative_ratio = sentiment_stats['negative'] / total * 100
# 显示结果
timestamp = datetime.now().strftime("%H:%M:%S")
print(f"[{timestamp}] {emoji} {stock}: {comment}")
print(f" 情感:{label}")
print(f" 多空比:🟢{positive_ratio:.1f}% : 🔴{negative_ratio:.1f}%")
print()
# 检测情绪异常
if total >= 5:
if positive_ratio > 80:
print(" ⚠️ 警报:过度乐观,注意风险!")
elif negative_ratio > 80:
print(" ⚠️ 警报:过度悲观,可能是机会!")
print()
# 最终统计
print("\n" + "=" * 60)
print("最终统计结果:")
print("=" * 60)
print(f"总评论数:{total} 条")
print(f"正面:{sentiment_stats['positive']} 条 ({positive_ratio:.1f}%)")
print(f"负面:{sentiment_stats['negative']} 条 ({negative_ratio:.1f}%)")
print(f"中性:{sentiment_stats['neutral']} 条 ({sentiment_stats['neutral']/total*100:.1f}%)")
if positive_ratio > negative_ratio:
print(f"\n整体情绪:🟢 偏向乐观")
elif negative_ratio > positive_ratio:
print(f"\n整体情绪:🔴 偏向悲观")
else:
print(f"\n整体情绪:⚪ 中性")
print("\n💡 使用建议:")
print(" 1. 结合技术指标一起看")
print(" 2. 不要盲目跟风")
print(" 3. 警惕过度一致的情绪")
print(" 4. 逆向思维:别人贪婪我恐惧")
print("\n🎊 监控系统演示完成!")
print("=" * 60)
🎉 今日费曼总结(30 分钟)⭐
完整的费曼学习流程
第 1 步:回顾今天的内容(5 分钟)
- 情感分析的基本概念
- BERT 情感分类原理
- 股票评论监控系统
第 2 步:合上教程,尝试完整教授(15 分钟)⭐
任务:假装你在给一个完全不懂的人上第二十四堂课
要覆盖:
- 情感分析是怎么工作的(用至少 2 个比喻)
- BERT 相比传统方法的优势
- 演示舆情监控系统
- 讲解实际应用价值
方式:写一篇 800 字左右的文章,或录一段 10-15 分钟的视频
第 3 步:标记卡壳点(5 分钟)
我今天卡壳的地方: □ _________________________________ □ _________________________________
第 4 步:针对性复习(5 分钟)
回到教程中卡壳的地方,重新学习,然后再次尝试解释!
📝 费曼学习笔记模板
╔═══════════════════════════════════════════════════╗
║ Day 24 费曼学习笔记 ║
╠═══════════════════════════════════════════════════╣
║ 日期:__________ ║
║ 学习时长:__________ ║
╠═══════════════════════════════════════════════════╣
║ ║
║ 1. 我向小白解释了: ║
║ _______________________________________________ ║
║ ║
║ 2. 我卡壳的地方: ║
║ □ _____________________________________________ ║
║ ║
║ 3. 我的通俗比喻: ║
║ • 情感分析就像 ______ ║
║ • BERT 理解上下文就像 ______ ║
║ • 舆情监控就像 ______ ║
║ ║
╚═══════════════════════════════════════════════════╝
📊 今日总结
✅ 你今天学到了:
-
情感分析基础
- 二元/多元分类
- 细粒度情感
- 复杂情感处理
-
BERT 情感分类
- 上下文理解
- 预训练 + 微调
- 评估指标
-
实战应用
- 股票评论分析
- 舆情监控
- 情绪预警
-
费曼输出能力 ⭐
- 能用比喻解释情感分析
- 能向小白说明 BERT 优势
- 能完整讲解监控系统
🎁 明日预告
明天你将学习:强化学习入门
内容:
- Q-learning 基础
- DQN 算法
- 实战:股票交易策略
- 应用:AI 自动炒股
准备好让 AI 学会自主决策了吗?继续前进!🚀
🔗 相关链接
🌐 项目资源
- 💻 GitHub 仓库: https://github.com/Lee985-cmd/AI-30-Day-Challenge
- 📖 CSDN 专栏: https://blog.csdn.net/m0_67081842?type=blog
- ⭐ 如果觉得有帮助,请给 GitHub 仓库 Star 支持!
本教程属于 AI 入门 30 天挑战 系列
🎉 恭喜你完成今天的学习!
🔗 资源汇总
- 📘 完整 30 天教程:CSDN 专栏 - AI 入门 30 天挑战
- 💻 完整代码 + 项目实战:GitHub 仓库 ⭐欢迎 Star
- ❓ 遇到问题:GitHub Issues 提问
💬 互动时间
思考题:今天的知识点中,哪个让你印象最深刻?为什么?
欢迎在评论区分享你的想法或疑问!👇
❤️ 如果有帮助
- 👍 点赞:让更多人看到这篇教程
- ⭐ Star GitHub:获取完整代码和项目
- ➕ 关注专栏:不错过后续更新
- 🔄 分享给朋友:一起学习进步
明天见!继续 Day 25 的学习~ 🚀
💡 学习建议
如果本篇教程对你有帮助,欢迎:
- Star GitHub 项目:https://github.com/Lee985-cmd/AI-30Days-Challenge
- 留言交流你的学习困惑
一起学习,一起进步! 🤝
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)