1

Weka を使用してテキスト分類器を構築しようとしていますdistributionForInstanceが、クラスの確率1.0は 1 つ0.0のケースと他のすべてのケースにあるため、classifyInstance常に予測と同じクラスを返します。トレーニングの何かが正しく機能しません。

ARFFトレーニング

@relation test1

@attribute tweetmsg    String
@attribute classValues {politica,sport,musicatvcinema,infogeneriche,fattidelgiorno,statopersonale,checkin,conversazione}

@DATA

"Renzi Berlusconi Salvini Bersani",politica
"Allegri insulta la terna arbitrale",sport
"Bravo Garcia",sport

トレーニング方法

public void trainClassifier(final String INPUT_FILENAME) throws Exception
{
    getTrainingDataset(INPUT_FILENAME);

    //trainingInstances consists of feature vector of every input

    for(Instance currentInstance : inputDataset)
    {           
        Instance currentFeatureVector = extractFeature(currentInstance);

        currentFeatureVector.setDataset(trainingInstances);
        trainingInstances.add(currentFeatureVector);                
    }

    classifier = new NaiveBayes();

    try {
        //classifier training code
        classifier.buildClassifier(trainingInstances);

        //storing the trained classifier to a file for future use
        weka.core.SerializationHelper.write("NaiveBayes.model",classifier);
    } catch (Exception ex) {
        System.out.println("Exception in training the classifier."+ex);
    }
}

private Instance extractFeature(Instance inputInstance) throws Exception
{       
    String tweet = inputInstance.stringValue(0);
    StringTokenizer defaultTokenizer = new StringTokenizer(tweet);
    List<String> tokens=new ArrayList<String>();
    while (defaultTokenizer.hasMoreTokens())
    {
        String t= defaultTokenizer.nextToken();
        tokens.add(t);
    }

    Iterator<String> a = tokens.iterator();
    while(a.hasNext())
    {
                String token=(String) a.next();
                String word = token.replaceAll("#","");
                if(featureWords.contains(word))
                {                                              
                    double cont=featureMap.get(featureWords.indexOf(word))+1;
                    featureMap.put(featureWords.indexOf(word),cont);
                }
                else{
                    featureWords.add(word);
                    featureMap.put(featureWords.indexOf(word), 1.0);
                }

    }
    attributeList.clear();
    for(String featureWord : featureWords)
    {
        attributeList.add(new Attribute(featureWord));   
    }
    attributeList.add(new Attribute("Class", classValues));
    int indices[] = new int[featureMap.size()+1];
    double values[] = new double[featureMap.size()+1];
    int i=0;
    for(Map.Entry<Integer,Double> entry : featureMap.entrySet())
    {
        indices[i] = entry.getKey();
        values[i] = entry.getValue();
        i++;
    }
    indices[i] = featureWords.size();
    values[i] = (double)classValues.indexOf(inputInstance.stringValue(1));
    trainingInstances = createInstances("TRAINING_INSTANCES");

    return new SparseInstance(1.0,values,indices,1000000);
}


private void getTrainingDataset(final String INPUT_FILENAME)
{
    try{
        ArffLoader trainingLoader = new ArffLoader();
        trainingLoader.setSource(new File(INPUT_FILENAME));
        inputDataset = trainingLoader.getDataSet();
    }catch(IOException ex)
    {
        System.out.println("Exception in getTrainingDataset Method");
    }
    System.out.println("dataset "+inputDataset.numAttributes());
}

private Instances createInstances(final String INSTANCES_NAME)
{
    //create an Instances object with initial capacity as zero 
    Instances instances = new Instances(INSTANCES_NAME,attributeList,0);
    //sets the class index as the last attribute
    instances.setClassIndex(instances.numAttributes()-1);

    return instances;
}

public static void main(String[] args) throws Exception
{
      Classificatore wekaTutorial = new Classificatore();
      wekaTutorial.trainClassifier("training_set_prova_tent.arff");
      wekaTutorial.testClassifier("testing.arff");
}

public Classificatore()
{
    attributeList = new ArrayList<Attribute>();
    initialize();
}    

private void initialize()
{

    featureWords= new ArrayList<String>(); 

    featureMap = new TreeMap<>();

    classValues= new ArrayList<String>();
    classValues.add("politica");
    classValues.add("sport");
    classValues.add("musicatvcinema");
    classValues.add("infogeneriche");
    classValues.add("fattidelgiorno");
    classValues.add("statopersonale");
    classValues.add("checkin");
    classValues.add("conversazione");
}

試験方法

public void testClassifier(final String INPUT_FILENAME) throws Exception
{
    getTrainingDataset(INPUT_FILENAME);

    //trainingInstances consists of feature vector of every input
    Instances testingInstances = createInstances("TESTING_INSTANCES");

    for(Instance currentInstance : inputDataset)
    {

        //extractFeature method returns the feature vector for the current input
        Instance currentFeatureVector = extractFeature(currentInstance);
        //Make the currentFeatureVector to be added to the trainingInstances
        currentFeatureVector.setDataset(testingInstances);
        testingInstances.add(currentFeatureVector);

    }


    try {
        //Classifier deserialization
        classifier = (Classifier) weka.core.SerializationHelper.read("NaiveBayes.model");

        //classifier testing code
        for(Instance testInstance : testingInstances)
        {

            double score = classifier.classifyInstance(testInstance);
            double[] vv= classifier.distributionForInstance(testInstance);
            for(int k=0;k<vv.length;k++){
            System.out.println("distribution "+vv[k]); //this are the probabilities of the classes and as result i get 1.0 in one and 0.0 in all the others
            }
            System.out.println(testingInstances.attribute("Class").value((int)score));
        }
    } catch (Exception ex) {
        System.out.println("Exception in testing the classifier."+ex);
    }
}

短いメッセージ用のテキスト分類子を作成したいのですが、このコードはこのチュートリアルhttp://preciselyconcise.com/apis_and_installations/training_a_weka_classifier_in_java.phpに基づいています。問題は、クラスの確率が正しくないため、分類器が testing.arff 内のほぼすべてのメッセージに対して間違ったクラスを予測することです。training_set_prova_tent.arff には、クラスごとに同じ数のメッセージがあります。私がフォローしている例では、featureWords.dat を使用し、メッセージに存在する場合は 1.0 を単語に関連付けます。代わりに、training_set_prova_tent に存在する単語とテストに存在する単語を使用して独自の辞書を作成し、すべての単語に関連付けます。発生数。

PS私はこれがフィルターStringToWordVectorでできることを正確に知っていますが、トレーニングセット用とテストセット用の2つのファイルでこのフィルターを使用する方法を説明する例は見つかりませんでした。そのため、見つけたコードを適応させる方が簡単なようです。

どうもありがとうございました

4

1 に答える 1