天天看點

文本特征提取之詞袋模型

1 引例

在前面幾講的示例介紹中,我們所用到的資料集都是别人已經處理好的資料集,換句話說這些資料集的每個特征次元都已經是數值了。但是在實際的模組化任務中,我們拿到的資料集并不是這樣的形式。例如接下來我們要完成的一個任務:對中文垃圾郵件進行分類。

為什麼兩個人在一起會有愛情呢? 愛真的需要勇氣 把自己的内心毫無保留的展示給對方 也勇敢的去 接受對方的點點滴滴,過去的事情雖然不能再改變什麼,但是 看了你的貼子,你說你不需要建議. 我想問你個問題,如果你願意的話可以試着回答一下,你認為真愛是什麼啊??? 你這輩子會對一個女孩死心蹋地嗎??? 如果下次你再遇到一個比現在這個女孩還"特别的"你會怎麼樣, 因為你之是以選擇後者,主要是因為她很與衆不同吧!是以我用特别這個詞來說.

例如,對于上面這樣一個郵件(樣本),我們應該怎麼來對其進行量化呢?同時,我們知道在模組化過程中需要保證每個樣本的特征次元數都一樣,但是這裡每一封郵件的長度卻并不同,那我們該怎麼處理呢?最後,這裡的每個樣本都是由若幹個句子組成,我們是否應該在一定程度上對這些句子進行分割呢?接下來,我們就來開始學習第一種向量化方法——詞袋模型。

2 詞袋模型

什麼是詞袋模型(Bag of words) 呢?其實詞袋模型這個叫法很形象,凸出了模型的核心思想。所謂詞袋模型就是:首先将訓練樣本中所有不重複的詞放到這個袋子中構成一個詞表(字典);然後再以這個詞表為标準來周遊每一個樣本,如果詞表中對應位置的詞出現在了樣本中,那麼對應位置就用1來表示,沒有出現就用0來表示;最後,對于每個樣本來說都将其向量化成了一個和詞表長度一樣的0-1向量。

2.1 具體步驟

文本特征提取之詞袋模型

如圖所示為一個直覺的詞袋模型轉換示意圖,左邊為原始資料集(包含兩個樣本),中間為詞表,右邊為向量化的結果。具體為,第一步:首先需要将原始資料的每個樣本都進行分詞處理(英文語料可以跳過這步);第二步:然後在所有的分詞結果中去掉重複的部分,保證每個詞語隻出現一次;第三步:周遊每個資料樣本,若詞表中的詞出現在該樣本中,則對應位置為1,沒出現則為0 。例如圖中樣本“沒有 你 的 地方 都是 他鄉”,其中有6個詞都出現在了詞表中,是以詞表中每個詞的對應位置為1,而‘旅行’和‘流浪’這個兩個詞并沒有出現在樣本中,是以對應位置為0。

可以看出,向量化後每個樣本特征次元的長度都和詞表長度相同(圖示中為8),而這很容易導緻次元災難。因為通常一個一般大小的中文資料集,都可能會出現數十萬個詞語(而這意味着轉化後向量的次元也有這麼大)。是以在實際處理的過程中,我們在分詞結束後通常還會進行詞頻統計這一步,即統計每個詞在資料集中出現的次數,然後隻選擇其中出現頻率最高的前

K

K

K個詞作為最終的詞表。最後,通常也會将一些無意義的虛詞(停用詞)去掉,例如:“的,啊,了,”等。

2.2 分詞

從上面的介紹可以知道,向量化的第一步是需要對文本進行分詞。下面我們開始介紹一款常用的開源分詞工具​

​jieba​

​​。使用​

​jieba​

​​庫的前提當然是安裝了,可以通過指令​

​pip install jieba​

​進行安裝,然後再通過内置的方法進行分詞即可。

我們先用一段文本來進行分詞并做詞頻統計:

央視網消息:當地時間11日,美國國會參議院以88票對11票的結果通過了一項動議,允許國會“在總統以國家安全為由決定征收關稅時”發揮一定的限制作用。這項動議主要針對加征鋼鋁關稅的232調查,目前尚不具有限制力。動議的主要發起者——共和黨參議員鮑勃·科克說,11日的投票隻是一小步,他會繼續推動進行有限制力的投票。

