【Python机器学习】NLP信息提取——值得提取的信息

目录

提取GPS信息

提取日期


如下一些关键的定量信息值得“手写”正则表达式:

  • GPS位置;
  • 日期;
  • 价格;
  • 数字。

和上述可以通过正则表达式轻松捕获的信息相比,其他一些重要的自然语言信息需要更复杂的模式:

  • 问题触发词;
  • 问题目标词;
  • 命名实体。

提取GPS信息

GPS位置时我们希望正则表达式从文本中提取的各种数值类型数据的典型代表。GPS位置具有成对的经纬度数值。它们有时还包括第三个数值,如高度或海拔高度,但暂时先忽略它。我们只提取十进制的经纬度对,用度数表示。这么模式适用于许多谷歌地图的URL地址。虽然严格说URL不是自然语言,但它们通常是非结构化文本数据的一部分,并且我们希望提取这种信息,从而让聊天机器人能够像了解事物一样了解位置信息。

我们使用十进制数字模式,但增加更多约束,确保该值在纬度和经度的有效范围内。最北到北极(+90度),最高到南极(-90度),具体代码:

import relat=r'([-]?[0-9]?[0-9][.][0-9]{2,10})'
lon=r'([-]?1?[0-9]?[0-9][.][0-9]{2,10})'sep=r'[,/ ]{1,3}'
re_gps=re.compile(lat+sep+lon)print(re_gps.findall('http://...maps/@34.0551066,-118.2496763'))
print(re_gps.findall("Zig Zag Cafe is at 45.344, -121.9323 on my GPS"))

数值类数据很容易提取,特别是当数字式可机读字符串的一部分的时候。URL和其他可机读字符串以可推测的顺序、格式或单位放置纬度和经度等数字,为提取提供了方便。上述模式还可以处理一些超出真实世界的经度和维度值,它可以较好的处理从地图Web应用程序中复制的大部分URL。

提取日期

提取日期比提取GPS坐标要难很多。日期更接近自然语言,可以通过不同的方言表达类似的事物。在美国,17年圣诞节的表示是“12/25/17”,而在欧洲,却表示为“25/12/17”。我们可以检查用户区域设置,并假设在同一个区域,日期表示方式是一样的。但这种假设可能在实际中是不成立的。

因此,大多数日期和时间提取器尝试适配上面两种日/月的表示顺序,并检查以确保是有效的日期。这也是当我们看到这样的日期时大脑的工作方式。即使是美国英语使用者,圣诞节在欧洲,也能认出“25/12/17”是一个假期。

这种在计算机编程中适用的“鸭子类型”方法也适用于自然语言。如果它看起来像一只鸭子并且表现得像是一一只鸭子,那么它可能就是一只鸭子。如果它看起来像日期并且表现得像日期,那么它可能就是日期。我们将在其他自然语言处理任务重也使用这种“先斩后奏”的方法。下面将尝试一系列方法并选择结果正确的方法,这里将尝试使用提取器或生成器,然后在其上运行验证器来判断它是否合理。

对聊天机器人来说,这是一种特别强大的方法,允许我们组合多个自然语言生成器的最佳结果。为了改善体验,可以生成大量回复并选择具备最佳拼写、语法和情感的回复,例如:

us=r'((([01]?\d)[-/]([0123]?\d))([-/]([0123]\d)\d\d)?)'
mdy=re.findall(us,"Santa came 12/25/2017.An elf appeared 12/12")
print(mdy)

通过把月、日和年转换成整数并使用有意义的名称标注这些数字信息,我们可以使用列表解析式为提取的数据提供结构化表示,如下所示:

dates=[{'mdy':x[0],'my':x[1],'m':int(x[2]),'d':int(x[3]),'y':int(x[4].lstrip('/') or 0),'c':int(x[5] or 0)} for x in mdy]
print(dates)

即使对于这些简单的日期,也不可能设计一个可以处理“12/12”这个日期中存在的奇异的正则表达式。日期表示中往往存在含糊不清的情况,只有人可以通过使用圣诞节相关的知识或作者的意图来猜测。例如,“12/12”可能表示:

  • 2017年12月12日——基于指代消解估计得到的年份的月/日格式;
  • 2018年12月12日——出版时当年年份的月/日格式;
  • 2012年12月——2012年的月/年格式。

因为月/日在美国日期和正则表达式中都出现在年份的前面,所以“12/12”被认为是某个未知年份的12月12日。我们可以使用在内存的结构化数据的上下文中最近读取到的年份来填充任何缺失的数字字段:

