第3章 社交媒体情绪挖掘:文本情感分析基础
好,咱们进入正题。社交媒体情绪挖掘,说白了就是从海量文本里把人的情绪「捞」出来。我刚开始做这个方向时,以为就是简单的「正面」「负面」二分类,后来发现——嗯,水很深。
你想想看,一条推文说「这股票涨得我心脏病要犯了」,到底是正面还是负面?情绪这东西,本身就带着语境和反讽。所以这一章,咱们把基础打牢。
3.1 文本情感分析的核心逻辑
情感分析本质上是个映射问题:把非结构化的文本,映射到情绪标签或情绪分数上。我个人习惯把它拆成三个层次:
- 文档级:整篇文章是正面还是负面?适合新闻、研报。
- 句子级:逐句判断情绪。适合短评、推文。
- 方面级:针对某个实体(比如某只股票)的情绪。这是最难也最有用的。
我在项目中遇到过一个问题:某只股票明明财报很好,但社交媒体情绪却持续走低。后来发现,是用户都在吐槽它的客服。你看,方面级分析才能抓到这种细节。
核心观点:情绪挖掘不是为了判断「好」或「坏」,而是为了捕捉「变化」和「异常」。市场波动往往发生在情绪拐点,而不是情绪极值。
3.2 基于词典的方法:简单但有效
词典方法,就是预先准备一个情绪词库,然后数文本里正面词和负面词的数量。听起来很土?但我在实盘回测中发现,某些场景下它比深度学习还稳。
3.2.1 常用情绪词典
| 词典名称 | 语言 | 词条数 | 特点 |
|---|---|---|---|
| LIWC | 英文 | ~6400 | 心理语言学分类,含情绪、认知、社会等维度 |
| Harvard IV-4 | 英文 | ~4200 | 通用情感词典,偏学术 |
| 知网Hownet | 中文 | ~9000 | 中文情感词+程度词,适合金融文本 |
| NTUSD | 中文 | ~11000 | 台湾大学构建,正面/负面词各半 |
我建议你手头至少备两套词典:一套通用型,一套金融专用型。通用型抓大情绪,专用型抓行业黑话。比如「割肉」「踏空」这种词,通用词典根本认不出来。
3.2.2 词典方法的计算流程
流程其实很简单,但细节决定成败。我踩过的坑,都写在注释里了。
def sentiment_score(text, pos_dict, neg_dict, intensifier_dict):
"""
基于词典的情感得分计算
text: 输入文本
pos_dict: 正面词集合
neg_dict: 负面词集合
intensifier_dict: 程度副词词典,如"非常"=1.5,"有点"=0.5
"""
# 分词(中文用jieba,英文用nltk)
words = segment(text)
score = 0.0
intensifier = 1.0 # 默认程度
for i, word in enumerate(words):
# 先检查程度词
if word in intensifier_dict:
intensifier = intensifier_dict[word]
continue
# 再检查情感词
if word in pos_dict:
score += 1.0 * intensifier
intensifier = 1.0 # 重置
elif word in neg_dict:
score -= 1.0 * intensifier
intensifier = 1.0
else:
# 检查否定词(比如"不"+"好")
if i > 0 and words[i-1] in negation_words:
score -= 1.0 * intensifier # 反转极性
intensifier = 1.0
return score
我曾经踩过的坑:忘记处理否定词。一条「不看好」的文本,词典方法直接判成正面,因为「看好」是正面词。后来我加了个滑动窗口否定检测,准确率从62%直接跳到78%。
3.3 机器学习情感分类:从规则到统计
词典方法有个硬伤:它不认识新词。比如「yyds」「芭比Q了」这种网络梗,词典里根本没有。这时候就需要机器学习出马了。
3.3.1 特征工程:文本怎么变成数字
机器学习不吃文本,只吃数字。所以第一步是把文本向量化。我常用的方法有三种:
- Bag of Words (BoW):统计每个词出现的次数。简单,但丢失了词序信息。
- TF-IDF:不仅看词频,还看这个词在整个语料中的稀有度。能过滤掉「的」「了」这种无意义词。
- Word2Vec / GloVe:词嵌入,把每个词映射到高维空间。能捕捉语义相似性。
我个人习惯在金融情感分析中用TF-IDF。为什么?因为金融文本里,稀有词往往携带更强的情绪信号。比如「暴雷」「熔断」这种词,出现一次就够你紧张半天了。
3.3.2 分类模型选型
别一上来就上BERT。我见过太多人拿大炮打蚊子。先试试这些:
| 模型 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 逻辑回归 | 可解释性强,训练快 | 无法处理非线性关系 | 基线模型,快速验证 |
| 朴素贝叶斯 | 对小样本友好 | 特征独立性假设太强 | 短文本(推文、标题) |
| XGBoost | 精度高,能处理缺失值 | 容易过拟合 | 中等规模数据(万级) |
| LSTM | 能捕捉上下文 | 训练慢,需要大量数据 | 长文本(研报、新闻) |
我的经验:先用逻辑回归跑一遍,看特征权重。如果某个词权重异常高(比如「利好」权重0.8),说明数据有偏。这时候别急着调模型,先回去看数据标注质量。
3.3.3 完整训练流程
下面是一个完整的训练pipeline。注意,我刻意省略了超参数调优,因为那部分咱们后面章节会细讲。
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split
# 假设你已经有了标注好的数据
# X: 文本列表, y: 标签 (0=负面, 1=中性, 2=正面)
# 构建pipeline
pipeline = Pipeline([
('tfidf', TfidfVectorizer(
max_features=5000, # 限制特征数,防止过拟合
ngram_range=(1, 2), # 考虑单个词和双词组合
stop_words='english' # 去掉停用词
)),
('clf', LogisticRegression(
C=1.0, # 正则化强度
class_weight='balanced' # 处理类别不平衡
))
])
# 训练
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
pipeline.fit(X_train, y_train)
# 评估
accuracy = pipeline.score(X_test, y_test)
print(f"测试集准确率: {accuracy:.3f}")
3.4 知识体系总览
说了这么多,咱们用一张图把整个逻辑串起来。这是我做课程时画的,你一看就明白。
3.5 避坑指南与实战建议
最后,分享几个我这些年攒下来的经验。不一定全对,但至少能让你少走弯路。
关于数据标注:别迷信众包平台。我试过让五个人标注同一批金融文本,一致性只有60%。后来改成「金融背景+情绪标注」双人复核,一致性才提到85%。
关于词典更新:社交媒体词汇迭代极快。我建议每个月跑一次词频统计,把新出现的高频词手动加入词典。比如2023年的「遥遥领先」,2024年的「硬控」,你不加进去就漏信号。
关于过拟合:机器学习模型在训练集上准确率99%,一到实盘就崩。为什么?因为训练数据里的情绪表达方式,和实盘数据不一样。解决办法:用时间序列交叉验证,而不是随机划分。
好了,这一章的内容就到这。文本情感分析是情绪挖掘的「眼睛」,眼睛不好使,后面所有预测都是空中楼阁。下一章咱们会聊如何把情绪信号转化成交易策略——那才是真正见真章的地方。
公众号:蓝海资料掘金营,微信deep3321