可以看到,這段文本當中還包含了很多标點符号和數字,顯然這不是我們想要的,是以在分詞的時候要去掉這些。

  • 普通分詞模式

    ​import jieba import re def cutWords(s): cut_words = [] s = re.sub("[A-Za-z0-9\:\·\—\,\。\“ \”]", "", s) seg_list = jieba.cut(s, cut_all=True) cut_words.append(" ".join(seg_list)) print(cut_words)>> 結果 ['央視網 消息 當地 時間 日 美國國會參議院 以票 對票 的 結果 通過 了 一項 動議 允許 國會 在 總統 以 國家 安全 為 由 決定 征收 關稅 時 發揮 一定 的 限制 作用 這項 動議 主要 針對 加征 鋼鋁 關稅 的 調查 目前 尚 不 具有 限制力 動議 的 主要 發起者 共和黨 參議員 鮑勃 科克 說 日 的 投票 隻是 一 小步 他會 繼續 推動 進行 有 限制力 的 投票' ]​

    ​最後輸出的結果便是分詞後的形式。但是,對于有的句子來說可以有不同的分詞方法,例如:“美國國會參議院”既可以分成“美國 國會 參議院”,也可以是“美國國會 參議院”,甚至都可以直接是“美國國會參議院”。是以,​

    ​jieba​

    ​還提供了一種全分詞模式。
  • 全分詞模式

    ​seg_list = jieba.cut(s, cut_all=True)print(cut_words)>> 結果 ['央視 央視網 視網 消息 當地 時間 日 美國 美國國會 美國國會參議院 國會 參議 參議院 議院 以 票 對 票 的 結果 通過 了 一項 動議 允許 許國 國會 在 總統 以 國家 家安 安全 為 由 決定 征收 關稅 時 發揮 一定 的 限制 制作 作用 這項 動議 的 主要 發起 發起者 共和 共和黨 黨參 參議 參議員 議員 鮑 勃 科克 說 日 的 投票 隻是 一小 小步 他 會 繼續 推動 進行 有 限制 限制力 的 投票' ]​

    ​可以看出對于有的句子,分詞後的結果确實看起來結結巴巴的,而這就是全分詞模式的作用。

2.3 詞頻統計

上面介紹到,分詞後通常還會進行詞頻統計,以選取出現頻率最高的前

K

K

K個詞來作為詞表。做詞頻統計需要用到另外一個包​

​collection​

​​中的​

​Counter​

​​計數器(如果沒有自行安裝,安裝方法同​

​jieba​

​​一樣)。但是需要注意的是,像上面那樣分詞後的形式不能做詞頻統計,因為​

​Counter​

​​是将​

​list​

​中的一個元素視為一個詞,是以在上面要略微修改。

def wordsCount(s):
    cut_words = ""
    s = re.sub("[A-Za-z0-9\:\·\—\,\。\“ \”]", "", s)
    seg_list = jieba.cut(s, cut_all=False)
    cut_words += (" ".join(seg_list))
    all_words = cut_words.split()
    c = Counter()
    for x in all_words:
        if len(x) > 1 and x != '\r\n':
            c[x] += 1
    vocab = []
    print('\n詞頻統計結果:')
    for (k, v) in c.most_common(5):  # 輸出詞頻最高的前5個詞
        print("%s:%d" % (k, v))
        vocab.append(k)
    print(vocab)
#結果
詞頻統計結果:
動議:3
關稅:2
主要:2
限制力:2
投票:2
['動議', '關稅', '主要', '限制力', '投票']
      

2.4 向量化

通過上面的操作,我們便能得到一個最終的詞表​

​vocab​

​。最後一步的向量化工作則是周遊每個樣本,檢視詞表中每個詞是否出現在目前樣本中,如果出現則詞表對應次元用1表示,沒出現則用0表示。

def vetorization(s):
    ......
    x_vec = []
    for item in x_text:
        tmp = [0]*len(vocab)
        for i,w in enumerate(vocab):
            if w in item:
                tmp[i] = 1
        x_vec.append(tmp)
    print("詞表:",vocab)
    print("文本:",x_text)
    print(x_vec)

if __name__ == '__main__':
    s = ['分詞工具可用于對文本進行分詞處理', '常見的用于文本的分詞處理工具有很多']
    vetorization(s)

#結果
詞表: ['分詞', '工具', '用于', '文本', '處理', '進行', '常見']
文本: [['分詞', '工具', '可', '用于', '對', '文本', '進行', '分詞', '處理'], 
     ['常見', '的', '用于', '文本', '的', '分詞', '處理', '工具', '有', '很多']]
[[1, 1, 1, 1, 1, 1, 0], [1, 1, 1, 1, 1, 0, 1]]
      

由于文章篇幅所限,此處隻列出了部分代碼,具體實作代碼可參見示例代碼。

3 總結

在本篇文章中,筆者首先介紹了第一種将文本轉化為向量的詞袋模型;然後介紹了一款常用的分詞工具​

​jieba​

​​庫并示範了如何同​

​jieba​

​進行分詞處理以及詞頻統計;最後介紹了如何實作詞袋模型的最後一步向量化。在下一篇文章中,我們将通過一個真實的垃圾郵件分類案例來進行介紹。本次内容就到此結束,感謝閱讀!

引用

[1] Anaconda環境配置

[2] https://github.com/fxsjy/jieba

[3] 示例代碼:關注公衆号回複“示例代碼”即可直接擷取!

交流群:883638095