lightLDA輸出接口-java版本

根據(jù)LightLDA的輸出文件得到文檔-主題分布主題-詞分布以及表示某篇文檔的topN關鍵詞乞娄。

import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.List;
import java.util.PriorityQueue;

/**
 * Created by yangxin on 2017/8/11.
 */
public class LDAResult {
    private double alpha;  //主題分布Dirichlet分布參數(shù)
    private double beta;   //詞分布Dirichlet分布參數(shù)
    private int topic_num;  //主題數(shù)目
    private int vocab_num;  //詞數(shù)目
    private int doc_num;    //文檔數(shù)目
    private double[][] doc_topic_mat = null;  //文檔_主題概率矩陣
    private double[][] topic_vocab_mat = null; //主題_詞概率矩陣
    private Item[][] doc_word_info = null;   //文檔_top詞的信息矩陣

    /**
     * lda每個doc對應的前n個詞Id
     */
    public static class Item implements Comparable<Item>{
        public double prob;
        public int word_id;

        public Item(double prob, int word_id) {
            this.prob = prob;
            this.word_id = word_id;
        }

        @Override
        public String toString() {
            return "Item{" +
                    "prob=" + prob +
                    ", word_id=" + word_id +
                    '}';
        }

        @Override
        public int compareTo(Item o) {
            return prob - o.prob > 0 ? 1 : -1;
        }
    }

    public LDAResult(double alpha, double beta, int topic_num, int vocab_num, int doc_num) {
        this.alpha = alpha;
        this.beta = beta;
        this.topic_num = topic_num;
        this.vocab_num = vocab_num;
        this.doc_num = doc_num;

        doc_topic_mat = new double[topic_num][doc_num];
        topic_vocab_mat = new double[vocab_num][topic_num];
    }

    /**
     * 得到每個文檔前n個關鍵詞
     * @param n
     * @return
     */
    public Item[][] getDocTopWordInfo(int n){
        doc_word_info = new Item[doc_num][n];
        for(int i = 0; i < doc_num; ++i){ //每篇文檔
            PriorityQueue<Item> queue = new PriorityQueue<>();
            for(int j = 0; j < vocab_num; ++j){ //每個詞
                double prob = 0;
                for(int k = 0; k < topic_num; ++k){ //每個主題
                    prob += doc_topic_mat[k][i] * topic_vocab_mat[j][k];
                }
                Item item = new Item(prob, j);
                queue.offer(item);
                if(queue.size() > n){
                    queue.poll();
                }
            }
            int q = queue.size();
            while(!queue.isEmpty()){
                doc_word_info[i][--q] = queue.poll();
            }
        }
        return doc_word_info;
    }

    /**
     * 寫每個文檔的前n個關鍵詞到文件中
     * @param n
     * @param output  輸出文件
     * @param titles  doc標題列表
     * @param words   詞列表
     * @throws Exception
     */
    public void dumpTopResult(int n, String output, final List<String> titles, final List<String> words) throws Exception{
        if(n <= 0) return;
        BufferedWriter bw = new BufferedWriter(new FileWriter(output));
        if(doc_word_info == null){
            doc_word_info = getDocTopWordInfo(n);
        }

        for(int i = 0; i < doc_num; ++i){  //doc_id
            bw.write(titles.get(i) + " : ");
            for(Item item : doc_word_info[i]){
                bw.write(words.get(item.word_id) + "/" + item.prob + " ");
            }
            bw.newLine();
            bw.flush();
        }

        bw.close();
    }

    /**
     * 加載文檔_主題模型
     * @param model_path
     * @throws Exception
     */
    public void loadDocTopicModel(String model_path) throws Exception{
        //將計數(shù)寫入到矩陣中
        BufferedReader br = new BufferedReader(new FileReader(model_path));
        String line = null;
        while((line = br.readLine()) != null){
            String[] doc_info = line.split("[\t ]+");
            int doc_id = Integer.parseInt(doc_info[0]);  //文檔號禀酱,從0開始

            for(int i = 1; i < doc_info.length; ++i){
                String[] topic_info = doc_info[i].split(":");   //對應的主題信息
                int topic_id = Integer.parseInt(topic_info[0]);  //主題id
                int topic_cnt = Integer.parseInt(topic_info[1]);  //主題次數(shù)
                doc_topic_mat[topic_id][doc_id] = topic_cnt;
            }
        }
        br.close();

        //計數(shù)
        int[] doc_cnts = new int[doc_num];  //每個文檔對應的主題數(shù)量和幔欧,即包含詞的數(shù)目
        for(int i = 0; i < doc_num; ++i){  //對每個文檔
            for(int j = 0; j < topic_num; ++j){  //對每個主題
                doc_cnts[i] += doc_topic_mat[j][i];
            }
        }

        //計算概率
        double factor = topic_num * alpha;
        for(int i = 0; i < doc_num; ++i){  //對每個文檔
            for(int j = 0; j < topic_num; ++j){  //對每個主題
                doc_topic_mat[j][i] = (doc_topic_mat[j][i] + alpha) / (doc_cnts[i] + factor);
            }
        }
    }

