原文链接:https://tecdat.cn/?p=41149
原文出处:拓端数据部落公众号

分析师:Zhenzhen Liu,Shuai Fung

作为数据科学家,我们始终关注如何从非结构化数据中提取高价值信息。本专题合集聚焦企业年报的文本分析技术,通过Python与R语言实战案例,系统展示如何利用自然语言处理(NLP)技术量化企业年报的情感倾向。以10家上市银行2010-2022年的130份年报为研究对象,我们构建了包含停用词过滤、情感词典匹配、LSTM神经网络分类等完整技术链路,最终生成可量化的乐观指标矩阵。
本专题合集的核心价值在于突破传统财务分析的局限性。当企业未披露数字化转型等非结构化指标时,文本挖掘技术可通过词频统计、语义网络分析等方法揭示深层信息。例如,通过分析"数字""智能"等关键词的出现频次与情感关联度,能够客观评估企业的技术投入态度。这种跨学科研究不仅为投资决策提供新维度,更为监管机构识别市场情绪波动提供技术支持。
专题合集包含4大技术模块:中文分词与情感计算、LSTM神经网络在社交媒体情感分析中的应用、R语言古典文本挖掘实战、汽车口碑数据采集词云可视化。特别值得关注的是LSTM模型在微博评论数据集上的迁移学习实践。而《红楼梦》文本挖掘案例则展示了如何通过词云可视化与t检验分析,验证不同章节的作者风格差异。
本专题合集已分享在交流社群,阅读原文进群和500+行业人士共同交流和成长。数据科学的魅力在于连接技术与商业场景,我们期待与您共同探索文本数据中的商业密码。

企业年报语调分析:以上市银行为例

在当今的商业世界中,企业年报是了解企业经营状况和未来发展前景的重要窗口。然而,年报中的文字信息往往蕴含着丰富的情感和态度,这些信息对于投资者、分析师和监管者来说都具有重要的参考价值。传统的财务指标分析往往难以捕捉到这些非量化的信息,因此,文本分析技术应运而生。

故事的起源

在金融市场中,上市银行的年报是投资者关注的焦点之一。从2010年到2022年,这13年的时间里,金融市场风云变幻,上市银行面临着各种挑战和机遇。我们想要了解这些银行在不同年份的年报中所传达出的语气和态度,以此来洞察银行的经营信心和市场预期。但是,银行年报往往篇幅巨大,人工分析不仅耗时耗力,而且容易出现主观偏差。于是,我们决定借助Python编程语言,利用文本分析技术来完成这项任务。

准备工作

要进行年报语气评分,首先得有年报数据。我们把目标锁定在了巨潮资讯网,这是一个权威的上市公司信息披露平台。我们要模拟点击的方式,下载10家上市银行2010 - 2022年的年报,然后将这些年报转换为txt格式,这样就能方便后续的文本处理了。经过一番操作,我们一共得到了130个文本文件。
接下来,我们需要设置停用词表和情感词表。停用词是指在文本中频繁出现但没有实际意义的词语,比如“的”“是”“在”等,去除这些停用词可以提高文本分析的准确性。情感词表则分为积极情感词表和消极情感词表,用于判断文本中的积极和消极情感。
下面是读取词表文件的代码:

def read\_file(file\_path):
 # 以只读模式打开文件,使用utf-8编码
 with open(file_path, 'r', encoding='utf-8') as file:
 # 读取文件的所有行
 content = file.readlines()
 # 去除每行末尾的换行符
 content = \[line.strip() for line in content\]
 # 替换特殊字符
 content = \[line.replace('"', '') for line in content\]
 return content
# 读取停用词文件
stopwords = read_file(r'E:\\python\\14weekpython\\stopwords.txt')
print(stopwords)
# 读取积极情感词典文件
posdict = read_file(r'E:\\python\\14weekpython\\posdict.txt')
# 读取消极情感词典文件
negdict = read_file(r'E:\\python\\14weekpython\\negdict.txt')

分词与情感分析

有了年报数据和词表,接下来就是对年报进行分词和情感分析了。我们使用jieba库对文本进行分词,然后过滤掉停用词。

import jieba
import re
# 对文本进行分词并过滤停用词
def segment(text):
 seg_list = jieba.cut(text)
 filtered\_words = \[word for word in seg\_list if word not in stopwords\]
 return filtered_words

