R語言自然語言處理:詞性標註與命名實體識別

R語言自然語言處理:詞性標註與命名實體識別

歡迎關注天善智能,我們是專注於商業智能BI,人工智能AI,大數據分析與挖掘領域的垂直社區,學習,問答、求職一站式搞定!

對商業智能BI、大數據分析挖掘、機器學習,python,R等數據領域感興趣的同學加微信:tstoutiao,邀請你進入數據愛好者交流群,數據愛好者們都在這兒。

作者:黃天元,復旦大學博士在讀,目前研究涉及文本挖掘、社交網絡分析和機器學習等。希望與大家分享學習經驗,推廣並加深R語言在業界的應用。

郵箱:[email protected]

原理簡介

在之前的文章中(

R語言自然語言處理:中文分詞

)介紹瞭如何利用jiebaR來做中文分詞,這次希望研究如果利用R語言來做詞性標註,並利用標註來做命名實體識別。 首先需要明確詞性標註的概念,就是要把中文分詞後的每一個詞,確定其性質。是名詞?動詞?還是形容詞?如果是名詞,是人名、地名還是機構團體名稱?對這些詞性進行更為細緻的標註,有助於我們對信息進行提取(有的時候動詞和形容詞其實不包含我們感興趣的信息,但是名詞卻非常重要)。此外,也有利於我們瞭解作者的用詞習慣(這個時候,名詞又不一定重要了,一個人的行文習慣可以體現在他經常用的動詞和形容詞)。 因為我們是用jiebaR來做分詞,根據官方文檔說明,它的標註是根據北大《人民日報》語料庫進行訓練的,最後的標準整理為ICTPOS3.0詞性標記集,內容如下:

n 名詞
nr 人名
nr1 漢語姓氏
nr2 漢語名字
nrj 日語人名
nrf 音譯人名
ns 地名
 nsf 音譯地名
nt 機構團體名
nz 其它專名
nl 名詞性慣用語
ng 名詞性語素
t 時間詞
  tg 時間詞性語素
s 處所詞
f 方位詞
v 動詞
vd 副動詞
vn 名動詞
vshi 動詞“是”
vyou 動詞“有”
vf 趨向動詞
vx 形式動詞
vi 不及物動詞(內動詞)
vl 動詞性慣用語
vg 動詞性語素
a 形容詞
ad 副形詞
an 名形詞
ag 形容詞性語素
al 形容詞性慣用語
b 區別詞
bl 區別詞性慣用語
z 狀態詞
r 代詞

rr 人稱代詞
rz 指示代詞
rzt 時間指示代詞
rzs 處所指示代詞
rzv 謂詞性指示代詞
ry 疑問代詞
ryt 時間疑問代詞
rys 處所疑問代詞
ryv 謂詞性疑問代詞
rg 代詞性語素
m 數詞
mq 數量詞
q 量詞
qv 動量詞
qt 時量詞

詞性標註實踐

話不多說,我們上代碼來做詞性標註分析。需要注意的是,我們要做詞性標註的輸入,既可以是一大段沒有經過分詞處理字符串,也可以是已經分詞完畢的分詞結果(也就是字符向量)。我們先介紹第一種情況,就是沒有經過分詞的大段字符串,要完成分詞,然後對每個詞都進行詞性標註。

 1library(pacman)
2p_load(jiebaR,tidyverse)
3
4cn = "我想寫一本書,名字叫做《R語言高效數據處理》。" #構造中文文本

5tag_worker = worker(type = "tag") #構造分詞標註器
6
7tag_result = tagging(cn,tag_worker) #進行分詞標註
8
9tag_result #查看結果
10## r v v m r n
11## "我" "想" "寫" "一" "本書" "名字"
12## v eng a n
13## "叫做" "R語言" "高效" "數據處理"

我們得到的tag_result實質上是一個帶屬性的向量,這樣其實不是特別好用。因此我要把它變成數據框的格式,方便以後利用。

 1str(tag_result) #查看數據類型
2## Named chr [1:10] "我" "想" "寫" "一" "本書" "名字" "叫做" "R語言" ...
3## - attr(*, "names")= chr [1:10] "r" "v" "v" "m" ...
4enframe(tag_result) -> tag_table #轉換數據存儲格式
5
6tag_table
7## # A tibble: 10 x 2
8## name value
9##
10## 1 r 我
11## 2 v 想
12## 3 v 寫
13## 4 m 一
14## 5 r 本書
15## 6 n 名字
16## 7 v 叫做
17## 8 eng R語言
18## 9 a 高效
19## 10 n 數據處理

其實這裡分詞效果還不是那麼盡如人意,因為“本書”應該分為“本”、“書”,而這裡被認定為代詞,指代之前提過的一本書(然而我並沒有指代任何詞)。不過大體來說還算滿意。注意“R語言”之所以能夠被分出來,是因為我上次處理加了用戶詞庫,因此這次自動地進行了識別。如果大家沒有把“R語言”加入到用戶自定義詞庫中,你們看到的應該是“R”、“語言”。關於如何定義用戶詞庫,見上一篇文章R語言自然語言處理:

