こんにちは!!!クライアントエンジニアの小林です。
今回はノベルゲームでの使用を想定した、いわゆる領域特化な日本語OCRを作ってみました。
- 作業環境
- 概要
- リポジトリ
- 文字領域の検出(CRAFT)
- 文字ピクセルの抽出(PostCRAFT)
- 文字分類(CoAtNet)
- ReinVisionOCR
- 動作デモの配布(期間限定)
- 今後の課題
- おわり!!!
- 続き
- 参考
作業環境
・windows 10
・visual studio code
・python 3.9.12
・Lightning AI
概要
今回のOCR開発における目的についてです。
目的はPyTorch Lightningに慣れること、CNNの理解を深めることです。
その手段としてOCR開発を選択しました。
理由としては以前からTesseractやCloudVisionを使用しており、その際に意外と不便なところや改良して欲しい箇所がありありで「いつか自分で作ったろー」と思っていたことからです。
続いてOCRの要件です。
・ノベルゲームに特化した運用を前提とする
・精度はTesseract 5.1がボーダーライン
理想はCloudVision以上
・対応文字は日本語全般
・ふりがなは対応しない
・モデルに汎用性、学習やランタイムコストは考慮しない
ノベルゲームを選んだ理由ですが、データ数が豊富とかそんな現実的な理由では無く、シンプルに好きだからです。
リポジトリ
今まではブログ内にコード直書きをしていましたが、今回はコード量も多いのでリポジトリのURLを添付する形を取っています。
一部抜粋することはあるかもしれませんが、全文を載せることは無いので詳細を確認したい方はリポジトリを参照してください。
階層についてですが、各モデルのデータ生成や学習環境ごとにフォルダ分け、それらを全てReinVisionOCRに突っ込んでいます。
モデルごとにブランチも切っているので、一部だけ見たい方はそのブランチだけ取得してください。
筆者はこんな感じで仮想環境をReinVisionOCR下に作成して、各ブランチは全てその仮想環境を使うようにしています。
2023/02/18時点で公開予定なものは、craft, post-craft, coatnet, rein-vision-ocr, resourcesの5つです。
その他はdistil-bertは精度が不安定なので非公開、resourcesは著作権の塊なので一部のみ公開、rein-vision-apiは別ネタで使うのでその時に公開予定となっています。
あとREADMEは気が向いたら整備します。
実質的にこのブログがREADMEということで、ご勘弁を。
ドキュメント整備は面倒なのです。
環境構築
前提として機械学習まわりのセットアップが諸々終わっているとします。
cudaまわりの環境構築について触れるとそれだけでネタになりそうなので割愛します。
仮想環境を作成してrequirements.txtから必要ライブラリを落としてきます。
pytorchはcudaを考慮して入れていないため、各々で任意のバージョンを落としてください。
あとpytorch lightningもpytorch入れてからの方が安心なはずなので入れていません。
筆者はcudaのバージョンアップをサボりにサボって未だに11.3を使用しています。
最適化の面を考えるとよくないのでしょうが、まぁこれでも動くんでねぇ、バージョンアップ、、、面倒なんですよねぇ。。。
文字領域の検出(CRAFT)
文字領域の検出にはCharacter Region Awareness for Text DetectionことCRAFTを使用しています。
SceneTextDetectionタスクで高スコアを叩き出したモデルです。
2022/12時点ではTextFuseNetがランキングを埋め尽くしてはいますが。

CRAFTの採用理由です。
・テキスト領域だけではなく、文字単位での検出に優れている
・ベースがTextFuseNetはdetectron2に対して、CRAFTはVGG16で分かりやすい
主に2番目の理由が強いです。
detectron2がつよつよなのは分かるのですが、初めて扱うにしては大規模過ぎました。
その点VGG16は16層の(全結合を含む)CNNとシンプルで分かりやすかったです。
データセット
単語や文章をプロットした画像と、ノベルゲーム風なプロットをした画像の計3種類を使用しています。
記事書いてて思いましたが、単語や文章である必要あんまり無いですよね。
リアルタイムな事柄ですが、WordNetの英単語に大文字が含まれていないor少ないので「女生徒C」の「C」が小文字想定な文字領域として検出され、後述するCoAtNetは賢いのでその意図を組んで小文字の「c」と検出することがありました。
WordNetの英単語を2分割して片方を大文字に変換することで解消はしましたが、望まないデータの偏りが存在する以上単語帳を使う必要性あるのかなぁと思ったりしました。要検証ですね。
word image generator
ReinVisionOCR/craft/dataset_generator/word.py at main · spark-kobayashi-arata/ReinVisionOCR · GitHub