for i,d in enumerate(dates):for k,v in d.items():if not v:d[k]=dates[max(i-1,0)][k]
print(dates)
from datetime import date
datetimes=[date(d['y'],d['m'],d['d']) for d in dates]
print(datetimes)

上面是从自然语言文本中提取日期信息的基本但相当鲁棒的方法。如果将该方法用作生产系统的日期提取器,还需要做的主要工作是添加一些适用于我们应用程序的异常捕获和上下文管理。

我们可以通过一些硬编码逻辑来处理极端情况以及月甚至日的自然语言名称。但是再复杂的逻辑也无法处理“12/11”中存在的日期歧义,它可能是:

  • 某个看到或听到过年份的12月11日;
  • 11月12日;
  • 2011年12月;
  • 2012年11月。

即使是人脑也无法解决一些自然语言的歧义问题。但是,需要确保日期提取器可以通过在正则表达式中颠倒月和日来处理欧洲日/月顺序的日期:

eu=r'((([0123]?\d)[-/]([01]?\d))([-/]([0123]\d)?\d\d)?)'
dmy=re.findall(eu,"Alan Mathison Turing OBE FRS(23/6/1912-7/6/1954) as an English computer scientist.")
print(dmy)
dmy=re.findall(eu,"Alan Mathison Turing OBE FRS(23/6/12-7/6/54) as an English computer scientist.")
print(dmy)

正则表达式能够正确的从文字中提取日期。但上面的例子中已经把“June”转换成了数字“6”。我们希望聊天机器人能够从没有经过人工预处理的文章中提取日期,从而可以研读信息并学习导入日期。如果希望正则表达式能够处理更自然的像是百科文档中出现的日期信息,就需要再日期提取正则表达式中添加诸如“June”(及其所有缩写)之类的单词。

我们不需要任何特殊的符号来表示词组(按顺序组合在一起的字符),完全按照这些词组在输入中的拼写顺序,可以直接把它们写到正则表达式中,包括大小写。我们所要做的就是在正则表达式中使用一个OR符号(|)隔开这些词组。而且需要确保这个正则表达式既可以处理美国月/日的日期格式,也可以处理欧洲的日期格式。将这两个等同的日期“拼写”添加到正则表达式中,并在它们之间使用一个OR(|)作为正则表达式中决策树的分支。

我们使用一些命名分组来帮助我们识别像1984年的“84”和2008年的“08”这样的年份。尝试更准确地表示想要匹配的4位数年份,从过去的0年到未来的2999年:

yr_19xx=(r'\b(?P<yr_19xx>'+'|'.join('{}'.format(i) for i in range(30,100))+r'?\b'
)
yr_20xx=(r'\b(?P<yr_20xx>' +'|'.join('{:02d}'.format(i) for i in range(10)) + '|' +'|'.join('{}'.format(i) for i in range(10,30))+r')\b'
)
yr_cent=r'\b(?P<yr_cent>'+'|'.join('{}'.format(i) for i in range(1,40))+r')'
yr_ccxx=r'(?P<yr_ccxx>'+'|'.join('{:02d}'.format(i) for i in range(0,100))+r')\b'
yr_xxxx=r'\b(?P<yr_xxxx>'+yr_cent+')('+yr_ccxx+r'))\b'
yr=(r'\b(?P<yr>'+yr_19xx+'|'+yr_20xx+'|'+yr_xxxx+r')\b'
)
groups=list(re.finditer(yr,"0,2000,01,'08,99,1984,2030/1970 85 47 `66"))
full_years=[g['yr'] for g in groups]
print(full_years)

仅仅是使用正则表达式中一些简单的年份规则,还没有用到Python,工作量就很大了。但是软件包可用于识别常见的日期格式,它们更精确、更通用。所以不需要自己编写复杂的正则表达式。上面的示例仅是提供了一种可以遵循的模式,以防将来需要使用正则表达式提取特定类型的数字。在货币数值和IP地址提取的例子中,带有命名分组的更复杂的正则表达式可能会派上用场。

在百科文章的日期中,在提取日期时添加月份名称对应的模式“June”或者“Jun”,来完成正则表达式以提取日期:

mon_words='January February March April May June July August September October November December'
mon=(r'\b('+'|'.join('{}|{}|{}|{}|{:02d}'.format(m,m[:4],m[:3],i+1,i+1) for i,m in enumerate(mon_words.split()))+r')\b')
print(re.findall(mon,"January has 31 days,February the 2nd month of 12, has 28,except in a Leap Year."))

