1. 程式人生 > >基於的樸素貝葉斯的文本分類(附完整代碼(spark/java)

基於的樸素貝葉斯的文本分類(附完整代碼(spark/java)

ava -s for 轉換成 模型保存 ext js rgs cti txt

本文主要包括以下內容:
1)模型訓練數據生成(demo)
2 ) 模型訓練(spark+java),數據存儲在hdfs上
3)預測數據生成(demo)
4)使用生成的模型進行文本分類。

一、訓練數據生成

spark mllib模型訓練的輸入數據格式通常有兩種,一種叫做 LIBSVM 格式,樣式如下:
label index1:value1 index2:value2
label為類別標簽,indexX為特征向量索引下標,value為對應的那維的取值。
另一種格式樣式如下:
label f1,f2,f3,…,fn
fx為特征取值
兩種格式的文件,分別可以通過方法:
org.apache.spark.mllib.util.MLUtils.loadLibSVMFile
org.apache.spark.mllib.util.MLUtils.loadLabeledData
讀取。
我們這裏采用第一種格式。

現在開始正式生成這種格式的數據文件。在模型訓練階段,會直接從這個文件中讀取數據訓練。這個後面會講到。
我們這裏假設對於文本,我們已經提取了關鍵詞作為特征。特征列表如下:
features = [w1,w2,w3,…,wn]
同時,文本的主題(類別)集為:
topics = [t1,t2,…tm]
然後有很多的經過簡單處理(分詞,去停用詞等)得到訓練數據,每行的格式大概如下:
t2 w1,w23,w34,w1,…
我們直接將詞頻當做特征的取值。下面是生成libsvm格式的python代碼,僅供參考:

    for info in result:
        sstr = ""
        topic_name = info[0] #主題名
        content = str(info[1]).split() #處理後的文本內容(詞列表)
        index = topics.index(channel_name)
        sstr += str(index)
        features_val = ""
        for i,word in enumerate(features):
            freq = content.count(word)
            if freq:
                features_val += " "
                features_val += str(i+1) + ":" + str(freq)
        if not features_val:continue
        sstr += features_val
        #bayes_data.write(sstr+"\n")
        print n
        n += 1
    hdfs_client.write_list(sstr_lst,BAYES_DATA_PATH)#寫到hdfs指定路徑        
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

這樣,訓練數據就算生成完成了。

二、模型訓練

這步就簡單了。spark官網上有例子,直接拿來用就行了。現在貼出略做調整後的java代碼:

public static void training(JavaSparkContext jsc){
        String path = "data/libsvm_data.txt";

         JavaRDD<LabeledPoint> inputData = MLUtils.loadLibSVMFile(jsc.sc(), path).toJavaRDD();
         JavaRDD<LabeledPoint>[] tmp = inputData.randomSplit(new double[]{0.6, 0.4}, 12345);
         JavaRDD<LabeledPoint> training = tmp[0]; // training set
         JavaRDD<LabeledPoint> test = tmp[1]; // test set
         final NaiveBayesModel model = NaiveBayes.train(training.rdd());
         JavaPairRDD<Double, Double> predictionAndLabel =
           test.mapToPair(new PairFunction<LabeledPoint, Double, Double>() {
             @Override
             public Tuple2<Double, Double> call(LabeledPoint p) {
               return new Tuple2<Double, Double>(model.predict(p.features()), p.label());
             }
           });
         double accuracy = predictionAndLabel.filter(new Function<Tuple2<Double, Double>, Boolean>() {
           @Override
           public Boolean call(Tuple2<Double, Double> pl) {
             return pl._1().equals(pl._2());
           }
         }).count() / (double) test.count();
        //System.out.println(accuracy);
         // Save and load model
         model.save(jsc.sc(), "target/tmp/NaiveBayesModel");
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

如何執行這個任務?
具體完整的代碼大家可以從spark的項目上找,或者看本文最後貼出的補充部分代碼,基本也就全了。
把代碼所在的工程打包(jar),比如打包為XX.jar。
然後執行命令:
spark-submit –class “yourclass” –master yarn XX.jar
就可以了。打包,已經spark-submit命令就不要詳細講了吧?
模型訓練完成,可以打印模型的評測結果(準確率),並且將模型保存到hdfs上。註意上面的兩個路徑都是指hdfs上的路徑。

三、使用模型對文本進行分類

拿來展示分類的文本數據生成過程就不介紹了。和模型數據生成一樣。基本就是對你的文章分詞等,然後轉換成libsvm格式的文件,放到hdfs上。下面直接上分類的代碼:

public static void predict(JavaSparkContext jsc){
        NaiveBayesModel sameModel = NaiveBayesModel.load(jsc.sc(), "target/tmp/NaiveBayesModel");
        String path = "/data/pred_data.txt";
        JavaRDD<String> rdd = jsc.textFile(path);

        for(String features:rdd.collect()){
            //System.out.println(features);
            String[] feature_str_lst = features.split(",");
            double[] feature_lst = new double[feature_str_lst.length];
            for(int i = 0;i<feature_str_lst.length;i++){
                feature_lst[i] = Double.parseDouble(feature_str_lst[i]);
            }
            System.out.println(sameModel.predict(Vectors.dense(feature_lst)));

        }

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

執行後的結果正常情況你會看到如下的輸出:(框起來的都是預測的類別)

技術分享

還不會,沒有執行完整個demo?
代碼main()方法的也貼給你們:

public static void main(String[] args){
        SparkConf sparkConf = new SparkConf().setAppName("JavaNaiveBayesExample");
         JavaSparkContext jsc = new JavaSparkContext(sparkConf);
         //training(jsc);
         predict(jsc);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

好了。講完了,是不是很簡單。實現很簡單,算法原理也很簡單。有興趣就自己去研究吧。

基於的樸素貝葉斯的文本分類(附完整代碼(spark/java)