単語はWordNetのデータベースから取得しています。
WordNet単体では囲い文字や句読点、記号などのデータが不足ないし存在しないため、任意の文字列を先頭と末尾に挿入させています。
text image generator
ReinVisionOCR/craft/dataset_generator/text.py at main · spark-kobayashi-arata/ReinVisionOCR · GitHub
文章データは*.transdataという独自のテキストフォーマットから取得しています。
これに関しては公開予定はないので、*.txtに書き換えて任意のテキストファイルから取得するか、WordConfigの一部実装を持ってきて"".join([self.random_choice_word() for n in range(3)])
こんな感じで単語結合などしてください。
Textなんて命名していますが、データ的には単語よりも長い文字列に過ぎないので。
気が向いたら改修しておきます。
game image generator
ReinVisionOCR/craft/dataset_generator/game.py at main · spark-kobayashi-arata/ReinVisionOCR · GitHub
ランダムサイズな背景に、透明度グラデーションなカラーキャンバスを貼り付け、その上に文章をプロット、最後に固定サイズの灰色の単色キャンバスに中央寄せで貼り付けています。
OCRフローでの推論時には入力サイズを固定化するために、コレと同様の処理をするため割と重要なデータです。
重要ではありますが、ノベルゲーム風にする必要は全く持って無いです。
完全に趣味ですね。
この時は気分が上がって作っちゃった感じです。
fontview
データセットに使用されるフォントの確認用です。
今回は汎用性重視では無いのでフォントサイズごと合わせにいきます。
設定を諸々した上で実行すると、ウィンドウに結果が描画されます。
これをスクリーンショットして実際のゲーム画面のフォントと合っているかを確認します。
確認する際はお手元のペイントソフトのレイヤーに貼り付けてブレンドモードを「差の絶対値」にするのがおすすめです。
確認すべき点はフォントサイズと装飾が似ているかの2点です。
文字間隔や行間は考慮する必要ありません。
というよりPillowのフォント描画は標準では文字間隔の調整が出来ません。
ライブラリ追加するか描画後にピクセル切り抜き+移動するかなどの面倒なことをしないとなのです。
生成手順
1. fontviewで適切なパラメータを探す
2. 1の結果からconfig.yamlを書き換える
3. generate.pyをポチッ
正常に生成が完了すると、画像ファイルが*.pngとして、文字描画位置とサイズが*.pickleとして出力されます。
生成数の比率についての注意としてGame画像の比率はリポジトリで公開している2:1より上げないようにしてください。
メインはWordとText、実際の推論環境の再現としてGameが存在しているイメージなためGame画像が多すぎると、なんの学習を進めているのか分からなくなりCRAFTさんが迷子になる傾向が見られました。
データセットの推奨削除方法
ReinVisionOCR/craft/dataset_generator/fast_remove.py at main · spark-kobayashi-arata/ReinVisionOCR · GitHub
ReinVisionOCR/post-craft/dataset_generator/fast_remove.py at main · spark-kobayashi-arata/ReinVisionOCR · GitHub
ReinVisionOCR/coatnet/dataset_generator/fast_remove.py at main · spark-kobayashi-arata/ReinVisionOCR · GitHub
CRAFTは例外的にファイルサイズが大きくファイル数が少ないのですが、以降のデータセットではファイルサイズが小さくファイル数が多いという構成になっています。
ファイル数が多いとwindowsさんは極端に削除時間を要するようになります。
上記のコードから削除ディレクトリを指定することで、この時間をかなり短縮できます。
スレッド処理してるだけですが格段に処理速度が上がります。
注意点としてダイアログ表示も無しに、問答無用で消します。
Gaussian Generator
ReinVisionOCR/craft/models/gaussian.py at main · spark-kobayashi-arata/ReinVisionOCR · GitHub
ヒートマップ画像の生成クラスです。
先ほど*.pickleに文字描画位置とサイズを格納と触れた通り、これらの情報からヒートマップ画像を作成します。
CRAFTでは文字単位のヒートマップ画像をRegion、それを隣接文字まで拡張して横長なヒートマップ画像をAffinityと命名しています。
今回はプロットされる文字列群が斜めになることがない単調なものなので、Affinityは使用せずにRegionのみとして、学習と推論速度を重視しています。
余談ですがvscodeでregionって変数名をコメントアウトするとC#のアレと誤認しちゃって少々面倒でした。
region to bboxes
def region_to_bboxes( region:np.ndarray, binary_threshold:float, char_size:int, char_threshold:float, ) -> list[tuple[int, int, int, int]]:
2値化したヒートマップをラベリングすることで文字領域であるbboxを計算しています。
bbox計算に重要なパラメータが3つあります。
binary_threshold | ヒートマップを2値化する際の閾値 |
char_size | 文字領域と判定する最小面積 |
char_threshold | 文字領域に含まれているべき最小階調の閾値 |
2つに別けられている理由ですが、binary_threaholdは全体の閾値に対して、char_thresholdは文字領域ごとです。
binary_thresholdは大きすぎるとbboxが小さくなり過ぎるため、ある程度小さくする必要があります。
ですがそうすると小さなノイズも文字領域として誤検出されてしまいます。
それを防ぐためにchar_thresholdで文字領域ごとに再度、閾値判定をすることでノイズなどから生成された文字領域を誤検出として切り捨てることができます。
bboxview
ReinVisionOCR/craft/bboxview.py at main · spark-kobayashi-arata/ReinVisionOCR · GitHub
ヒートマップから文字領域を推定する際に重要なパラメータのdratioの確認用です。
文字領域のサイズ自体はbinary_thresholdでも調整はできるのですが、どうやらこの値は0.01で固定運用した方がbboxの比率が安定化して精度が高くなる傾向が見られました。
2値化の閾値なのであまり細かいと形が歪になり結果的にズレが生じているのだと思います。
そのため可能な限りdratioを合わせにいきます。
文字サイズぴったり+ほんの少しの余白が理想的です。
調整幅は0.2単位が良きです。
0.1単位だと細か過ぎて2値化で差分が出ません。
学習
ReinVisionOCR/craft/train.py at main · spark-kobayashi-arata/ReinVisionOCR · GitHub
バッチサイズはデータセット数と同等かそれ未満がちょうど良いです。
複数のデータセットの利用は汎用性を高めますが、最初は避けた方がいいです。
まずはフローに慣れないと効率が悪いです。


汎用性を求めたい場合は下記のフローで進めると良いでしょう。
1. 任意のフォント修飾で学習
2. 後述のCoAtNetまで完了して精度が良い
3. 影付きと縁取り、縁取り+影付きの3種類をそれぞれ生成
4. 3種類のデータセットをバッチサイズ3で学習
5. 作成されたモデルで2と同等の精度になれば汎用性の高いCRAFTモデルの完成
6. 5が失敗する場合はdratioの見直しを検討する必要があります
複数の修飾設定が存在することでdratioの最適解が変わる可能性があるためです
汎用性を求めるつもりはなかったのですが、モデル性能が高すぎて汎用性持たせられちゃうんですよねぇ。
すげー。
文字ピクセルの抽出(PostCRAFT)
CRAFTのラベルであるRegionをグレースケールな文字画像に置き換えた応用利用です。
便宜上CRAFTの後に実行するのでPostCRAFTとしています。
データセット
背景画像に文字をプロットしたものとグレースケールな文字のみをプロットした2種類の画像を使用しています。
character image generator
2種類の画像を次元方向に結合、4次元データを作成し出力しています。
結合し1つのファイルにすることでDataLoaderからのファイル操作を減らし高速化に貢献しています。
charviewの使い方
調整方法については言語化し難いため実例紹介。
下の画像はPostCRAFTの推論結果です。
「天」の右上ピクセルと「困」の右端ピクセルが、正常に抽出できていません。
学習に用いた設定ファイルを元にcharviewで確認してみます。
ぱっと見ですが余白が多く縁ギリギリまで文字が描画されていることが少ないように見えます。
このことを踏まえて縁まで描画されるようなパラメータに変更しました。
変更後の設定から作成したデータセットから作成したモデルでは縁ギリギリな文字も正常にピクセル抽出ができるようになっていました。
このようにデータセット作成前のパラメータ探しや、学習に失敗した際の原因調査のひとつとして使用します。
学習
ReinVisionOCR/post-craft/train.py at main · spark-kobayashi-arata/ReinVisionOCR · GitHub
CRAFTと異なりバッチサイズは高めでも大丈夫ですが、いうて数100万のデータがある訳でも無いので高過ぎるとすぐに精度低下します。
「エポック数増やせばいいじゃない」と思うかもしれませんが、それするくらいならバッチサイズ落とした方が収束が安定します。


