JGibbLDA是Java版本的LDA(Latent Dirichlet Allocation)實現,下載地址http://jgibblda.sourceforge.net/
我這里下載的是JGibbLDA-v.1.0,下載完成解壓時候的文件結構如下
其中models文件夾當中是兩個已經成長的主題模型例子,lib文件夾當中是個jar包args4j-2.0.6.jar,是用於處理java命令行參數的一個jar包,導入項目時需將此包也導入構建路徑,我用的是win 7,感覺用命令行別扭,就想着把它改造一下,用配置文件吧。
JGibbLDA的參數基本上有下面幾個:
- #-est 此參數初次訓練LDA模型;
- #-estc:此參數用於從已有的模型當中訓練LDA模型;
- #-inf: 此參數用於對新的文檔進行測試;
- #-model <string>: 已有的模型的名稱;
- #-alpha<double>:α超參數,默認是50/K,K為主題數量;
- #-beta <double>: β超參數,默認為0.1;
- #-ntopics <int>: 主題數量,默認100;
- #-niters <int>: Gibbs抽樣迭代次數,默認為2000;
- #-savestep <int>: 保持模型的迭代次數,即每迭代多少次將保持一次結果模型。默認為200;
- # -twords <int>: 每個主題最可能的單車數量。默認為0,如果設定大於0,比如20,JGibbLDA將會根據此參數在每次保持模型時為每個主題打印出最可能的20個詞;
- #-dir <string>: 輸入詞集文件夾目錄;此目錄也是模型結果輸出目錄
- # -dfile <string>: 輸入詞集文件名稱
輸入詞集格式一般如下
[M]
[document1]
[document2]
...
[documentM]
其中:M是文檔個數[documenti]為文檔詞集,按空格分隔
輸出數據
建立模型階段,會輸出5類以如下規則命名的文件類型:
model-XXXXX.others:
model-XXXXX.phi
model-XXXXX.theta
model-XXXXX.tassign
model-XXXXX.twords
XXXXX都以數字組成。最后一次迭代所保存的這些數字將會換成“final”。
其中:
.others為“信息文件”。文件保存的是跟該LDA模型有關的參數,比如alpha,beta,ntopiccs,ndocs,nwords,liter( the Gibbssampling iteration at which the model was saved)
.phi文件為“詞項-類簇概率分布文件”,表現上是一個大矩陣M。其中,假設設類簇的數目topict為1000個,每一個類簇需要列出top 100個詞項wordw,則M以100為行,1000為列。即M每一行是詞項,每一列是類簇。M元素值則為條件概率p(wordw|topict)。
.theta文件為“記錄-類簇概率分布文件”。表現上也是一個大矩陣M。每一行是訓練數據的一條記錄,每一列是一個類簇,元素值則為條件概率 p(topict|documentm)。
.tassign文件為“記錄-詞項-類簇分布文件”。文件每一行代表訓練數據的一條記錄,原記錄由一組詞項組成,現每一行為原來的記錄詞項指派了其最大可能的所屬類簇。注意,不包含該記錄所屬類簇。
.twords文件為“詞項-類簇推斷文件”。這個文件作為模型參數結果推斷出了每一個類簇下最優的topN個詞項及其概率。請注意這里的類簇數和N都是事先指定的。
這5個文件包括副產品wordmap.txt在有些應用場景下有時並不是完全需要的,是否生成可視情況而定。如果利用類簇下topN詞項來做基於距離的聚類,可能只需.twords即可。
推斷新數據和關鍵代碼
將產生如下文件,其組織和意義如前所述一致:
newdocs.dat.others
newdocs.dat.phi
newdocs.dat.tassign
newdocs.dat.theta
newdocs.dat.twords
修改運行模式為配置文件的修改代碼如下
PropertyUtils.java讀取配置文件src/option.properties

