雖然以前也寫過gensim庫的word2vec的教程,可是對於文本分析的特徵提取並不太理解。最近看了幾篇scikit的外文教程,對機器學習中文本的特徵提取有了一些瞭解。機器學習
首先作文本的機器學習(天然語言處理),咱們要理解這幾個概念:ide
文檔(document)這裏是指一段單獨的文本信息。這多是一則短信、一條推特、一封郵件、一本書、或者一首歌詞。通常一個文檔對應於一個觀測值或一行數據。學習
語料(corpus) 文檔的集合(語料大於等於1條文檔)。這至關於咱們要研究對象的全部文本數據測試
首先讓咱們給出一個語料例子。編碼
corpus = ["Hey hey hey lets go get lunch today :)", "Did you go home?", "Hey!!! I need a favor"]
CountVectorizer
首先咱們要明白,計算機是不能從文本字符串中發現規律的。只有將字符串編碼爲計算機能夠理解的數字,計算機纔有可能發現文本中的規律。spa
最容易理解的實現思路:3d
對文本編碼,就是讓詞語與數字對應起來,創建基於給定文本的詞典。(fit方法 )code
scikit庫的CountVectorize類就是這種思路。orm
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值變小了
上面的例子是經過TF詞頻操做TFIDF值的。下面咱們從IDF出發,改變TFIDF值。
corpus = ["Hey hey hey lets get lunch :)", "I need a favor"] createDTM(corpus)