推論
ReinVisionOCR/post-craft/test.py at main · spark-kobayashi-arata/ReinVisionOCR · GitHub
configを元にデータセット生成時と同様な処理で画像を生成、それを推論し結果をタイル画像で出力しています。
すごいですね。しっかりピクセル抽出できています。
文字分類(CoAtNet)
文字分類にはCoAtNetを使用しています。
こちらはCRAFTの採用理由とは異なり、最初に目に付いたからという直感に従いました。
とはいえ精度が高いという前提ありきの直感ですが。

データセット
2値化した文字画像を使用しています。
binary character image generator
複数のフォントサイズとオフセットを用いることで2値化の結果にばらつきを持たせています。
threshview
2値化結果にバラつきが保てているかの確認用です。
実行するとデータセットの出力先にdebugという名のフォルダが作られ画像が出力されます。
出力された画像のファイル名の先頭にthreshとsimilarの2つがあります。
threshはフォントサイズが適切であるかの確認用で、similarは後述する類似文字の確認用です。
類似文字の概念
ここにおける類似文字の定義です。
・ピクセル配置的にほぼ同一である
・スケール調整次第でほぼ同一である
・ひらがなとひらがな小文字は類似文字ではない
モトヤLマルベリの類似文字の一例です。
ピクセル配置的にほぼ同一 | スケール調整次第でほぼ同一 |
---|---|
![]() |
![]() |
人間でも文字単体で見た際には正確に識別できないはずです。
特にゴシック系では「とめ・はね・はらい」が存在しないor目立たないため余計に分かりません。
これらの類似文字をデータセットに含めた場合、当然ながら損失が起きます。
しかしこの損失は見逃すべきものです。
人間だって分からんのだから、前後の文字列を考慮していない非時系列であるCoAtNetさんが分かる訳がないのです。
そのためCoAtNetのデータセットではこれらの類似文字ごとにグループ化、その先頭文字のみをデータセットに含めることとしています。
画像だと緑枠のみを生成し、赤枠はデータセットに含んでいません。
これをすることで正しい損失計算をすることができます。
類似文字に関しては後述するBERTのMaskedMLで推定しているのですが、これがいまいち精度が安定しないという残念な結果になっていますが、それはまた別の機会に改善するとします。
生成手順
GitHub: Let’s build from here · GitHub
1. threshviewで適切なフォントサイズを探す
2. threshviewで類似文字を探す
3. 1と2の結果からconfig.yamlを書き換える
4. generate.pyをポチッ
類似文字はフォントごとに意外と異なるので、パラメータ使いまわし厳禁です。
"_debug"フォルダには出力結果がタイル画像で保存されます。
学習
ReinVisionOCR/coatnet/train.py at main · spark-kobayashi-arata/ReinVisionOCR · GitHub
モデルバージョンはCoAtNet-1を使用しています。
バッチサイズはデータセット1~2つで64が安定していました。




