こんにちは。イノベーションセンターの加藤です。 手書きから活字へスタイル変換するモデルをFlow Matchingで学習しようとして色々試したものの上手くいかなかったため、試行錯誤の記録をブログの形で残したいと思います。
背景
このモデルを学習しようとしたきっかけは手書き文字OCRの性能を向上させようという取り組みでした。OCRの難しい点として、現実のデータにはさまざまな特殊文字が現れるという問題があります。これら全ての手書き文字を学習データとして用意するのは難しく、色々な手法が提案されています。
その手法のひとつに、「活字から手書き文字を生成するモデルを作る」というものがあります。活字はフォントファイルから手に入るため、すでに手元にある手書きデータと共に手書き文字生成モデルを学習し、未知の活字からさまざまな形の手書き文字を学習データ用に生成することで、OCRのデータセットを増強できるというモチベーションです。 この方法を聞いたときに、同じことを「手書きから活字を生成するモデル」でもできるのではないか?と思いました。しかもこちらの方が色々な手書き文字を作って学習を回すという手間を省けるという利点があります。
そこで、Flow Matchingと呼ばれる生成モデル学習手法を使って手書き文字から活字に変換するモデルの学習に挑戦しました。手書き文字データセットはETL9B1、活字データセットはGoogle Noto Font2を利用し、JIS第1水準漢字を対象にしました。
上手くいかなかった手法たち
手法1:手書き文字分布から活字分布への変換
最初に試したことは、手書き文字から活字へ少しずつ変化させるUNetモデルの学習です。 TorchCFM3と呼ばれるライブラリを用いて、手書き文字の分布から活字文字の分布に少しずつ変化させるモデルを学習します。
今回のケースでは以下のような変換過程を学習しています。
データセットの分割はStratified K-Foldを用いて、学習で利用した文字種は評価時に現れないよう工夫しました。
結果は次のような画像になりました。稀にさんずいやしんにょうなどを捉えることはできていますが、基本的によくわからない文字になってしまっています。また、「沖」という文字が「汁」になっているなど、形が似ている別の学習データになってしまっている例も見受けられました。
手法2:ControlNet学習
先ほどの実験では入力に似た学習セット内の文字が出力されるというケースがありました。 そこで次はあらかじめ全ての活字に対して学習を回せるという仮定をおき、まず活字を生成するモデルを作ってから手書き文字で条件付けるという方法を試しました。 フォントデータは手書きよりも簡単に多くの文字種を得られるため、この仮定に無理はないはずです。 この方法でよく使われるのはControlNet4です。これはあらかじめ画像生成モデルとして学習されたUNetに、画像で表現できるcontrol情報を注入するためのUNetを新しく学習する手法です。 これによって例えば人体の姿勢情報からそれに沿った人物の画像を出力するなどといったことが可能になります。
データセットの分割は先ほどとは異なり、まず全ての活字画像を使ってランダムノイズから活字を生成するモデルを作り、そしてStratified K-Foldで分割された手書き文字画像を使って条件付けモデルを学習させました。 そのため変換過程は以下のようになり、途中からヒントとして手書き文字の特徴量を加える形になります。
まず活字生成モデルは次のようになりました。学習時には上下左右反転のdata augmentationを行っているので向きが変わっていますが、元の活字のスタイルを正しく生成できているようです。
しかし条件付けモデルの結果は以下のように、残念ながら入力した条件に従わせることができず、相変わらずランダムな活字風の画像が生成されてしまいました。
このように条件に従ってくれない現象はControlNetの元論文でも指摘されており、しばらく学習するとちゃんと従うようになるとされているのですが、残念ながらこの実験ではそのような収束が見られませんでした。おそらく一般的な画像生成とは異なり、文字の生成ではあまりに簡単すぎるため手書き文字画像によるヒントがうまく使われなかったのではないかと思います。
手法3:学習済みの活字生成モデルを手法1で転移学習する
手法1ではあらかじめ全ての活字画像を学習時に活用できず、手法2ではうまく手書き文字画像をヒントとして活用できませんでした。そこで、手法2で作成した活字画像生成モデルの重みを手法1の初期値に利用することで、2つの手法の欠点を補ってみます。
結果は次のような画像になりました。一部うまくいった文字もあり(く、詠、円など)、心なしか似たような文字が出せるようにはなったのですが、結局ほとんどは関係のない活字に変換してしまいました。
まとめ
手書き文字を活字に変換するためFlow Matching周りの手法を色々試してみましたが、異なるスタイルの文字を一対一対応させるのはかなり難しそうでした。 GANなどの方がむしろ安定して学習できる可能性もあるため、こちらも試してみたいです。
- ETL文字データベース http://etlcdb.db.aist.go.jp↩
- Noto Sans Japanese https://fonts.google.com/noto/specimen/Noto+Sans+JP↩
- conditional-flow-matching https://github.com/atong01/conditional-flow-matching↩
- https://arxiv.org/abs/2302.05543↩