中文分詞

。 如果已經分詞完畢,需要對這些詞進行詞性標註,可以使用vector_tag函數。我們先按照正常流程進行分詞:

1#正常分詞流程
2
3worker() -> wk
4segment(cn,wk) -> seg_cn
5
6seg_cn
7## [1] "我" "想" "寫" "一" "本書" "名字"
8## [7] "叫做" "R語言" "高效" "數據處理"

然後我們利用函數進行標註。

1vector_tag(seg_cn,tag_worker)
2## r v v m r n
3## "我" "想" "寫" "一" "本書" "名字"

4## v eng a n
5## "叫做" "R語言" "高效" "數據處理"

這個結構與我們上面得到的tag_result是一致的。

命名實體識別嘗試

現在我們嘗試用詞性標註的方法來進行命名實體識別。我們的目的是:對於既定的一套字符串,我們希望得到裡面的名詞,因為我們認為它會代表一些實際的實體對象。我非常喜歡一篇文章,是王小波的《一隻特立獨行的豬》,原諒我的任性,我要把這篇文章直接放在這裡作為我們的中文語料對象。

1cn = "插隊的時候,我餵過豬、也放過牛。假如沒有人來管,這兩種動物也完全知道該怎樣生活。它們會自由自在地閒逛,飢則食渴則飲,春天來臨時還要談談愛情;這樣一來,它們的生活層次很低,完全乏善可陳。人來了以後,給它們的生活做出了安排:每一頭牛和每一口豬的生活都有了主題。就它們中的大多數而言,這種生活主題是很悲慘的:前者的主題是幹活,後者的主題是長肉。我不認為這有什麼可抱怨的,因為我當時的生活也不見得豐富了多少,除了八個樣板戲,也沒有什麼消遣。有極少數的豬和牛,它們的生活另有安排。以豬為例,種豬和母豬除了吃,還有別的事可幹。就我所見,它們對這些安排也不大喜歡。種豬的任務是交配,換言之,我們的政策准許它當個花花公子。但是疲憊的種豬往往擺出一種肉豬(肉豬是閹過的)才有的正人君子架勢,死活不肯跳到母豬背上去。母豬的任務是生崽兒,但有些母豬卻要把豬崽兒吃掉。總的來說,人的安排使豬痛苦不堪。但它們還是接受了:豬總是豬啊。 

2對生活做種種設置是人特有的品性。不光是設置動物,也設置自己。我們知道,在古希臘有個斯巴達,那裡的生活被設置得了無生趣,其目的就是要使男人成為亡命戰士,使女人成為生育機器,前者像些鬥雞,後者像些母豬。這兩類動物是很特別的,但我以為,它們肯定不喜歡自己的生活。但不喜歡又能怎麼樣?人也好,動物也罷,都很難改變自己的命運。
3以下談到的一隻豬有些與眾不同。我餵豬時,它已經有四五歲了,從名分上說,它是肉豬,但長得又黑又瘦,兩眼炯炯有光。這傢伙像山羊一樣敏捷,一米高的豬欄一跳就過;它還能跳上豬圈的房頂,這一點又像是貓——所以它總是到處遊逛,根本就不在圈裡待著。所有餵過豬的知青都把它當寵兒來對待,它也是我的寵兒——因為它只對知青好,容許他們走到三米之內,要是別的人,它早就跑了。它是公的,原本該劁掉。不過你去試試看,哪怕你把劁豬刀藏在身後,它也能嗅出來,朝你瞪大眼睛,噢噢地吼起來。我總是用細米糠熬的粥餵它,等它吃夠了以後,才把糠對到野草裡喂別的豬。其他豬看了嫉妒,一起嚷起來。這時候整個豬場一片鬼哭狼嚎,但我和它都不在乎。吃飽了以後,它就跳上房頂去曬太陽,或者模仿各種聲音。它會學汽車響、拖拉機響,學得都很像;有時整天不見蹤影,我估計它到附近的村寨裡找母豬去了。我們這裡也有母豬,都關在圈裡,被過度的生育搞得走了形,又髒又臭,它對它們不感興趣;村寨裡的母豬好看一些。它有很多精彩的事蹟,但我餵豬的時間短,知道得有限,索性就不寫了。總而言之,所有餵過豬的知青都喜歡它,喜歡它特立獨行的派頭兒,還說它活得瀟灑。但老鄉們就不這麼浪漫,他們說,這豬不正經。領導則痛恨它,這一點以後還要談到。我對它則不止是喜歡——我尊敬它,常常不顧自己虛長十幾歲這一現實,把它叫做“豬兄”。如前所述,這位豬兄會模仿各種聲音。我想它也學過人說話,但沒有學會——假如學會了,我們就可以做傾心之談。但這不能怪它。人和豬的音色差得太遠了。