ReinVisionOCR
OCR用に各モデルをフローに落とし込んで、プリプロ・ポストプロセスを追加していきます。
処理フロー
- 文字領域検出
- 行ソート
- 文字ピクセル抽出
- 文字分類
- 辞書の適用
- DistilBERTのMaskedMLによる類似文字推定
行ソートは読んで字の如くです。
単位切り上げや切り捨てなどをしても稀に行位置がズレることがあるので、そのあたりを上手いことしてくれるようにソートしています。
5と6については今回は非公開です。
理由は本環境に実装できるほどの精度が担保できていないためです。
学習方法が運よく行くと推定精度9割越えもあったのですが、再現性が驚くほど低く、公開できるものではなかったです。
BERTはCNNと違って時系列ということもあり別途勉強が必要だなぁといった感じです。
実際に使ってみた
実際のゲーム画像を入力、テキストデータをラベルとしてスコアを算出します。
計算方法はゲシュタルトパターンマッチングに近いです。
ゲームの利用規約は守ろう
ADV好きな人なら把握していると思いますが、どのゲームも基本的には利用規約で個人利用の範疇を超える場合のスクショ等は禁止されています。
データセットに含める行為は現行法では問題ないかもしれませんが、さーすがにモラルなさすぎると思うので、避けてほしいなというのがお気持ちです。
ちなみに【フリー素材】 みんちりえ 【背景イラスト配布サイト】というめっちゃADVっぽい背景を公開して下さっているサイトのおかげで、ゲーム内スクショを一切使わずにデータセットの作成ができました。感謝。
ゲシュタルトパターンマッチング寄りな理由
注意点として寄りです。
本家ゲシュタルトパターンマッチングとは微妙にアルゴリズムが異なります。
主な理由は「…」「ー」などの単調で且連続性のある記号を稀にCRAFTが検出してくれないor2値化の時に不適切な結合をしてしまうことがあります。
これにより画像に含まれる文字数と検出された文字数に乖離が生じ、インデックス依存な比較では壊滅的なスコア算出をすることがあるためです。
ゲシュタルトパターンマッチングは皆さんご存知の通り、インデックスのズレはある程度許容してくれます。
その他にも総数除算より失敗当たりの減点数が大きいこともありますが、正直誤差レベルではあるので割愛します。
我流なスコア算出は如何なものかと思うかもしれませんがあくまで領域特化、というより勉強兼趣味な開発なので許して。
精度テスト
分類精度とOCR精度の2つの指標から計算します。
異なる点は類似文字に関するスコア計算です。
1つ目の分類精度は、類似文字が類似文字として検出された時点で正解となります。
2つ目のOCR精度は、類似文字が検出された際はその推定結果までを成否判定としています。
類似文字推定のフローが未完成なためOCR精度は低いです。
とはいえ現時点での精度も知りたかったので載せています。
リポジトリにあるコードでは分類精度のみ測れます。
作品名 | モデル | 分類精度 | OCR精度 | フォント設定 |
---|---|---|---|---|
リドジョ | mtlmr3m | 39,143/39,143 (100.0000%) |
39,124/39,143 (99.9504%) |
モトヤLマルベリに変更 それ以外はデフォルト |
D.C.4 | msgothic | 24,380/24,381 (99.9967%) |
24,376/24,381 (99.9816%) |
デフォルト |
カルマルカ | mtlmr3m | 26,806/26,807 (99.9968%) |
26,800/26,807 (99.9722%) |
デフォルト |
カルマルカ | mtlmr3m (bboxes計算改修版) |
26,807/26,807 (100.0000%) |
26,801/26,807 (99.9754%) |
デフォルト |
作品によるスコアの偏りも無く、なによりCRAFTの文字領域検出の安定感が凄まじいです。
CoAtNetもPostCRAFTの補助があるとはいえ「鷲逗」や「鷺澤」などの有効ピクセルが多い漢字や「双璧」や「双壁」などの類似性がある漢字もしっかりと分類できていました。
大変、かなり、マジで大満足な結果です。
。。。久々にゲームしたわ。
カルマルカの失敗数1はCRAFTで少し触れた「女生徒C」の件ですね。
これ実はCRAFTのデータセット改修しなくてもプリプロセスの改修で抑制できました。
各モデルの精度が高すぎてプリプロ、ポストプロセスがかなり雑になっていました。反省。
学習済みモデル
Release v1.0.0-alpha · spark-kobayashi-arata/ReinVisionOCR · GitHub
精度テストで使用した学習済みモデルを公開しています。
学習済みモデルに関してはフォントライセンスを継承しているため使用に注意してください。
学習済みモデルは現状すべてCC BY-NC 4.0を適用しています。
pytorchが公開しているvgg16の学習済みモデルにImageNetが使われている関係です。
動作デモの配布(期間限定)
Release v1.0.0-alpha · spark-kobayashi-arata/ReinVisionOCR · GitHub
こちらの動作デモは機械学習の環境構築をすることなくReinVisionOCRを試せます。
対応フォントは「モトヤLマルベリ」のみです。
regin_to_bboxes関数のパラメータもデータ量を削減するため固定化しています。
そのためノイズが文字領域として検出されたり、文字が文字領域として検出されないことがあるかもしれません。
フォント装飾には依存しませんが、ウィンドウサイズでのプレイを想定しています。
フルスクリーンはまともに動かないので間違えても撮らないでください。
リクエスト数が無駄になるので。
注意点
リクエスト数と触れた通りアクセス総数の上限が存在します。
こちらで用意したAPIリクエスト数を超過した時点で全てのリクエストが弾かれ、動作不良を起こします。
サーバー維持にはお金が掛かるのです。すまん。
ローカルで使用しているエディタに機能制限を掛けて公開用にしています。
その過程で消しちゃいけない実装部分を消している可能性もあります。
それが原因で動作不良起こしたらこれもすまんです。
精度テストでは*.pngなエンコードに対して、動作デモでは*.jpgなエンコードをしています。
それが原因で分類精度の劣化を確認しています。
これは動作デモを動かすために使用しているSageMaker Serverless Inferenceが、データの送受信量も料金に含まれるため少しでも減らして費用削減したいという筆者のお財布事情その2です。すまん。
操作方法
0. rein_vision_ocr_demo.zipを解凍します。
ライセンスフォルダと*.exeファイルが1つ、サンプル画像が3枚内包されています。
アイコン可愛い。
1. rein_vision_ocr_demo.exeを開きます。
場合によってはセキュリティソフトが激怒します。
この時点で開かない場合は非対応です。
諦めてください。
2. タイトル横のコンボボックスから撮影対象のウィンドウ名を選択します。
例としてsample.pngをwindows標準ソフトのフォトで開いているものを選択します。
フォト使用時の注意点として拡大率を100%にしてください。
データセットのフォントサイズから大きくズレると正常に動作しなくなります。
3. ウィンドウ名の選択が正常に完了すると「撮影範囲の編集」が有効になるので選択します。
4. 「撮影範囲の編集」を選択すると別ウィンドウが開きます。
そのウィンドウ内でペイントソフトで図形描画をする感覚で撮影範囲を囲みます。
微調整は上下左右のみ可能です。
撮影範囲が定まったらウィンドウを×ボタンで閉じます。
5. 撮影範囲の編集が正常に完了すると「撮影」が有効になるので選択します。
6. 40秒ほど待ちます。
サーバーが眠っている場合は「撮影」しても1、2回ほどタイムアウトします。
7. サーバーが起きている場合は数秒ほどで推論が完了し、結果が返ってきます。
推論は10秒に1回可能です。
可能なだけで多用する場合は環境構築して学習済みモデルで試してください。
今後の課題
・類似文字推定の精度を上げる
・CRAFTの軽量化
→CNN盛り沢山なのでGhostNetとの相性良さそう。V2も出たことだし。
・CRAFTのデータセット改修
→単語や文章を使っている都合、存在しない文字群がある。もはや文字列群で良いのでは。
・全体的なデータセット改修
→2010年代までの小規模ブランド特有のアウトラインガサガサフォントを擬似的に再現して、それも読めるようにしたい。
おわり!!!
お疲れさまでした!!!
当初の目的の達成や要件を満たせるものも作れて満足です。
精度については思った以上で使うたびに我ながらぐへへへへです。
最後になりますが、各モデル開発者様、リポジトリやリソースを公開頂いている方々にはすごく感謝です。
続き
参考
- [1904.01941] Character Region Awareness for Text Detection
- 【論文読解】Character Region Awareness for Text Detection #DeepLearning - Qiita
- GitHub - clovaai/CRAFT-pytorch: Official implementation of Character Region Awareness for Text Detection (CRAFT)
- GitHub - fcakyon/craft-text-detector: Packaged, Pytorch-based, easy to use, cross-platform version of the CRAFT text detector
- [1802.08948] Multi-Oriented Scene Text Detection via Corner Localization and Region Segmentation
- 【論文読み】 Multi-Oriented Scene Text Detection via Corner Localization and Region Segmentation #DeepLearning - Qiita
- 物体検出についての歴史まとめ(1) #深層学習 - Qiita
- 物体検出についての歴史まとめ(2) #深層学習 - Qiita
- [2106.04803] CoAtNet: Marrying Convolution and Attention for All Data Sizes
- 畳み込み+Attention=最強?最高性能を叩き出した画像認識モデル「CoAtNet」を解説! #機械学習 - Qiita
- GitHub - chinhsuanwu/coatnet-pytorch: A PyTorch implementation of "CoAtNet: Marrying Convolution and Attention for All Data Sizes".
- 【フリー素材】 みんちりえ 【背景イラスト配布サイト】