【建议收藏】|信息抽取与经济学文本量化分析(上)

简介: 【建议收藏】|信息抽取与经济学文本量化分析

本文实现的核心问题

通过信息抽取技术实现实体、关系抽取任务。通过光学字符识别能力扩大企业公告 pdf 的识别来源。通过对开源数据集及开源深度学习解决方案实现预训练语言模型训练工作、实体识别训练工作、关系抽取训练工作。

通过 networks 实现关系可视化,关系可视化布局、pagerank 节点重要性排序。

本文涉及技术点

深度学习封装框架

  • paddleocr
  • paddlenlp
  • bert4keras

可视化框架

  • networkx
  • pyvis

分布式加速框架

  • ray
  • pyspark

对外提供接口形式

  • TensorFlow serving
  • ray["serve"]
  • fast api
  • onnxruntime

本文所涉及数据集

  • duie 百度构建娱乐关系抽取数据集
{"postag": [{"word": "查尔斯", "pos": "nr"}, {"word": "·", "pos": "w"},
{"word": "阿兰基斯", "pos": "nr"}, {"word": "(", "pos": "w"}, {"word": "Charles Aránguiz", "pos": "nz"},
{"word": ")", "pos": "w"}, {"word": ",", "pos": "w"}, {"word": "1989年4月17日", "pos": "t"},
{"word": "出生", "pos": "v"}, {"word": "于", "pos": "p"}, {"word": "智利圣地亚哥", "pos": "ns"},
{"word": ",", "pos": "w"}, {"word": "智利", "pos": "ns"}, {"word": "职业", "pos": "n"},
{"word": "足球", "pos": "n"}, {"word": "运动员", "pos": "n"}, {"word": ",", "pos": "w"}, {"word": "司职", "pos": "v"},
{"word": "中场", "pos": "n"}, {"word": ",", "pos": "w"}, {"word": "效力", "pos": "v"}, {"word": "于", "pos": "p"},
{"word": "德国", "pos": "ns"}, {"word": "足球", "pos": "n"}, {"word": "甲级", "pos": "a"}, {"word": "联赛", "pos": "n"},
{"word": "勒沃库森足球俱乐部", "pos": "nt"}],
"text": "查尔斯·阿兰基斯(Charles Aránguiz),1989年4月17日出生于智利圣地亚哥,智利职业足球运动员,司职中场,效力于德国足球甲级联赛勒沃库森足球俱乐部",
"spo_list": [{"predicate": "出生地", "object_type": "地点", "subject_type": "人物", "object": "圣地亚哥", "subject": "查尔斯·阿兰基斯"},
{"predicate": "出生日期", "object_type": "Date", "subject_type": "人物", "object": "1989年4月17日", "subject": "查尔斯·阿兰基斯"}]}
  • 海通大智慧经济因果抽取数据集
{"id": 865,
"text": "自2012年二季度开始,整个家禽养殖业就进入下行亏损通道,随后2012年末爆发的“速成鸡事件”与2013年的“H7N9”等不可抗力因素导致了家禽业进入深度亏损状态,在2013年上半年同期,“圣农发展”的净利润为亏损2.33亿元",
"relations": [{"id": 2472, "from_id": 3652, "to_id": 3654, "type": "Influence"},
              {"id": 2473, "from_id": 3653, "to_id": 3654, "type": "Influence"}],
"entities": [{"id": 3652, "start_offset": 40, "end_offset": 47, "label": "event"},
             {"id": 3653, "start_offset": 54, "end_offset": 60, "label": "event"},
             {"id": 3654, "start_offset": 70, "end_offset": 81, "label": "event"}]}
  • 企业年报数据集 被抽取的数据来源

年报数据原始格式为 pdf,通过年报 pdf 数据处理流程转换为 txt 格式文本数据

前置安装 pip install ray pdfmner3k