分词完成后,我们要统计年报中积极和消极语调的数量。具体来说,我们会计算积极语调、消极语调、积极词汇数量、消极词汇数量、段落总词数、停用词数量和总句数量。

# 计算积极语调、消极语调、积极词汇数量、消极词汇数量、段落总词数、停用词数量、总句数量
def analyze_text(text):
 pos_count = 0
 neg_count = 0
 pos\_word\_count = 0
 neg\_word\_count = 0
 word_count = 0
 stopword_count = 0
 sentence_count = 0
 # 将文本按段落分割
 paragraphs = re.split('\\n|\\r', text)
 for para in paragraphs:
 if not para.strip():
 continue
 # 将段落分割成句子
 sentences = re.split('\[-!?。\]', para)
 for sentence in sentences:
 if not sentence.strip():
 continue
 # 将句子分词并过滤停用词
 words = segment(sentence)
 word_count += len(words)
 stopword_count += sum(\[1 for word in words if word in stopwords\])
 pos\_word\_count += len(\[word for word in words if word in posdict\])
 neg\_word\_count += len(\[word for word in words if word in negdict\])
 # 判断句子的情感倾向
 if pos\_word\_count > neg\_word\_count:
 pos_count += 1
 elif pos\_word\_count < neg\_word\_count:
 neg_count += 1
 sentence_count += 1
 return pos\_count, neg\_count, pos\_word\_count, neg\_word\_count, word\_count, stopword\_count, sentence_count

计算乐观指标

为了量化年报的语气,我们引入了乐观指标。乐观指标的计算公式为:乐观指标 = 积极语调数量 / (积极语调数量 + 消极语调数量)。

# 计算乐观指标
def calculate\_optimism(pos\_count, neg\_count, sentence\_count):
 if pos\_count + neg\_count == 0:
 return 0
 optimism = pos\_count / (pos\_count + neg_count)
 return optimism

处理年报文件

最后,我们要读取所有的年报文件,并对每个文件进行分析,将计算得到的乐观指标等信息输出到excel表中。

import os
# 读取年报文件并分析文本
def analyze\_report(file\_path):
 with open(file_path, 'r', encoding='utf-8') as f:
 text = f.read()
 pos\_count, neg\_count, pos\_word\_count, neg\_word\_count, word\_count, stopword\_count, sentence\_count = analyze\_text(text)
 optimism = calculate\_optimism(pos\_count, neg\_count, sentence\_count)
 return {'pos\_count': pos\_count, 'neg\_count': neg\_count, 'pos\_word\_count': pos\_word\_count,
 'neg\_word\_count': neg\_word\_count, 'word\_count': word\_count, 'stopword\_count': stopword\_count,
 'sentence\_count': sentence\_count, 'optimism': optimism}
# 读取目录下的所有年报文件并分析
def analyze\_reports(dir\_path):
 company_reports = {}
 for root, dirs, files in os.walk(dir_path):
 for file in files:
 if file.endswith('.txt'):
 company_name = file.split(':')\[0\]
 file_path = os.path.join(root, file)
 report\_data = analyze\_report(file_path)
 if company\_name in company\_reports:
 company\_reports\[company\_name\].append(report_data)
 else:
 company\_reports\[company\_name\] = \[report_data\]
 return company_reports
# 设置年报文件目录
dir_path = "年报"
company\_reports = analyze\_reports(dir_path)

结果与启示

通过对这10家上市银行2010 - 2022年的年报进行语气评分,我们可以得到每个银行在不同年份的乐观指标。这些指标可以反映出银行在不同时期的经营信心和市场预期。例如,如果某家银行在某一年的乐观指标较高,说明该银行在年报中传达出了积极的态度,可能意味着该银行在这一年的经营状况较好,对未来的发展充满信心。相反,如果乐观指标较低,则可能表示银行面临着一些挑战和压力。
这种文本分析方法不仅适用于上市银行的年报分析,对于其他难以量化的指标或者难以针对每个企业衡量的指标,也具有很好的应用价值。比如当前较热的数字化转型,企业可能没有专门披露这一指标,我们就可以通过对其年报进行分析,了解企业在数字化转型方面的进展和态度。
总之,文本分析技术为我们打开了一扇了解企业的新窗口,让我们能够从文字信息中挖掘出更多有价值的信息。随着技术的不断发展,相信文本分析在金融领域和企业研究中的应用会越来越广泛。

LSTM神经网络模型在微博中文文本评论情感分析|附数据代码

分析师:Shuai Fung

本文将通过视频讲解,展示如何用python的LSTM模型对中文文本评论情感分析,并结合一个TensorFlow的长短期记忆神经网络(LSTM)、指数移动平均法预测股票市场和可视化实例的代码数据,为读者提供一套完整的LSTM模型分类预测的实践数据分析流程。

基于LSTM模型的中文文本评论情感分析

研究背景

在自然语言处理(NLP)领域,情感分析一直是研究的热点之一。尽管国外研究人员在早期就针对英文文本开展了情感分析的研究,但由于中英文在语法结构、词汇含义以及表达方式上存在显著差异,中文文本情感分析面临着独特的挑战。尤其是随着微博等社交媒体的兴起,网络文本呈现出短小精悍、数据稀疏、上下文信息有限等特点,使得传统的基于情感词典的分析方法难以直接应用。

因此,中文文本情感分析的研究不仅具有理论价值,更具有重要的现实意义。通过对海量互联网评论文本进行情感分析,不仅可以实现异常或突发事件的检测和监控,还能助力网络舆情监控系统的完善,为企业的市场营销策略提供有力支持。此外,情感分析在心理学、语言学、教育学、社会学、金融预测等多个领域也具有广泛的应用前景。

研究内容

本研究主要基于长短期记忆网络(Long Short-Term Memory, LSTM)实现中文文本情感分析。具体研究内容包括:

  1. 数据集的收集、整理与分析,以及对数据集进行词向量等预处理操作,以适应LSTM模型的输入要求。
  2. 构建一个情感分析模型,利用PyTorch框架搭建LSTM网络,并将此网络模型应用于中文文本情感分析任务中。通过训练模型,使其能够准确识别文本的情感倾向,并输出混淆矩阵等评价指标。

研究流程

本研究遵循以下流程进行:

  1. 数据获取:使用微博情感分析数据集,该数据集包含积极情感和消极情感两种标签,共计约12万条数据。
  2. 数据预处理:利用公开的Vocab和腾讯发布的词向量预训练模型,对文本数据进行词向量预处理,以便后续模型训练。
  3. 搭建模型:使用PyTorch框架搭建LSTM网络模型,设置合适的网络结构和参数。
  4. 模型训练:通过调整batch_size、epoch等超参数,对模型进行训练,并输出训练日志以监控训练过程。
  5. 模型评估:在测试集上评估模型的性能,输出混淆矩阵,并采用精准率、召回率、F1值等指标对模型进行综合评价。

算法原理

LSTM是一种特殊的循环神经网络(RNN),它通过引入门控机制来解决RNN在处理长序列时存在的梯度消失和梯度爆炸问题。LSTM包含三个门:遗忘门、输入门和输出门,以及一个记忆单元。在每个时间步,LSTM都会根据当前输入和上一时刻的输出更新记忆单元和门控状态,从而实现对长序列信息的有效处理。

在情感分析任务中,LSTM网络通过学习文本序列中的依赖关系,能够捕捉文本中的情感信息,并输出相应的情感倾向。通过训练LSTM网络模型,我们可以实现对中文文本情感分析任务的有效处理。

模型搭建

LSTM模型通过引入门控机制,能够处理长序列数据中的依赖关系,适用于情感分析任务。在模型搭建过程中,我们设置了合适的网络结构和参数,包括隐藏层大小、学习率、批次大小(batch size)等超参数。

原始数据

超参数

预处理一一分割文本、划分训练集

首先,对原始数据集进行文本分割,将长文本切分为适合模型输入的短文本序列。接着,将数据集划分为训练集、验证集和测试集,确保模型在训练过程中能够有效利用数据,并通过验证集进行模型调优,最终在测试集上评估模型的性能。

预处理一一张量转化

将预处理后的文本数据转化为张量(tensor)格式,以适应PyTorch等深度学习框架的输入要求。通过词嵌入(word embedding)技术,将文本中的每个词映射为一个固定维度的向量,从而捕获文本的语义信息。

训练

在模型训练过程中,我们使用训练集数据对模型进行迭代训练,通过反向传播算法和梯度下降优化器更新模型的参数。同时,我们记录了训练过程中的损失函数值和准确率等指标,以便对模型的训练过程进行监控和调优。 

