第1章:文本预处理——中文分词、去停用词与词性标注

各位同学,咱们今天聊聊文本预处理。说实话,很多做量化的人一上来就搞模型、跑策略,结果数据质量不过关,后面全白搭。我做了这么多年金融数据,最深的体会就是:预处理做得好,模型成功一半

文本预处理,说白了就是把那些乱七八糟的原始文本,变成机器能理解的干净语料。你想想看,一篇财经新闻里全是「的、了、是、在」这种词,对情绪分析有啥用?没用的。所以我们要做三件事:分词、去停用词、词性标注

1.1 中文分词:用jieba把句子切碎

中文和英文不一样。英文单词之间有空格的,中文没有。所以第一步就是分词。我个人习惯用 jieba,它速度快、准确率高,而且支持自定义词典。

为什么需要自定义词典?我在项目中遇到过一个问题:分析某只股票的新闻时,「格力电器」被分成了「格力」和「电器」,这显然不对。后来我加了一个自定义词典,把「格力电器」作为一个整体词,效果立马好了。

核心要点: jieba 支持三种分词模式——精确模式、全模式、搜索引擎模式。做情绪分析,用精确模式就够了。
import jieba

text = "今日A股市场情绪偏乐观,北向资金净流入超百亿。"
words = jieba.lcut(text)
print(words)
# 输出:['今日', 'A股', '市场', '情绪', '偏', '乐观', ',', '北向', '资金', '净流入', '超', '百亿', '。']

嗯,这里要注意:jieba.lcut() 返回的是列表,方便后续处理。如果你用 jieba.cut() 返回的是生成器,在大数据量时更省内存。

1.2 去停用词:扔掉那些没用的词

停用词是什么?就是那些高频但没啥实际意义的词,比如「的、了、是、在、有」。你想想看,一篇研报里出现100次「的」,对判断市场情绪有帮助吗?没有。

我建议准备一个停用词表。网上有很多现成的,比如哈工大停用词表、百度停用词表。但我个人习惯自己维护一个金融领域的停用词表,因为有些词在通用领域是停用词,但在金融领域是有意义的。

小技巧: 我一般会把停用词表存成 .txt 文件,每行一个词。加载时用 set() 存储,查询速度更快。
def load_stopwords(filepath):
    with open(filepath, 'r', encoding='utf-8') as f:
        stopwords = set([line.strip() for line in f])
    return stopwords

stopwords = load_stopwords('stopwords.txt')
clean_words = [w for w in words if w not in stopwords and len(w) > 1]
print(clean_words)
# 输出:['A股', '市场', '情绪', '偏', '乐观', '北向', '资金', '净流入', '百亿']

看到了吗?去掉了「今日」「,」「。」这些没用的东西,剩下的词才是我们真正关心的。

1.3 词性标注:给每个词打上标签

词性标注,就是告诉机器这个词是名词、动词还是形容词。为什么要做这个?因为不同词性对情绪的贡献不一样。比如「上涨」是动词,但「上涨趋势」里的「上涨」就是名词性的。搞混了会影响情绪打分。

jieba 自带词性标注功能,用 jieba.posseg 就行。

import jieba.posseg as pseg

text = "市场情绪明显回暖,投资者信心增强。"
words = pseg.lcut(text)
for word, flag in words:
    print(f"{word}: {flag}")
# 输出:
# 市场: n
# 情绪: n
# 明显: a
# 回暖: v
# 投资者: n
# 信心: n
# 增强: v

这里 n 表示名词,a 表示形容词,v 表示动词。我一般会保留形容词和动词,因为它们对情绪的指示性最强。名词嘛,有时候可以留着做上下文参考。

避坑指南: 我曾经在分析财报电话会议记录时,发现「预期」这个词被标成了名词,但它在「我们预期增长」里是动词。后来我加了一个金融领域词性修正规则,才解决了这个问题。所以,不要完全依赖默认词性标注,要根据业务场景做调整。

1.4 构建干净的文本语料库

好了,前面三步做完,我们就可以构建语料库了。说白了,就是把原始文本经过分词、去停用词、词性标注后,变成一个结构化的数据。

我个人习惯用 pandas 来管理语料库,每一行是一篇文档,每一列是处理后的结果。

import pandas as pd

def preprocess_text(text, stopwords):
    words = jieba.lcut(text)
    words = [w for w in words if w not in stopwords and len(w) > 1]
    return ' '.join(words)

# 假设我们有一个新闻列表
news_list = [
    "今日A股市场情绪偏乐观,北向资金净流入超百亿。",
    "市场出现恐慌性抛售,投资者情绪极度悲观。",
    "政策利好频出,市场信心逐步恢复。"
]

corpus = pd.DataFrame({
    'raw_text': news_list,
    'clean_text': [preprocess_text(t, stopwords) for t in news_list]
})

print(corpus)
# 输出:
#                        raw_text              clean_text
# 0  今日A股市场情绪偏乐观,北向资金净流入超百亿。  A股 市场 情绪 偏 乐观 北向 资金 净流入 百亿
# 1  市场出现恐慌性抛售,投资者情绪极度悲观。  市场 出现 恐慌性 抛售 投资者 情绪 极度 悲观
# 2  政策利好频出,市场信心逐步恢复。  政策 利好 频出 市场 信心 逐步 恢复

你看,原始文本和干净文本的差别一目了然。干净文本里全是关键词,没有废话。这就是我们后续做情绪分析的基础。

1.5 本章知识体系

为了让你更直观地理解整个流程,我画了一张图。这张图展示了从原始文本到干净语料库的完整路径。

文本预处理流程 原始文本 财经新闻/研报 中文分词 jieba.lcut() 去停用词 停用词表过滤 词性标注 jieba.posseg 构建干净语料库 pandas DataFrame 输入 中间结果 输出:可用于情绪分析的干净语料

这张图你看懂了吗?从左到右是主流程,从上到下是并行处理。分词和词性标注其实可以同时做,我习惯用 pseg 一步到位。

1.6 总结

文本预处理这件事,看起来简单,但坑不少。我总结几个关键点:

  • 分词要准:一定要加自定义词典,尤其是金融领域的专有名词
  • 停用词要狠:该删的删,但别把有意义的词删了
  • 词性要活用:不同词性对情绪的贡献不同,别一视同仁
  • 语料库要干净:最终输出的语料库,应该只有关键词,没有废话

好了,这一章就到这里。下一章我们聊聊如何从这些干净语料里提取情绪特征。记住,数据干净了,模型才有灵魂


公众号:蓝海资料掘金营,微信deep3321