背景介绍

  在平时的NLP任务中,我们经常用到命名实体识别(NER),常用的识别实体类型为人名、地名、组织机构名,但是我们往往也会有识别其它实体的需求,比如时间、品牌名等。在利用算法做实体识别的时候,我们一般采用序列标注算法,这就对标注的文本格式有一定的要求,因此,一个好的序列标注的平台必不可少,将会大大减少我们标注的工作量,有效提升算法的更新迭代速度。
  本文将介绍笔者的一个工作:自制的序列标注平台。我们以时间识别为例。比如,在下面的文章中:

按计划,2019年8月10日,荣耀智慧屏将在华为开发者大会上正式亮相,在8月6日,荣耀官微表示该产品的预约量已破十万台,8月7日下午,荣耀总裁赵明又在微博上造势率先打出差异化牌,智慧屏没有开关机广告,并表态以后也不会有,消费者体验至上,营销一波接一波,可谓来势汹汹。

我们需要从该文章中标注出三个时间:2019年8月10日8月6日8月7日下午,并形成标注序列。
  下面将详细介绍笔者的工作。

序列标注平台

  由于开发时间仓促以及笔者能力有限,因此,序列标注平台的功能还没有很完善,希望笔者的工作能抛砖引玉。
  项目的结构图如下:

templates中存放静态资源,time_index.html为平台的操作界面,time_output为平台标注完实体后的文件保存路径,time_server.py是用tornado写的服务端路径控制代码,utils.py中是获取某个路径下的txt文件的最大数值的函数。

  其中,utils.py的完整代码如下:

# -*- coding: utf-8 -*-
# time: 2019-03-14
# place: Xinbeiqiao, Beijingimport os# 获取当前所在目录的txt文本的最大数值
def get_max_num(path):files = os.listdir(path)if files:numbers = list(map(lambda x: int(x.replace('.txt', '')), files))return max(numbers)else:return 0

  time_server.py的完整代码如下:

# -*- coding: utf-8 -*-
# time: 2019-08-08
# place: Xinbeiqiao, Beijingimport os.path
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
from tornado.options import define, options
from utils import get_max_num#定义端口为9005
define("port", default=9005, help="run on the given port", type=int)# GET请求
class QueryHandler(tornado.web.RequestHandler):# get函数def get(self):self.render('time_index.html', data = ['', []])# POST请求
class PostHandler(tornado.web.RequestHandler):# post函数def post(self):# 获取前端参数, event, time, indexevent = self.get_argument('event')times = self.get_arguments('time')indices = self.get_arguments('index')print(event)print(times)print(indices)# 前端显示序列标注信息tags = ['O'] * len(event)for time, index in zip(times, indices):index = int(index)tags[index] = 'B-TIME'for i in range(1, len(time)):tags[index+i] = 'I-TIME'data = [event, tags]self.render('time_index.html', data=data)# 保存为txt文件dir_path = './time_output'with open('./%s/%s.txt' % (dir_path, get_max_num(dir_path)+1), 'w', encoding='utf-8') as f:for char, tag in zip(event, tags):f.write(char+'\t'+tag+'\n')# 主函数
def main():# 开启tornado服务tornado.options.parse_command_line()# 定义appapp = tornado.web.Application(handlers=[(r'/query', QueryHandler),(r'/result', PostHandler)], #网页路径控制template_path=os.path.join(os.path.dirname(__file__), "templates") # 模板路径)http_server = tornado.httpserver.HTTPServer(app)http_server.listen(options.port)tornado.ioloop.IOLoop.instance().start()main()

  time_index.html文件如下:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>时间抽取标注平台</title><link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css"><script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script><script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script><style>mark {background-color:#00ff90; font-weight:bold;}p{text-indent:2em;}</style><script>var click_cnt = 0;// 双击第i个select, 添加文字的indexfunction select_click(i){var content = document.getElementById('event').value;var time = document.getElementById('time_'+i.toString()).value;for(var j=0; j<=content.length-time.length; j++){if(content.substr(j, time.length) == time){var select = document.getElementById('index_'+i.toString());var option = document.createElement("option");option.value = j;option.innerHTML = j;select.appendChild(option);}}}// 添加输入框和select框$(document).ready(function(){$("#add_time").click(function(){click_cnt = click_cnt + 1;var input_id = new String('time_'+click_cnt.toString());var index_id = new String('index_'+click_cnt.toString());var content = "<input type='text' id=" + input_id + " class='form-control' style='width:306px;' name='time' /> \&emsp;&emsp;&emsp; <select class='form-control' name='index' id="+ index_id + " style='width:120px;' \οndblclick='select_click("+click_cnt.toString()+")'></select>";$(content).appendTo($("#time_column"));});});</script>
