Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UniDic 2023に対応したい #1471

Open
Hiroshiba opened this issue Sep 7, 2024 · 10 comments
Open

UniDic 2023に対応したい #1471

Hiroshiba opened this issue Sep 7, 2024 · 10 comments
Labels
機能向上 状態:実装者募集 実装者を募集している状態

Comments

@Hiroshiba
Copy link
Member

内容

openjtalkで使われている辞書の大元はおそらくUniDicで、どうやらUniDicは更新されていることに気づきました。
https://clrd.ninjal.ac.jp/unidic/back_number.html#unidic_cwj

そのままではopenjtalkで使えない気がしますが、辞書さえ変換すれば使える・・・と思われます。
このissueはVOICEVOX ENGINEで新しいUniDicが使えるようになれば達成だと思います。

Pros 良くなる点

アクセントなどがより良くなる?

実現方法

新しくopenjtlak用のcsvファイルを作る必要があるのかがわからないのですが、新しく作らないといけない前提の工程を考えてみました。

  1. UniDicからopenjtalk用のリソースファイルを作成し、どこかのリポジトリに展開する
    • VOICEVOX org内にリポジトリを作るのが良さそう?
    • この工程が必要かどうか定かではないので、リポジトリは未作成
    • 誰かが作ったものがあれば、そこからダウンロードして使う形もありかも
  2. VOICEVOX org内のpyopenjtalk辞書のダウンロードURLを書き換える
  3. VOICEVOX ENGINEから使うpyopenjtalkのバージョンを上げる
  4. 完成

VOICEVOXのバージョン

0.20.0

その他

@Hiroshiba Hiroshiba added 機能向上 状態:実装者募集 実装者を募集している状態 labels Sep 7, 2024
@Hiroshiba
Copy link
Member Author

Hiroshiba commented Sep 7, 2024

@takana-v さんとか辞書に詳しい印象があり、コメントなど頂けるととても心強いです!
もしお時間あれば取り組んでいただけませんか・・・? 👀

@takana-v
Copy link
Member

takana-v commented Sep 8, 2024

ざっくりと調べてみました。
ちょっと自信のない所もあるので、 @yamachu さん辺りにも意見を伺えたら心強いです!

実現方法

現在VOICEVOXで使っている辞書は、r9r9氏のopen_jtalkリポジトリのreleaseにあります。
https://github.com/r9y9/open_jtalk/releases
このファイルの元となっているフォルダは、ここら辺です。
https://github.com/r9y9/open_jtalk/tree/1.11/src/mecab-naist-jdic

VOICEVOX Orgでは、既に自前でopen_jtalkを管理しているので、このリポジトリにファイルを置けば良さそうです。
https://github.com/VOICEVOX/open_jtalk

なので、更新を掛ける時の流れとしては、

  • VOICEVOXのopen_jtalkリポジトリのunidic-csj.csvを更新する
  • VOICEVOXのopen_jtalkリポジトリにreleaseを作成する
  • pyopenjtalkの参照しているopen_jtalkと辞書のダウンロードURLを更新する
  • voicevox_engineの参照しているpyopenjtalkを更新する

といった感じになります。

辞書の更新内容

Winmergeを使ってUniDic 2.2.0(open_jtalkの使用バージョン)と2023_02(最新)を大まかに調べてみましたが、
追加:20000強 削除:9000くらい でした。
(差分の取り方の関係で、実際の値と誤差があるかもしれません)
また、文脈ID周りに大きく更新が入っているようでした。

image
(左が最新、右が古い方にのみ含まれる単語です。「アルハラ」が入っているのに時代を感じますね。)

問題点

単に最新の辞書を配置するだけでOKとはならなさそうでした。
辞書の更新を実現するのは、なかなか大変そうです…

大きな問題は、UniDicとnaist-jdicで文脈IDの割り振りが異なることです。
open_jtalkに含まれているUniDicのファイルを確認してみると、全てnaist-jdic用の文脈IDが振られていました。
そのため、UniDicの最新版で追加された単語を抜き出し、naist-jdic用の文脈IDを振りなおしてコストを推定する必要がありそうです。
(更新が入り精度が向上したであろう、UniDicのコストの値を捨てる必要があるのがもったいない…)

