特化させるための追加学習Tauri側に組み込むあとがき前編の振り返り前編の記事ではツールを作成することになった背景と、ツールの構成について説明しました。tauri側ではプロジェクトの作成~ビルドまでを一通り解説しています。先に前編をご覧になることをおすすめします!形態素解析とはこの記事の本編である形態素解析について説明です。「文章を意味のわかる最小単位まで分解して、それらの品詞(名詞や動詞、形容詞など)を解析する」です。形態素解析では、単語レベルで分解した上でそれぞれの品詞を解析・分類し、文の構成や自然言語処理などの研究でよく使用されています。今回使用する、スキルの説明文とマスタの例としては下のようになっています。敵/全体/に/水/属性/の/攻撃/(/威力/:/180/)/を/行う/と分解することができると思います。ここから不要な文字(接続詞)を削除して解析しやすいように編集します。敵/全体/水/属性/攻撃/威力/180/接続詞などを削除するとこのようになります。これならプログラム側で制御できそうですね。ちなみにですが、接続詞などの削除はバックエンドのrust側で行なっています。品詞分解した値は配列として返却されるため、削除する文字のリスト(解析には不要な文字のリスト)を持っておき一致した場合には配列から削除するようにしています。するライブラリはTinySegmenterです。このライブラリは品詞解析まではできないのですが、非常に軽量で高速に分かち書き後行ってくれます。辞書等は持っておらずサーバとの通信も不要で、このライブラリ単体で実行可能という利点があります。他の形態素解析ライブラリでは品詞分解という、分割した形態素がどの品詞かという解析も可能なライブラリもありますが、今回は品詞の情報は不要なため、分かち書きで十分です。試しに、配布サイトで精度の確認を行ってみます。属性/の/攻撃/(/威力/:/180/)/を/行う/このように出力されれば成功です。理想形とは結構違う出力がされてしまいました...他の例文も試してみます。このようにかなり精度が低い状態です。理由としては、こちらのライブラリは新聞記事を元に学習を行っているため、新聞記事とは全く異なるスキルの説明文はうまく対応ができません。TinySegmenterには追加学習ができるツールが存在しています。特化させるための追加学習TinySegmenterMakerこちらのツールはTinySegmenter向けに作成された、モデルの追加学習ツールです。使用方法としては、教師データとして事前にスペースで分かち書きを行ったファイルを用意し学習させます。そのあとは、js用のモデルを出力させて、アプリケーションに組み込みます。分かち書きのデータとしては、すでに存在しているスキルの説明文を130件ほど持ってきて、こちらが意図する分かち書きの形式で記述します。敵単体に、火属性の攻撃(威力:300)を行う味方全体に、回復(効果:50)を行うなど、ユニークな説明文があればそれぞれ追加します。学習方法についてはREADMEに書かれている通り、train.cppをコンパイルした上で実行を行います。コンパイルにはc++コンパイラのg++が必要です。学習tarin.cppの処理では、機械学習の精度向上に使用されるAdaBoostを使用しているようです。新しい弱分類器の分類精度が0.001以下,繰り返し回数が10000回以上が例として挙げられていたので、その通りに学習させてみます。時間としては10秒程度で完了しました。学習させた後のモデルの実行結果です。上3行が入力、下3行が分かち書きの結果になります。正確に意図通りの分かち書きを出力できました!(教師データが少し異なるので、効果値の後の)が分解できていないようです)試しに全く学習させていない説明文も入力してみます。綺麗に分かち書きすることができました!あとは、モデルをjsで読み込める形式に出力します。perlなど様々な言語への出力のサポートを行っています。実行方法は下記のようにすると、JavaScriptでの出力を行ってくれます。model出力されたものの一部がこちららです。default_model変数に入っているものが、追加学習後のモデルとなっているようです。"O";}Tauri側に組み込む分かち書きのモデルを特化することができたので、いよいよtauriのフロントエンドに組み込みます。tauriのプロジェクトに配置して実行できれば良かったのですが、先ほど出力された形式に問題がありました。language_">this</span>);具体的にはこの書き方で、こちらは即時関数での書き方かつgrobalに追加しています。これはTinySegmenterMakerが古いプロジェクトのため、tauriで読み込める書き方と合わなかったということが考えられます。そこで、下のようにJavaScriptのモジュールとして定義しimportする形で読み込むようにしました。tinySegmenter.segment(description);importしたあとは、インスタンスを生成し、segment関数に説明文を入力すると、分かち書きで分割されたarray型で返ってきます。最後に、前編でも紹介した通りrustのバックエンド側に分かち書きされたarrayを渡し、説明文と対になっているマスタの値を返してもらうことで、説明文からマスタの値に変換を行うことができました!あとがき今回rustとtauriを使うのが初めてだったのですが、今までとかなり異なる言語だったため、新鮮だったと同時にかなり苦戦しました。(笑)特にrustは型付けがかなり厳密で、今まで通ってきたどの言語とも異なる書き方だったため、最初は思ったように記述できずずっとコンパイルエラーに頭を悩ませていました。