</head>
<body><center><br><br><br>
<form class="form-horizontal" role="form" method="post" action="/result" style="width:600px"><div class="form-group"><label for="event" class="col-sm-2 control-label">输入语料</label><div class="col-sm-10"><textarea type="text" class="form-control" id="event" style="width:490px; height:200px" name="event"></textarea></div></div><div class="form-inline" style="text-align:left;"><label for="time_0" class="col-sm-2 control-label">时间</label><div class="col-sm-10" id="time_column"><input type="text" class="form-control" id="time_0" style="width:306px;" name="time" />&emsp;&emsp;&emsp;<select class="form-control" id="index_0" name="index" style="width:120px;" ondblclick="select_click(0)"></select></div></div><div class="form-group"><div class="col-sm-offset-2 col-sm-10"><br><button type="button" class="btn btn-default" id="add_time">添加时间</button><button type="submit" class="btn btn-success">显示标签</button><a href="/query"><button type="button" class="btn btn-danger">返回</button></a><button type="reset" class="btn btn-warning">重置</button></div></div></form><br><div style="width:600px"><p> 原文:{{data[0]}} </p><table class="table table-striped">{% for char, tag in zip(data[0], data[1]) %}<tr><td>{{char}} </td><td>{{tag}} </td></tr>{%end%}</table></div>
</center></body>
</html>

平台使用

  运行上述time_server.py后,在浏览器端输入网址: http://localhost:9005/query , 则会显示如下界面:

  在输入语料框中,我们输入语料:

8月8日是“全民健身日”,推出重磅微视频《我们要赢的,是自己》。

在时间这个输入框中,可以标注语料中的时间,同时双击同一行中的下拉列表,就能显示该标注时间在语料中的起始位置,有时候同样的标注时间会在语料中出现多次,那么我们在下拉列表中选择我们需要的标注的起始位置即可。
  点击添加时间按钮,它会增加一行标注,允许我们在同一份预料中标注多个时间。我们的一个简单的标注例子如下:

  点击显示标注,则会显示我们标注完后形成的序列标注信息,同时将该序列信息保存为txt文件,该txt文件位于time_output目录下。在网页上的序列标注信息如下:

同时,我们也可以查看保存的txt文档信息,如下:

  点击返回按钮,它会允许我们进行下一次的标注。刚才展示的只是一个简单例子,稍微复杂的标注如下图:

它形成的标注序列(部分)如下:

按    O
计   O
划   O
,    O
2   B-TIME
0   I-TIME
1   I-TIME
9   I-TIME
年   I-TIME
8   I-TIME
月   I-TIME
1   I-TIME
0   I-TIME
日   I-TIME
,    O
荣   O
耀   O
智   O
慧   O
屏   O
将   O
在   O
华   O
为   O
开   O
发   O
者   O
大   O
会   O
上   O
正   O
式   O
亮   O
相   O
,    O
在   O
8   B-TIME
月   I-TIME
6   I-TIME
日   I-TIME
,    O
荣   O
耀   O
官   O
微   O
表   O
示   O
该   O
产   O
品   O
......

总结

  本平台仅作为序列标注算法的前期标注工具使用,并不涉及具体的算法。另外,后续该平台也会陆续开放出来,如果大家有好的建议,也可以留言~
  本项目已上传只Github, 网址为: https://github.com/percent4/entity_tagging_platform

注意:不妨了解下笔者的微信公众号: Python爬虫与算法(微信号为:easy_web_scrape), 欢迎大家关注~