4後來,豬兄學會了汽笛叫,這個本領給它招來了麻煩。我們那裡有座糖廠,中午要鳴一次汽笛,讓工人換班。我們隊下地幹活時,聽見這次汽笛響就收工回來。我的豬兄每天上午十點鐘總要跳到房上學汽笛,地裡的人聽見它叫就回來——這可比糖廠鳴笛早了一個半小時。坦白地說,這不能全怪豬兄,它畢竟不是鍋爐,叫起來和汽笛還有些區別,但老鄉們卻硬說聽不出來。領導上因此開了一個會,把它定成了破壞春耕的壞分子,要對它採取專政手段——會議的精神我已經知道了,但我不為它擔憂——因為假如專政是指繩索和殺豬刀的話,那是一點門都沒有的。以前的領導也不是沒試過,一百人也治不住它。狗也沒用:豬兄跑起來像顆魚雷,能把狗撞出一丈開外。誰知這回是動了真格的,指導員帶了二十幾個人,手拿五四式手槍;副指導員帶了十幾人,手持看青的火槍,分兩路在豬場外的空地上兜捕它。這就使我陷入了內心的矛盾:按我和它的交情,我該舞起兩把殺豬刀衝出去,和它並肩戰鬥,但我又覺得這樣做太過驚世駭俗——它畢竟是隻豬啊;還有一個理由,我不敢對抗領導,我懷疑這才是問題之所在。總之,我在一邊看著。豬兄的鎮定使我佩服之極:它很冷靜地躲在手槍和火槍的連線之內,任憑人喊狗咬,不離那條線。這樣,拿手槍的人開火就會把拿火槍的打死,反之亦然;兩頭同時開火,兩頭都會被打死。至於它,因為目標小,多半沒事。就這樣連兜了幾個圈子,它找到了一個空子,一頭撞出去了;跑得瀟灑之極。以後我在甘蔗地裡還見過它一次,它長出了獠牙,還認識我,但已不容我走近了。這種冷淡使我痛心,但我也贊成它對心懷叵測的人保持距離。

5我已經四十歲了,除了這隻豬,還沒見過誰敢於如此無視對生活的設置。相反,我倒見過很多想要設置別人生活的人,還有對被設置的生活安之若素的人。因為這個原故,我一直懷念這隻特立獨行的豬。"

現在,我想識別這篇文章裡面所有的名詞。

1tagging(cn,tag_worker) %>% 
2 enframe() %>%
3 filter(name == "n") -> tag_names

現在我把文中的名詞都篩選了出來。詞性的列名稱為name,詞語的列名稱為value。我要統計一下王小波在這篇文章中用到名詞的詞頻。

 1tag_names %>% 
2 count(value) %>% #對名詞進行計數
3 arrange(desc(n)) #降序排列
4## # A tibble: 113 x 2
5## value n
6##
7## 1 豬 17
8## 2 人 12
9## 3 母豬 8
10## 4 汽笛 5
11## 5 動物 4
12## 6 領導 4
13## 7 主題 4
14## 8 狗 3
15## 9 火槍 3
16## 10 牛 3
17## # ... with 103 more rows

有意思,“豬”是出現最多的名詞,其次是“人”,再到“母豬”。

實際運用中,想必還是會有很多障礙。大家要記得,在用戶自定義詞庫中,我們是可以給詞性進行標註的!也就是我們的詞想要識別成什麼,我們自己可以說了算。這在垂直領域的運用中,是相當有用的。至於應該如何設置標註,大家可以觀察原始詞庫的格式,然後對文本文件進行修飾。原始文件的位置在哪裡?請直接鍵入DICTPATH,你會找到路徑,然後用文本格式來查看這個文件即可。然後按照相應格式,來更改用戶詞典(同一個文件目錄下的“user.dict.utf8”)。 我還是認為,算法是不可能超越詞庫的,多在詞庫下功夫,算法才能夠發揮效用。應該想方設法構建更加優秀的自定義詞庫,並進行面向業務的精準標註,才能夠在實際應用中獲得好的效果。

R語言自然語言處理:詞性標註與命名實體識別

往期精彩:

  • R語言自然語言處理:中文分詞
  • 找工作難,面試失敗的核心原因已經找到
  • R語言中文社區2018年終文章整理(作者篇)
  • R語言中文社區2018年終文章整理(類型篇)
R語言自然語言處理:詞性標註與命名實體識別

回覆 爬蟲 爬蟲三大案例實戰

回覆 Python 1小時破冰入門

回覆 數據挖掘 R語言入門及數據挖掘

回覆 人工智能 三個月入門人工智能

回覆 數據分析師 數據分析師成長之路

回覆 機器學習 機器學習的商業應用

回覆 數據科學 數據科學實戰

回覆 常用算法 常用數據挖掘算法


分享到:


相關文章: