如何從文本中提取特徵信息?

雖然之前也寫過gensim庫的word2vec的教程,但是對於文本分析的特徵提取並不太理解。最近看了幾篇scikit的外文教程,對機器學習中文本的特徵提取有了一些瞭解。

首先做文本的機器學習(自然語言處理),我們要理解這幾個概念:

  • 文檔(document)這裏是指一段單獨的文本信息。這可能是一則短信、一條推特、一封郵件、一本書、或者一首歌詞。一般一個文檔對應於一個觀測值或一行數據。

  • 語料(corpus) 文檔的集合(語料大於等於1條文檔)。這相當於我們要研究對象的所有文本數據

  • 單詞或詞語(token) 英文中對應的是單詞,漢語是詞語。例如“How are you”這個文檔,是由how、are、you三個單詞組成的。token相當於機器學習中的特徵(列)。

首先讓我們給出一個語料例子。

corpus = ["Hey hey hey lets go get lunch today :)",
           "Did you go home?",
           "Hey!!! I need a favor"]

CountVectorizer
首先我們要明白,計算機是不能從文本字符串中發現規律的。只有將字符串編碼爲計算機可以理解的數字,計算機纔有可能發現文本中的規律。

最容易理解的實現思路:

  • 對文本編碼,就是讓詞語與數字對應起來,建立基於給定文本的詞典。(fit方法 )

  • 再根據詞典對所有的文本數據進行轉碼。(transform方法)

scikit庫的CountVectorize類就是這種思路。


from sklearn.feature_extraction.text import CountVectorizer

vectorize = CountVectorizer()

使用fit方法,CountVectorizer()類的會從corpus語料中學習到所有詞語,進而構建出corpus詞典。

#fit學會語料中的所有詞語,構建詞典


vectorize.fit(corpus)
CountVectorizer(analyzer='word', binary=False, decode_error='strict',
        dtype=<class 'numpy.int64'>, encoding='utf-8', input='content',
        lowercase=True, max_df=1.0, max_features=None, min_df=1,
        ngram_range=(1, 1), preprocessor=None, stop_words=None,
        strip_accents=None, token_pattern='(?u)\\b\\w\\w+\\b',
        tokenizer=None, vocabulary=None)
#這裏我們查看下“詞典”,也就是特徵集(11個特徵詞)
vectorize.get_feature_names()
['did',
 'favor',
 'get',
 'go',
 'hey',
 'home',
 'lets',
 'lunch',
 'need',
 'today',
 'you']

這裏,特徵集(get_feature——name)返回的結果,有要注意的事情:

  • 所有的單詞都是小寫

  • 單詞長度小於兩個字母的,會被剔除掉

  • 標點符號會剔除掉

  • 不重複

  • 這個特徵集是有順序的

接下來會按照這個順序去編碼文本數據,這裏會出現一個新概念文檔-詞頻矩陣(document-term matrix),英文簡寫爲dtm。我們讓機器挖掘文本中的規律時,餵給機器的數據就是 這文檔-詞頻矩陣(document-term matrix)。

#構建 文檔詞頻矩陣
dtm = vectorize.transform(corpus)dtm
<3x11 sparse matrix of type '<class 'numpy.int64'>'
    with 13 stored elements in Compressed Sparse Row format>

構建文檔詞頻矩陣。結果3*11。

3指的是語料中的三個文檔;11指的是corpus中11個特徵詞。爲了方便我們理解,我用pandas庫將其展現出來


import pandas as pd

pd.DataFrame(dtm.toarray(), columns = vectorize.get_feature_names())

如何從文本中提取特徵信息?
從上面的dataframe表中,行代表一個文檔,列代表特徵詞。比如第1行,hey列的所對應的單元格值爲3,說明corpus中第一個document(Hey hey hey lets go get lunch today :) 出現了三次hey。

這裏有一個我要提示的重點,在此時我們已經構件號了文檔詞頻矩陣dtm,如果你還想加入新的文檔。我們應該注意tranform和fit的區別。


new_document = ['Hey lets go get a drink tonight']
new_dtm = vectorize.transform(new_document)
pd.DataFrame(new_dtm.toarray(), columns=vectorize.get_feature_names())

如何從文本中提取特徵信息?

即使new_document含有6個單詞,但是在上面的dataframe表中只有4個特徵詞被有效編碼,drink和tonight詞未被表徵。這是因爲我們初識的corpus語料所構建的詞典並未含有這些詞。但是對文本進行特徵表徵時,使用的確實corpus所生產的詞典。

我們機器學習所用的數據,一般被分成訓練集和測試集。訓練集是爲了讓機器學習數據的規律,測試集是爲了驗證規律的有效性。訓練集本質上代表的是過去及現在已知的數據,測試集本質上代表的是未來的未知數據(現在不存在的數據),我們是用已知的數據預測未來。

所以我們只能讓fit方法操作於訓練集,構建基於過去或已知數據的特徵集。

TfidfVectorizer
scikit庫除了CountVectorizer類,還有TfidfVectorizer類。TF-IDF這個定義相信大家應該已經耳熟能詳了:

TF 詞頻出現的次數 IDF = 1/(語料中含有該詞語的文檔的數目)


TF簡單點說有的時候詞語出現越多,這個詞越是特徵詞。但同時,有些“的它呢”等無意義詞出現的多並沒有什麼意義,反而是像“核能”這種詞,雖然不怎麼出現,但是一出現往往很具有特徵性。

綜合TF*IDF,就能很好的刻畫一個詞語是否具有表徵文本信息能力,作爲特徵是否合適。有了上面的基礎知識,我們接下來繼續寫代碼,便於理解TFIDF


from sklearn.feature_extraction.text import TfidfVectorizer

def createDTM(corpus):
    """構建文檔詞語矩陣"""
    vectorize = TfidfVectorizer()
    #注意fit_transform相當於fit之後又transform。
    dtm = vectorize.fit_transform(corpus)

    #打印dtm
    return pd.DataFrame(dtm.toarray(), columns=vectorize.get_feature_names()) 

corpus = ["Hey lets get lunch :)",
           "Hey!!! I need a favor"]
createDTM(corpus)

如何從文本中提取特徵信息?
我們看到hey這個詞在所有大於0的值裏面,是最小的。因爲hey同時出現在兩個文檔中,不具有文本的表徵能力,所以TFIDF小。而favor和need因爲他們僅僅出現在第二個文檔中,所以他們的TFIDF值更高。

現在我們改變corpus內容。將第一個文檔從Hey lets get lunch改爲Hey hey hey lets get lunch。我們希望第一個文檔的hey詞頻增大,進而使得其TFIDF值變大。


corpus = ["Hey hey hey lets get lunch :)",
           "Hey!!! I need a favor"]

createDTM(corpus)

如何從文本中提取特徵信息?

我們發現第一個文檔hey的TFIDF值變大,但這裏有兩點要注意:

  • 第一個文檔中其餘特徵詞的TFIDF值變小了

  • 第二個文檔中hey的TFIDF未發生變化

上面的例子是通過TF詞頻操作TFIDF值的。下面我們從IDF出發,改變TFIDF值。


corpus = ["Hey hey hey lets get lunch :)",
           "I need a favor"]

createDTM(corpus)

如何從文本中提取特徵信息?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章