本人是一個文科生,本科學英語,碩士學翻譯。學院裏都流行的是語言學研究,我我的更喜歡的是計算語言學,看了幾本書和論文以後就對計算語言學和語料庫語言學深感興趣。奈何讀書那會對這些技術一竅不通,代碼也看不進去,工做幾年後仍是對這方面感興趣,就從10月份開始學python,作了個基礎的入門,而後開始挑選適合本身的NLP技術方案。html
對於技術小白來講,能少寫代碼就少寫代碼,越簡單越好,由於我只是奔着一個目的來的:輸入文本,處理文本,返回處理後的數據。便可。python
此次我要實現的是語料庫語言學研究中的TTR(Type Token Ratio)的統計,它表示的是一個文本中相同的詞和全部詞之間的比例關係。shell
舉個例子:json
CIPS-SIGHAN CLP 2010(國家天然科學基金(基金號:90920004))中,TTR在不一樣類型的文體中有着不同的數據(下圖),若以其中「文學」的數據爲基準,其餘做者的文本的TTR超過這個基準數據,那意味着做者在寫做的時候用詞豐富性不夠、重複內容較多、語言較通俗易懂等,低於這個基準數據,則意味着做者用了一些生僻的詞語、用詞豐富性很高等。
這僅僅是語言學進行分析時的一個指標,還有不少不少其餘的。這裏只討論如何用python+百度NLP去實現TTR。api
本人半路出家寫代碼,確定有各類各樣的問題,還請各路大神出來指點,寫出來的代碼能運行不報錯,就ok了。bash
爲何選百度?app
同時留下了沒有技術和沒有金錢的淚水……函數
精挑細選(數個小時的嘗試),阿里雲的NLP,10萬次要270塊錢,騰訊文智5萬次免費,百度雲免費用QPS = 5 (Query Per Second,每秒請求次數(這個我當時還不知道啥意思,當超了的時候才明白是一秒只能請求多少次))。ui
阿里雲的基礎版說是有每日5萬次免費額度,可是沒找到在哪。文智的api和sdk,卡在了簽名鑑權上,放棄。阿里雲
最後只能選擇百度,並且如今只寫百度,之後等我學會了其餘的, 我再把另外兩家補上。
對於小白來講,除了python自己的一些代碼我不須要查以外,剩下的都得慢慢學慢慢查,變學變進步吧!因此,技術文檔的詳細程度也決定個人動手能力和成果。
(插一句,媽耶,掘金上傳圖片的背景顏色還會忽閃忽閃的)
環境:python 3.7,baidu-aip 模塊,vscode+jupyter notebook(比心)
在shell裏輸入,而後等待安裝完成
pip install baidu-aip複製代碼
提示success以後,務必命令行裏輸入python,進入python後
import aip
複製代碼
確認不會報錯,就能夠啓動了!
在啓動以前,須要去百度雲控制面板獲取開啓本服務的APP_ID
點擊左側的應用列表,建立應用
天然語言處理沒法勾選,怎麼回事,哦原來是默認全選的,這些足夠了,寫好名稱和描述(隨意),當即建立,拿到發動機鑰匙了!
留好,下面會用到
差很少就是這麼個順序,發動機,打火,啓動!
好,讓咱們來處理一下這首朱自清的現代詩《贈友》
你的手像火把,
你的眼像波濤,
你的言語如石頭,
怎能使我忘記呢?
你飛渡洞庭湖,
你飛渡揚子江;
你要建紅色的天國在地上!
地上是荊棘呀,
地上是狐兔呀,
地上是行屍呀;
你將爲一把快刀,
披荊斬棘的快刀!
你將爲一聲獅子吼,
狐兔們披靡奔走!
你將爲春雷一震,
讓行屍們驚醒!
我愛看你的騎馬,
在塵土裏馳騁---
一下子, 不見蹤跡!
我愛看你的手杖,
那鐵的鐵的手杖;
它有顏色,有斤兩,
有錚錚的聲響!
我想你是一陣飛沙
走石的狂風,
要吹倒那不能搖撼的黃金的王宮!
那黃金的王宮!
嗚---吹呀!
去年一個夏天大早我見着你:
你何其憔悴呢?
你的眼還澀着,
你的發太長了!
但你的血的熱加倍的薰灼着!
在灰泥裏展轉的我,
彷彿被焙炙着通常!---
你如郁烈的雪茄煙,
你如釅釅的白蘭地,
你如通紅通紅的辣椒,
我怎能忘記你呢?
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接口的配置,你須要替換成本身的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。
而後咱們打印一下這個列表的內容,以及計算一下它的長度。
print(seg_list)token_count = len(seg_list)print(token_count)複製代碼
能夠看到,這首詩全部的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裏只包含惟一的元素,很是適合去重使用。
而後for循環,將內容不斷地往set裏面塞……
獲得的結果是:type的長度是118,也就是說這首詩裏面不重複的詞有118個。
最後咱們來計算一下這個ratio。
ratio = float(len(type_count) / token_count) * 100
print('Type Token Ratio: {:.2f}%'.format(ratio))複製代碼
哎嘿,結果出來了,這首詩的TTR是47.01%。
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我以爲也頗有意思,是用來作情感分析的。配合抓取內容後對情緒進行分析,能夠了解某我的物或者某個事件裏文字所反映出來的情緒,對於一些事情作輔助判斷。
下一篇寫這個好了,仍是蠻有意思的。
本人半路出家寫代碼,確定有各類各樣的問題,還請各路大神出來指點。