1 package cn.edu.gdut.utils; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.util.Properties; 8 9 public class PropertyUtils { 10 11 private static Properties p = null; 12 13 private static Properties getProperties() { 14 if (p == null) { 15 synchronized (FileUtils.class) { 16 if (p == null) { 17 p = new Properties(); 18 try { 19 InputStream in = new FileInputStream(new File( 20 "src/option.properties")); 21 p.load(in); 22 in.close(); 23 } catch (IOException e) { 24 e.printStackTrace(); 25 return null; 26 } 27 } 28 } 29 } 30 return p; 31 } 32 33 public static boolean getEst() { 34 if (getProperties().get("est") == null 35 || "".equals(getProperties().get("est"))) { 36 return false; 37 } 38 return ("true").equals((String) getProperties().get("est")) ? true 39 : false; 40 } 41 42 public static boolean getEstc() { 43 if (getProperties().get("estc") == null 44 || "".equals(getProperties().get("estc"))) { 45 return false; 46 } 47 return ("true").equals((String) getProperties().get("estc")) ? true 48 : false; 49 } 50 51 public static boolean getInf() { 52 if (getProperties().get("inf") == null 53 || "".equals(getProperties().get("inf"))) { 54 return false; 55 } 56 return ("true").equals((String) getProperties().get("inf")) ? true 57 : false; 58 } 59 60 public static double getAlpha() { 61 if (getProperties().get("alpha") == null 62 || "".equals(getProperties().get("alpha"))) { 63 return 50.0 / getNtopics(); 64 } 65 return Double.parseDouble((String) getProperties().get("alpha")); 66 } 67 68 public static double getBeta() { 69 if (getProperties().get("beta") == null 70 || "".equals(getProperties().get("beta"))) { 71 return 0.1; 72 } 73 return Double.parseDouble((String) getProperties().get("beta")); 74 } 75 76 public static int getNiters() { 77 if (getProperties().get("niters") == null 78 || "".equals(getProperties().get("niters"))) { 79 return 2000; 80 } 81 return Integer.parseInt((String) getProperties().get("niters")); 82 } 83 84 public static int getNtopics() { 85 if (getProperties().get("ntopics") == null 86 || "".equals(getProperties().get("ntopics"))) { 87 return 100; 88 } 89 return Integer.parseInt((String) getProperties().get("ntopics")); 90 } 91 92 public static void setNtopics(int K) { 93 getProperties().setProperty("ntopics", String.valueOf(K)); 94 } 95 96 public static int getSavestep() { 97 if (getProperties().get("savestep") == null 98 || "".equals(getProperties().get("savestep"))) { 99 return 200; 100 } 101 return Integer.parseInt((String) getProperties().get("savestep")); 102 } 103 104 public static int getTwords() { 105 if (getProperties().get("savestep") == null 106 || "".equals(getProperties().get("savestep"))) { 107 return 200; 108 } 109 return Integer.parseInt((String) getProperties().get("twords")); 110 } 111 112 public static String getDir() { 113 if (getProperties().get("dir") == null 114 || "".equals(getProperties().get("dir"))) { 115 return "models\\casestudy-zh"; 116 } 117 return (String) getProperties().get("dir"); 118 } 119 120 public static String getOutDir() { 121 if (getProperties().get("outdir") == null 122 || "".equals(getProperties().get("outdir"))) { 123 return "LDAModels\\casestudy-zh"; 124 } 125 return (String) getProperties().get("outdir"); 126 } 127 128 public static String getDfile() { 129 if (getProperties().get("dfile") == null 130 || "".equals(getProperties().get("dfile"))) { 131 return "sdate.dat"; 132 } 133 return (String) getProperties().get("dfile"); 134 } 135 136 public static String getModel() { 137 if (getProperties().get("dfile") == null 138 || "".equals(getProperties().get("dfile"))) { 139 return ""; 140 } 141 return (String) getProperties().get("model"); 142 } 143 144 145 }
修改LDA代碼

1 package jgibblda; 2 3 import cn.edu.gdut.util.FileUtil; 4 5 public class LDA { 6 7 public static void main(String args[]) { 8 LDACmdOption option = new LDACmdOption(); 9 fillOption(option); 10 if (!option.est && !option.estc && !option.inf) { 11 System.out.println("請選擇一種模式!"); 12 return; 13 } 14 15 if (option.est || option.estc) { 16 Estimator estimator = new Estimator(); 17 estimator.init(option); 18 estimator.estimate(); 19 } else if (option.inf) { 20 Inferencer inferencer = new Inferencer(); 21 inferencer.init(option); 22 23 Model newModel = inferencer.inference(); 24 25 for (int i = 0; i < newModel.phi.length; ++i) { 26 System.out 27 .println("-----------------------\ntopic" + i + " : "); 28 for (int j = 0; j < 10; ++j) { 29 System.out.println(inferencer.globalDict.id2word.get(j) 30 + "\t" + newModel.phi[i][j]); 31 } 32 } 33 } 34 } 35 36 private static void fillOption(LDACmdOption option) { 37 option.est = FileUtil.getEst(); 38 option.estc = FileUtil.getEstc(); 39 option.inf = FileUtil.getInf(); 40 option.alpha = FileUtil.getAlpha(); 41 option.beta = FileUtil.getBeta(); 42 option.dir = FileUtil.getDir(); 43 option.dfile = FileUtil.getDfile(); 44 option.modelName = FileUtil.getModel(); 45 option.niters = FileUtil.getNiters(); 46 option.K = FileUtil.getNtopics(); 47 option.savestep = FileUtil.getSavestep(); 48 option.twords = FileUtil.getTwords(); 49 } 50 51 }
這個時候,lib文件夾當中args4j-2.0.6.jar可以丟棄了。