LDA模型概要

1)從狄利克雷分佈α中抽樣,生成文檔d的主題分佈θ

2)從主題的多項式分佈θ中抽樣,生成文檔d的第i個詞的主題zi

3)從狄利克雷分佈β中抽樣,生成主題zi對應的詞語分佈φi

4)從詞語的多項式分佈φi中採樣,最終生成詞語wi

 

這個模型圖的解釋如下:

1.:這個過程表示生成第n個詞對應的topic。在生成第m篇文檔的時候,先從topic骰子中抽了一個骰子,然後投擲這個骰子,得到文檔中第n個詞的topic編號

2.:這個過程表示生成文檔中的第n個詞。在手裏的K個word骰子中,選編號爲的那個骰子進行投擲,生成

這裏需要提一下狄利克雷分佈的問題:對於一個3維狄利克雷參數向量(α, α, α)來說,當α小於1時,生成的概率向量偏向於某幾維,值越小,偏得越厲害;當α大於1時,生成的概率向量傾向於中間,值越大,趨中越厲害。

 經過一堆的數學推導之後,最後的形式是這個樣子的:

其中的α和β就是狄利克雷分佈的兩個參數,K是語料中的topic數,是個超參,M是語料集中的文檔數,,其中表示第k個topic產生的詞中word t的個數。

 

得到了p(w,z)這個乾淨的表達式之後,就可以用gibbs sampling算法對這個分佈進行採樣。爲什麼要進行採樣呢?當我們在面對一個未知或者複雜的分佈時,積分、期望或者說聯合分佈很難算出來,是個NP難問題,但是條件概率很容易算出來,這時候就要進行採樣。採樣的目的是得到這個分佈的樣本,通過這些樣本明確出該分佈的具體結構,常用MCMC來進行分佈採樣。MCMC本身解決的是無法直接採樣或理解的分佈問題的,不是對已知分佈進行採樣。gibbs是對MCMC的一種改進。在LDA中,後驗概率無法直接獲得,我們通過gibbs採樣的方法去採樣該分佈,從而得到模型結構。

我們現在需要求的是p(z|w),需要採樣的也是p(z|w)這個分佈,就是求某個單詞應該屬於什麼topic。gibbs採樣採的是(w, z),即聯合分佈的樣本。收斂後在聯合分佈的樣本空間,統計出各個參數。LDA是個生成模型,但是直接求聯合分佈概率,分母計算量比較大,只能通過gibbs採樣,採樣出聯合分佈的樣本,執行多次之後產生的樣本服從真實樣本的分佈,然後在聯合樣本空間計算出統計特性。gibbs採樣做LDA的好處是簡單,速度快,收斂結果也不錯。

 

以上就是整個LDA的大致過程,通俗版以及公式版。簡而言之,pLSA貝葉斯化就變成了LDA,對LDA模型進行改進有很多種方式,LDA的非參數化就變成了HDP(這個模型的優點就是自動確定topic的個數)

 

spark 代碼:

//屏蔽日誌
    Logger.getLogger("org.apache.spark").setLevel(Level.ERROR)
    Logger.getLogger("org.eclipse.jetty.server").setLevel(Level.OFF)

    val warehouseLocation = "/Java/Spark/spark-warehouse"
    val spark=SparkSession
            .builder()
            .appName("myClusters")
            .master("local[4]")            
            .config("spark.sql.warehouse.dir",warehouseLocation)            
            .getOrCreate();   

    val dataset_lpa=spark.read.format("libsvm")
                          .load("/spark-2.0.0-bin-hadoop2.6/data/mllib/sample_lda_libsvm_data.txt")                    
    //------------------------------------1 模型訓練-----------------------------------------
    /** 
     * k: 主題數,或者聚類中心數 
     * DocConcentration:文章分佈的超參數(Dirichlet分佈的參數),必需>1.0,值越大,推斷出的分佈越平滑 
     * TopicConcentration:主題分佈的超參數(Dirichlet分佈的參數),必需>1.0,值越大,推斷出的分佈越平滑 
     * MaxIterations:迭代次數,需充分迭代,至少20次以上
     * setSeed:隨機種子 
     * CheckpointInterval:迭代計算時檢查點的間隔 
     * Optimizer:優化計算方法,目前支持"em", "online" ,em方法更佔內存,迭代次數多內存可能不夠會拋出stack異常
     */  
    val lda=new LDA()
                .setK(3)
                .setTopicConcentration(3)
                .setDocConcentration(3)
                .setOptimizer("online")
                .setCheckpointInterval(10)
                .setMaxIter(100)

    val model=lda.fit(dataset_lpa)   

    /**生成的model不僅存儲了推斷的主題,還包括模型的評價方法。*/
    //---------------------------------2 模型評價-------------------------------------

    //模型的評價指標:ogLikelihood,logPerplexity
    //(1)根據訓練集的模型分佈計算的log likelihood,越大越好。
    val ll = model.logLikelihood(dataset_lpa)

    //(2)Perplexity評估,越小越好
    val lp = model.logPerplexity(dataset_lpa)

    println(s"The lower bound on the log likelihood of the entire corpus: $ll")
    println(s"The upper bound bound on perplexity: $lp")

    //---------------------------------3 模型及描述------------------------------
    //模型通過describeTopics、topicsMatrix來描述 

    //(1)描述各個主題最終的前maxTermsPerTopic個詞語(最重要的詞向量)及其權重
    val topics=model.describeTopics(maxTermsPerTopic=2)
    println("The topics described by their top-weighted terms:")
    topics.show(false)


    /**主題    主題包含最重要的詞語序號                     各詞語的權重
        +-----+-------------+------------------------------------------+
        |topic|termIndices  |termWeights                               |
        +-----+-------------+------------------------------------------+
        |0    |[5, 4, 0, 1] |[0.21169509638828377, 0.19142090510443274]|
        |1    |[5, 6, 1, 2] |[0.12521929515791688, 0.10175547561034966]|
        |2    |[3, 10, 6, 9]|[0.19885345685860667, 0.18794498802657686]|
        +-----+-------------+------------------------------------------+
     */    

    //(2) topicsMatrix: 主題-詞分佈,相當於phi。
    val topicsMat=model.topicsMatrix
    println("topicsMatrix")
    println(topicsMat.toString())
     /**topicsMatrix
        12.992380082908886  0.5654447550856024  16.438154549631257  
        10.552480038361052  0.6367807085306598  19.81281695100224   
        2.204054885551135   0.597153999004713   6.979803589429554 
    * 
    */

    //-----------------------------------4 對語料的主題進行聚類--------------------- 
    val topicsProb=model.transform(dataset_lpa)
    topicsProb.select("label", "topicDistribution")show(false)

    /** label是文檔序號 文檔中各主題的權重
        +-----+--------------------------------------------------------------+
        |label|topicDistribution                                             |
        +-----+--------------------------------------------------------------+
        |0.0  |[0.523730754859981,0.006564444943344147,0.46970480019667477]  |
        |1.0  |[0.7825074858166653,0.011001204994496623,0.206491309188838]   |
        |2.0  |[0.2085069748527087,0.005698459472719417,0.785794565674572]   |
        ...

    */

    spark.stop()

Dirichlet分佈的參數α、β
       docConcentration(Dirichlet分佈的參數α) 
       topicConcentration(Dirichlet分佈的參數β) 
       首先要強調的是EM和Online兩種算法,上述兩個參數的設置是完全不同的。 
EM方法: 
       (1)docConcentration: 只支持對稱先驗,K維向量的值都相同,必須>1.0。向量-1表示默認,k維向量值爲(50/k)+1。 
       (2)topicConcentration: 只支持對稱先驗,值必須>1.0。向量-1表示默認。 
       docConcentration: Only symmetric priors are supported, so all values in the provided k-dimensional vector must be identical. All values must also be >1.0. Providing Vector(-1) results in default behavior (uniform k dimensional vector with value (50/k)+1 
       topicConcentration: Only symmetric priors supported. Values must be >1.0. Providing -1 results in defaulting to a value of 0.1+1. 

由於這些參數都有明確的設置規則,因此也就不存在調優的問題了,計算出一個固定的值就可以了

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