自從開始使用Python作深度學習的相關項目時,大部分時候或者說基本都是在研究圖像處理與分析方面,可是找工做反而碰到了不少關於天然語言處理(natural language processing: NLP)的問題,因此決定花點時間學習而且寫下來,但願那些跟我同樣同時在學習NLP的朋友能有一些幫助,學習過程當中以英文爲文本標準,後期會嘗試用中文,而且將相關的信息補進來博客文章中。剛開始學習哪裏講得很差,多海涵而且歡迎指出。算法
NLP的首要任務就是將文本內容作Tokenization(標識化)處理,也就是說咱們將文本分割成一個小塊一個小塊的例如以一個英文單詞爲單位或者一個漢字爲單位,這樣子的操做主要是方便咱們能夠更集中的去分析文本信息的內容和文本想表達的含義。固然分割是一個大範圍,不只僅是文本分紅不一樣的詞,也能夠將整個文本分紅段落,進而分紅句子,句子在細分到詞。固然,咱們通常所說的標識化就是將整句分割爲單個標識符(tokens)。數組
文本標識化主要是將沒有結構的數據(unstructured data)或者天然語言文本分割成不一樣的分散的(discrete)塊信息,從而能夠被進行統計計算,這樣子作的緣由是咱們能夠經過計算每一個標識符(tokens)在文件中出現的頻次從而造成一個頻次向量(vector)組來表示文件,由於計算機是沒法直接處理咱們人類所能辨識的文本信息,因此咱們用統計的方式將純文本信息轉化爲數字信息。完成了轉換以後,咱們就能夠直接將這些頻次向量做爲特徵輸入到機器學習或者深度學習相關的算法模型中去進行訓練。機器學習
當咱們實際處理的時候一個比較簡單的標記化處理就是利用空格做爲分隔符將字符串分割,下面的代碼是簡單的將英文句子進行分割:函數
1 sentence_example = """I love deep learning, I love natural language processing.""" 2 token_seq1 = str.split(sentence_example) 3 token_seq2 = sentence_example.split(' ') 4 print("token_seq1: ", token_seq1) 5 print("token_seq2: ", token_seq2)
第二和第三行採用不一樣形式對句子進切分割,輸出的結果是同樣的:學習
token_seq1: ['I', 'love', 'deep', 'learning,', 'I', 'love', 'natural', 'language', 'processing.'] token_seq2: ['I', 'love', 'deep', 'learning,', 'I', 'love', 'natural', 'language', 'processing.']
可是咱們能夠看出上面的作的標識化的結果是有問題的,processing後面跟了句號,正常狀況下,咱們在一個句子的末尾是不須要跟着句號的在作天然語言處理分析的時候,固然這個狀況分的比較多種,假若咱們句子的最後是一個數字13,那麼‘13.’是表示13呢仍是標識一個13以後有小數呢?這點須要咱們進行必定的的解析。這裏咱們先不對句號等標點符號進行處理,隨着學習的深刻,咱們也會遇到,到時再以相應的技巧進行處理。spa
在完成句子詞結構分割以後,咱們須要作的就是將其轉化成計算機系統能識別和處理的數字,這個過程咱們叫作one-hot-encoding:即咱們能夠建立一個數組(矩陣),數組由多個向量組成,每一個向量中有一個數字爲1,其他數字爲0,1在向量所在的位置表明的是該英文單詞出現的位置,one-hot也就所以而來,下面代碼演示如何進行one-hot-encoding:code
1 import numpy as np 2 3 token_seq = str.split(sentence_example) # 使用str.plit()函數分割句子 4 vocab = sorted(set(token_seq)) # set函數找出句子中全部獨特惟一的單詞,sorted函數則按照數字字母(先大寫後小寫)方式排序 5 ','.join(vocab) # 按照分割的單詞組成新的語句 6 num_tokens = len(token_seq) # 讓咱們知道句子是由多少個標識符組成 7 print("The total tokens are: ", num_tokens) 8 vocab_size = len(vocab) # 句子中包含多少個單詞(這裏統計的是非重複的,區別於標識符) 9 print("the vocabulary size is: ", vocab_size) 10 one_hot_vector = np.zeros((num_tokens, vocab_size), int) # 建立一個空矩陣來初始化one-hot-vectors 11 for i, word in enumerate(token_seq): 12 one_hot_vector[i, vocab.index(word)] = 1 13 14 print(one_hot_vector)
輸出結果爲:blog
The total tokens are: 9 the vocabulary size is: 7 [[1 0 0 0 0 0 0] [0 0 0 0 1 0 0] [0 1 0 0 0 0 0] [0 0 0 1 0 0 0] [1 0 0 0 0 0 0] [0 0 0 0 1 0 0] [0 0 0 0 0 1 0] [0 0 1 0 0 0 0] [0 0 0 0 0 0 1]]
這是比較原始的方法,其實若是用這個直接做爲特徵輸入到機器學習算法模型中的話,是很是很差的,主要有如下幾點須要考慮:排序
一個比較簡單的方法解決上述的問題就是咱們用Python的字典來標識已有的字符,以下面的代碼所示:token
1 sent_bow = {} 2 for token in sentence_example.split(): 3 sent_bow[token] = 1 4 print(sorted(sent_bow.items()))
經過運行上述的代碼,咱們能夠獲得下列的結果,而且能夠看出這樣子要比矩陣的形式的要簡單的多,對於計算的開銷也就沒那麼大,致使這樣子的緣由是字典形式只須要儲存1就好了
[('I', 1), ('deep', 1), ('language', 1), ('learning,', 1), ('love', 1), ('natural', 1), ('processing.', 1)]
綜上,NLP的第一步就是tokenization而後將其轉換成計算機能夠處理的數字,由於咱們主要是讓計算機從數字中去尋找文字當中隱含的模式和對應的標記關係,這在NLP中是很是重要的一步,也將影像日後的每一步NLP流程。