import importlib
import os
# encoding: utf-8
import sys
# pip uninstall pdfminer.six
importlib.reload(sys)
from pdfminer.pdfparser import PDFParser, PDFDocument
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import PDFPageAggregator
from pdfminer.layout import LTTextBoxHorizontal, LAParams
import ray
ray.init(num_cpus=os.cpu_count()*2)
@ray.remote
def parse(path, out_path):
    if os.path.exists(out_path + ".txt"):
        return "ok"
    fp = open(path, 'rb')
    # 用文件对象来创建一个pdf文档分析器PDFParser
    praser = PDFParser(fp)
    # 创建一个PDF文档PDFDocument
    doc = PDFDocument()
    # 连接分析器 与文档对象
    praser.set_document(doc)
    doc.set_parser(praser)
    # 提供初始化密码,如果没有密码 就创建一个空的字符串
    doc.initialize()
    # 检测文档是否提供txt转换,不提供就忽略
    if not doc.is_extractable:
        # raise PDFTextExtractionNotAllowed
        return "ok"
    else:
        # 创建PDf 资源管理器 来管理共享资源PDFResourceManager
        rsrcmgr = PDFResourceManager()
        # 创建一个PDF设备对象LAParams
        laparams = LAParams()
        # 创建聚合器,用于读取文档的对象PDFPageAggregator
        device = PDFPageAggregator(rsrcmgr, laparams=laparams)
        # 创建一个PDF解释器对象,对文档编码,解释成Python能够识别的格式:PDFPageInterpreter
        interpreter = PDFPageInterpreter(rsrcmgr, device)
        try:
            # 循环遍历列表,每次处理一个page的内容
            for page in doc.get_pages():  # doc.get_pages() 获取page列表
                # 利用解释器的process_page()方法解析读取单独页数
                try:
                    interpreter.process_page(page)
                except:
                    continue
                # 这里layout是一个LTPage对象,里面存放着这个page解析出的各种对象,一般包括LTTextBox, LTFigure, LTImage, LTTextBoxHorizontal等等,想要获取文本就获得对象的text属性,
                # 使用聚合器get_result()方法获取页面内容
                layout = device.get_result()
                for x in layout:
                    if (isinstance(x, LTTextBoxHorizontal)):
                        # 需要写出编码格式
                        with open(out_path + ".txt", 'a',
                                  encoding='utf-8') as f:
                            results = x.get_text()
                            f.write(results + '\n')
            return "ok"
        except:
            return "ok"
if __name__ == '__main__':
    base_path = "../../上市公司年报"
    out_path = "../../公司年报txt"
    first_path = os.listdir(os.path.join(base_path))
    futures = [parse.remote(os.path.join(base_path, first_path),
                            os.path.join(out_path, first_path)) for first_path in first_path]
    print(ray.get(futures))  # [0, 1, 4, 9]

年报数据处理流程

640.png

编辑切换为居中

添加图片注释,不超过 140 字(可选)

其中固定长度文本提取部分代码采用以下代码实现。


策略 年报数据按照句号进行分割。考虑长度在 10-128 范围内长度的文本。去除包含页眉页脚内容。

import os
base_path = "./2021年报_text_dir"
base_path_list = os.listdir(base_path)
word_list = []
for base_path_one in base_path_list:
    try:
        base_path_two = os.listdir(os.path.join(base_path,base_path_one))
        base_path_data = open(os.path.join(base_path,base_path_one,base_path_two[0]),"r").read().replace("\n", " ")
    except:
        continue
    words = ""
    for i in base_path_data.split("。"):
        if "年年度报告" in i:
            continue
        if len(i) < 10:
            continue
        if len(words + i) < 128:
            words+=i.replace(" ","")+"。"
        if len(words+i) > 128:
            if len(words):
                word_list.append(words)
            words = ""

其中年年度报告 是目前发现的页眉页脚文本具有的特征。

关系抽取数据集读取代码

  • duie 百度构建娱乐关系抽取数据集 在基于 bert4keras 的 gplinker 关系抽取框架下数据读取部分代码实现。
def normalize(text):
    """简单的文本格式化函数
    """
    return ' '.join(text.split())
def load_data(filename):
    """加载数据
    单条格式:{'text': text, 'spo_list': [(s, p, o)]}
    """
    D = []
    with open(filename, encoding='utf-8') as f:
        for l in f:
            l = json.loads(l)
            D.append({
                'text': normalize(l['text']),
                'spoes': [(
                    normalize(spo['subject']), spo['predicate'],
                    normalize(spo['object'])
                ) for spo in l['spo_list']]
            })
    return D
# 加载数据集
train_data = load_data('../小说人物关系抽取/train_data.json')
valid_data = load_data('../小说人物关系抽取/dev_data.json')
predicate2id, id2predicate = {}, {}
with open('../小说人物关系抽取/all_50_schemas') as f:
    for l in f:
        l = json.loads(l)
        if l['predicate'] not in predicate2id:
            id2predicate[len(predicate2id)] = l['predicate']
            predicate2id[l['predicate']] = len(predicate2id)

