調性(感情)を認識するタスクのためのWekaプロジェクト

これは私の出版物の英語の翻訳です。



インターネットには、実用的な問題を解決するために機械学習(ML)を使用した記事、メモ、ブログ、成功事例が満載です。 次の図のように、誰かがそれを長続きさせて元気づけます:



画像



確かに、これらの分野の専門家ではない人が既存のツールにアクセスするのはそれほど簡単ではない場合があります。 確かに、 scikit Pythonライブラリなどの実用的な機械学習への優れた比較的迅速なパスがあります。 ちなみに、 このプロジェクトには、SkyNetチーム(筆者がたまたまその主要参加者である)で記述されたコードが含まれており、ライブラリとのやり取りの容易さを示しています。 Java開発者の場合、いくつかの優れたツールがあります。WekaApache Mahoutです。 どちらのライブラリも、推奨システムからテキストの分類まで、特定のタスクへの適用性の点で普遍的です。 ツールボックスがあり、テキストベースの機械学習用にさらに洗練されています。 マレットスタンフォードライブラリのセットです。 Java-MLのようなあまり知られていないライブラリがあります。



この投稿では、Wekaライブラリに焦点を当て、特定の例(感情分析または感情検出のタスク)を使用して、テキストマシン学習用のドラフトプロジェクトまたはテンプレートプロジェクトを作成します。 これらすべてにもかかわらず、このプロジェクトは完全に運用可能であり、商用フレンドリーライセンス(Weka自体はGPL 3.0の下)、すなわち 強い要望があれば、プロジェクトにコードを適用することもできます。



選択した問題に一般的に適しているWekaアルゴリズムのセット全体から、 多項単純ベイズアルゴリズムを使用します。 この投稿では、ほとんど常に英語版と同じリンクを引用しています。 しかし、翻訳は創造的な仕事なので、トピックに関するリンクを機械学習に関する国内のリソースに提供できるようにします。



私の意見と機械学習ツールとの対話の経験では、プログラマは通常、1つまたは別のMLライブラリを使用する際の3つの問題の解決策を探しています:アルゴリズムのセットアップ、アルゴリズムとI / Oのトレーニング、つまり ディスクに保存し、訓練されたモデルのディスクからメモリにロードします。 リストされている純粋に実用的な理論的側面に加えて、おそらく最も重要なのはモデルの品質の評価です。 これについても触れます。



だから、順番に。



分類アルゴリズムのセットアップ



調性を3つのクラスに認識するタスクから始めましょう。



public class ThreeWayMNBTrainer { private NaiveBayesMultinomialText classifier; private String modelFile; private Instances dataRaw; public ThreeWayMNBTrainer(String outputModel) { // create the classifier classifier = new NaiveBayesMultinomialText(); // filename for outputting the trained model modelFile = outputModel; // listing class labels ArrayList<attribute> atts = new ArrayList<attribute>(2); ArrayList<string> classVal = new ArrayList<string>(); classVal.add(SentimentClass.ThreeWayClazz.NEGATIVE.name()); classVal.add(SentimentClass.ThreeWayClazz.POSITIVE.name()); atts.add(new Attribute("content",(ArrayList<string>)null)); atts.add(new Attribute("@@class@@",classVal)); // create the instances data structure dataRaw = new Instances("TrainingInstances",atts,10); } }
      
      





上記のコードでは、次のことが起こります。







同様に、より多くの出力ラベルを使用して、5つのクラスの分類子が作成されます。



