N-grams模型、停頓詞(stopwords)和標准化處理 - NLP學習(2)
在上一篇博文中,簡單地闡述了如何將文本向量化及詞袋模型的。文本向量化是為了將文本轉換成機器學習算法可以直接處理的數字,直白點說就是這些轉換后數字代表了文本的特征(此過程稱之為特征提取或者特征編碼),可以直接為機器學習模型所用。詞袋模型(Bag-of-Words: BOW)則指的是統計單詞在一個文本中出現的次數的表現形式(occurence of words within a specific document),主要是考量文本的兩個方面:
- 展現文本中出現的已知的詞匯 --- 詞匯量;
- 量化單詞的存在。
而之所以稱之為詞袋主要是因為該方式忽略了文本本來的有序性和結構性。一般詞袋模型主要是用來衡量文檔的相似性,因為兩個類似的文檔所含有的類似的文本內容。緊接着,就可以用BOW來做進一步分析,如語意分析等。在這篇博文中,將主要闡述如何從詞袋模型過度到TF-IDF詞袋模型,接着解釋TF-IDF是如何被運用到主題模型中的。
主題模型
1.1 齊波夫定律(Zipf's Law)
在正式介紹TF-IDF之前,先看看什么是齊波夫定律,因為這樣子有助於理解TF-IDF的含義。下面是關於英文的介紹:
“Zipf's Law describes that given some corpus of natural language utterances, the frequency of any word is inversely proportional to its rank in the frequency table.”
上面這段話表述的是:給定一個文檔,任何一個單詞出現的頻次是與其在頻次表(很多地方用的頻率,這里用頻次是為了做一定的區分,頻率想表述的是一種占比關系,頻次則說明次數的問題)上的位置(排名)成反比的。比如說一個單詞出現在頻次表上的第一位,那么它出現的次數基本(非嚴格意義)是排在第二位的單詞出現的次數的2倍,第三位的3倍,以此推斷下去。上面有說非嚴格意義的意思是說,並不是精准的兩倍三倍的差距,而是說在一個文本足夠大的情況下是如此。
1.2 主題模型(Topic Modelling)
知道一個文本各個單詞的出現的頻次可以提供給機器學習算法一些初步的特征,但是單單知道單詞的頻次並不能賦予我們做更多的事,也無從得知某個單詞對於該文檔的重要性。這里正式引入逆文本頻率指數(IDF:Inverse Doccument Frequency),通過了解IDF來引出最終所需要的TF-IDF整個計算公式和運用。TF-IDF的意思是:如果一個單詞(文本標識符)出現在一個文檔中的次數越多,但是卻很少出現在其他文檔中,那么就可以假設這個單詞在這個特定的文本中的分量是很重要的。具體的計算公式如下:
IDF = total number of documents (文本集含有的文本總數) / the number of documents contain a term (含有特定單詞的文本數)
舉個例子,假設我們現在有一個文本集,這個文本集一共含有5個不同的文本內容,其中3個文本含有‘China’這個單詞,那么IDF('China') = 5 / 3 = 1.67。但是直接拿IDF來衡量一個單詞在一個文本中的重要性,那樣子顯然會碰到一個問題,那就是數量級問題。比如我們有一個文本集,該文本集有100萬個文檔,在這100個文檔中尋找apple這個單詞,已知只有一個文本含有apple這個單詞,又已知有10個文檔含有orange這單詞,那么可以得到這兩個單詞的IDF分別為:100萬和10萬,通過這個例子可以看到量級差別太巨大,並不適合比較,所以在處理這樣子情況下建議引入log()和exp()函數來讓單詞的出現的頻次和文檔頻次處於統一水平,這樣子做的好處是后期計算得到的TF-IDF值會是均勻分布(uniformly distributed)。通過引入log,這個時候之前關於查找apple和orange的例子就會變成:
IDF('apple') = log(1000000/1) = 6
IDF('orange') = log(1000000/10) = 5
綜上,假設一個標識符 t 出現在一個文本集 D 中的特定文檔 d 的頻率可以定義為:
TF(t, d) = number of t appears in document d /total tokens in document d
IDF(t, D) = log(number of documents / number of documents containing t)
TF-IDF(t, d, D) = TF * IDF
從上述公式可以看出,如果一個單詞出現在特定文檔的次數越多,那么IDF的值也會相應的增大,緊接着TF-IDF的權重也會變大。這也就是說明了TF-IDF的值可以幫助理解一個文檔想要表達的或者幫助理解主題模型,因為按照之前的假設,一個單詞出現次數越多越能表達一個文檔想要表達的意思(注意停頓詞等的影響要去除)。下面代碼簡單描述了如何計算TF-IDF向量:
1 import copy 2 from nltk.tokenize import TreebankWordTokenizer 3 from collections import OrderedDict 4 5 docs = ["The faster Harry got to the store, the faster and faster Harry would get home."] 6 docs.append("Harry is hairy and faster than Jill.") 7 docs.append("Jill is not as hairy as Harry.") 8 9 tokenizer = TreebankWordTokenizer() 10 11 doc_tokens = [] 12 13 for doc in docs: 14 doc_tokens += [sorted(tokenizer.tokenize(doc.lower()))] 15 all_doc_tokens = sum(doc_tokens, []) 16 lexicon = sorted(set(all_doc_tokens)) 17 zero_vector = OrderedDict((token, 0) for token in lexicon) 18 19 document_tfidf_vectors = [] 20 for doc in docs: 21 22 vec = copy.copy(zero_vector) 23 tokens = tokenizer.tokenize(doc.lower()) 24 token_counts = Counter(tokens) 25 26 for key, value in token_counts.items(): 27 docs_containing_key = 0 28 for _doc in docs: 29 if key in _doc: 30 docs_containing_key += 1 31 tf = value / len(lexicon) 32 if docs_containing_key: 33 idf = len(docs) / docs_containing_key 34 else: 35 idf = 0 36 vec[key] = round(tf * idf, 4) 37 document_tfidf_vectors.append(vec)