将这些正则表达式组合成一个可以处理所有日期格式的大型表达式的难点在于我们不能为分组(正则表达式中的括号内的部分)复用相同的名称。所以不能再不同格式对应的月份和年份的命名正则表达式之间使用OR。此外,表达式中需要包含日、月和年之间任意分隔符的模式。

下面是一个满足上述需求的例子:

day=r'|'.join('{:02d}|{}'.format(i,i) for i in range(1,32))
eu=(r'\b('+day+r')\b[-,/ ]{0,2}\b('+mon+r')\b[-,/ ]{0,2}\b('+yr.replace('<yr','<eu_yr')+r')\b')
us=(r'\b('+mon+r')\b[-,/ ]{0,2}\b('+day+r')\b[-,/ ]{0,2}\b('+yr.replace('<yr','<us_yr')+r')\b')
date_pattern=r'\b('+eu+'|'+us+r')\b'
print(list(re.finditer(date_pattern,'31 Oct, 1970 25/12/2017')))

最后,需要验证日趋的日期,看这个日期是否可以转换为有效的Python datetime对象:

import datetime
dates=[]
for g in groups:#print(g.groupdict())month_num=(g['us_mon'] or g['eu_mon']).strip()try:month_num=int(month_num)except ValueError:month_num=[w[:len(month_num)]for w in month_num].index(month_num)+1date=datetime.date(int(g['us_yr'] or g['eu_yr']),month_num,int(g['us_day'] or g['eu_day']))dates.append(date)
print(dates)

日期提取器看起来运行正常,至少在这几个简单的、无歧义的日期上是这样的。

如果只要想一个最先进的日期提取器,基于统计(机器学习)的方法能够更快的满足需求。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【win工具】win安装flameshot并设置截图快捷键

1.下载flameshot软件2.windows端配置flameshot快捷键3.取消win自带截图快捷键 1.下载flameshot软件 https://flameshot.org/#download installer版本为安装包 portable版本为免安装版 2.windows端配置flameshot快捷键 https://cloud.tencent.com/developer/article/2114952 W…

Linux 防火墙:iptables (二)

文章目录 SNAT 原理与应用SNAT 应用环境SNAT 原理SNAT 转换前提条件SNAT 格式SNAT 转换规则配置 DNAT 原理与应用DNAT 应用环境DNAT 原理DNAT 转换前提条件DNAT 格式DNAT 转换规则配置 iptables 规则的备份和还原导出&#xff08;备份&#xff09;所有表的规则导入&#xff08;…

电脑USB端口禁止软件有哪些?什么软件能指定USB端口禁用?分享四款好用软件!

想象一下&#xff0c;你正准备在办公桌上插入U盘&#xff0c;打算快速拷贝文件&#xff0c;突然系统蹦出一个警告&#xff1a;“这个USB端口已被禁用&#xff01;” 是不是感觉好像被一双隐形的手制止了&#xff1f; 其实&#xff0c;这双“隐形的手”就是专门为企业安全设计…

redis群集三种模式:主从复制、哨兵、集群

redis群集有三种模式 redis群集有三种模式&#xff0c;分别是主从同步/复制、哨兵模式、Cluster&#xff0c;下面会讲解一下三种模式的工作方式&#xff0c;以及如何搭建cluster群集 ●主从复制&#xff1a;主从复制是高可用Redis的基础&#xff0c;哨兵和集群都是在主从复制…

集采良药:从“天价神药”到低价良药,伊马替尼的真实世界研究!

在医疗科技日新月异的今天&#xff0c;有一种药物以其卓越的疗效和深远的影响力&#xff0c;成为了众多患者心中的“精准武器”——伊马替尼。这款药物不仅在慢性髓细胞白血病&#xff08;CML&#xff09;的治疗上屡创佳绩&#xff0c;更是胃肠道间质瘤&#xff08;GIST&#x…

哪个牌子的护眼台灯性价比高?网上排名前列的护眼台灯推荐

现在市面上形形色色的打着“护眼”口号的台灯太多了&#xff0c;因为眼睛对于我们来说很重要&#xff0c;我们看到美丽的事物都因为有他&#xff0c;所以大家一听到护眼就会选择购买。很多商家为了赚钱&#xff0c;随便贴个标签就说护眼&#xff0c;其实一点用都没有。哪个牌子…

AJAX Jquery $.get $.post $.getJSON

AJAX AJAX Asynchronous JavaScript and XML (异步的J avascript和XML)。 Ajax $.ajax <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, in…

828华为云征文|基于华为云Flexus云服务器X实现个人博客搭建

