NLP将迎来黄金十年,7个案例带你入门(附Python代码)
導讀:近日,微軟研究院發文稱,NLP即將迎來“黃金十年”。他們認為,各領域對NLP的需求會大幅度上升,對NLP質量也提出更高要求。如果你想趕上這“黃金十年”,現在好好學習還來得及!
很多的數據科學庫、框架、模塊以及工具箱可以有效地實現NLP大部分常見的算法與技術,掌握與運用正則表達式、Numpy是開始NLP工作的好方式。
作者:涂銘,劉祥,劉樹春,如需轉載請聯系大數據(ID:hzdashuju)
對于自然語言處理的學習,很多人會爭論用什么樣的編程語言實現最好?有些人認為是Java或者時下流行的Scala,我認為Python才是最佳的選擇!
對于學習和從事自然語言處理工作來說,Python具有幾大優勢:
提供豐富的自然語言處理庫
編程語法相對簡單(尤其易于理解)
具有很多數據科學相關的庫
01 正則表達式在NLP的基本應用
正則表達式是一種定義了搜索模式的特征序列,主要是用于字符串的模式匹配,或是字符的匹配。隨著計算機的普及以及互聯網的發展,大量的信息以電子文檔方式呈現在人們的面前。
NLP通常所需要處理的語料一部分來自于web網頁的信息抽取,一部分來自于文本格式的文檔。Web網頁具有很強的開發價值,具有時效性強,信息量大,結構穩定,價值高等特點,文本格式的文檔多來源于人為編寫或系統生成,其中包含了非結構化文本、半結構化文本以及結構化文本。
正則表達式的作用之一是將這些文檔內容從非結構化轉為結構化以便后續的文本挖掘。
正則表達式的另一個作用就是去除“噪聲”。在處理大量文本片段的時候,有非常多的文字信息與最終輸出的文本無關,這些無關的片段稱之為“噪聲”(比如url或鏈接、語氣助詞、標點符號等)。
正則表達式是處理NLP的最基本的手段之一,學習與掌握正則表達式在Python中的應用,可以幫助我們在格式復雜的文本中抽取所需要的文本信息。
比如說抽取以下文本中的年份,每一行的格式不同,因此沒有辦法通過Python提供的字符串方法來抽取,這個時候我們往往考慮使用正則表達式。
-“July 16, 2017”
-“16/07/2009”
-“Summer 2008”
02 匹配字符串
在Python中,我們會使用re模塊來實現正則表達式。為了讓大家更好地理解正則表達式在Python中的應用,我們會通過一系列的例子來闡述。
案例中,我們會提到re的一個方法: re.search。
通過使用re.search(regex,string)這個方法,我們可以檢查這個string字符串是否匹配正則表達式regex。如果匹配到,這個表達式會返回一個match對象,如果沒有匹配到則返回None。
我們先看下準備的有關爬蟲介紹的文字信息。句子和句子之間是以句號分隔。具體的文本如下所示:
文本最重要的來源無疑是網絡。我們要把網絡中的文本獲取形成一個文本數據庫。利用一個爬蟲抓取到網絡中的信息。爬取的策略有廣度爬取和深度爬取。根據用戶的需求,爬蟲可以有主題爬蟲和通用爬蟲之分。
例1 獲取包含“爬蟲”這個關鍵字的句子
查找哪些語句包含“爬蟲”這個關鍵字。Python的代碼實現如下:
text_string?=?'文本最重要的來源無疑是網絡。我們要把網絡中的文本獲取形成一個文本數據庫。利用一個爬蟲抓取到網絡中的信息。爬取的策略有廣度爬取和深度爬取。根據用戶的需求,爬蟲可以有主題爬蟲和通用爬蟲之分。'
regex?=?'爬蟲'
p_string?=?text_string.split('。')?#以句號為分隔符通過split切分
for?line?in?p_string:
????if?re.search(regex,line)?is?not?None:?#search方法是用來查找匹配當前行是否匹配這個regex,返回的是一個match對象
????????print(line)?#如果匹配到,打印這行信息
運行上面的程序,我們可以看到輸出結果為:
根據用戶的需求,爬蟲可以有主題爬蟲和通用爬蟲之分
例2 匹配任意一個字符
正則表達式中,有一些保留的特殊符號可以幫助我們處理一些常用邏輯。如下表所示。
符號 | 含義 |
. | 匹配任意一個字符 |
▲匹配任意一個字符
我們來舉幾個例子:
正則表達式 | 可以匹配的例子 | 不能匹配的例子 |
“a.c” | “abc”, “branch” | “add”,“crash” |
“..t” | “bat”,“oat” | “it”,“table” |
▲提示: “.” 代替任何單個字符(換行除外)?
我們現在來演示下如何查找包含“爬”+任意一個字的句子。代碼如下:
text_string?=?'文本最重要的來源無疑是網絡。我們要把網絡中的文本獲取形成一個文本數據庫。利用一個爬蟲抓取到網絡中的信息。爬取的策略有廣度爬取和深度爬取。根據用戶的需求,爬蟲可以有主題爬蟲和通用爬蟲之分。'
regex?=?'爬.'
p_string?=?text_string.split('。')?#以句號為分隔符通過split切分
for?line?in?p_string:
????if?re.search(regex,line)?is?not?None:?#search方法是用來查找匹配當前行是否匹配這個regex,返回的是一個match對象
????????print(line)?#如果匹配到,打印這行信息
上述代碼基本不變,只需要將regex中的“爬”之后加一個“.”,即可以滿足需求。我們來看下輸出會多一行。因為不僅是匹配到了“爬取”也匹配到了“爬蟲”。
爬取的策略有廣度爬取和深度爬取
根據用戶的需求,爬蟲可以有主題爬蟲和通用爬蟲之分
例3 匹配起始和結尾字符串
現在介紹另一個特殊符號,具體功能如下表所示。
符號 | 含義 |
^ | 匹配開始的字符串 |
$ | 匹配結尾的字符串 |
▲匹配開始與結尾的字符串
舉個例子:
“^a”代表的是匹配所有以字母a開頭的字符串
“a$”代表的是所有以字母a結尾的字符串
我們現在來演示下如何查找以“文本”這兩個字起始的句子。代碼如下:
text_string?=?'文本最重要的來源無疑是網絡。我們要把網絡中的文本獲取形成一個文本數據庫。利用一個爬蟲抓取到網絡中的信息。爬取的策略有廣度爬取和深度爬取。根據用戶的需求,爬蟲可以有主題爬蟲和通用爬蟲之分。'
regex?=?'^文本'
p_string?=?text_string.split('。')?
for?line?in?p_string:
if?re.search(regex,line)?is?not?None:????????
print(line)?
我們可以看到輸出為:
例4? 使用中括號匹配多個字符
現在介紹另一個特殊符號,具體功能如下表所示:
符號 | 含義 |
[ ] | 匹配多個字符 |
▲匹配多個字符串
舉個例子:
“[bcr]at”代表的是匹配”bat””cat”以及”rat”
我們先看下文字信息。句子和句子之間是以句號分隔。
[重要的] 今年第七號臺風23日登陸廣東東部沿海地區
上海發布車庫銷售監管通知:違規者暫停網簽資格
[緊要的] 中國對印連發強硬信息,印度急切需要結束對峙
我們希望提取以[重要的]或者[緊要的]為起始的新聞標題。代碼如下:
text_string?=?['[重要的]?今年第七號臺風23日登陸廣東東部沿海地區','上海發布車庫銷售監管通知:違規者暫停網簽資格','[緊要的]?中國對印連發強硬信息,印度急切需要結束對峙']
regex?=?'^\[[重緊]..\]'
for?line?in?text_string:
????if?re.search(regex,line)?is?not?None:?
????????print(line)?
????else:
????????print('not?match')
觀測下數據集,我們發現一些新聞標題是以“[重要的]”“[緊要的]”為起始,所以我們需要添加“^”特殊符號代表起始,之后因為存在“重”或者“緊”,所以我們使用“[ ]”匹配多個字符,然后以“.”“.”代表之后的任意兩個字符。
運行以上代碼,我們看到結果正確提取了所需的新聞標題。
not?match
[緊要的]?中國對印連發強硬信息,印度急切需要結束對峙
03 使用轉義符
上述代碼中,我們看到使用了“\”為轉義符,因為“[ ]”在正則表達式中是特殊符號。
與大多數編程語言相同,正則表達式里使用“\”作為轉義字符,這就可能造成反斜杠困擾。假如你需要匹配文本中的字符“\”,那么使用編程語言表示的正則表達式里將需要4個反斜杠“\\\\”:前兩個和后兩個分別用于在編程語言里轉義成反斜杠,轉換成兩個反斜杠后再在正則表達式里轉義成一個反斜杠。
Python里的原生字符串很好地解決了這個問題,這個例子中的正則表達式可以使用r“\\”表示。同樣,匹配一個數字的“\\d”可以寫成r“\d”。有了原生字符串,你再也不用擔心是不是漏寫了反斜杠,寫出來的表達式也更直觀。
為了方便理解我們來舉個例子:
if?re.search("\\\\","I?have?one?nee\dle")?is?not?None:
????print("match?it")
else:
????print("not?match")
通過上述例子,我們就可以匹配到字符串中匹配到的那個反斜杠“nee\dle”。為了簡潔一點我們可以換一個寫法:
if?re.search(r"\\","I?have?one?nee\dle")?is?not?None:
????print("match?it")
else:
????print("not?match")
通過加一個r,我們就不用擔心是不是漏寫反斜杠了。
04 抽取文本中的數字
1. 通過正則表達式匹配年份
“[0-9]”代表的是從0到9的所有數字,那相對的“[a-z]”代表的是所有a-z小寫字母。我們通過一個小例子來講解下如何使用。首先我們定義一個list分配于一個變量strings,匹配包含的年份是在1000年~2999年之間的。代碼如下:
strings?=?['War?of?1812',?'There?are?5280?feet?to?a?mile',?'Happy?New?Year?2016!']
for?string?in?strings:
????if?re.search('[1-2][0-9]{3}',?string):#字符串有英文有數字,匹配其中的數字部分,并且是在1000~2999之間,{3}代表的是重復之前的[0-9]三次,是[0-9]?[0-9]?[0-9]的簡化寫法。
????????year_strings.append(string)
print(year_strings)
2. 抽取所有的年份
我們使用Python中的re模塊的另一個方法findall()來返回匹配帶正則表達式的那部分字符串。re.findall(“[a-z]”,“abc1234”)得到的結果是[“a”,“b”,“c”]。
我們定義一個字符串years_string,其中的內容是'2015 was a good year, but 2016 will be better!'。現在我們來抽取一下所有的年份。代碼如下:
years_string?=?'2016?was?a?good?year,?but?2017?will?be?better!'
years?=?re.findall('[2][0-9]{3}',years_string)
在Anaconda中執行這段語句,我們能看到輸出['2016', '2017']。
延伸學習:關于Python的教程比比皆是,官方教程是不錯的入門選擇:
https://docs.python.org/3/tutorial/
關于作者:涂銘,阿里巴巴數據架構師,對大數據、自然語言處理、Python、Java相關技術有深入的研究,積累了豐富的實踐經驗。
劉祥,百煉智能自然語言處理專家,主要研究知識圖譜、NLG等前沿技術,參與機器自動寫作產品的研發與設計。
劉樹春,七牛云高級算法專家,七牛AI實驗室NLP&OCR方向負責人,主要負責七牛NLP以及OCR相關項目的研究與落地。
本文摘編自《Python自然語言處理實戰:核心技術與算法》,經出版方授權發布。
延伸閱讀《Python自然語言處理實戰》
點擊上圖了解及購買
轉載請聯系微信:togo-maruko
推薦語:阿里巴巴、前明略數據和七牛云的高級專家和科學家撰寫,零基礎掌握NLP的核心技術、方法論和經典算法。
據統計,99%的大咖都完成了這個神操作
▼
更多精彩
在公眾號后臺對話框輸入以下關鍵詞
查看更多優質內容!
PPT?|?報告?|?讀書?|?書單
大數據?|?揭秘?|?人工智能?|?AI
Python?|?機器學習?|?深度學習?|?神經網絡
可視化?|?區塊鏈?|?干貨?|?數學
猜你想看
2018世界幸福指數中國排第86,這種報告是怎樣做出來的?
從入門到頭禿,2018年機器學習圖書TOP10
寫給中學生的算法入門:學代碼之前看這篇就夠了
機器學習重大挑戰:壞數據和壞算法正在毀掉你的項目
Q:?你要趕上這“黃金十年”嗎?
歡迎留言與大家分享
覺得不錯,請把這篇文章分享給你的朋友
轉載 / 投稿請聯系:baiyu@hzbook.com
更多精彩,請在后臺點擊“歷史文章”查看
點擊閱讀原文,了解更多
總結
以上是生活随笔為你收集整理的NLP将迎来黄金十年,7个案例带你入门(附Python代码)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 什么是Apache Spark?这篇文章
- 下一篇: 什么是机器阅读理解?跟自然语言处理有什么