模型评估

在模型训练完成后,我们使用测试集数据对模型进行评估。评估指标包括精准率(Precision)、召回率(Recall)和F1值等。通过输出混淆矩阵(Confusion Matrix),我们可以更直观地了解模型在不同情感类别上的表现。

此外,我们还通过可视化工具展示了模型在训练过程中的损失函数值和准确率变化曲线,以便对模型的训练效果进行更深入的分析。 

模型局限

尽管基于LSTM的模型在中文文本情感分析任务中取得了不错的效果,但仍存在一些局限性:

  1. 长期依赖处理:LSTM模型虽然能够处理长期依赖关系,但在某些情况下可能无法完全捕捉到较长距离之间的依赖关系,导致模型在处理一些复杂的情感语义时出现困难。
  2. 数据不平衡问题:在情感分析任务中,积极和消极情感的数据往往不平衡,这可能导致模型在学习时偏向于出现更多的样本数量较多的情感类别。为了解决这个问题,可以采用数据增强、重采样等技术来平衡数据集。
  3. 语义理解挑战:情感分析需要对文本的语义进行准确的理解,而LSTM模型可能无法完全捕捉到复杂的语义关系。为了提高模型的语义理解能力,可以引入注意力机制(Attention Mechanism)等技术来增强模型对关键信息的关注。
  4. 知识表示限制:LSTM模型通常使用词嵌入来表示文本的语义信息,但词嵌入可能无法准确地捕捉到一些特定领域或文化背景中的情感表达。为了解决这个问题,可以引入领域知识或文化背景信息来丰富词嵌入的表示能力。

针对以上局限性,未来的研究可以探索更先进的模型架构和算法,以提高中文文本情感分析的准确性和效率。

R语言《红楼梦》文本挖掘:词频统计、词云可视化及前后对比分析|附数据代码

作为中国古典文学的瑰宝,《红楼梦》具有极高的文学价值和丰富的主题内涵。近年来,随着大数据和文本挖掘技术的发展,对《红楼梦》等古典文学作品的深度分析成为可能。本研究采用R语言作为分析工具,对《红楼梦》全文进行文本挖掘,通过词频统计、词云可视化以及前后对比分析,以期深入探索这部经典小说的主题演变和人物塑造。

读入数据

将需要分析的文本放入记事本中,保存到相应路径,并在R中打开。这儿我导入的是《红楼梦》的文本。

先导入rJava和Rwordseg两个包

library(Rwordseg)

分词+统计词频

words=unistlapplyX=lecture, UN=sgmntCN))
#unlist将list类型的数据,转化为vector  
#lapply()返回一个长度与X一致的列表,每个元素为FUN计算出的结果,且分别对应到X中的每个元素。

table统计数据的频数

降序排序

v=rev(sort(v))

过滤掉1个字的结果和词频小于100的结果

d1=subset(d, nchr(ascharctr(d$词汇))>1 & d$词频.Freq>=100)

画出标签云

