SEN PRODUCT BLOG

千株式会社のプロダクト開発メンバーによるブログ

DINOは『顔』を見分けられるのか? LoRAで顔認証モデルを作ってみた

こんにちは!

MLエンジニアのよねすけ(@ebichizu39)と申します。

SEN Advent Calendar 2025 18日目の記事になります。

今回はDINOを使って顔認証(FaceRecognition)モデルが作れるか実験した内容についてご紹介します。

📖 本記事を3行で要約!

  • 画像基盤モデル「DINOv2」の汎用性を維持しつつ、低コストな学習手法「LoRA」で顔認証タスクに適応させる方法を解説!
  • 比較対象(FaceNet)の1/300以下のデータ量という過酷な条件下で、どこまで精度が出るか検証!
  • 結果はAUC 0.9510を記録!FaceNet(0.9866)に迫るスコアを出し、小規模学習におけるDINOとLoRAのポテンシャルを実証!

DINO

皆さんはAIと聞くとChatGPTやGeminiのようなLLMを想像するでしょうか?

ChatGPTの「T」は「Transformer」といって、現在のLLMをはじめとした自然言語(NLP)の分野で広く活用されている技術です。

Transformerを画像認識に応用した「VisionTransformer」(以下ViT)があり、現在でも研究・開発が進んでいます。

最近注目されているのが、ViTにおける基盤モデル(汎用性が高い高性能モデル)になると言われている「DINO」シリーズです。

ai.meta.com

DINOはMeta社が研究・開発した画像認識基盤モデルです。

今年の8月にはDINOv3が論文としても発表されました。

arxiv.org

DINOの技術的な詳細については割愛しますが、要点として「画像内の物体を汎用的に見分ける高性能モデル」であると捉えていただければと思います。

私はこのDINOをはじめとしたViTに注目しており、社内の画像認識タスクへの活用を進めております。

DINOの可能性を探求したい、DINOの汎用的に物を見分ける力を活用すれば、顔の細かい特徴をうまく識別できるのではないか。

これらが本実験の動機となります。

顔認証(FaceRecognition)

顔認証を行うためには、以下のステップで処理を行います。

  1. 画像内のどこの位置に顔が映っているか、顔検出モデルで検出する

  2. 検出した顔画像を特定のモデルでベクトル化する

  3. ベクトル同士のコサイン類似度を計算して判定する

    FaceRecognitionイメージ図

DINOは2番目のベクトル化の役割を担うイメージです。

どうやってDINOに顔を認識させるのか

それではどうやってDINOに顔認識できるよう訓練するのでしょうか。

一般的に機械学習モデルを訓練する方法として、「ファインチューニング」があります。

機械学習モデルは膨大な重みパラメータを保有しており、膨大な入力データと出力データのペア(データセット)を使って重みパラメータを最適化します。

ただし今回使用するDINOは既に膨大なデータを使って汎用性を獲得したモデルですので、再調整してしまうと元々DINOが持っていた汎用性を壊してしまう(破滅的忘却)可能性があります。

これをできるだけ壊さない方法として、一部のパラメータだけを更新する「転移学習」という手法もありますが、それでも汎用性能に影響が出てしまわないか不安です。

またDINOはそこそこ大きなモデルなので、学習させるためには多くの時間と計算リソースが必要となります。

これらの問題への対策として、「PFFT(Parameter-Efficient Fine-Tuning)」における「LoRA」という手法を採用しました。

LoRA

LoRAは「Low-Rank Adaptation」の略で、Stable Diffusionなどの画像生成AIでもよく使われています。

arxiv.org

上記論文中にあるFig1を引用します。

Fig1

平たくまとめると、ファインチューニングによるパラメータ差分を低次元行列で近似することで、計算コストを抑えつつファインチューニングに近い性能を出すことを目的としています。

左側のPretrained WeightsがDINOの重みパラメータで、こちらのパラメータは更新しません。

その代わり右側の行列パラメータがDINOのアダプターの役割をしてパラメータを更新します。

これにより、DINOの汎用性を失うことなく、DINOの出力結果に対して顔認識専用アダプターが補正を行うイメージです。

以上の前提知識を踏まえて、本実験の概要ついて解説します。

実験概要

データセット

まず学習に使う顔画像データセットですが、YLFWを最初の候補に挙げました。

arxiv.org

github.com

LFWは顔認識でよく使われているデータセットですが、その中でも若い年代(Young)の顔画像を集めたものがYLFWです。

YLFWにはBenchmarkとDevがあり、Devが訓練用データになります。