    /**
     * 加載主題_詞模型
     * @param model_path  主題_詞模型位置,對應文件 server_model_0
     * @param model_summary_path   主題數(shù)目統(tǒng)計谋减,對應文件 server_model_1
     * @throws Exception
     */
    public void loadTopicWordModel(String model_path, String model_summary_path) throws Exception{
        //將計數(shù)寫入到矩陣中
        BufferedReader br = new BufferedReader(new FileReader(model_path));
        String line = null;
        while((line = br.readLine()) != null){
            String[] info = line.split(" ");
            int word_id = Integer.parseInt(info[0]);  //詞id
            for(int i = 1; i < info.length; ++i){
                String[] topic_info = info[i].split(":"); //對應的每個topic信息
                int topic_id = Integer.parseInt(topic_info[0]);  //topic id
                int topic_cnt = Integer.parseInt(topic_info[1]);  //topic計數(shù)
                topic_vocab_mat[word_id][topic_id] = topic_cnt;
            }
        }
        br.close();

        //寫每個主題出現(xiàn)的次數(shù)
        int[] topic_cnts = new int[topic_num];   //主題出現(xiàn)的次數(shù)
        br = new BufferedReader(new FileReader(model_summary_path));
        String[] cnts = br.readLine().split(" ");
        for(int i = 1; i < cnts.length; ++i){
            String[] cnt_info = cnts[i].split(":");
            int topic_id = Integer.parseInt(cnt_info[0]);
            int topic_cnt = Integer.parseInt(cnt_info[1]);
            topic_cnts[topic_id] = topic_cnt;
        }
        br.close();

        //寫概率
        double factor = vocab_num * beta;   //歸一化因子
        for(int i = 0; i < vocab_num; ++i){  //每個詞
            for(int j = 0; j < topic_num; ++j){  //每個主題
                topic_vocab_mat[i][j] = (topic_vocab_mat[i][j] + beta) / (topic_cnts[j] + factor);
            }
        }
    }
}

調(diào)用

public static void main(String[] args) throws Exception{
    String doc_topic_path = "doc_topic.0";
    String topic_word_path = "server_0_table_0.model";
    String topic_summary = "server_0_table_1.model";
    String ori_doc_path = "merge_texts";
    String ori_word_path = "vocab";
    String output = "result";
    LDAResult result = new LDAResult(0.22, 0.1, 220, 1539967, 146119);
    result.loadTopicWordModel(topic_word_path, topic_summary);  //得到主題-詞概率分布
    result.loadDocTopicModel(doc_topic_path);   //得到文檔-主題概率分布
    List<String> titles = Util.getTitles(ori_doc_path);  //所有文檔名
    List<String> words = Util.getVocabs(ori_word_path);  //所有詞
    result.dumpTopResult(10, output, titles, words);  //每篇文檔的前10個關鍵詞寫入到output中
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末安聘,一起剝皮案震驚了整個濱河市哄酝,隨后出現(xiàn)的幾起案子难裆,更是在濱河造成了極大的恐慌子檀,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件乃戈,死亡現(xiàn)場離奇詭異褂痰,居然都是意外死亡,警方通過查閱死者的電腦和手機症虑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門缩歪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人谍憔,你說我怎么就攤上這事驶冒。” “怎么了韵卤?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵骗污,是天一觀的道長。 經(jīng)常有香客問我沈条,道長需忿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮屋厘,結(jié)果婚禮上涕烧,老公的妹妹穿的比我還像新娘。我一直安慰自己汗洒,他們只是感情好议纯,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著溢谤,像睡著了一般瞻凤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上世杀,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天阀参,我揣著相機與錄音,去河邊找鬼瞻坝。 笑死蛛壳,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的所刀。 我是一名探鬼主播衙荐,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼浮创!你這毒婦竟也來了忧吟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蒸矛,失蹤者是張志新(化名)和其女友劉穎瀑罗,沒想到半個月后胸嘴,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雏掠,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年劣像,在試婚紗的時候發(fā)現(xiàn)自己被綠了乡话。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡耳奕,死狀恐怖绑青,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情屋群,我是刑警寧澤闸婴,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站芍躏,受9級特大地震影響邪乍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一庇楞、第九天 我趴在偏房一處隱蔽的房頂上張望榜配。 院中可真熱鬧,春花似錦吕晌、人聲如沸蛋褥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽烙心。三九已至,卻和暖如春柏靶,著一層夾襖步出監(jiān)牢的瞬間弃理,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工屎蜓, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留痘昌,地道東北人。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓炬转,卻偏偏與公主長得像辆苔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子扼劈,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎部分 基礎部分的順序:基本語法驻啤,類相關的語法,內(nèi)部類的語法荐吵,繼承相關的語法骑冗,異常的語法,線程的語...
    子非魚_t_閱讀 31,644評論 18 399
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,185評論 25 707
  • 上善若水水善利萬物而不生處眾人之所惡故幾于道居善地心善緣與善仁言善信政善治事善能動善時夫唯不爭故無憂
    MR0k閱讀 307評論 0 0
  • 清晨被鬧鐘醒來先煎,醒覺的片刻贼涩,看著天花板,安靜的能聽見自己的心跳薯蝎,由于長期北漂遥倦,常常會有一種特別不安全的感覺,并不是...
    海草爸爸閱讀 180評論 0 0
  • [下載地址]https://git.oschina.net/mrj_mrj/pagesFilp.git 實現(xiàn)原理:...
    孤獨的劍客閱讀 1,110評論 0 13