文章目录 ❀前言❀部署前准备❀宝塔安装❀安全组开放❀web访问验证❀安装docker❀安装wordpress❀安全组开放18040端口❀访问博客网址❀发布个人博客❀总结 ❀前言 大家好&#xff0c;我是早九晚十二。 近期华为云推出了最新的华为云Flexus云服务器X&#xff0c;这款云主机在算…

服务器自动巡检(Server automatic inspection)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

Microsoft Edge 五个神级插件

&#x1f423;个人主页 可惜已不在 &#x1f424;这篇在这个专栏 插件_可惜已不在的博客-CSDN博客 &#x1f425;有用的话就留下一个三连吧&#x1f63c; 目录 Microsoft Edge 一.安装游览器 ​编辑 二.找到插件商店 1.打开游览器后&#xff0c;点击右上角的设置&#x…

BLE 协议之链路层

目录 一、前言二、状态和角色三、Air Interface Packets1、Preamble 字段2、Access Address 字段2.1 静态地址2.2 私有地址 3、PDU 字段3.1 Advertising Channel PDU3.1.1 Header 字段3.1.2 Payload 字段 3.2 Data Channel PDU3.2.1 Header 字段3.2.2 Payload 字段 4、CRC 字段…

STM32上实现FFT算法精准测量正弦波信号的幅值、频率和相位差(标准库)

在研究声音、电力或任何形式的波形时&#xff0c;我们常常需要穿过表面看本质。FFT&#xff08;快速傅里叶变换&#xff09;就是这样一种强大的工具&#xff0c;它能够揭示隐藏在复杂信号背后的频率成分。本文将带你走进FFT的世界&#xff0c;了解它是如何将时域信号转化为频域…

【微信小程序】搭建项目步骤 + 引入Tdesign UI

目录 创建1个空文件夹&#xff0c;选择下图基础模板 开启/支持sass 创建公共style文件并引入 引入Tdesign UI: 1. 初始化&#xff1a; 2. 安装后&#xff0c;开发工具进行构建&#xff1a; 3. 修改 app.json 4. 使用 5. 自定义主题色 创建1个空文件夹&#xff0c;选择下…

初始c++:入门基础(完结)

打字不易&#xff0c;留个赞再走吧~~~ 目录 一函数重载二引用1 引⽤的概念和定义2引⽤的特性3引⽤的使⽤三inline四nullptr 一函数重载 C⽀持在同⼀作⽤域中出现同名函数&#xff0c;但是要求这些同名函数的形参不同&#xff0c;可以是参数个数不同或者 类型不同。这样C函数调⽤…

FPGA随记-二进制转格雷码

反射二进制码&#xff08;RBC&#xff09;&#xff0c;也称为反射二进制&#xff08;RB&#xff09;或格雷码&#xff08;Gray code&#xff09;&#xff0c;得名于Frank Gray&#xff0c;是二进制数制的一种排列方式&#xff0c;使得连续两个值之间仅有一个比特&#xff08;二…

【Python进阶】requests库有哪些常用的参数和方法?一篇文章带你详细了解!!!附带源码

常用的requests库参数和方法 常用方法 requests库中定义了多个常用的请求方法&#xff0c;其中requests.get()和requests.post()是最常用的方法。这些方法对应于HTTP协议中的GET和POST方法。 requests.get(url, paramsNone, **kwargs): 用于发送GET请求。requests.post(url…

【高阶数据结构】二叉搜索树的插入、删除和查找(精美图解+完整代码)

&#x1f921;博客主页&#xff1a;醉竺 &#x1f970;本文专栏&#xff1a;《高阶数据结构》 &#x1f63b;欢迎关注&#xff1a;感谢大家的点赞评论关注&#xff0c;祝您学有所成&#xff01; ✨✨&#x1f49c;&#x1f49b;想要学习更多《高阶数据结构》点击专栏链接查看&a…

Mysql梳理6——order by排序

目录 6 order by排序 6.1 排序数据 6.2 单列排序 6.3 多行排列 6 order by排序 6.1 排序数据 使用ORDER BY字句排序 ASC&#xff08;ascend&#xff09;:升序DESC(descend):降序 ORDER BY子句在SELECT语句的结尾 6.2 单列排序 如果没有使用排序操作&#xff0c;默认…

一、桥式整流电路

桥式整流电路 1、二极管的单向导电性: 伏安特性曲线: 理想开关模型和恒压降模型 2、桥式整流电流流向过程 输入输出波形: 3、计算:Vo,lo,二极管反向电压。 学习心得