  public class FiveWayMNBTrainer { private NaiveBayesMultinomialText classifier; private String modelFile; private Instances dataRaw; public FiveWayMNBTrainer(String outputModel) { classifier = new NaiveBayesMultinomialText(); classifier.setLowercaseTokens(true); classifier.setUseWordFrequencies(true); modelFile = outputModel; ArrayList<Attribute> atts = new ArrayList<Attribute>(2); ArrayList<String> classVal = new ArrayList<String>(); classVal.add(SentimentClass.FiveWayClazz.NEGATIVE.name()); classVal.add(SentimentClass.FiveWayClazz.SOMEWHAT_NEGATIVE.name()); classVal.add(SentimentClass.FiveWayClazz.NEUTRAL.name()); classVal.add(SentimentClass.FiveWayClazz.SOMEWHAT_POSITIVE.name()); classVal.add(SentimentClass.FiveWayClazz.POSITIVE.name()); atts.add(new Attribute("content",(ArrayList<String>)null)); atts.add(new Attribute("@@class@@",classVal)); dataRaw = new Instances("TrainingInstances",atts,10); } }
      
      







分類器トレーニング



分類アルゴリズムまたは分類子のトレーニングは、ペア(x、y)に配置されたアルゴリズムの例(オブジェクト、ラベル)と通信することにあります。 オブジェクトは、あるクラスのオブジェクトを別のクラスのオブジェクトから定性的に区別できるセット(またはベクトル)によって、いくつかの機能によって記述されます。 たとえば、フルーツオブジェクトをオレンジとリンゴの2つのクラスに分類するタスクでは、サイズ、色、にきびの存在、尾の存在などの兆候が考えられます。 調性認識問題のコンテキストでは、特徴ベクトルは単語(ユニグラム)または単語のペア(バイグラム)で構成できます。 そして、ラベルはキークラスの名前(またはシリアル番号)になります:NEGATIVE、NEUTRALまたはPOSITIVE。 例に基づいて、アルゴリズムが学習し、「特徴ベクトルxによる」未知のラベルyの予測レベルに一般化できることが期待されます。



ペア(x、y)を追加してキーを3つのクラスに分類するメソッドを実装します。 特徴ベクトルは単語のリストであると仮定します。



 public void addTrainingInstance(SentimentClass.ThreeWayClazz threeWayClazz, String[] words) { double[] instanceValue = new double[dataRaw.numAttributes()]; instanceValue[0] = dataRaw.attribute(0).addStringValue(Join.join(" ", words)); instanceValue[1] = threeWayClazz.ordinal(); dataRaw.add(new DenseInstance(1.0, instanceValue)); dataRaw.setClassIndex(1); }
      
      







実際、2番目のパラメーターとして、文字列の配列の代わりにメソッドと文字列を渡すことができます。 ただし、要素の配列を意図的に使用して、コードが必要なフィルターを適用できるようにします。 調性分析の場合、非常に関連性の高いフィルターは、否定語(粒子など)と次の単語を接着することです: do like => do not _ like 。 したがって、「 好き」と「 嫌い」の兆候は、異極エンティティを形成します。 接着せずに、肯定的なコンテキストと否定的なコンテキストの両方でlikeという単語を見つけることができます。これは、(現実とは異なり)必要な信号を運ばないことを意味します。 次のステップでは、分類子を作成するときに、文字列要素の文字列がトークン化され、ベクトルに変換されます。



実際、分類器のトレーニングは1行で実装されます。

 public void trainModel() throws Exception { classifier.buildClassifier(dataRaw); }
      
      







シンプル!



I / O(モデルの保存と読み込み)



機械学習の分野で非常に一般的なシナリオは、メモリ内の分類子モデルのトレーニングと、それに続く新しいオブジェクトの認識/分類です。 ただし、製品の一部として機能するには、モデルをディスクに配信してメモリにロードする必要があります。 ディスクへの保存とディスクからWekaの訓練されたモデルのメモリへのロードは、分類アルゴリズムのクラスがとりわけSerializableインターフェイスを実装するため、非常に簡単に実現されます。



訓練されたモデルの保存:



  public void saveModel() throws Exception { weka.core.SerializationHelper.write(modelFile, classifier); }
      
      







訓練されたモデルの読み込み:



  public void loadModel(String _modelFile) throws Exception { NaiveBayesMultinomialText classifier = (NaiveBayesMultinomialText) weka.core.SerializationHelper.read(_modelFile); this.classifier = classifier; }
      
      







ディスクからモデルをロードした後、テキストの分類を扱います。 3クラス予測の場合、次のメソッドを実装します。



  public SentimentClass.ThreeWayClazz classify(String sentence) throws Exception { double[] instanceValue = new double[dataRaw.numAttributes()]; instanceValue[0] = dataRaw.attribute(0).addStringValue(sentence); Instance toClassify = new DenseInstance(1.0, instanceValue); dataRaw.setClassIndex(1); toClassify.setDataset(dataRaw); double prediction = this.classifier.classifyInstance(toClassify); double distribution[] = this.classifier.distributionForInstance(toClassify); if (distribution[0] != distribution[1]) return SentimentClass.ThreeWayClazz.values()[(int)prediction]; else return SentimentClass.ThreeWayClazz.NEUTRAL; }
      
      







if if(distribution [0]!= Distribution [1])という行に注意してください 。 覚えているように、この場合のクラスラベルのリストは{NEGATIVE、POSITIVE}として定義しました。 したがって、原則として、分類子は少なくともバイナリでなければなりません。 しかし! 与えられた2つのラベルの確率分布が同じ(それぞれ50%)であれば、中立クラスを扱っているとかなり自信を持って想定できます。 したがって、分類子を3つのクラスに分けます。



分類子が正しく構築されている場合、次の単体テストが正しく機能するはずです。



