Python - 深度学习系列35 重塑实体识别2

说明

上一篇Python - 深度学习系列34 重塑实体识别介绍了如何进行训练,这篇讨论如何应用。

详细review了之后,发现其实早先的服务还是略有欠缺的。例如:

  • 1 最早的时候好像还没有pipeline,我用DataFrame并行处理,然后用模型的裸方法,可能不一定那么优雅。(意味着性能或信息有丢失)
        minput = torch.cat(the_ss_codecs_values)

        if self.device == 'cuda':
            if self.model.device.type != 'cuda':
                self.model.to('cuda')
            with torch.no_grad():
                input_cuda = minput.to('cuda')
                outputs_cuda = self.model(input_cuda).logits

                predictions = torch.argmax(outputs_cuda, dim=2)
                predictions_list = list(predictions.to('cpu').numpy())
  • 2 在输出结果时丢掉了位置信息。最直观的问题是,如果产品需要进行高亮,那么是没办法的。
    import numpy as np 
    @staticmethod
    def inv_convert_chinese_word_tag_list2BIO_v3(data_dict):
        data_list = data_dict['data_list']
        tag_list = data_dict['tag_list']

        res_data_list = []
        data_list1 = copy.deepcopy(data_list)

        # 如果tag_list都是无用词
        if set(tag_list) == {'O'}:
            return ','

        else:
            tag_arr = np.array(tag_list)
            ner_start_idx_list = list(np.where(tag_arr=='B')[0])
            
            for the_ner in ner_start_idx_list:

                tem_data = ''
                for i in range(198):

                    if the_ner+i == len(data_list1):
                        break
                    if the_ner+i >=198:
                        break
                    if tag_list[the_ner+i] != 'O':
                        tem_data += data_list1[the_ner+i]
                    else:
                        break
                    

                res_data_list.append(tem_data + ',')

            return ','.join(res_data_list)

内容

1 目标

本次迭代之后可以直接看到的效果应该是:

  • 1 模型的训练与调用方法更科学
  • 2 输出的结果更完整(按序输出)
  • 3 句子的分割更合理(仅以部分强分隔符切分句子)
  • 4 初步形成流水线方法

下一阶段的目标则是不断用更多的模型类型以及尺寸去调教一套实体识别模型。之后至少会使用Electra, Roberta,DistilBert几类模型;并且除了实体识别,还需要有情感分析和局对匹配等内容。

2 使用实例

载入模型,注意device选项
在这里插入图片描述

from Basefuncs import * 
# 载入模型
import transformers 
import torch 
from transformers import AutoModelForMaskedLM, AutoTokenizer
xmodel_path = 'model01'
from transformers import pipeline

# 加载中文 Electra 模型和 tokenizer
ner = pipeline("ner", model=xmodel_path, tokenizer=xmodel_path, device=0)  

获取数据

host = 'xxxxxx.cn'
port = 19000
database = 'model_train_datasets'
user = 'xxx'
password = 'xxx'
name = 'tem'
chc = CHClient(host = host, port = port , database = database, user = user, password = password, name = name )
the_sql = 'show tables'
chc._exe_sql(the_sql)
# 取数
data_tuple_list = chc.get_table('train_ner_news_title_org_20240517')
df = pd.DataFrame(data_tuple_list, columns = ['mid', 'x', 'y'])
data_list = list(df['x'])
# sub_list 
sub_list = data_list[:1000]

模型执行预测

sentences = sub_list
entities = ner(sentences)

在这里,CPU和GPU执行有巨大的时间差别。使用 timeit测试,CPU对100条数据的识别大约是6.9秒,而GPU对1000条数据的执行约为8.11秒。其中GPU的负载观察下来只有25%,所以还可以继续并行。
CPU的信息如下,因为是虚拟机切分,所以单精度浮点算力约为0.4T
在这里插入图片描述
而GPU单精约为30T。
在这里插入图片描述
理论上GPU应该快60倍,实际上如果可以满载的话大约是40倍。中间有部分因为流程原因,如tokenize或者内存-显存搬运消耗掉了。所以这类任务应该进行一些并行化,大约到30倍左右就比较理想了。

解析

通过pipeline可以很快获得实体的结果,但是无法直接使用。
在这里插入图片描述
每一个sentence的解析结果是listofdict, 序列分类的任务结果是每个token都有一个分类。我们需要从这些结果中解析出实体以及对应的起始位置。考虑到数据增强,位置现在变得更关键,我希望结果可以通过labelstudio进行有效的展示和标注,然后形成质量更好的回流数据。

