こんにちは、Initial SのDavidです。

MeCloudなどの製品でAI機能を開発する中で、私たちは「ユーザーの写真を、名刺・レシート・その他にどう正確に分類するか」という課題にたびたび向き合います。

名刺、ショップカード、グリーティングカード。人には区別しやすくても、写真になると、ロゴや文字、レイアウトがよく似ています。「名刺に似た画像を探す」ことと、「これは名刺だと分類する」ことには違いがあります。

私たちはローカルでの写真整理に向けて、小さな実験を行いました。EmbeddingGemma 2を固定し、名刺・レシート・その他を判定する線形分類ヘッドだけをCPUで学習する方法です。固定した437枚で比較すると、未学習のテキストアンカー方式に対して、全体の正解率は 87.2%から94.5% に上がり、「その他」を名刺やレシートと誤判定した件数は 39件から8件 に減りました。

ただし、名刺の適合率が上がる一方で、再現率は下がりました。今回はそのトレードオフも含め、構成、データ、評価結果を紹介します。

埋め込みモデルを固定し 小さな分類ヘッドを加える

EmbeddingGemma 2は、Google DeepMindのマルチモーダル埋め込みモデルです。画像とテキストを共通のベクトル空間に写像できます。今回使うのは、正規化された768次元の画像ベクトルです。画像の説明文ではなく、分類に利用する特徴表現と考えると分かりやすいでしょう。

EmbeddingGemma 2と線形分類ヘッドの学習および推論構成

図1:埋め込みモデルは固定。画像ベクトルの生成にはMacのMetalバックエンドを使い、緑色の分類ヘッドだけをCPUで学習します。新しい写真にも同じ画像エンコーダーと学習済みヘッドを使います。

モデルにはggml-orgのGGUF版を使用し、Q8_0量子化、画像トークン数70、出力768次元に固定しました。画像はEXIFに従って向きを補正し、RGB化したうえで、長辺を最大512ピクセルに縮小します。小さな画像は拡大しません。生成したベクトルはローカルに保存して再利用します。

分類ヘッドは多項ロジスティック回帰です。768次元のベクトルを線形変換し、softmaxで3つのクラスのスコアを計算します。

処理の流れ
画像 → 固定の前処理 → 凍結したEmbeddingGemma 2 → 768次元ベクトル x
最大スコアのクラスを出力:名刺 / レシート / その他
数式
p=softmax⁡(Wx+b)\mathbf{p} = \operatorname{softmax}(\mathbf{W}\mathbf{x} + \mathbf{b})

必要な重みは3×768と3個のバイアス、合計 2,307パラメーター です。埋め込みモデルのファインチューニングは行っていません。分類経路にOCRを追加したり、生成モデルに画像ごとの回答を求めたりもしていません。

タイトルの「CPUだけで学習」は、分類ヘッドの学習を指します。画像の埋め込み生成はMetalで高速化しているため、画像処理全体をCPUのみで計測した結果ではありません。

比較対象は 学習なしのテキストアンカー方式

比較対象では、「個人の名刺写真」「買い物のレシート写真」など、画像の種類を表すテキストを用意します。画像ベクトルとテキストベクトルの類似度を比較し、種類を判定します。今回は既存の120個のアンカーを使用し、各グループの最大類似度から選んだ結果を3クラスにまとめました。

この方法はラベル付き訓練データがなくても始められます。ただし、意味が近いことと、業務上同じクラスに属することは一致しません。たとえばショップカードは名刺に似ていますが、今回の定義では「その他」です。一方、店主の名前と個人の連絡先が記載された名刺は、店のロゴがあっても名刺として扱います。

分類ヘッドには、この業務上の境界を学習させます。

使ったデータと その偏り

学習用画像は 2,565枚、別途確保した校正用データは 656枚 です。今回の実験では既存の画像をそのまま使い、以前は独立クラスだった請求書と契約書を「その他」に統合しました。新たに収集中の候補画像は加えていません。

クラス 学習枚数 割合 主な構成と制約
名刺 626 24.4% 合成画像120枚、ローカルNASの実写5枚。残りは主に公開の印刷事例やWeb画像
レシート 327 12.7% 主にJaWildText。ローカルNASの画像3枚を含む
その他 1,612 62.8% 一般写真、ショップカード、グリーティングカード、販促物、旧請求書・契約書クラス

割合は丸めのため合計が100%にならない場合があります。

JaWildTextなどの公開データに、公開Web画像、合成画像、PDFからのレンダリング画像、ローカルの実写を組み合わせました。公開画像でも商用学習への利用が無条件に許可されるわけではありません。本記事では方法と集計結果を示し、元画像は再配布しません。

ラベルは主に同一のAIアシスタントが画像と掲載元の文脈を照合して確認したもので、独立した人間のチームによる完全な正解ラベルではありません。学習・校正・テストの分割では、同じ人物や発行元、完全重複、近似画像を確認しました。ファイル名や撮影角度が違うだけでは独立サンプルとみなしません。ただし、画像類似度やOCR、発行元の確認にも見落としはあり得ます。

名刺は印刷事例の比率が高く、自然な利用場面の実写が不足しています。また、旧請求書クラスの120/126枚は合成、旧契約書クラスの48/49枚はPDFレンダリングでした。「その他」に統合しても、この偏り自体は残ります。

