3、文本预处理实战:中文分词(Jieba)、去停用词、词干提取与词形还原
好,咱们直接进入正题。文本预处理,说白了就是把那些乱七八糟的新闻文本,变成机器能理解的干净数据。这一步做不好,后面再牛的模型也是白搭。我刚开始做量化因子的时候,就吃过这个亏——数据没洗干净,回测曲线漂亮得不行,实盘一跑直接崩了。
今天咱们要搞定的,是中文文本预处理的四个核心步骤:分词、去停用词、词干提取、词形还原。其中分词和去停用词是中文特有的,词干提取和词形还原更多用在英文场景,但咱们做新闻情绪因子,偶尔也会碰到中英文混杂的情况,所以一并讲了。
3.1 中文分词:Jieba 实战
中文不像英文,词与词之间没有空格。所以第一步,就是把连续的汉字序列切分成有意义的词语。这个活儿,业内最常用的就是 Jieba 分词库。
我个人习惯用 Jieba 的精确模式,它最适合做文本分析。全模式虽然快,但会输出所有可能的词,冗余太多。搜索引擎模式更不用说了,那是给搜索引擎用的。
3.1.1 安装与基本使用
# 安装
pip install jieba
# 基本使用
import jieba
text = "今日A股市场迎来大幅上涨,北向资金净流入超过百亿元。"
seg_list = jieba.cut(text, cut_all=False) # 精确模式
print(" / ".join(seg_list))
# 输出:今日 / A股 / 市场 / 迎来 / 大幅 / 上涨 / , / 北向 / 资金 / 净流入 / 超过 / 百亿元 / 。
你看,Jieba 把「北向资金」切成了一个词,把「百亿元」也正确识别了。这背后是它的词典在起作用。但有些专业术语,比如「量化宽松」,默认词典可能没有,这时候就需要自定义词典。
3.1.2 自定义词典
# 加载自定义词典
jieba.load_userdict("finance_dict.txt")
# finance_dict.txt 内容示例:
# 量化宽松 5
# 逆回购 3
# 北向资金 5
# 降准 3
text = "央行宣布实施量化宽松政策,同时进行逆回购操作。"
seg_list = jieba.cut(text)
print(" / ".join(seg_list))
# 输出:央行 / 宣布 / 实施 / 量化宽松 / 政策 / , / 同时 / 进行 / 逆回购 / 操作 / 。
嗯,这里要注意:自定义词典的格式是「词语 词频 词性」。词频越高,Jieba 越倾向于把它当作一个词。我一般给金融术语设 3-5 的词频,够用了。
3.2 去停用词:把噪音扔掉
分词之后,你会发现有很多「的」「了」「是」「在」这类词。它们对情绪分析毫无贡献,反而会干扰模型。去停用词,就是把这些无意义的词过滤掉。
我建议准备两份停用词表:一份是通用的中文停用词表(网上很多),另一份是金融领域专用的。比如「报告」「公告」「显示」这类词,在新闻里频繁出现,但对情绪没有指示作用。
# 加载停用词表
stopwords = set()
with open("stopwords.txt", "r", encoding="utf-8") as f:
for line in f:
stopwords.add(line.strip())
# 去停用词
def remove_stopwords(words):
return [w for w in words if w not in stopwords and len(w) > 1]
text = "今日A股市场迎来大幅上涨,北向资金净流入超过百亿元。"
seg_list = jieba.cut(text)
filtered_words = remove_stopwords(seg_list)
print(filtered_words)
# 输出:['A股', '市场', '迎来', '大幅', '上涨', '北向', '资金', '净流入', '超过', '百亿元']
你看,「今日」「,」「。」都被去掉了。剩下的词,基本就是情绪分析的核心素材了。
3.3 词干提取与词形还原
这两个概念,主要针对英文。中文没有词形变化,所以一般用不到。但咱们做量化,新闻里经常夹杂英文术语,比如「earnings」「earned」「earning」,它们其实都是同一个词根「earn」。这时候就需要做词干提取或词形还原。
词干提取:简单粗暴,直接砍掉词缀。比如「running」变成「run」,「flies」变成「fli」。速度快,但结果可能不是合法单词。
词形还原:更智能,会考虑词性,还原成词典里的原形。比如「better」还原成「good」,「ran」还原成「run」。准确率高,但速度慢。
我个人建议:做新闻情绪因子,用 词形还原。因为情绪词典里都是原形词,比如「good」「bad」「increase」。如果你用词干提取,把「increased」变成「increas」,情绪词典就匹配不上了。
# 使用 NLTK 进行词形还原
from nltk.stem import WordNetLemmatizer
from nltk.corpus import wordnet
lemmatizer = WordNetLemmatizer()
# 需要指定词性,否则默认是名词
words = ["earnings", "earned", "earning", "increased", "increasing"]
for w in words:
# 先判断词性,这里简化处理
lemma = lemmatizer.lemmatize(w, pos='v') # 假设都是动词
print(f"{w} -> {lemma}")
# 输出:
# earnings -> earnings (名词,没变)
# earned -> earn
# earning -> earn
# increased -> increase
# increasing -> increase
3.4 完整预处理流程
好了,咱们把上面三步串起来,形成一个完整的预处理流水线。我画了一张流程图,方便你理解整个逻辑。
这个流程看起来简单,但实际项目中坑不少。我总结了一个表格,把常见问题和解决方案列出来,你直接拿去用。
| 步骤 | 常见问题 | 解决方案 |
|---|---|---|
| 中文分词 | 金融术语被错误切分 | 加载自定义金融词典,词频设为3-5 |
| 去停用词 | 误删否定词,导致情绪反转 | 停用词表中排除「不」「没」「无」等否定词 |
| 词形还原 | 英文术语匹配不上情绪词典 | 先判断词性,再选择是否还原 |
| 整体流程 | 处理速度慢,影响实盘 | 使用多进程并行处理,或预加载词典 |
好了,这一章的内容就到这里。下一章咱们会讲如何构建情绪词典,以及如何给新闻文本打情绪分。到时候我会分享一个我自己踩过的坑——情绪词典的权重设置,差点让我回测数据全废了。