解析依赖的功能有以下几个:

  • 1 convert_entity_label 将LABEL_0,1,2转为最初的字符标签
  • 2 detokenize 反令牌化,将一些因为tokenize而改变的字还原回来(这里我也理解了为什么是按单个字拆分令牌,因为模型会加上##作为特殊的拓展)

在这里插入图片描述

  • 3 extract_bio_positions 抽出实体所在位置。这里将循环改为正则真的是灵感,快多了。
from datasets import ClassLabel
# 定义标签列表
label_list = ['B', 'I', 'O']
# 创建 ClassLabel 对象
class_label = ClassLabel(names=label_list)
def convert_entity_label(x):
    x1 = int(x.split('_')[-1])
    return class_label.int2str(x1)

def detokenize(word_piece):
    """
    将 WordPiece 令牌还原为原始句子。
    """
    if word_piece.startswith('##'):
        x = word_piece[2:]
    else:
        x = word_piece
    return x
import re

def extract_bio_positions(bio_string):
    pattern = re.compile(r'B(I+)(O|$)')
    matches = pattern.finditer(bio_string)
    
    results = []
    for match in matches:
        start, end = match.span()
        results.append((start, end - 1))  # end-1 to include the last 'I'
    
    return results
# 示例字符串
bio_string = "BIIIIIIOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"
# 提取位置
positions = extract_bio_positions(bio_string)
# 打印结果
for start, end in positions:
    print(f"Entity starts at {start} and ends at {end}")

对于每一个句子的结果处理,有两种思路:

  • 1 使用pandas + apply, 直观但是开销比较大
  • 2 使用 map, 不直观,但是开销小

返回都是 (ent, start, end) tuple list

pandas apply方法

some_entity_list = entities[0]
def parse_ent_pos_pandas_apply(some_listofdict = None):
    some_entity_list = some_listofdict
    some_entity_df = pd.DataFrame(some_entity_list)
    some_entity_df['label'] = some_entity_df['entity'].apply(convert_entity_label)
    some_entity_df['ori_word'] = some_entity_df['word'].apply(detokenize)
    label_list = list(some_entity_df['label'])
    oriword_list = list(some_entity_df['ori_word'])
    label_str = ''.join(label_list)
    oriword_str = ''.join(oriword_list)
    pos_list = extract_bio_positions(label_str)
    part_ent_list = [(oriword_str[x[0]:x[1]] , *x) for x in pos_list]
    return part_ent_list

%%timeit
parse_ent_pos_pandas_apply(some_entity_list)
1.15 ms ± 2.12 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

map方法: 快了10倍不止。

def parse_ent_pos_map(some_listofdict = None):
    some_entity_list = some_listofdict
    word_list = [x['word'] for x in some_entity_list]
    label_list = [x['entity'] for x in some_entity_list]
    label_str =''.join(map(convert_entity_label,label_list))
    ori_word_str =''.join(map(detokenize,word_list))
    pos_list = extract_bio_positions(label_str)
    part_ent_list = [(ori_word_str[x[0]:x[1]] , *x) for x in pos_list]
    return part_ent_list
%%timeit
parse_ent_pos_map(some_entity_list)
76.5 µs ± 137 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

最后进行批量生成

some_s = pd.Series(entities)
some_s2 =some_s.apply(parse_ent_pos_map)
res_df = pd.DataFrame()
res_df['clean_data'] = list(sub_list[:10])
res_df['ent_tuple_list0'] =list(some_s2)[:10]
res_df['ent_tuple_list'] = res_df['ent_tuple_list0'].apply(lambda x: [a + ('ORG',) for a in x])
res_df.head()

在这里插入图片描述
写到这里,暂时告一段落,先看看效果再进行下一步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/645219.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

matlab 图像的中值滤波

目录 一、功能概述1、算法概述2、主要函数3、计算公式二、代码实现三、结果展示四、参考链接本文由CSDN点云侠翻译,放入付费专栏只为防不要脸的爬虫。专栏值钱的不是本文,切勿因本文而订阅。 一、功能概述 1、算法概述 中值滤波是图像处理中一种常用的非线性运算,用于减少…

摸鱼大数据——Hive基础理论知识——Hive环境准备

Hive环境准备 1、shell脚本执行方式 方式1: sh 脚本 注意: 需要进入脚本所在目录,但脚本有没有执行权限不影响执行 方式2: ./脚本 注意: 需要进入脚本所在目录,且脚本必须有执行权限 方式3: /绝对路径/脚本 注意: 不需要进入脚本所在目录,但必须有执行…

Pytorch深度学习实践笔记6(b站刘二大人)

🎬个人简介:一个全栈工程师的升级之路! 📋个人专栏:pytorch深度学习 🎀CSDN主页 发狂的小花 🌄人生秘诀:学习的本质就是极致重复! 《PyTorch深度学习实践》完结合集_哔哩哔哩_bilibi…

【Spring Security + OAuth2】OAuth2

Spring Security OAuth2 第一章 Spring Security 快速入门 第二章 Spring Security 自定义配置 第三章 Spring Security 前后端分离配置 第四章 Spring Security 身份认证 第五章 Spring Security 授权 第六章 OAuth2 文章目录 Spring Security OAuth21、OAuth2简介1.1、OAu…

绘唐科技绘唐ai工具邀请码

绘唐科技绘唐ai工具邀请码 绘唐AI工具 https://qvfbz6lhqnd.feishu.cn/wiki/QBr4wOAz2ilF4NknrqbcoKRhn2c TensorFlow是一个开源的机器学习框架,由Google开发并维护。它提供了一个灵活且高效的接口,用于构建和训练各种机器学习模型。 TensorFlow的基本概念包括: 1. 张量(…

基于python的网页自动刷新工具

1.下载webdriver https://msedgewebdriverstorage.z22.web.core.windows.net/?prefix122.0.2365.59/下载Edge的浏览器驱动 2.安装selenium pip install selenium4.11.1 3.写代码 # -*- coding: utf-8 -*- import tkinter as tk from tkinter import messagebox import thr…

当标签中出现输入了字母或者数字直接在一行上,没有换行的 情况时怎么办

当标签块中输入的是包含字母或者数字的时候,他不会换行,在一行上显示滚动条的形式,而我们想让他走正常文档流,该换行的时候换行 想要的如下效果 给相应的元素块添加该代码即可 word-break: break-all; .card-content { …

uniapp使用uni.chooseImage选择图片后对其是否符合所需的图片大小和类型进行校验

uni.chooseImage的返回值在H5平台和其他平台的返回值有所差异,具体差异看下图 根据图片可以看出要想判断上传的文件类型是不能直接使用type进行判断的,所以我使用截取字符串的形式来判断,当前上传图片的后缀名是否符合所需要求。 要求&#…

牛客网刷题 | BC97 回文对称数

目前主要分为三个专栏,后续还会添加: 专栏如下: C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读! 初来乍到,如有错误请指出,感谢! 描述 今天牛牛学到了回文…

电子电器架构 - AUTOSAR软件架构介绍

电子电器架构 - AUTOSAR软件架构介绍 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己…

Nginx代理配置(专业版)

写在前面提醒:使用代理,如果可以,请尽量支持双协议,http、https均要支持哈。 注意:监控系统只是运行代码,是否支持https,需要运维同学在你们的服务器上配置https证书,配置好证书&…

关于构建生成式AI产品的思考

在过去的六个月里,我们 LinkedIn 的团队一直在努力开发一种新的人工智能体验。我们希望重新构想我们的会员如何进行求职和浏览专业内容。 生成式人工智能的爆炸式增长让我们停下来思考一年前不可能实现的事情。我们尝试了许多想法,但都没有真正实现&…

OpenAI模型GPT-4o、GPT-4、Gemini 1.5性能比较

大家好,OpenAI最新推出的GPT-4o,标志着人工智能语言模型和交互方式迈入了新纪元。最引人注目的是,GPT-4o支持实时互动和流畅的对话切换,让交流更加自然。 本文将对比分析GPT-4o、GPT 4以及谷歌的Gemini和Unicorn模型,…

LabelMe下载及关键点检测数据标注

本文关键点数据集链接,提取码:x1pk 1.LabelMe下载 这部分内容和YOLOv8_seg的标注软件是一样的,使用anaconda创建虚拟环境安装LabelMe,指令如下: conda create -n labelme python=3.6 -y conda activate labelme conda install pyqt conda install pillow pip install la…

第六节:带你全面理解vue3 浅层响应式API: shallowRef, shallowReactive, shallowReadonly

前言 前面两章,给大家讲解了vue3中ref, reactive,readonly创建响应式数据的API, 以及常用的计算属性computed, 侦听器watch,watchEffect的使用 其中reactive, ref, readonly创建的响应式数据都是深层响应. 而本章主要给大家讲解以上三个API 对应的创建浅层响应式数据的 API,…

使用Java和XxlCrawler获取各城市月度天气情况实践

目录 前言 一、历史数据获取 1、关于天气后报 2、信息界面分析 二、数据的提取开发 1、PageVo的定义 2、属性定义 3、实际信息抓取 三、信息抓取调试以及可能的问题 1、信息获取成果 2、关于超时的问题 四、总结 前言 这篇文章主要来源于一个我们家小朋友的一个作业…

数据库管理-第194期 网络加速RDMA初探(20240526)

数据库管理194期 2024-05-26 数据库管理-第194期 网络加速RDMA初探(20240526)1 概念2 发展3 使用总结 数据库管理-第194期 网络加速RDMA初探(20240526) 作者:胖头鱼的鱼缸(尹海文) Oracle ACE A…

GCANet去雾算法

目录 1. 引言 2. 门控上下文注意机制(GCA) 3. 去雾流程 4. 模型代码 5. GCANet的优势 6. 去雾效果 1. 引言 GCANet(Gate-Controlled Attention Network)是一种用于图像去雾的深度学习算法,通过引入注意力机制来改进传统的去雾方法&…

使OpenCV可以读取中文路径图片的方法

一.问题复现 1.代码 #! /usr/bin/env python # -*- coding: utf-8 -*-# File: show_img.pyimport cv2# 读取图片 img cv2.imread("车牌素材/冀A.png")# 显示图片 cv2.imshow("img", img) cv2.waitKey(0)2.报错截图 3.报错内容 [ WARN:00.05…

简单好用的文本识别方法--付费的好用,免费的更有性价比

文章目录 先说付费的进入真题,免费的来喏!PixPin微信 先说付费的 直达网址!!! 进入真题,免费的来喏! PixPin 商店里就有 使用示例: 可以看到:贴在桌面上的图片可以复制图片中的文字,真的很…