しかし、naist-jdicの配布ファイルには、コスト推定に必要なファイル(UniDicだとmodel.def)が見つかりませんでした。
そのため、naist-jdic用の自動コスト推定ができない可能性があります。

参考:mecabのコストの自動推定機能について(ページ下部に記載あり)
https://taku910.github.io/mecab/dic.html

その他、単語の選定についても少し問題があります。
どうやら、UniDic 2.2.0には含まれているがopen_jtalkの辞書ファイルには含まれていない単語が存在しているようです。
(出現が低頻度な単語が省かれているっぽい?例えば「囁きかえそふ」が含まれていませんでした。)
ここら辺の単語の選定をどうするかは要議論かもしれません。(ファイルサイズとのトレードオフ)

@Hiroshiba
Copy link
Member Author

おーーー ありがとうございます!!!

大きな問題は、UniDicとnaist-jdicで文脈IDの割り振りが異なることです。
open_jtalkに含まれているUniDicのファイルを確認してみると、全てnaist-jdic用の文脈IDが振られていました。

ここちょっとわかってないのですが、openjtalkはnaist-jdic用の文脈IDじゃないと動かないということでしょうか? 👀
ちょっとopenjtalkのコードを見た感じ、context_idが振られていれば実はnaist-jdic用の文脈IDでも動いたりしないのかな・・・とか思いました!
全然ちゃんと知らないので、トンチンカンなこと言ってたらすみません!!

@takana-v
Copy link
Member

takana-v commented Sep 8, 2024

ここちょっとわかってないのですが、openjtalkはnaist-jdic用の文脈IDじゃないと動かないということでしょうか? 👀

openjtalkには、naist-jdicの品詞分類(文脈IDの割り振り方)に依存したコードがあるようです。
少なくとも以下の部分は依存しているっぽいです。もしかしたら別の部分にもあるかもしれません。
https://github.com/VOICEVOX/open_jtalk/blob/1.11/src/njd2jpcommon/njd2jpcommon_rule_utf_8.h

ちなみにnaist-jdicは1377種類の品詞がある(1376番まで文脈IDがある)ようですが、UniDicだと19067種類のようです。

@Hiroshiba
Copy link
Member Author

Hiroshiba commented Sep 9, 2024

なるほどです!!

ちなみになのですが、単純に置き換えても何かしらのエラーが出て動かなかった感じでしょうか?👀
もし動かないと思われる感じでしたら、なんかやってみれば意外と動くのではとか期待できるなぁと!!!
(まあたぶん前者だろうなーと思ってます)

コストの振り直しはおっしゃる通り勿体無い気がします。
というのと、もしかしたらunidic用にopenjtalkを書き換えたほうが手っ取り早い…?

例えば、例に挙げてくださったコードにあるnjd2jpcommon_ctype_listの中身をunidic用に書き換えるとか…。
そもそもopenjtalk側で辞書の品詞が必要なのは一部openjtalk内で必要なものだけだと思うので、そのマッピングを簡単に付け替えられればあるいは…………?
(1:1対応してないとかであればなかなか大変そうなので、簡単なことを祈りたい…)

@takana-v
Copy link
Member

ちなみになのですが、単純に置き換えても何かしらのエラーが出て動かなかった感じでしょうか?👀

単に辞書を置き換えただけだと、下記のような警告が出て、うまく動作しませんでした。
WARNING: convert_pos() in njd2jpcommon.c: [品詞名] are not appropriate POS.

というのと、もしかしたらunidic用にopenjtalkを書き換えたほうが手っ取り早い…?

もしかしたらそうかもしれません。
UniDicだとコスト推定用のモデルが同梱されているので、naist-jdic側をUniDicの文脈IDに書き換えることもできそうです。
ただ、実際どこを変更しなければいけないのか、openjtalkのコードを全て確認しなければいけないので、時間が掛かるかもしれません。
(自分は、今後数カ月割と忙しい予感がするので、結構時間が掛かってしまうかも…)

@Hiroshiba
Copy link
Member Author

