yuta1984's picture
Update README.md
12ea146 verified
metadata
language: ja
license: cc-by-sa-4.0
pipeline_tag: image-classification
tags:
  - kuzushiji
  - japanese-historical
  - image-classification
  - convnext
  - onnx

そらまる

そらまる くずし字認識モデル (convnext_v4)

ブラウザ完結のくずし字(一文字)認識を目的とした ConvNeXt-tiny ベースの ONNX モデル。 みんなで翻刻 のマスコット「そらまる」がアシスタント役を務めるデモサイトで使用されています。

モデル概要

項目
アーキテクチャ ConvNeXt-tiny (timm/convnext_tiny.fb_in22k_ft_in1k を fine-tune)
入力 384 × 384 RGB
出力 3,673 クラスへの logits
形式 ONNX (opset 17)
ランタイム ONNX Runtime Web / Python onnxruntime

学習データ

ページ画像から各 bounding box を切り出し、一文字単位の分類タスクとして再構成しています。

区分 件数
学習サンプル 887,133
検証サンプル 68,481
出力クラス数 3,673

学習設定

  • 事前学習: ImageNet-22k → ImageNet-1k (timm 提供のチェックポイント)
  • Fine-tune: 2 段階(低解像度で大まかに学習 → 384px で仕上げ)
  • 損失: Cross-Entropy
  • サンプラー: WeightedRandomSampler で各クラスの 1 epoch あたりの期待出現回数を平準化
  • クラス除外: 出現件数が 3 件未満のクラスは学習対象から除外(cutoff=3)

性能評価

検証セット val_kr(Kaggle Kuzushiji Recognition の hold-out 68,481 件、3,673 クラス出力空間で argmax):

指標 top-1 top-5 top-20
micro 平均 96.5% 99.5% 99.6%
macro 平均(val に出現する 1,268 クラス) 96.9% 99.4% 99.5%

val_kr + val_extra を併せた 3,673 全クラスでの評価(極稀少クラスを含む厳しめの条件):

指標 top-1 top-5 top-20
micro 95.3% 99.0% 99.4%
macro(出現 3,673 クラス) 71.9% 91.3% 95.7%

訓練サンプル数別の per-class recall(macro 平均)

訓練サンプル数 クラス数 検証件数 top-1 top-5 top-20
3 〜 10 1,690 1,690 52.5% 85.2% 93.5%
10 〜 30 431 431 66.6% 90.0% 93.7%
30 〜 100 622 2,168 92.5% 97.9% 98.4%
100 〜 500 632 7,890 96.1% 98.4% 98.6%
500 〜 2,000 213 11,096 95.7% 98.9% 99.1%
2,000 以上 85 47,611 95.2% 99.3% 99.5%

頻度の高い文字では top-1 が 95% 以上に達します。出現 10 件未満の極稀少クラスでは top-1 を外しがちですが、top-20 候補に含まれる確率は 93% あり、候補列挙ベースの翻刻支援用途では有効です。

前処理

中央正方形クロップ → 384×384 リサイズ → ImageNet 標準で正規化
mean = [0.485, 0.456, 0.406]
std  = [0.229, 0.224, 0.225]

入力テンソル: float32 [1, 3, 384, 384] (NCHW)

出力

shape [1, 3673] の logits。softmax + argmax で top-1 クラスを取得し、convnext_v4.meta.jsonclasses 配列で対応する Unicode コード(例: U+3042)に変換します。

使い方

ブラウザ (ONNX Runtime Web)

import * as ort from "onnxruntime-web";

const url = "https://huggingface.co/yuta1984/soramaru_kuzushiji_ai/resolve/main/convnext_v4.onnx";
const session = await ort.InferenceSession.create(url, { executionProviders: ["wasm"] });

// preprocess: 中央正方形クロップ → 384×384 → Float32Array [1,3,384,384]
const tensor = new ort.Tensor("float32", buf, [1, 3, 384, 384]);
const out = await session.run({ [session.inputNames[0]]: tensor });
const logits = out[session.outputNames[0]].data;

完全な実装例は app.js を参照。

Python (onnxruntime)

import numpy as np, onnxruntime as ort
from PIL import Image

sess = ort.InferenceSession("convnext_v4.onnx", providers=["CPUExecutionProvider"])

img = Image.open("kuzushiji.png").convert("RGB")
w, h = img.size
s = min(w, h)
img = img.crop(((w-s)//2, (h-s)//2, (w+s)//2, (h+s)//2)).resize((384, 384), Image.BICUBIC)

x = (np.array(img, dtype=np.float32) / 255.0 - [0.485, 0.456, 0.406]) / [0.229, 0.224, 0.225]
x = x.transpose(2, 0, 1)[None].astype(np.float32)

logits = sess.run(None, {sess.get_inputs()[0].name: x})[0][0]
top5 = logits.argsort()[::-1][:5]
# → meta.json["classes"][k] で Unicode コードに変換

制限

  • 1 文字単位の分類のみ。ページ全体の検出・OCR ではありません(事前に文字単位で切り出す必要があります)
  • 学習データに含まれない字体・崩し方には弱く、信頼度が下がります
  • top-1 確率が低い場合は誤認識の可能性が高いため、上位複数候補の参照を推奨

ライセンス

学習元データの再配布条件に倣い、本モデルは CC BY-SA 4.0 で公開しています。派生物を公開する際は本モデルおよび以下のデータセットを引用してください:

  • Kaggle Kuzushiji Recognition (2019)
  • 東京大学史料編纂所くずし字データセット

クレジット