NLP(十四)自制序列标注平台相关推荐

  1. 新手探索NLP(八)——序列标注

    转载自知乎https://zhuanlan.zhihu.com/p/50184092 NLP中的序列标注问题(隐马尔可夫HMM与条件随机场CRF) Introduction 序列标注问题(sequen ...

  2. 深聊全链路压测之:第二十四讲 | 分布式调度平台的选型与落地。

    落地分布式调度平台 1.引言 2.平台选型 2.1 中间件对比与筛选 2.2 XXL-JOB介绍 3.平台落地思路与实践 3.1 落地思路 3.2 落地实践 3.2.1 搭建XXL-JOB 3.2.2 ...

  3. Openstack云平台脚本部署之Ceph存储集群配置(十四)

    目录 一.简介 二.部署脚本 三.参考文档 四.源码 五.系列文章 一.简介 Openstack的后端存储对接Ceph分布式统一存储,将Glance镜像.Nova虚拟机及快照.Cinder-Volum ...

  4. 【Microsoft Azure 的1024种玩法】七十四.五分钟在Azure Virtual Machines中快速部署一套软件项目管理及自动构建工具

    [简介] Apache Maven由 Apache 软件基金会所提供的一个软件项目管理及自动构建工具,Maven 为开发者提供了一套完整的构建生命周期框架.开发团队几乎不用花多少时间就能够自动完成工程 ...

  5. 【Microsoft Azure 的1024种玩法】六十八.基于Azure云平台使用Azure Virtual machines快速搭建Docker容器

    [简介] Docker 是一个开放源代码软件,主要应用于开发应用.交付应用.运行应用,Docker 可以将应用程序及其依赖项打包到可以在任何 Linux.Windows 或 macOS 计算机上运行的 ...

  6. NLP(三十四)使用keras-bert实现序列标注任务

      对于不同的NLP任务,使用BERT等预训练模型进行微调无疑是使用它们的最佳方式.在网上已经有不少的项目,或者使用TensorFlow,或者使用Keras,或者使用PyTorch对BERT进行微调. ...

  7. 自然语音处理(NLP)系列(三)——什么是序列标注?

    自然语音处理(NLP)是人工智能领域中的重要一环,在过去的二十年里,NLP利用机器学习和深度学习的研究成果,在很多方面取得了不小的进步.比尔·盖茨曾说,"语言理解是人工智能皇冠上的明珠&qu ...

  8. PaddleHub实战篇{ERNIE实现文新闻本分类、ERNIE3.0 实现序列标注}【四】

     相关文章: 基础知识介绍: [一]ERNIE:飞桨开源开发套件,入门学习,看看行业顶尖持续学习语义理解框架,如何取得世界多个实战的SOTA效果?_汀.的博客-CSDN博客_ernie模型 百度飞桨: ...

  9. NLP(三十七)使用keras-bert实现英语序列标注任务

      在文章NLP(三十四)使用keras-bert实现序列标注任务中,我们已经用keras-bert模块实现了中文序列标注任务,其中对BERT进行微调.当前,我们也可以顺便实现下英语序列标注任务.   ...

最新文章

  1. CPU的自动调度矩阵乘法
  2. Set Up the Dispatcher Console
  3. 中国煤炭行业十四五投资战略与供需形势分析报告2022版
  4. 终结 Python 原生字典?这个库要逆天改命了
  5. java objectid_需要一种解决方法来查找objectID foreignField的字符串
  6. 看《长安十二时辰》可以了解哪些算法知识
  7. Android之XML序列化和解析
  8. Fiddler 抓包(二)—Android
  9. (淘宝无限适配)手机端rem布局详解(转载非原创)
  10. keepalived配置参数官方文档中文翻译版
  11. linux和宿主机windows之间建立共享文件夹
  12. 转:浅析 Java Thread.join()
  13. office2013简体中文版官方下载
  14. 汪文君PowerMock实战视频
  15. oracle 11 ora 12514,oracle 11g ORA 12514错误,我的解决办法
  16. @千行百业,一起乘云而上
  17. 课程预约小程序开发需要哪些功能?
  18. 通行宝深交所上市:市值84亿 腾讯云与上汽是股东
  19. CVPR 2022 | Accuracy和F1-score真的能代表车道线检测网络性能吗?
  20. (云服务器学习)部署python程序到云服务器

热门文章

  1. Educoder头歌—Java多线程基础常用函数
  2. Oracle 主外键约束
  3. 回顾:oauth2和 spring cloud alibaba gateway 整合
  4. S7-300 400 PLC 系统软件冗余调试的常见问题
  5. 霍金 北京《宇宙的起源》演讲全文
  6. canvas截取多个视频的第一帧,第n秒画面
  7. 技术无罪,那快播呢?
  8. R语言使用epiDisplay包的mlogit.display函数获取无序多分类logistic回归模型的汇总统计信息(各分组模型对应的系数及标准差、相对危险降低率RRR值及其置信区间、AIC值等)
  9. 高通mdm9607 mcfg_sw.mbn配置编译流程
  10. python中同名函数