小白使用百度 NLP 实现语料库 TTR 统计

栏目: 编程工具 · 发布时间: 5年前

内容简介:本人是一个文科生,本科学英语,硕士学翻译。学院里都流行的是语言学研究,我个人更喜欢的是计算语言学,看了几本书和论文之后就对计算语言学和语料库语言学深感兴趣。奈何读书那会对这些技术一窍不通,代码也看不进去,工作几年后还是对这方面感兴趣,就从10月份开始学python,做了个基础的入门,然后开始挑选适合自己的NLP技术方案。对于技术小白来说,能少写代码就少写代码,越简单越好,因为我只是奔着一个目的来的:输入文本,处理文本,返回处理后的数据。即可。这次我要实现的是语料库语言学研究中的TTR(Type Token

本人是一个文科生,本科学英语,硕士学翻译。学院里都流行的是语言学研究,我个人更喜欢的是计算语言学,看了几本书和论文之后就对计算语言学和语料库语言学深感兴趣。奈何读书那会对这些技术一窍不通,代码也看不进去,工作几年后还是对这方面感兴趣,就从10月份开始学python,做了个基础的入门,然后开始挑选适合自己的NLP技术方案。

对于技术小白来说,能少写代码就少写代码,越简单越好,因为我只是奔着一个目的来的:输入文本,处理文本,返回处理后的数据。即可。

这次我要实现的是语料库语言学研究中的TTR(Type Token Ratio)的统计,它表示的是一个文本中相同的词和所有词之间的比例关系。

举个例子:

CIPS-SIGHAN CLP 2010(国家自然科学基金(基金号:90920004))中,TTR在不同类型的文体中有着不一样的数据(下图),若以其中“文学”的数据为基准,其他作者的文本的TTR超过这个基准数据,那意味着作者在写作的时候用词丰富性不够、重复内容较多、语言较通俗易懂等,低于这个基准数据,则意味着作者用了一些生僻的词语、用词丰富性很高等。

小白使用百度 NLP 实现语料库 TTR 统计

这仅仅是语言学进行分析时的一个指标,还有很多很多其他的。这里只讨论如何用python+百度NLP去实现TTR。

本人半路出家写代码,肯定有各种各样的问题,还请各路大神出来指点,写出来的代码能运行不报错,就ok了。

为何选百度

为什么选百度?

同时留下了没有技术和没有金钱的泪水……

小白使用百度 NLP 实现语料库 TTR 统计

精挑细选(数个小时的尝试),阿里云的NLP,10万次要270块钱,腾讯文智5万次免费,百度云免费用QPS = 5 (Query Per Second,每秒请求次数(这个我当时还不知道啥意思,当超了的时候才明白是一秒只能请求多少次))。

阿里云的基础版说是有每日5万次免费额度,但是没找到在哪。文智的api和sdk,卡在了签名鉴权上,放弃。

最后只能选择百度,而且现在只写百度,以后等我学会了其他的, 我再把另外两家补上。

对于小白来说,除了 python 本身的一些代码我不需要查之外,剩下的都得慢慢学慢慢查,变学变进步吧!所以,技术文档的详细程度也决定我的动手能力和成果。

NLP号,启动!

小白使用百度 NLP 实现语料库 TTR 统计

(插一句,妈耶,掘金上传图片的背景颜色还会忽闪忽闪的)

环境:python 3.7,baidu-aip 模块,vscode+jupyter notebook(比心)

shell 里输入,然后等待安装完成

pip install baidu-aip复制代码

提示success之后,务必命令行里输入python,进入python后

import aip
复制代码

确认不会报错,就可以启动了!

wait,钥匙没插进去呢

在启动之前,需要去百度云控制面板获取开启本服务的APP_ID

小白使用百度 NLP 实现语料库 TTR 统计

点击左侧的应用列表,创建应用

小白使用百度 NLP 实现语料库 TTR 统计

自然语言处理无法勾选,怎么回事,哦原来是默认全选的,这些足够了,写好名称和描述(随意),立即创建,拿到发动机钥匙了!

留好,下面会用到

程序设计思路

  1. python读取文档内容,写入变量
  2. 对内容进行简单处理(去除前后空格)
  3. 送入百度NLP去处理
  4. 返回数据后提取相关数据,计算TTR

差不多就是这么个顺序,发动机,打火,启动!

小白使用百度 NLP 实现语料库 TTR 统计

好,让我们来处理一下这首朱自清的现代诗《赠友》

你的手像火把,

你的眼像波涛,

你的言语如石头,

怎能使我忘记呢?

你飞渡洞庭湖,

你飞渡扬子江;

你要建红色的天国在地上!

地上是荆棘呀,

地上是狐兔呀,

地上是行尸呀;

你将为一把快刀,

披荆斩棘的快刀!

你将为一声狮子吼,

狐兔们披靡奔走!

你将为春雷一震,

让行尸们惊醒!

我爱看你的骑马,

在尘土里驰骋---

一会儿, 不见踪影!

我爱看你的手杖,

那铁的铁的手杖;

它有颜色,有斤两,

有铮铮的声响!

我想你是一阵飞沙

走石的狂风,

要吹倒那不能摇撼的黄金的王宫!

那黄金的王宫!

呜---吹呀!

去年一个夏天大早我见着你:

你何其憔悴呢?

你的眼还涩着,

你的发太长了!

但你的血的热加倍的薰灼着!

在灰泥里辗转的我,

仿佛被焙炙着一般!---

你如郁烈的雪茄烟,

你如酽酽的白兰地,

你如通红通红的辣椒,

我怎能忘记你呢?

读取文档内容,写入变量

from aip import AipNlp
import time  

file = open("C:\\workspace\\nltk\\shi.txt",
            'r',
            encoding="utf-8-sig").readlines() 

for i in range(len(file)):
    file[i].strip() #将句子前后的空格去掉    print('\n【即将分词这一句】',file[i],'\n\n')

    seg_word(file[i]) #送入百度NLP处理
复制代码

读取文档的过程中遇到过一个问题,编码采用utf-8的话会在开头出现一个奇怪的字符,才用utf-8-sig后就不再出现这个问题。

此时file是个list。我觉得在写python的过程中,时时刻刻需要注意变量的类型,几乎每时每刻我都在打印内容,好找错误。

加入for循环,循环list[i]的,使用.strip()去除每一行前后的空格。而在某些文本中,空格还会在处理的时候报错,我还需要去手动修改文档。现在还没学会这个技能,所以文档里的内容是没有包含空行和奇怪空格的。学艺不精,慢慢来吧。

*百度nlp不能输入空白内容,会报错。

送入百度NLP去处理

在此之前,我们要完成对nlp接口的配置,你需要替换成自己的id、API_key、Secret_key。

APP_ID = "148595**"
API_KEY= "M91DlMXQ0rTAvlL******"
SECRET_KEY = "FzCDK9hzWPd1Qgvt*****"
client =AipNlp(APP_ID, API_KEY, SECRET_KEY)复制代码

这里使用nlp的lexer接口,输入句子,返回分词结果。(接口说明文档)

def seg_word(abc):    
    text = abc    
    res = client.lexer(text) #返回的是词典    
    res_1 = res['items'] #从词典中取出返回值中的核心内容items,是一个新的字典        
    for i in range(len(res_1)):        
        s = res_1[i]['item'] #从字典的每一条中抽出一个对应的分词数据来        
        # print('将把这个词放入列表中【',s,'】\n')        
        seg_list.append(s) #加入list中,变成只获得分词    
    print('\n现已分词的词语包括',seg_list)
复制代码

res返回的是一个json字典结构,我们需要的内容是items对应的value:

{'log_id': 2198288401988815642, 
    'text': '你', 
    'items': [{'loc_details': [],
             'byte_offset': 0,
             'uri': '',
             'pos': 'r',
             'ne': '',
             'item': '你',
             'basic_words': ['你'],
             'byte_length': 2,
             'formal': ''}]
}
复制代码

分词的结果中,我们需要的是item对应的value,它就是TTR中的一个token。我们取这个Token的值,放入一个新的列表seg_list中。用append方式添加。

seg_word这个function会将file文档里的每一行进行分词,在这个function里使用for循环,将每一个分词的结果提取items下面的item的value,写入seg_list(这是一个list)。

seg_list里包含这首诗的所有分词后的Token。

计算TTR

然后我们打印一下这个列表的内容,以及计算一下它的长度。

print(seg_list)token_count = len(seg_list)print(token_count)复制代码

小白使用百度 NLP 实现语料库 TTR 统计

可以看到,这首诗所有的token都在做合理,还算比较准的。长度为251,有251个词,包含重复的。这就是我们要计算TTR里面的Token了。

现在,我们要将这些Token去重,获得一个不重复的词语列表。

type_count = set()

for i in range(len(seg_list)):
    print("现在我们将【",seg_list[i],'】加入type列表')
    type_count.add(seg_list[i])

print('type列表目前包含:', type_count)
print('type的长度为', len(type_count))
复制代码

去重的一个思路是使用set,因为set里只包含唯一的元素,非常适合去重使用。

小白使用百度 NLP 实现语料库 TTR 统计

然后for循环,将内容不断地往set里面塞……

小白使用百度 NLP 实现语料库 TTR 统计

得到的结果是:type的长度是118,也就是说这首诗里面不重复的词有118个。

最后我们来计算一下这个ratio。

ratio = float(len(type_count) / token_count) * 100
print('Type Token Ratio: {:.2f}%'.format(ratio))复制代码

小白使用百度 NLP 实现语料库 TTR 统计

哎嘿,结果出来了,这首诗的TTR是47.01%。

小白使用百度 NLP 实现语料库 TTR 统计

emmmm……好像比上面提到的基准数据差的很远很远呢。原因很简单,诗句的用词本身就很精炼,我们回过头去看那首诗就明白了,为了保持诗的结构,会使用很多重复的词语,比如“你”、“飞”、“地上”、“手杖”、“我”等。

-----------------------

完整代码

#coding=utf-8
#%%  用过jupyter的都说好
from aip import AipNlp
import time APP_ID = "14859***"
API_KEY= "M91DlMXQ0rT*****"
SECRET_KEY = "FzCDK9hzWPd1Qgvt*********"
client =AipNlp(APP_ID, API_KEY, SECRET_KEY)
# client.lexer(text) #核心运行
seg_list = []
type_count = set()

#%% def seg_word(abc):
    text = abc
    res = client.lexer(text) #这里返回的是词典
    res_1 = res['items'] #从词典中取出返回值中的核心内容items,是一个新的字典
    # print('百度nlp处理后的数据:\n',res_1,'\n')

    for i in range(len(res_1)):
        s = res_1[i]['item'] #从字典的每一条中抽出一个对应的分词数据来
        # print('将把这个词放入列表中【',s,'】\n')
        seg_list.append(s) #加入list中,变成只获得分词

    print('\n现已分词的词语包括',seg_list)

#延时器
def sleep(a):
     a=int(a)
     time.sleep(a)

#%% 读取文档内容
file = open("C:\\workspace\\nltk\\shi.txt",'r',encoding="utf-8-sig").readlines()
# print('原始文档内容:\n',file,'\n')
#循环将句子或段落带入function,超量预警\a响铃
for i in range(len(file)):
    #加入一个5次请求的1秒延时器
    n = i + 1
    m = (i/5)*10
    if (m%5) ==0:
        sleep(1)
        print("\a***********************可能会超过api限制,休息1秒*************************")
    file[i].strip() #将句子前后的空格去掉
    print('\n【即将分词这一句】',file[i],'\n\n')
    seg_word(file[i]) #送入function去让百度处理
#%% 计算token词数量
print(seg_list)
token_count = len(seg_list)
print(token_count)

#%%计算type词数量
for i in range(len(seg_list)):
    print("现在我们将【",seg_list[i],'】加入type列表')
    type_count.add(seg_list[i])
print('type列表目前包含:', type_count)
print('type的长度为', len(type_count))

#%%计算type token ratio
ratio = float(len(type_count) / token_count) * 100
print('Type Token Ratio: {:.2f}%'.format(ratio))
复制代码

完整代码在这里,里面还加入了sleep延时的功能。

因为百度NLP的QPS是5,也就是一秒5次,所以我写了一个每请求5次就休息1秒的函数放在里面,这样就不会超量后报错。其实也可以直接在每一次请求后sleep 0.2-0.3秒来确保稳定且不会超过额度。

文章里的lexer接口只是其中的一个,还有sentimentClassify我觉得也很有意思,是用来做情感分析的。配合抓取内容后对情绪进行分析,可以了解某个人物或者某个事件里文字所反映出来的情绪,对于一些事情做辅助判断。

下一篇写这个好了,还是蛮有意思的。

本人半路出家写代码,肯定有各种各样的问题,还请各路大神出来指点。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

颠覆者:周鸿祎自传

颠覆者:周鸿祎自传

周鸿祎、范海涛 / 北京联合出版公司 / 2017-11 / 49.80元

周鸿祎,一个在中国互联网历史上举足轻重的名字。他被认为是奠定当今中国互联网格局的人之一。 作为第一代互联网人,中国互联网行业最好的产品经理、创业者,他每时每刻都以自己的实践,为互联网的发展贡献自己的力量。 在很长一段时间内,他没有在公共场合发声,甚至有粉丝对当前死水一潭的互联网现状不满意,发出了“人民想念周鸿祎”的呼声。 但周鸿祎在小时候,却是一个踢天弄井,动不动就大闹天宫的超级......一起来看看 《颠覆者:周鸿祎自传》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器