Devを使うには、ライセンス同意書を書いてパスワードを取得する申請をする必要があります。

で、申請してみたのですが、大学や研究機関に所属していないと発行できないと断られてしまったため、今回は断念しました。

なので今回はCALFWというデータセットを使います。

arxiv.org

whdeng.cn

こちらは公開されたデータであり、LFWの改良版ということで、年齢別の偏りも改善されています。

CALFWのデータセットは人数こそ約5,700人の顔データで構成されていますが、一人当たり数枚程度しか含まれておりません。

なので全体でも12,000枚程度と小規模なデータセットであり、さらにテスト用に2割程度使用するので訓練に使えるデータは多くありません。

そんなデータで大丈夫か?というのも重要な観点となりますので、頭の片隅に置いておいてください。

⚠️ 本記事に関するご注意
本記事は、技術的な知見の共有および個人的な検証(Research purpose)を目的としており、商用利用を意図したものではないことを強調しておきます。

DINOv2 + LoRA

今回はライセンスや実装の手軽さの観点で、DINOv2を採用しました。

github.com

DINOv2にLoRAを追加したモデルを構築するために、HuggingFaceのtransformersライブラリを使用しました。

huggingface.co

from transformers import AutoModel
from peft import get_peft_model, LoraConfig

model_name = "facebook/dinov2-base"
base_model = AutoModel.from_pretrained(model_name)
lora_config = LoraConfig(
        r=4,  
        target_modules=["query", "value"],
    )
peft_model = get_peft_model(base_model, lora_config)

PEFT専用のライブラリがあり、HuggingFaceと組み合わせると簡単にLoRAモデルを作成できます。

LoRAConfigの引数についてですが、以下の論文を参考にしております。

arxiv.org

target_modulesは、LoRAアダプターをどこに差し込むかを決めます。

DINOを構成するViT内部ではSelf-Attentionという構造があり、Q, K, Vの層が存在します。

画像をパッチ(断片)に分割してインプットした際、それぞれの断片が「画像のどこに注目すべきか」という対応関係を関連づける仕組みなのですが、ここにLoRAアダプターを挿入します。

ただし、Kの部分はDINOのデータベース的な役割を果たしているため、ここにはアダプターをつけないという判断をしています。

論文中よりFig2を引用します。

Fig2

(補足ですが、厳密にはimage_tokensの矢印はKだけでなくQとVにもかかっています)

rはLoRAの低ランクサイズを指しており、一般的に4, 8, 16が使われます。

数字が大きいほど近似の表現力が上がるため性能として高くなりやすい一方、計算コストはやや高くなります。

しかしこの論文内ではなんと4が最も性能が高い結果になったそうです。

論文中よりTable4を引用します。

Table4

本実験ではこれらのデータを参考に設定しました。

その他技術要件

コードや各技術の詳細を全て紹介することは、本記事内では物理的に難しいため割愛させていただきます。

その他使用したものを列挙しておきます。

気になる方はご参考ください。

基本的にはPyTorchなどでお馴染みのファインチューニングコードや設定値で実装しております。

  • 顔検出:RetinaFace(MobileNet)
  • 分類器(損失関数):AdaFace
  • Optimizer:AdamW
  • Scheduler:get_constant_schedule_with_warmup(HuggingFace)
  • 学習率:10^-3
  • batch_size:64
  • epoch数:50(簡易的な実験のため今回は決め打ち)

AdaFaceなどの分類器は、いかに異なる顔同士を遠ざけ同じ顔同士を近づけるかという顔認証用の距離学習で重要な技術となってます。

すでに綺麗にまとめられた先人の資料がありましたので、もしご興味があればご参考ください。

speakerdeck.com

学習環境としてはAWSのEC2インスタンス「g4dn.xlarge」で行いました。

aws.amazon.com

大体1時間弱で完了しました。とても低コストで試せます。

評価

評価方法

評価指標には顔認証でよく使われるROC曲線とAUCを採用しました。

ROC曲線やAUCに関する参考記事をいくつか貼っておきます。

developers.google.com

www.kikagaku.co.jp

学習に使っていないCALFWをテスト用として用意しておき、同一人物のペア画像と異なる人物のペア画像の組み合わせを作ります。

このペア画像において冒頭のベクトル類似度を計算し、同一人物は同一人物である、異なる人物は異なる人物であるとどの程度正しく判定できているかを評価しているイメージです。

DINOv2 + LoRAの比較対象に、FaceNetという顔認証モデルを用意しました。

github.com

LFWにおいてAUCが0.9965(VGGFace2)という高い性能を出すオープンソースモデルです。

