LDA + SVM 文字分類
關於LDA的一些理解
對於語料庫中的每篇文件,LDA定義瞭如下生成過程(generative process):
- 對每一篇文件,從主題分佈中抽取一個主題;
- 從上述被抽到的主題所對應的單詞分佈中抽取一個單詞;
- 重複上述過程直至遍歷文件中的每一個單詞。
文件document中出現單詞word的概率 = 主題topic中出現word的概率 document中出現topic的概率。
- 以Topic作為中間層,可以通過當前的和得到,其中,利用得到,通過得到。
- 實際上,利用當前的和,我們可以為一個文件中的一個單詞計算它對應任意一個Topic時的,然後根據這些結果來更新這個詞對應的Topic。如果這個更新改變了這個單詞所對應的Topic,就會反過來影響和。
公式背景:
-
一個函式:Gamma函式
- Gamma函式是階乘函式在實數上的推廣
-
四個分佈:二項分佈、多項分佈、beta分佈、Dirichlet分佈
-
一個概念和一個理念:共軛先驗和貝葉斯框架
- 共軛分佈:後驗概率(posterior probability) 似然函式(likelyhood function) $\times $先驗概率(prior probability)
-
兩個模型:pLSA、LDA
-
一個取樣:Gibbs取樣
sklean.decomposition.LatentDirichletAllocation
sklearn的LDA方法與引數說明:
class sklearn.decomposition.LatentDirichletAllocation(n_components = 10,doc_topic_prior = None,topic_word_prior = None,learning_method = None,learning_decay = 0.7,learning_offset = 10.0,max_iter = 10,batch_size = 128,evaluate_every = -1,total_samples = 1000000.0,perp_tol = 0.1,mean_change_tol = 0.001,max_doc_update_iter = 100,n_jobs = 1,verbose = 0,random_state = None,n_topics = None )
n_components:int,optional(預設值= 10)
主題數量,老版本該引數名為n_topics
doc_topic_prior:float,optional(預設=無)
之前的文件主題分發theta。如果值為None,則預設為1 / n_components。在文獻中,這被稱為阿爾法。
topic_word_prior:float,optional(預設=無)
之前的主題詞分發beta。如果值為None,則預設為1 / n_components。在文獻中,這被稱為eta。
learning_method:‘batch’(批量更新)| ‘online’(線上更新),預設=‘online’
用於更新_component的方法。僅用於fit方法。通常,如果資料量很大,則線上更新將比批量更新快得多。預設學習方法將在0.20版本中更改為“批處理”。有效選項:
'batch':批量變分貝葉斯方法(Batch variational Bayes method)。每次EM更新都會使用所有訓練資料。 舊的components_將在每次迭代中被覆蓋。 'online':線上變分貝葉斯方法(Online variational Bayes method)。在每次EM更新中,使用 小批量的訓練資料來更新components_變數的遞增,學習率由learning_decay和learning_offset引數控制。
learning_decay:float,optional(預設值= 0.7)
它是線上學習方法中控制學習率的引數。該值應設定在(0.5,1.0)之間以保證漸近收斂。當值為0.0且batch_size為時
n_samples
,更新方法與批量學習相同。在文獻中,這稱為kappa。
learning_offset:float,optional(預設值= 10.)
一個(正)引數,可以降低線上學習中的早期迭代。它應該大於1.0。在文獻中,這稱為tau_0。
max_iter:整數,可選(預設= 10)
最大迭代次數。
batch_size:int,optional(預設值= 128)
每次EM迭代中使用的文件數。僅用於線上學習。
evaluate_every:int,optional(預設值= 0)
多久評估一次困惑。僅用於fit方法。將其設定為0或負數,以便根本不評估訓練中的困惑。評估困惑可以幫助您檢查培訓過程中的收斂,但也會增加總培訓時間。評估每次迭代中的困惑可能會將訓練時間增加兩倍。
total_samples:int,optional(default = 1e6)
檔案總數。僅用於partial_fit方法。
perp_tol:float,optional(預設值= 1e-1)
批量學習中的困惑容忍度。僅在
evaluate_every
大於0時使用。
mean_change_tol:float,optional(預設值= 1e-3)
在E步驟中停止更新文件主題分發的容差。
max_doc_update_iter:int(預設值= 100)
在E步驟中更新文件主題分發的最大迭代次數。
n_jobs:int,optional(預設值= 1)
在E步驟中使用的作業數。如果為-1,則使用所有CPU。對於
n_jobs
-1以下,使用(n_cpus + 1 + n_jobs)。
verbose:int,optional(預設值= 0)
詳細程度。
random_state:int,RandomState例項或None,可選(預設=無)
如果是int,則random_state是隨機數生成器使用的種子; 如果是RandomState例項,則random_state是隨機數生成器; 如果沒有,隨機數生成器所使用的RandomState例項np.random。
方法
fit (X [,y]) |
使用變分貝葉斯方法學習資料X的模型。 |
---|---|
獲取此估算工具的引數。 | |
線上VB與Mini-Batch更新。 | |
perplexity (X [,doc_topic_distr,sub_sampling]) |
計算資料X的近似困惑。 |
score (X [,y]) |
計算近似對數似然值作為分數。 |
設定此估算器的引數。 | |
根據擬合模型轉換資料X. |
-
__init__
(n_components = 10,doc_topic_prior = None,topic_word_prior = None,learning_method = None,learning_decay = 0.7,learning_offset = 10.0,max_iter = 10,batch_size = 128,evaluate_every = -1,total_samples = 1000000.0,perp_tol = 0.1,mean_change_tol = 0.001,max_doc_update_iter = 100,n_jobs = 1,verbose = 0,random_state = None,n_topics = None )[source] -
fit
(X,y =無)[來源]使用變分貝葉斯方法學習資料X的模型。當learning_method為“線上”時,請使用小批量更新。否則,請使用批量更新。引數:X:類似陣列或稀疏矩陣,shape =(n_samples,n_features)文件字矩陣。y:忽略了。return:self
-
fit_transform
(X,y =無,*** fit_params* )[來源]適合資料,然後轉換它。使用可選引數fit_params使變換器適合X和y,並返回X的變換版本。引數:X:numpy陣列形狀[n_samples,n_features]訓練集。y:numpy陣列形狀[n_samples]目標值。返回:X_new:numpy形狀陣列[n_samples,n_features_new]變形陣列。
-
get_params
(深=真)[來源]獲取此估算工具的引數。引數:deep:布林值,可選如果為True,將返回此估計器的引數幷包含作為估算器的子物件。返回:params:將字串對映到任意字串對映到其值的引數名稱。
-
partial_fit
(X,y =無)[來源]線上VB與Mini-Batch更新。引數:X:類似陣列或稀疏矩陣,shape =(n_samples,n_features)文件字矩陣。y:忽略了。return:self
-
perplexity
(X,doc_topic_distr =‘不贊成’,sub_sampling = False )[來源]計算資料X的近似困惑。困惑定義為exp(-1。每個單詞的對數似然)版本0.19中已更改:已棄用doc_topic_distr*引數並將其忽略,因為使用者無法再訪問非標準化分佈引數:X:類似陣列或稀疏矩陣,[n_samples,n_features]文件字矩陣。doc_topic_distr:無或陣列,shape =(n_samples,n_components)文件主題分發。此引數已棄用,目前正在被忽略。從版本0.19開始不推薦使用。sub_sampling:bool是否進行二次取樣。返回:得分:漂浮困惑得分。
-
score
(X,y =無)[來源]計算近似對數似然值作為分數。引數:X:類似陣列或稀疏矩陣,shape =(n_samples,n_features)文件字矩陣。y:忽略了。返回:得分:漂浮使用近似界限作為分數。
-
set_params
(*** params* )[來源]設定此估算器的引數。該方法適用於簡單估計器以及巢狀物件(例如管道)。後者具有表單的引數,
<component>__<parameter>
以便可以更新巢狀物件的每個元件。return:self -
transform
(X )[來源]根據擬合模型轉換資料X.在版本0.18中更改:doc_topic_distr現在已標準化引數:X:類似陣列或稀疏矩陣,shape =(n_samples,n_features)文件字矩陣。返回:doc_topic_distr:shape =(n_samples,n_components)X的文件主題分發。
例項1 : 使用LDA+SVM進行文字多分類
網上沒找到LDA與SVM結合的程式碼,我自己的實現方法如下,不知道用的正不正確,僅供參考。由於在比賽,暫不提供完整的參考程式碼。
Step 1. CV特徵提取
- LDA模型學習時的訓練資料並不是一篇篇文字,而是Document-word matrix,它可以是array也可以是稀疏矩陣,維數是n_samples*n_features,其中n_features為詞(term)的個數。因此在訓練LDA主題模型前,需要先利用CountVectorizer統計詞頻並儲存
from sklearn.feature_extraction.text import CountVectorizer
# 構建總單詞矩陣
count_v0= CountVectorizer();
counts_all = count_v0.fit_transform(all_text); #all_text為訓練集+測試集語料庫
# 構建訓練集單詞矩陣
count_v1= CountVectorizer(vocabulary=count_v0.vocabulary_)
counts_train = count_v1.fit_transform(train_texts)
# 構建測試集單詞矩陣
# count_v2 = CountVectorizer(vocabulary=count_v0.vocabulary_)
# counts_test = count_v2.fit_transform(test_texts);
Step 2. LDA構建詞模型(不太清楚這裡應該怎麼說?感覺依舊在做特徵工程)
- 核心程式碼為三步:構建模型、擬合數據(fit)、根據擬合模型轉換資料(transform)。
from sklearn.decomposition import LatentDirichletAllocation
lda = LatentDirichletAllocation(n_components=n_component, max_iter=50, learning_method='batch')
X_train = lda.fit(counts_train).transform(counts_train)
# X_test = lda.fit(counts_test).transform(counts_test)
Step 3. 使用分類模型(SVC為例)
- 把LDA構建好的詞模型輸入到分類器中即可。
svclf = SVC(kernel = 'linear')
svclf.fit(x_train,y_train)
preds = svclf.predict(x_test)
# ...
例項2 :使用LDA進行文字多分類
# 載入資料,使用sklearn自帶的fetch_20newsgroups資料集
from sklearn.datasets import fetch_20newsgroups
dataset = fetch_20newsgroups(shuffle=True, random_state=1,
remove=('headers', 'footers', 'quotes'))
n_samples=200
data_samples = dataset.data[:n_samples] #擷取需要的量,n_samples=2000
# CountVectorizer統計詞頻
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.externals import joblib #也可以選擇pickle等儲存模型,請隨意
n_features=2500
#構建詞彙統計向量並儲存,僅執行首次
tf_vectorizer = CountVectorizer(max_df=0.95, min_df=2,
max_features=n_features,
stop_words='english')
tf = tf_vectorizer.fit_transform(data_samples)
joblib.dump(tf_vectorizer,'tf_Model.pkl',compress=3)
#==============================================================================
#得到儲存的tf_vectorizer,節省預處理時間
#from sklearn.externals import joblib
#tf_vectorizer = joblib.load('tf_Model.pkl')
#tf = tf_vectorizer.fit_transform(data_samples)
#==============================================================================
from sklearn.decomposition import LatentDirichletAllocation
n_topic = 10
n_topics = 30
lda = LatentDirichletAllocation(n_topics=n_topic,
max_iter=50,
learning_method='batch')
lda.fit(tf) #tf即為Document_word Sparse Matrix
def print_top_words(model, feature_names, n_top_words):
#列印每個主題下權重較高的term
for topic_idx, topic in enumerate(model.components_):
print ("Topic #%d:" % topic_idx)
print (" ".join([feature_names[i] for i in topic.argsort()[:-n_top_words - 1:-1]]))
#列印主題-詞語分佈矩陣
print (model.components_)
n_top_words=20
tf_feature_names = tf_vectorizer.get_feature_names()
print_top_words(lda, tf_feature_names, n_top_words)
#print trained topic model
tf_feature_names = tf_vectorizer.get_feature_names()
for idx, topic in enumerate(lda.components_, start=1):
print('Topic #%d' % idx)
print("/".join([tf_feature_names[i] for i in topic.argsort ()[:-11:-1]])) #列印(主題-詞彙)向量
lda.transform(tf)[0] #列印(文章-主題)向量