  @org.junit.Test public void testArbitraryTextPositive() throws Exception { threeWayMnbTrainer.loadModel(modelFile); Assert.assertEquals(SentimentClass.ThreeWayClazz.POSITIVE, threeWayMnbTrainer.classify("I like this weather")); }
      
      







完全を期すために、分類子を構築およびトレーニングし、モデルをディスクに保存し、モデルの品質をテストするラッパークラスを実装します。



  public class ThreeWayMNBTrainerRunner { public static void main(String[] args) throws Exception { KaggleCSVReader kaggleCSVReader = new KaggleCSVReader(); kaggleCSVReader.readKaggleCSV("kaggle/train.tsv"); KaggleCSVReader.CSVInstanceThreeWay csvInstanceThreeWay; String outputModel = "models/three-way-sentiment-mnb.model"; ThreeWayMNBTrainer threeWayMNBTrainer = new ThreeWayMNBTrainer(outputModel); System.out.println("Adding training instances"); int addedNum = 0; while ((csvInstanceThreeWay = kaggleCSVReader.next()) != null) { if (csvInstanceThreeWay.isValidInstance) { threeWayMNBTrainer.addTrainingInstance(csvInstanceThreeWay.sentiment, csvInstanceThreeWay.phrase.split("\\s+")); addedNum++; } } kaggleCSVReader.close(); System.out.println("Added " + addedNum + " instances"); System.out.println("Training and saving Model"); threeWayMNBTrainer.trainModel(); threeWayMNBTrainer.saveModel(); System.out.println("Testing model"); threeWayMNBTrainer.testModel(); } }
      
      







モデル品質



既に推測しているかもしれませんが、モデルの品質のテストもWekaを使用して簡単に実装できます。 モデルの定性的特性の計算は、たとえば、モデルが再トレーニングされているか、未達成であるかを確認するために必要です。 モデルの控えめな表現では、直感的です。分類されたオブジェクトの最適な数の兆候が見つかりませんでした。モデルは単純すぎることが判明しました。 再訓練とは、モデルが例に合わせて調整されすぎていることを意味します。 それは現実世界に一般化せず、過度に複雑です。



モデルをテストするにはさまざまな方法があります。 これらの方法の1つは、トレーニングセット(たとえば、3分の1)からテストサンプルを抽出し、相互検証を実行することです。 つまり 新しい反復ごとに、トレーニングセットの新しい3分の1をテストサンプルとして取得し、解決される問題に関連する品質パラメーター(精度/完全性/精度など)を計算します。 そのような実行の最後に、すべての反復の平均を計算します。 これは、モデルの償却後の品質になります。 つまり、実際には、完全なトレーニングデータセットよりも低くなる可能性がありますが、実際の生活の質に近くなります。



ただし、モデルの精度を簡単に確認するには、精度を計算するだけで十分です。 不正解に対する正解の数:



  public void testModel() throws Exception { Evaluation eTest = new Evaluation(dataRaw); eTest.evaluateModel(classifier, dataRaw); String strSummary = eTest.toSummaryString(); System.out.println(strSummary); }
      
      







このメソッドは、次の統計を表示します。



 Correctly Classified Instances 28625 83.3455 % Incorrectly Classified Instances 5720 16.6545 % Kappa statistic 0.4643 Mean absolute error 0.2354 Root mean squared error 0.3555 Relative absolute error 71.991 % Root relative squared error 87.9228 % Coverage of cases (0.95 level) 97.7697 % Mean rel. region size (0.95 level) 83.3426 % Total Number of Instances 34345
      
      







したがって、トレーニングセット全体のモデルの精度は83.35%です。 コードを含む完全なプロジェクトは、私のgithubにあります。 コードはkaggleのデータを使用します。 したがって、コードを使用する(または競争に参加する)場合でも、参加条件に同意してデータをダウンロードする必要があります。 調性を5つのクラスに分類するための完全なコードを実装するタスクは、読者に残ります。 頑張って!



All Articles