この記事は ML.NET CLI を使用してセンチメントを分析する をもとに書かれています。
ただ上記は英語を対象にしています。日本語を対象にしたものはないのでしょうか?
これは主観(テキストの筆者1人)と客観(クラウドワーカ3人)の両方の立場から感情ラベルを付与したデータセットです。基本8感情(喜び、悲しみ、期待、驚き、怒り、恐れ、嫌悪、信頼)とその強度を4段階(0:無、1:弱、2:中、3:強)でラベル付けし、ver.2ではこれに感情極性(-2:強いネガティブ、-1:ネガティブ、0:ニュートラル、1:ポジティブ、2:強いポジティブ)も追加しています。60人の筆者から収集した35,000件がラベル付けされています。
Contents
WRIME: 主観と客観の感情分析データセットを使ってみる
wrime-ver2.tsvをダウンロードします。
タブ区切りで文章と筆者、日付、筆者の喜び、悲しみ、期待、驚き、怒り、恐れ、嫌悪、信頼とポジティブかネガティブかの感情極性、客観(3人)の喜び、悲しみ、期待、驚き、怒り、恐れ、嫌悪、信頼とポジティブかネガティブかの感情極性とその平均が数値でまとめられています。
ここで必要なのは筆者の感情極性と客観の感情極性の平均値です。筆者の感情極性と客観の感情極性の平均値の総和が正数ならポジティブ、負数ならネガティブ、0ならニュートラルとします。
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 26 27 28 29 30 31 32 33 |
string path = @"wrime-ver2.tsvがあるパス"; string path2 = @"加工後のテキストを保存するファイルのパス"; StreamReader sr = new StreamReader(path); string str = sr.ReadToEnd().Replace("\r", ""); sr.Close(); List<string> list = new List<string>(); string[] vs1 = str.Split('\n'); foreach (string s in vs1) { if (s.IndexOf("Sentence") != -1) // 最初の1行目は無視 continue; if (s == "" || s.IndexOf("\"") != -1) // 文のなかに改行があるものは除外 continue; string[] vs2 = s.Split('\t'); if (vs2.Length > 48) { // 筆者の感情極性と客観の感情極性の平均値の総和 int sentiment = int.Parse(vs2[12]) + int.Parse(vs2[48]); if (sentiment > 0) list.Add(vs2[0] + "\t1"); if (sentiment < 0) list.Add(vs2[0] + "\t-1"); if (sentiment == 0) list.Add(vs2[0] + "\t0"); } } StreamWriter sw = new StreamWriter(path2, false, Encoding.UTF8); sw.Write(string.Join("\n", list.ToArray())); sw.Close(); |
これで以下のようなテキストファイルが得られます。
1 2 3 4 5 |
ぼけっとしてたらこんな時間。チャリあるから食べにでたいのに… -1 今日の月も白くて明るい。昨日より雲が少なくてキレイな~ と立ち止まる帰り道。チャリなし生活も悪くない。 1 早寝するつもりが飲み物がなくなりコンビニへ。ん、今日、風が涼しいな。 0 眠い、眠れない。 -1 ただいま~ って新体操してるやん!外食する気満々で家に何もないのに!テレビから離れられない…! 0 |
mlnet classification コマンドを実行する
次にこのファイルがあるフォルダで以下を実行します。
1 2 |
cd <ファイルがあるフォルダのパス> mlnet classification --dataset "my-wrime-ver2.tsv" --label-col 1 --has-header false --train-time 300 |
このときmy-wrime-ver2.tsvが改行で終わっているとうまく処理がおこなわれません。
my-wrime-ver2.tsvは上記で生成したテキストファイルの名前です。最後の300はトレーニング時間です。文がたくさんあるのでこれくらい必要ではないかと思われます。
ML.NET CLIがインストールされていないときは以下のコマンドでインストールします。
1 2 3 4 5 |
(Winndows PCの場合) dotnet tool install --global mlnet-win-x64 (Macの場合) dotnet tool install --global mlnet-osx-x64 |
フォルダのなかにSampleClassificationというフォルダが生成され、中にSampleClassification.zipというシリアル化されたモデルが生成されるとともに、その生成されたモデルを実行/スコア付けする C# コードとそのモデルを生成するときに使用される C# トレーニング コードが生成されます。これをもとにWindowsFormsアプリケーションを作成します。
WindowsFormsアプリケーションで感情分析する
SampleClassification.zipをプロジェクトに追加して、SampleClassification.zipファイルのプロパティ:出力ディレクトリにコピー「常にコピーする」に変更します。
NuGetでMicrosoft.MLとMicrosoft.ML.FastTreeをインストールします。このとき対象プラットフォームをAny CPUからX64に変更しておかないとうまくいきません。
まずModelInputクラスとModelOutputクラスを定義します。これは上記で生成されたSampleClassification.consumption.csから拾ったものです。
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 26 27 28 |
public class ModelInput { [LoadColumn(0)] [ColumnName(@"col0")] public string Col0 { get; set; } [LoadColumn(1)] [ColumnName(@"col1")] public float Col1 { get; set; } } public class ModelOutput { [ColumnName(@"col0")] public float[] Col0 { get; set; } [ColumnName(@"col1")] public uint Col1 { get; set; } [ColumnName(@"Features")] public float[] Features { get; set; } [ColumnName(@"PredictedLabel")] public float PredictedLabel { get; set; } [ColumnName(@"Score")] public float[] Score { get; set; } } |
ポジティブかネガティブかを表示させるのであれば必要なコードはこれだけです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public partial class Form1 : Form { private static string MLNetModelPath = Path.GetFullPath("SampleClassification.zip"); public static readonly Lazy<PredictionEngine<ModelInput, ModelOutput>> PredictEngine = new Lazy<PredictionEngine<ModelInput, ModelOutput>>(() => CreatePredictEngine(), true); private static PredictionEngine<ModelInput, ModelOutput> CreatePredictEngine() { var mlContext = new MLContext(); ITransformer mlModel = mlContext.Model.Load(MLNetModelPath, out var _); return mlContext.Model.CreatePredictionEngine<ModelInput, ModelOutput>(mlModel); } public static ModelOutput Predict(ModelInput input) { var predEngine = PredictEngine.Value; return predEngine.Predict(input); } } |
テキストボックスに文を入力してボタンをクリックしたら感情分析をして、メッセージボックスでその結果を表示します。
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 |
public partial class Form1 : Form { private void button1_Click(object sender, EventArgs e) { if (textBox1.Text == "") return; ModelInput sampleData = new ModelInput() { Col0 = textBox1.Text, }; ModelOutput modelOutput = Predict(sampleData); string ret = ""; if (modelOutput.PredictedLabel == 1) ret = "ポジティブ"; if (modelOutput.PredictedLabel == -1) ret = "ネガティブ"; if (modelOutput.PredictedLabel == 0) ret = "ニュートラル"; MessageBox.Show(ret); } } |