Apitore blog

Apitoreを運営していた元起業家のブログ

【API】続・SentencePieceを形態素解析のように使えるAPIを公開した

はじめに

先日リリースしたSentencePieceを形態素解析のように使えるWebAPIですが、SentencePiece作者の工藤さんから色々とアドバイスを頂きました。前回の投稿は一部適切でない実装があったので、それを修正しました。こちらから無料で使えます。

2017/5/12 追記

しれっとTweet版のSentencePieceを追加しました。約200万ツイートで学習しています。

API

サンプルコード

関連記事

やったこと

前回との違いだけ記述します。 まず、SentencePieceでのモデル計算はいくつかモードがあります。今回はUnigramとBPEを試しました。

Unigramモード

工藤さんから以下のコメントをもらいました。

unigram だと、語彙テーブルの対数尤度に -1 かけて整数コストにし、未知語処理を切れば原理的には一緒になります。

というわけで、そのとおりにしました。 私がやったことを正確に伝えると、語彙テーブルの対数尤度に-100をかけてroundして整数コストにし、kuromoji/mecabの辞書に追加しました。未知語のところはkuromojiをextendモードで実行するとしました。未知語の単語コストはSentencePieceの語彙テーブルよりも十分高かったので、基本的にSentencePieceの語彙テーブルで形態素解析されます(たぶん)。extendモードで実行したのは、未知語が出てきたときに文字区切りにするためです。

BPEモード

こちらも工藤さんからコメントをもらいました。

BPE での分割は、ナイーブな実装でよければそれほど難しくありません。2つの文字を連結してみて辞書にあれば、その2文字を新しいシンボルに置換していきます。置換する箇所が複数ある場合は、優先度(最初に登録されている方が優先)順に置換します。 https://ja.wikipedia.org/wiki/%E3%83%90%E3%82%A4%E3%83%88%E5%AF%BE%E7%AC%A6%E5%8F%B7%E5%8C%96 2文字の連続を連結して、辞書引きをします。みつかれば、その2文字をつなげてつなげたものを1文字とみなします。 それを辞書引きができなくなるまで繰り返します。ナイーブな実装は、毎回2文字連続をスキャンするので、O(n^2) ですが、ヒープを使えば O(n log n)になります。

ヒープを使ううまいやり方が私にはわからなかったので、愚直にやりました。「語彙テーブルをルールとみなし、上から順番にルールを適用する」というものです。例えば、ルールが以下のように定義されているとします。

あい
うえ
あいう

入力が「あいうえお」だとしたら、この場合は出力は「あい うえ お」になります。過剰な説明かもしれませんが、下に示す別のルールの場合は、

あい
あいう
うえ

出力は「あいう え お」になります。

で結果はどう変わったのか?

ほぼ同じでした。 前回の例はUnigramだろうとBPEだろうとどちらも結果は変わりませんでした。UnigramとBPEの語彙テーブルを見比べてみましたが、かなーり近いです。Unigramの方はつっこんだデータも多いことがあり、一応BPEとの違いはあります。 ただ、正確に実装できた(と思うので)、安心して使ってもらえると思います。

おわりに

余談ですけど、UnigramモードはBPEモードに比べると省メモリなので、Wikipedia全文を学習につっこめました。その結果、12日間も計算しつづけました。。。電気代が・・・。というわけで、12日分の演算結果をApitoreでは無料で使えるので是非使ってみてください。