FaceNetはVGGFace2という約9000人のデータを330万枚集めた大規模なデータセットで学習しています。

顔認証のベンチマークとして、比較の参考に良いかと思い採用しました。

またLoRAの効果を確認するため、DINOv2のオリジナルも比較対象とします。

まとめると、

  • 評価指標:ROC曲線/AUC

  • 評価対象:DINOv2(オリジナル)、FaceNet、DINOv2 + LoRA

上記3つのモデルを評価指標に基づいて比較することで評価しました。

評価結果

ROC曲線とAUCをプロットしたグラフは以下です。

ROC曲線とAUC

グラフの見方としては、曲線ができるだけ縦軸の1に近ければ近いほど、正しいペアと異なるペアを見分ける性能が高いと解釈できます。

オリジナルのDINOv2(青線)はあまり顔を見分ける力が高くないことがわかります。

一方でFaceNet(紫線)はCALFWにおいても0.9866と高いAUCを出しており、限りなく1に近い曲線となっております。

そしてDINOv2 + LoRA(赤線)ですが、FaceNetには劣るものの、0.9510とかなり近い性能を出せていることがわかります。

考察

以下この結果に対する考察をいくつか述べます。

DINOで顔認証モデルは作れる!

学習データ量が1/300以下(330万枚 vs 1万枚)であるにも関わらず、FaceNetとのスコア差はわずか0.03(3%程度)でした。

この結果は顔認証モデルとして使えるレベルまで来ていると言って良いのではないでしょうか。

DINOの汎用性の高さと、それを守りながら特定のタスクに低コストに対応できるLoRAの持ち味が発揮された結果になったと考えます。

FaceNetに負けてしまったのはなぜ?

個人的にはFaceNetを上回るスコアが出る可能性も考えてました。

FaceNetに負けてしまった敗因として考えられるものをいくつか挙げてみます。

  • VGGFace2の圧倒的な物量

第一に考えられるのはこれですね。

AIの性能を決める重要な要素はデータセットの質と量です。

CALFWに対して画像枚数で300倍以上の物量を持っていることになりますので、流石に差が大きすぎたかもしれません。

言い換えればFaceNetが強すぎた、testデータが簡単すぎたとも解釈できそうです。

とはいえ、かなり大健闘したのではないかと個人的には思います。

  • フルファインチューニング > LoRA

第二に考えられるのは、LoRAは低コストで実現できるものの、近似であるためフルファインチューニングに性能で及ばないというのはありそうです。

あくまで低コストかつ本体のモデルの持ち味を壊さないと言う狙いで活用すると良いでしょう。

  • DINOは顔認証が得意なモデルではない

DINOv2がそもそも顔認証が得意な性能を持っていないことはグラフの結果を見てもそうなのですが、LVD-142Mという新しいデータセットを使っており、プライバシーの観点から人の顔画像をぼかしているというのがネックになっているかもしれません。

arxiv.org

そう考えればFaceNetは顔の特徴を見ることに特化して学習しているのに対して、顔以外のあらゆる物体を学習している上に顔はぼかされたDINOでは、スタートから大きなハンデを追っていたというのは考えられます。

とはいえこれだけの顔認証性能を出せたことは、DINOの物を見る力の汎用性の高さを十分実感できる結果だと考えます。

まとめと将来の展望

本記事ではDINOで顔認証モデルを作成する実験について紹介しました!

DINOは顔認証タスクも特化モデルに及ばないとはいえ、それに近い性能を出せることを確認できました!

またLoRAによるファインチューニングは汎用モデルの汎化性能を壊さず、低コストに特定の分野に特化する学習が可能であることも確認できました!

今回のDINOv2はbaseモデルを使用していますが、largeタイプや最新のv3モデルを使えばもっと高い性能が期待できるかもしれません! (もちろん学習・推論コストが上がってしまいますが・・)

Register(背景など外れ値的に注目してしまった情報を取り除く機能)つきのDINOなどもおすすめです!

arxiv.org

QLoRAなどは量子化なのでDINOだけでなく、LLMSLMなどへの応用も期待できそうです!

arxiv.org

azure.microsoft.com

皆さんもぜひDINOやLoRAの活用を試してみてはいかがでしょうか?

最後までご覧いただきありがとうございました!

千株式会社では、一緒に働く仲間をAIエンジニアだけでなく幅広く募集中です!

findy-code.io

ご興味ありましたら是非ご応募ください!

明日のSEN Advent Calendar 2025 19日目は、おすしさんです!お楽しみに!