同じ437枚で比較した結果

主な評価セットは、名刺91枚、レシート144枚、その他202枚。ローカルNASの170枚と公開サンプル267枚からなる、固定の437枚です。以下は全方式で同じ画像を用いた3クラス評価で、判定保留は使っていません。

437枚の固定評価セットで比較した正解率 名刺再現率 その他の誤判定件数

図2:分類ヘッドによって全体の正解率と誤判定件数は改善しましたが、名刺の再現率は低下しました。

再現率は「本当にそのクラスの画像をどれだけ検出できたか」、適合率は「そのクラスと判定した画像のうち、本当に正しかった割合」です。

方式 名刺 再現率 / 適合率 レシート 再現率 / 適合率 その他 再現率 / 適合率 全体の正解率
EG2テキストアンカー 分類ヘッド未学習 93.4% / 69.1% 92.4% / 98.5% 80.7% / 91.1% 87.2%(381/437)
EG2+3クラス分類ヘッド 85.7% / 89.7% 97.9% / 100% 96.0% / 92.8% 94.5%(413/437)

アンカー方式に対し、正解が 32枚増え、7.3ポイント改善しました。「その他」202枚のうち名刺やレシートに誤分類した数は39から8へ、この誤判定件数の相対削減率は約 79.5% です。

一方、本物の名刺91枚の検出数は85から78に減りました。3クラスを等しく重み付けしたマクロ平均再現率は93.2%、マクロ平均適合率は94.2%です。軽量分類ヘッドは全体の正解率と誤判定件数の改善に役立ちますが、名刺の見逃しには引き続き注意が必要です。5クラスから3クラスへの統合でも、この評価セットのクラス別指標は改善していません。

固定の0.7しきい値で判定保留を使う場合は、399/437枚正解、保留20枚、「その他」の誤判定6件、名刺再現率78.0%でした。保留は正解に数えません。またsoftmaxの0.7は、校正済みの「正しい確率70%」を意味しません。

CPUでの学習コスト

実験には24 GBメモリのMacBook Air M3を使用しました。分類ヘッドはscikit-learnのロジスティック回帰で、パラメーターを固定しています。

python
from sklearn.linear_model import LogisticRegression

head = LogisticRegression(
    C=100,
    class_weight="balanced",
    solver="lbfgs",
    max_iter=3000,
    random_state=20261015,
)
head.fit(X_train, y_train)  # キャッシュ済み768次元ベクトルと3クラスのラベル

本実験では構造、ハイパーパラメーター、判定保留しきい値の探索を行っていません。balancedはクラスの頻度に応じて重みを調整するため、クラス統合後は重みも再計算されます。

項目 実測値 計測範囲
分類ヘッドの学習 0.057秒 既存の2,565ベクトル。読み込みと検証を除く
1ベクトルの判定 中央値 0.005958ミリ秒 常駐ベクトル、softmax・クラス選択・0.7判定を含む
1ベクトルの判定 P95 0.006125ミリ秒 100回のウォームアップ後に2,000回計測

CPUは4スレッドで実行しました。写真のデコード、縮小、EG2による画像ベクトル生成は含みません。 既にベクトルがある場合の分類は非常に軽量ですが、新しい写真には画像エンコードが必要です。この数字からシステム全体の高速化倍率は主張できません。

実験から得られたこと

まずは単純な分類ヘッドを試す。 埋め込みが十分な情報を持っていれば、具体的な業務分類への適応に、必ずしも基盤モデルの微調整は必要ありません。

難しい負例は役立つが、見逃しも確認する。 ショップカードやグリーティングカードは重要な負例です。既存の校正セットを使ったデータ組み合わせ診断でも、負例追加による誤判定削減と、名刺再現率の低下が同時に見られました。

枚数よりも独立した場面の広がりを見る。 同じ人の名刺を10通りに撮影した画像は、10人の異なる自然な撮影場面の代わりにはなりません。人物、発行元、背景、遮蔽、撮影条件が重要です。

平均値だけで判断しない。 正解率94.5%は有用な途中結果ですが、名刺をどれだけ見逃したかは別に確認する必要があります。クラス別の再現率・適合率と、判定保留時のカバレッジを残すことが大切です。

94.5%をどう解釈するか

437枚は複数回の回帰評価に使用した固定セットであり、初見の独立ブラインドテストでも、実運用写真の無作為抽出でもありません。ラベルや公開画像の分布にも限界があるため、あらゆる日本語写真で94.5%になるという結果ではありません。今回の3クラス実験で、テスト結果を使ったパラメーター探索、しきい値変更、学習サンプル選択は行っていません。

個人の写真はローカルに保持しました。本記事では同じEG2エンコーダーを使った未学習のテキストアンカー方式と学習済み分類ヘッドを比較しており、他のシステムに対する優劣を示すものではありません。本記事は研究用プロトタイプの紹介であり、正式な製品機能としての提供告知ではありません。

次に重視したいのは、分類器を複雑にすることよりも、独立した実写名刺の充実です。新しいブラインドテストで、低い誤判定率を維持しながら名刺の再現率を取り戻せるかを検証していきます。