海通大智慧因果抽取数据读取代码

def load_data(filename):
    """加载数据
    单条格式:{'text': text, 'spo_list': [(s, p, o)]}
    """
    D = []
    id2predicate = {}
    predicate2id = {}
    with open(filename, encoding='utf-8') as f:
        for l in f:
            l = json.loads(l)
            entities_mapping = {}
            for i in l["entities"]:
                entities_mapping[i["id"]]=l['text'][i["start_offset"]:i["end_offset"]]
            D.append({
                'text': l['text'],
                'spo_list': [(entities_mapping[spo['from_id']], spo['type'], entities_mapping[spo['to_id']])
                             for spo in l['relations']]
            })
            for spo in l["relations"]:
                if spo['type'] not in predicate2id:
                    id2predicate[len(predicate2id)] = spo['type']
                    predicate2id[spo['type']] = len(predicate2id)
    return D,id2predicate,predicate2id
# 加载数据集
all_data,id2predicate,predicate2id = load_data('untitled.txt')
train_data = all_data[:int(len(all_data)*0.8)]
valid_data = all_data[int(len(all_data)*0.8):]
相关文章
|
11月前
|
自然语言处理 监控 搜索推荐
CAP 快速部署项目体验评测
在体验过程中,我选择了 RAG 模板,整体部署较为顺畅,CAP 平台的一键部署功能简化了配置步骤。但也遇到了环境依赖、模型加载速度和网络配置等挑战。性能测试显示响应速度较快,高并发时表现稳定。二次开发使用 Flask 和 Vue,调试顺利,功能正常运行。建议 CAP 增加 NLP、推荐系统、IoT 应用和开源项目集成等模板,以提升模板库的丰富度。
|
自然语言处理 Java 大数据
阿里云自然语言处理--文本纠错(中文)Java 调用示例
自然语言处理(Natural Language Processing,简称NLP),是为各类企业及开发者提供的用于文本分析及挖掘的核心工具,旨在帮助用户高效的处理文本,已经广泛应用在电商、文娱、司法、公安、金融、医疗、电力等行业客户的多项业务中,取得了良好的效果。文本纠错产品是基于海量大数据研发,为有文本纠错需求的产品提供服务。能够准确识别输入文本中出现的拼写错别字及其段落位置信息,并针对性给出正确的建议文本内容。本文将使用Java CommonSDK演示文本纠错(中文)服务的快速调用以供参考。
1790 0
阿里云自然语言处理--文本纠错(中文)Java 调用示例
|
安全 Unix Linux
Linux Clone函数
Linux Clone函数
211 3
|
存储 开发框架 缓存
ABP VNext框架中Winform终端的开发和客户端授权信息的处理
ABP VNext框架中Winform终端的开发和客户端授权信息的处理
|
JavaScript
【vue】 vue 实现视频播放 vue-video-player
【vue】 vue 实现视频播放 vue-video-player
696 0
|
机器学习/深度学习 供应链 监控
ERP系统中的供应链可视化与智能预测解析
【7月更文挑战第25天】 ERP系统中的供应链可视化与智能预测解析
488 5
阿里云域名实名认证需要多长时间通过?
阿里云域名实名认证通常在1天内完成,经测试一般10多分钟即可通过,最慢3-5个工作日。如果你的阿里云账号下有已经通过实名认证的域名信息模板,那么域名实名认证的时间会更快一些,如果是阿里云新账号,之前没有注册过域名,那么填写域名信息模板并等待实名认证,时间就会稍微多一些
|
新零售 供应链 数据挖掘
多商户商城入驻系统案例|方案设计|详情版
新零售的最大趋势是线上线下相结合,电商与线下实体商业,应该由原先的独立、冲突,走向混合、融合,通过精准化
|
XML Java 数据库连接
学会自己编写Mybatis插件(拦截器)实现自定义需求1
学会自己编写Mybatis插件(拦截器)实现自定义需求
249 0
|
消息中间件 弹性计算 关系型数据库
使用EDA架构部署在线外卖订单系统
本实验将使用消息系统构建超级外卖订单,通过订单流转及处理阐述如何在多环境,复杂场景下使用消息做订单解耦,业务分发等。