おーーーなるほどです!!! 全く存じませんでした。。。完全に同じファイルフォーマット+名前なのかと思ってました。

UniDicだとコスト推定用のモデルが同梱されているので、naist-jdic側をUniDicの文脈IDに書き換えることもできそうです。

おっとなるほどです!!
unidic使えばnaist-jdic側の辞書は1つも使わないのかと思ってたのですが、もしかしたらそんなことない・・・・・?
openjtalk用の辞書はnaist-jdicとunidicを混ぜて作ってるみたいな・・・?

どうやって作ったのか、どうやってわかるんだろ・・・・・・・・ 😇 😇 😇 😇 😇

@WariHima
Copy link

modelファイルはipadicの物が使えそうな気がしますね(ipadicを修正したものがnaistjdicなので、語句の増減だけの変更なら動きそう)
本家mecabの配布ページのバインディングの欄にあります。見つけづらいのでこの記事を参考に
https://qiita.com/wakisuke/items/d15b5defc1aad61cc910

2つの辞書を混ぜて作ってるかについては辞書のmakefileを見る限り多分そうですね
https://github.com/r9y9/open_jtalk/blob/1.11/src/mecab-naist-jdic/Makefile.am

上記のモデルファイルが使えるのなら、naist-jdicとunidicの対応表を作ってunidicを変換したほうが早いと思います。

@Hiroshiba
Copy link
Member Author

Hiroshiba commented Sep 25, 2024

コメントありがとうございます!!
ipadicにはmodelファイルがあるんですね!!

すみません、ちゃんと分かってないので一応確認させていただくと・・・
naist-jdic用のmodelファイルがないからunidicを変換できないんだけど、ipadicにはmodelファイルがあって互換性があるかも、という理解であってそうでしょうか!!

実際にやるとしたらどういう流れになるんだろう・・・。こう・・・・・・?(抜け漏れいっぱいありそう)

  • unidicとnaist-jdicの文脈ID?の対応を頑張って取る?
    • 旧unidicとopenjtalk内にあるunidic両方に共通する単語から、妥当な文脈IDの対応を得るとか?
  • unidicの単語全てにipadicのmodelでコストを割り当てる?
    • ここでどうしても精度が下がりそう
    • コストもunidicとnaist-jdicで対応関係を取るとかできないかな・・・・・
  • あとは辞書をビルドして終わり?

どれぐらい精度が下がるのか(というより以前のものからどれぐらい変わるのか)が気になるところですね・・・。
新しいのと前のとの辞書で1000文くらい適当な文章のアクセントを作ってみて比較してみる、とかかなぁ。

@WariHima
Copy link

辞書作成手順をmecabのドキュメントを参照しながらまとめると、

①unidicの品詞分類情報をnaist-jdicの項目に合わせる。

右文脈IDは, その単語を右から見たときの内部状態IDです. 通常システム 辞書と同一場所にある right-id.def から該当する ID を選択します. 空にしておくと, mecab-dict-index が自動的に ID を付与します.
→id.defから品詞情報が一致するものを選んでコストを設定するという意味だと推測される。
どちらにしろopenjtalkはnaist-jdic基準の品詞情報を使うので、品詞情報の変換は必須だと思われます

③モデルファイルでコストを推定する 
自動推定を行なう場合は, -m オプションでモデルファイルを指定し, コストのCSVフィールドを空にします. 空以外の値が設定されると, その値が優先されます.
コストは,その単語がどれだけ出現しやすいかを示しています.

単語コストについて具体的に説明すると単語とそれに似た単語、同形異音語など文字の一部を共有する場合の単語の出現率(でやすさ)です。

モデルファイルは単語コストがない場合やnaist-jdic(の元になったipa-dic)の単語コストを基準にしてコストを指定したい場合はいると思います。
unidicは単語の出現率を考慮して作られていると思うので、そのままのコストでも動きそうではありますが、naist-jdicと競合するかもしれません。どっちがいいか多分やってみないとわからないです

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
機能向上 状態:実装者募集 実装者を募集している状態
Projects
None yet
Development

No branches or pull requests

3 participants