wordcloud(d1$词

性格分析: 宝玉

xinggefenxi("宝玉")

从关键词“丫头”“出去”“姐姐”这些来看,贾宝玉是一个又奇又俗的人物。自幼深受祖母贾母疼爱,住贾母院。因此娇生惯养,构成他性格的主要特征是叛逆。他行为“偏僻而乖张”,是封建社会的叛逆者。他鄙视功名利禄,不愿走“学而优则仕”的仕途。他痛恨“八股”,辱骂读书做官的人是“国贼禄蠹”,懒于与他们接触拜会。

红楼梦前八十回与后四十回是否同一个人写的?

lecture<-read.csv("红楼梦前80回.txt", tringAsFactorsALSEheade=FALSE)  
   
words=ulit(lppl
#unlist将list类型的数,转化为vector  
#lapply()返回一个长度与X一致的列表,每个元素为FUN计算出的结果,且分别对应到X中的每个元素。  
word=lapply()

画出标签云

lecture<-read.csv("红楼梦后40回.txt", stringsAFacors=FLSE,header=FALSE)

前后红楼梦词频对比

qianword=qiwor\[which(qiaword\[ ,1\] %in% gongtngword),  \]  
  
houword=uword\[whih(houod\[ ,1\] %in% gongtonword),  \]

前红楼梦:

后红楼梦:

t检验

t检验是用t分布理论来推论差异发生的概率,从而比较两个平均数的差异是否显著。用于比较前后红楼梦的关键词出现频率的区别差异。

t.test(qianod\[,3\],huord\[,3\])

从结果来看,t检验的p值显著小于0.05,因此拒绝原假设。有95%的把握可以认为前后的红楼梦不是一个人所做。

R语言汽车口碑数据采集抓取、文本数据分词和词云可视化实现

本文以R语言为工具,帮助客户对汽车网站的口碑数据进行抓取,并基于文本数据分词技术进行数据清理和统计。通过词频统计和词云可视化,对口碑中的关键词进行分析,挖掘出消费者对汽车的评价和需求,为汽车制造商和销售商提供重要的市场参考。

随着社会经济的不断发展,汽车已经成为人们日常生活中不可或缺的交通工具。汽车口碑对于消费者购车决策起着至关重要的作用,同时也是汽车制造商和销售商了解市场需求、改进产品质量和服务的重要依据。传统的汽车口碑调查方式往往需要耗费大量的人力物力,而网络上的汽车口碑数据正逐渐成为研究汽车市场和消费者需求的重要数据来源。然而,如何高效地获取和分析这些数据变得越来越重要。因此,本文利用R语言的数据抓取和文本数据分词技术,对汽车网站的口碑数据进行抓取和分析,旨在为汽车行业提供更准确、更快速的市场研究手段。

本文主要实现以下两个目标:

  • 基于R语言的数据抓取部分。这一部分里面所有的结果都要实现
  • 基于R语言的文本数据分词

在每一页评价内容的抓取中 , 依然使用 xpath SApply 函数,再输入特定的 XML 路径来抓取网页上的用户评价内容

library(RCurl)


 Also load the other required package.  
library("methods")  
xpath <- '//div\[@class=\\"co81\\"\]'  
  
url <-"www.chekb.com/suonata/koubei/"

pagetree <- htmlTreeParse(webpage, error=function(...){}, useInternalNodes = TRUE,encoding="UTF-8")  
   pagetree  
   value <- getNodeSet(pagetree,xpath)  
   
  i <- length(value)                     统计满足条件的值个数,一般情况为1

读入数据

将需要分析的文本放入记事本中,保存到相应路径,并在R中打开。

head(lecture)

数据清理

lecture$评价=gsub(pattern="\[1|2|3|4|5|6|7|8|9|0\]"," ",lecture$评价);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  
lecture$评价=gsub(pattern="/"," ",lecture$评价);&nbsp;&nbsp;&nbsp;  
lecture$评价=gsub(pattern="!"," ",lecture$评价);
......

grepl 函数的 regexpr 函数、regmatches 函数,并结合正则表达式来匹配出“非灰色用户”的主页链接

grepl(pattern = "中国",x = lecture$网友)

分词+统计词频

word=lapply(X=words, FUN=strsplit, " ")  
v=table(unlist(word))

统计数据的频数

对词频进行排序table函数得到各词组的词频,最后运用 sort 函数让其按词频降序排列,生成文档词矩阵

创建数据框

d=data.frame(词汇=names(v), 词频=v)  
d

过滤掉1个字的结果和词频小于100的结果

筛选标准大家可以根据自己的需求进行修改

d1=subset(d, nchar(as.character(d$词汇))>1 & d$词频.Freq>=2)

词频统计结果(节选)如下:

画出标签云

(2)设置字体类型和字体颜色

mycolors <- brewer.pal(12,"Paired")

(3)画出标签云

dcloud(d1$词汇,d1$词频.Freq,random.order=FALSE,random.color=TRUE,colors=mycolors,family="myFont")

关于分析师

在此对Zhenzhen Liu对本文所作的贡献表示诚挚感谢,她在浙江财经大学完成了金融专业的硕士学位,专注数据采集与金融分析领域。擅长Matlab、Python编程,精通常规金融分析与文本挖掘技术。

Shuai Fung拓端研究室(TRL) 的研究员。在此对他对本文所作的贡献表示诚挚感谢,他在香港大学完成了数据科学专业的硕士学位,专注机器学习、数据分析、时间序列预测、深度学习、数理金融。擅长R语言、Python、SQL。


拓端tecdat
198 声望53 粉丝