在之前的 R 语言课程「R 语言文本分析」中,我介绍了使用词频统计进行情感分析的方法,也就是先对文本进行分词,根据情感词典统计积极、消极和中性词的词频进行分析。不过这种方法难以分析复杂的文本表述。
R 语言文本分析:https://rstata.duanshu.com/#/brief/course/bf37cf50eef04d38b43541cc52114c96
另外在课程「使用 R 语言调用百度大脑自然语言处理接口进行文本情感倾向分析」中,我又介绍了一种使用 API 接口进行文本情感分析的方法,不过这种方法需要付费,不够经济。
使用 R 语言调用百度大脑自然语言处理接口进行文本情感倾向分析: https://rstata.duanshu.com/#/brief/course/8c0ceabc989d4d2bb886862d256c7181
最近找到了一种新的方法,也就是借助一些预训练模型,这里我使用的是 finbert-tone-chinese 模型。
finbert-tone-chinese: https://hf-mirror.com/yiyanghkust/finbert-tone-chinese
该模型是基于 bert-base-chinese,使用大约 8000 份分析师报告文本进行训练得到,在测试集上的准确度为 0.88。
关于 bert-base-chinese 模型的使用,大家可以学习之前的课程:
名师讲堂|突破性创新与颠覆性创新:使用BERT和 SBERT 模型计算专利文本相似度(一):https://rstata.duanshu.com/#/brief/course/35f74d717a0b464ea103175adbb5d885
名师讲堂|突破性创新与颠覆性创新:使用BERT和 SBERT 模型计算专利文本相似度(二):https://rstata.duanshu.com/#/brief/course/b1e28818e8164cfda3430cc45fddaf91
类似上述课程,这里我们同样使用 R 语言运行这一模型。
附件中的“finbert-tone-chinese”文件夹就是该模型的文件。如果大家使用 Mac 电脑的话,可以使用下面的代码下载(注意是 shell 代码,不是 R 语言的。附件中有下载好的,不用再下载了):
brew 的安装在系列课程「R 语言数据科学」第一次课里面有介绍。
brew install git-lfs git lfs install git clone https://hf-mirror.com/yiyanghkust/finbert-tone-chinese
|
为了在 R 语言中调用,我们需要先使用 Python 编写一个函数:
# 下载模型(MAC 系统) # brew install git-lfs # git lfs install # git clone https:
from transformers import BertTokenizer, BertForSequenceClassification import torch import torch.nn.functional as F
def get_financial_sentiment_scores(text: str) -> dict: """ 输入一段中文金融文本,输出 FinBERT-Tone-Chinese 模型预测的三种情感(正面/负面/中性)得分
参数: text: str - 待分析的中文文本(建议为金融相关内容,如财报摘要、新闻标题、市场评论等)
返回: dict - 包含 "neutral"(中性得分)、"positive"(正面得分)、"negative"(负面得分)的字典, 得分范围为 [0,1],三者总和为 1 """ # 1. 定义模型名称(与 URL 对应)和情感标签映射 MODEL_NAME = "/Users/ac/Desktop/上市公司年报文本情感分析/finbert-tone-chinese/" SENTIMENT_LABELS = ["neutral", "positive", "negative"] # 模型输出顺序固定
try: # 2. 加载模型和分词器(首次调用会自动下载模型,后续复用本地文件) tokenizer = BertTokenizer.from_pretrained(MODEL_NAME) model = BertForSequenceClassification.from_pretrained(MODEL_NAME)
# 3. 文本预处理:将文本转换为模型可接受的张量格式 # truncation=True:超过模型最大长度(512)的文本截断 # padding=True:不足长度的文本补全 # return_tensors="pt":返回 PyTorch 张量 inputs = tokenizer( text, truncation=True, padding=True, max_length=512, return_tensors="pt" )
# 4. 模型推理(关闭梯度计算,提高效率) model.eval() # 切换为评估模式(避免训练时的随机 dropout) with torch.no_grad(): outputs = model(**inputs) # 传入预处理后的文本 logits = outputs.logits # 获取模型原始输出(未归一化的得分) probabilities = F.softmax(logits, dim=1) # 归一化,得到概率得分(总和为 1)
# 5. 结果转换:从张量提取数值,与情感标签对应 prob_values = probabilities.squeeze().tolist() # 去除多余维度,转为列表 sentiment_scores = dict(zip(SENTIMENT_LABELS, prob_values))
# 6. 保留 4 位小数(可选,提升可读性) sentiment_scores = {k: round(v, 4) for k, v in sentiment_scores.items()}
return sentiment_scores
except Exception as e: raise RuntimeError(f"情感分析失败:{str(e)}")
|
这个函数会输入一段中文金融文本,输出 FinBERT-Tone-Chinese 模型预测的三种情感(正面/负面/中性)得分。
然后回到 R 语言里面。首先加载相关 R 包,创建虚拟环境:
library(tidyverse) library(reticulate)
conda_create(envname = "bert2", python_version = "3.10")
use_condaenv("bert2")
requirements <- readLines("requirements.txt")
requirements <- grep("^[^#]", requirements, value = TRUE) requirements <- trimws(requirements) requirements <- requirements[requirements != ""]
requirements
conda_install(packages = requirements, envname = "bert2", python_version = "3.10", pip = T, pip_options = "--index-url https://pypi.tuna.tsinghua.edu.cn/simple")
|
然后就可以把 Python 的函数 source 成 R 语言的函数了:
使用示例:
get_financial_sentiment_scores(text = "公司2024年净利润同比增长50%,核心业务市场份额进一步扩大")
#> $neutral #> [1] 0.0005 #> #> $positive #> [1] 0.9992 #> #> $negative #> [1] 0.0003
get_financial_sentiment_scores(text = "此外宁德时代上半年实现出口约2GWh,同比增加200%+。")
#> $neutral #> [1] 0.0007 #> #> $positive #> [1] 0.9989 #> #> $negative #> [1] 0.0004
get_financial_sentiment_scores("公司因违规操作被监管处罚,预计本年度营收将减少20%")
#> $neutral #> [1] 0.0007 #> #> $positive #> [1] 0.0005 #> #> $negative #> [1] 0.9988
get_financial_sentiment_scores("央行今日发布2024年第二季度货币政策执行报告,详细阐述当前经济形势")
#> $neutral #> [1] 0.9934 #> #> $positive #> [1] 0.0048 #> #> $negative #> [1] 0.0018
|
如果是数据框,可以使用如此代码计算每段文本的情感得分:
tibble(text = c( "公司2024年净利润同比增长50%,核心业务市场份额进一步扩大", "此外宁德时代上半年实现出口约2GWh,同比增加200%+。", "公司因违规操作被监管处罚,预计本年度营收将减少20%", "央行今日发布2024年第二季度货币政策执行报告,详细阐述当前经济形势" )) -> df
df
df %>% mutate(res = map(text, get_financial_sentiment_scores)) -> df1
df1 %>% mutate(res = map(res, ~tibble(class = c("neutral", "positive", "negative"), value = unlist(.x)))) %>% unnest(res) %>% spread(class, value)
|
然后就可以进行其他分析了。
点击这里跳转到 RStata 短书平台获取附件:名师讲堂|R 语言中使用 finbert-tone-chinese 模型对上市公司年报文本进行情感分析
评论