論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説
📚 用語解説
顔認証
Face Recognition
画像認識バイオメトリクス

🔖 キーワード索引

30秒結論 文脈ボックス 直感 🎮 FAR/FRR体感 数式・定義 数式読解 実値計算 Python実装 パイプライン 落とし穴 倫理 関連手法 応用 関連用語 グループ教材 FAQ 🔎 解説深化 概念マップ

💡 30秒で分かる結論

🍰 まずはやさしく

顔認証は、顔写真から誰かを当てる技術です。

本人の確認や、個人の特定のために使います。

スマホのロック解除などで使われています。

この章では、認証の仕組みや流れを読みます。

📍 文脈ボックス — あなたが今見ているもの

🍰 まずはやさしく

顔認証は、画像認識という技術の一種です。

生体情報(体の特徴)を使って人を識別します。

指紋認証と同じグループの技術です。

この章では、関連する他の技術について読みます。

あなたは 「画像認識 / バイオメトリクス / 距離学習」 の交点にいる用語ページを見ています。 顔認証は 画像認識 の特殊例で、 入力に「人間の顔」という構造的事前知識が組み込まれます。

上位概念画像認識 / バイオメトリクス
同列概念ジェスチャー認識 / 指紋認証 / 虹彩認証
下位応用スマホロック解除 / 入退室管理 / 写真整理
前提知識深層学習 / PCA / 条件付き確率

🎨 直感で掴む

🍰 まずはやさしく

顔を数字の列(ベクトル)に変える技術です。

似ている人を、近い数字として扱います。

写真整理で同じ人を分ける仕組みに似ています。

この章では、数字で顔を比べる方法を読みます。

顔認証は 「人を 512 次元のベクトルに変換して、 そのベクトルが近ければ同一人物」 という考え方の技術です。 ディープニューラルネット(バックボーン)が顔画像を 128~512 次元の 顔埋め込み (face embedding) に圧縮します。

学習時は「同じ人の異なる画像は近く、 違う人は遠く」となるよう距離関数を直接最適化します(メトリック学習)。 Triplet Loss は「アンカー・正例・負例」の 3 つを使い、 正例が負例より近くなるよう margin を確保する。

SSDSE-B-2026 を「顔データセット」に見立てると、 47 都道府県の指標ベクトルが「47 人の顔」、 県同士の類似度計算が「2 人が同一の地域カテゴリか判定」する Verification タスクに対応します。

表 1. 顔認証の 4 段階処理
段階処理代表モデル
1. 検出画像から顔領域を切り出すMTCNN, RetinaFace
2. 整列眼・鼻の位置で正規化5/68 ランドマーク
3. 埋め込み高次元ベクトル化FaceNet, ArcFace
4. 照合距離計算で判定コサイン類似度

身近な例え:似顔絵を「特徴の数字メモ」に圧縮

顔認証エンジンの内部は「似顔絵を 512 個の数字メモに圧縮する装置」と思うとよい。 例えばメモ 1 番目が「眉の濃さ」、 2 番目が「鼻の高さ」、 3 番目が「目の間隔」... のように 512 個の特徴量が並ぶ。 もし君と弟の顔メモを並べたら「眉 0.82 vs 0.79、 鼻 0.61 vs 0.65、 ...」と似た数字が並ぶはず。 距離(コサイン類似度)を計算すると 0.95(近い)。 一方、 君と他人なら 0.4(遠い)。 こうして「数字の近さ」だけで同一人物判定ができる。

なぜディープラーニングが必要なのか

人手で「鼻の高さ・眉の角度」を測るアプローチは 1990 年代に試みられたが、 照明・角度・表情で精度が崩壊した。 ディープラーニングは数百万枚の顔から「同一人物 → 近く、 別人 → 遠く」となる埋め込みを自動学習する。 結果、 マスク着用・低照度でも安定し、 LFW ベンチマークで 99.8% を超える精度を達成した。

🎮 体感:閾値スライダーで FAR / FRR / EER を動かす

顔認証(生体認証)は結局「2 枚の顔から作った埋め込みベクトルの距離(類似度)が閾値より近いか遠いか」で本人/他人を分ける二値分類問題です。 下の図は 本人ペア(同一人物の 2 枚=似ているので類似度が高い)他人ペア(別人=類似度が低い)の類似度分布(架空・シードで生成した決定的なデータ)。 2 つの山は必ず重なり、 だからこそ 1 本の閾値では両方の誤りをゼロにはできません。 スライダー(または図を直接ドラッグ)で閾値 τ を動かし、 本人拒否率 FRR(本人なのに弾く)と 他人受入率 FAR(他人を通す)のトレードオフを体感してください。

FAR 他人受入率
他人ペアのうち τ 以上で誤って通した割合
FRR 本人拒否率
本人ペアのうち τ 未満で誤って弾いた割合
EER 等誤り率
FAR=FRR となる点(システム総合性能)

※ 分布は説明用の架空データ(本人ペア=N(0.72, 0.09)、 他人ペア=N(0.36, 0.11)、 各 2000 ペア、 乱数シード 12345 で決定的に生成)。 実運用値ではありません。 FAR/FRR は生成した標本から経験的に集計、 EER は τ を細かく掃引して FAR と FRR が最も近づく点として算出しています。

直感:近ければ本人・閾値で線引き

埋め込み空間では「本人の 2 枚」は近く(類似度が高く)、「別人」は遠い(類似度が低い)。 判定は 1 本の閾値 τ による線引きだけ。 τ を右へ動かすと「本人だと認めるハードル」が上がるので、 他人はほとんど弾ける(FAR↓)が本人まで弾いてしまう(FRR↑)。 左へ動かせば逆。 2 つの山が重なっている領域が、 どちらに転んでも必ず誤る「原理的に消せない誤り」で、 その最小バランス点が EER です。

落とし穴:トレードオフ・なりすまし・層による精度差・プライバシー

1:1 認証(照合)と 1:N 識別の違い

同じ「距離+閾値」でもタスクが 2 つあります。 1:1 照合(Verification)は「本人だと主張する 1 人」と登録テンプレート 1 件を比べ、 τ 以上なら受入。 上の図はこの 1:1 の話です。 1:N 識別(Identification)は 1 枚を N 件の登録全部と照合して「誰か(または該当なし)」を返す。 N 件それぞれで他人受入のチャンスがあるので、 N が大きいほど誰か 1 人に誤マッチする確率が上がり、 同じ FRR を保つには τ をより高く(厳しく)する必要があります。 だから登録規模で最適閾値が変わります(都道府県別 EER 設計参照)。

発展:生体検知・マルチモーダル・テンプレート保護

📐 数式または定義

🍰 まずはやさしく

顔認証は、数式を使って計算する技術です。

正しく判定するためのルールを決めます。

スマホの認証精度を高める計算に使われます。

この章では、判定に使う数式について読みます。

顔埋め込み関数 $f_\theta: \mathbb{R}^{H\times W\times 3} \to \mathbb{R}^d$ ($d=128 \sim 512$):

$$\mathbf{e} = f_\theta(\text{顔画像})$$

2 つの顔のコサイン類似度:

$$s(\mathbf{e}_1, \mathbf{e}_2) = \frac{\mathbf{e}_1 \cdot \mathbf{e}_2}{\|\mathbf{e}_1\| \|\mathbf{e}_2\|}$$

Triplet Loss(アンカー a・正例 p・負例 n、 マージン $\alpha$):

$$\mathcal{L} = \max\!\left( \|f(a) - f(p)\|^2 - \|f(a) - f(n)\|^2 + \alpha,\, 0 \right)$$

ArcFace Loss(角度マージン):

$$\mathcal{L}_\text{ArcFace} = -\log \frac{\exp(s \cdot \cos(\theta_y + m))}{\exp(s \cdot \cos(\theta_y + m)) + \sum_{j\neq y} \exp(s \cdot \cos\theta_j)}$$

Verification の判定:

$$\text{同一人物} \iff s(\mathbf{e}_1, \mathbf{e}_2) \geq \tau$$

ROC 曲線で False Accept Rate (FAR) と False Reject Rate (FRR) のトレードオフを評価。 Equal Error Rate (EER) が代表指標。

📐 cosine 類似度 — 数式を言葉で読み解く

$$\, s(x, y) \;=\; \frac{x \cdot y}{\|x\|_2 \, \|y\|_2} \;=\; \cos\theta \,$$

2 つのベクトルがなす角度のコサイン。 -1 (反対方向) 〜 +1 (同方向) を取る。 顔 embedding は通常 L2 正規化された単位ベクトルとして扱うので、 内積がそのまま cosine 類似度になり、 計算が高速。 ArcFace 学習後の embedding 空間では「同一人物」≈ 角度 0°、 「他人」≈ 角度 60-90°。

L2 距離との関係

$$\, \|x - y\|_2^2 \;=\; \|x\|_2^2 + \|y\|_2^2 - 2 \, x \cdot y \;=\; 2 (1 - s(x, y)) \quad \text{(単位ベクトルの場合)} \,$$

単位球面上では L2 距離と cosine 類似度は単調変換で 1:1 対応する。 face_recognition (dlib) は L2 距離、 ArcFace は cosine と慣習が異なるが本質は同じ。

✅ 性能を 1 段上げるチェックリスト

  1. 顔検出器を強化: RetinaFace / SCRFD で hard face のリコール改善。
  2. 5 点ランドマークでアライメント: 目・鼻・口を固定座標へ。
  3. マルチビュー登録: 1 人 5〜10 枚 (正面・横・上・下) embedding を平均。
  4. Quality Score: ぼけ・低照度の画像を弾く (BRISQUE, MagFace score)。
  5. TTA: 水平 flip 等で複数 embedding を平均。
  6. 大規模学習データ: WebFace260M で再学習。
  7. Hard Negative Mining: 似て非なる人物ペアを batch に積極追加。
  8. FP16 推論: 半精度で速度 2 倍、 精度ほぼ無劣化。
  9. マルチモーダル: 顔 + 音声 / 顔 + 歩容 で robustness 向上。
  10. 定期再評価: 半年に 1 度、 自社環境 EER を再測定し閾値を再調整。

🧬 顔 embedding と cosine 類似度: 都道府県別 EER 設計

顔認識の中核は 顔画像 → 128 次元 or 512 次元 embedding の写像と、 その埋め込み空間での cosine 類似度判定 である。 ここでは FaceNet 系の 128 次元ベクトルを想定し、 SSDSE-B-2026 の都道府県人口を「想定運用規模」 として扱い、 各県で 1:N 認証を行う場合の閾値設計を検討する。 大都市と地方で要求される FAR/FRR バランスが大きく異なる点が重要。

🐍 Python 実装: face_recognition + 都道府県別運用シミュレーション

🎯 このコードでやること: 都道府県人口を「登録ユーザ数 N」 と見立て、 1:N 認証で許容できる False Accept Rate (FAR) から cosine 類似度閾値を逆算する。 同時に SSDSE-B-2026 の都道府県別に必要な閾値の差を可視化する。

📥 入力データ (SSDSE-B-2026 都道府県人口、 抜粋):

都道府県 人口総数 想定登録 N (5% 想定) 東京都 14047594 702380 大阪府 8837685 441884 神奈川県 9237337 461867 鳥取県 548649 27432 島根県 665205 33260
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import pandas as pd
import numpy as np

# face_recognition は dlib ベース、 128 次元 embedding を返す
# import face_recognition
# enc = face_recognition.face_encodings(image)[0]  # shape=(128,)

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1)
# 実際の列名は「人口総数」ではなく「総人口」
pref = df.groupby('都道府県')['総人口'].mean().reset_index()
pref = pref.rename(columns={'総人口': '人口総数'})
pref['登録N'] = (pref['人口総数'] * 0.05).astype(int)  # 5% が登録ユーザ想定

# 異人物ペアの cosine 類似度は近似的に正規分布 N(0.30, 0.07) (LFW で計測された経験値)
# 1:N 認証で誤受入 1 件出る閾値: per-comparison FAR <= 1/N
from scipy.stats import norm
mu_imp, sd_imp = 0.30, 0.07
pref['per_FAR'] = 1.0 / pref['登録N']
pref['必要閾値'] = norm.ppf(1 - pref['per_FAR'], loc=mu_imp, scale=sd_imp)

# 同人物ペアの分布 N(0.78, 0.06) → 必要閾値での FRR
mu_gen, sd_gen = 0.78, 0.06
pref['推定FRR'] = norm.cdf(pref['必要閾値'], loc=mu_gen, scale=sd_gen)

top = pref.nlargest(3, '人口総数')[['都道府県','登録N','必要閾値','推定FRR']]
bot = pref.nsmallest(3, '人口総数')[['都道府県','登録N','必要閾値','推定FRR']]
print('大規模県:'); print(top.to_string(index=False))
print('小規模県:'); print(bot.to_string(index=False))
print('全国平均 必要閾値 =', round(pref['必要閾値'].mean(), 3))
print('全国平均 推定 FRR  =', round(pref['推定FRR'].mean(), 4))

📤 実行すると次の出力が得られる:

大規模県: 都道府県 登録N 必要閾値 推定FRR 東京都 687270 0.627395 0.005489 神奈川県 458598 0.621537 0.004132 大阪府 441467 0.620981 0.004021 小規模県: 都道府県 登録N 必要閾値 推定FRR 鳥取県 28132 0.578082 0.000382 島根県 34110 0.581277 0.000463 高知県 35486 0.581929 0.000481 全国平均 必要閾値 = 0.597 全国平均 推定 FRR = 0.0015

💬 結果の読み方: 東京都 (登録 N≈69 万) では cos≥0.627 でないと誤受入を 1 件以下に抑えられず、 結果として正規ユーザの 0.55% が拒否される。 一方鳥取県 (N≈2.8 万) は閾値 0.578 で済み、 FRR は 0.038% ── 東京の約 14 分の 1 である。 登録者数の差は 24 倍もあるのに閾値の差はわずか 0.049 しかない点にも注目したい。 閾値は登録数の対数程度でしか動かない(正規分布の裾を切るため)が、 裾の領域ではその 0.049 の移動が拒否率を 14 倍に変えてしまう。 同じモデル・同じ閾値でも、 運用規模で UX が激変する ことを示しており、 「全国一律閾値」 は明確に誤りだと分かる。

埋め込み手法と現実の選定

手法次元典型 EER (LFW)SSDSE 規模での適性
LBPH (OpenCV)~256~15%小規模 (~1000 人) の入退室のみ
FaceNet (Inception)1280.63%市町村規模 (~10 万人) まで
ArcFace (ResNet100)5120.10%都道府県規模 (~100 万人) 対応可
AdaFace + WebFace260M5120.05%全国 (~1 億人) でも 1:N 実用

⚠️ 運用前の必須テスト: (1) 自社設置カメラで撮った 1000 名で EER 実測 (LFW 数値は鵜呑み禁止)、 (2) 高齢者・マスク着用・逆光の sub-population で別個に評価、 (3) 差別防止 の観点で性別・年代別 FAR/FRR を必ず報告。 これらを怠ると「都市部だけ動作する顔認識」 になり、 地方住民の権利を侵害する恐れがある。 face_recognition / OpenCV / deepface / InsightFace のいずれを選ぶにせよ、 この検証ステップは省略不可。

🔬 数式を言葉で読み解く

記号意味
$f_\theta$顔→ベクトル変換ニューラルネット
$\mathbf{e}$顔埋め込み (face embedding)
$s(\cdot, \cdot)$類似度(コサイン or L2 距離の逆)
$\alpha$Triplet マージン(典型 0.2)
$\theta_y$クラス重みと埋め込みの角度
$m, s$角度マージン, スケール(典型 0.5, 64)
$\tau$判定閾値(FAR を制御)

Triplet Loss は「同一人物の距離 + マージン < 別人の距離」を強制する。 ArcFace は分類層をハイパースフィア上の角度マージン分類に置換した洗練版で、 現在の SOTA。

🔬 応用事例

🔬 数式を言葉で読み解く(顔認証技術)

1. Eigenface(固有顔法)

Eigenface は 1991 年に Turk と Pentland が提案した顔認識の古典的手法であり、 主成分分析(PCA)を顔画像に適用する。 数式 $\mathbf{x} \in \mathbb{R}^{d}$ は $d$ 次元(例:100×100=10,000 次元)の顔画像ベクトルを表し、 $N$ 枚の顔画像集合 $\{\mathbf{x}_1, \ldots, \mathbf{x}_N\}$ から平均顔 $\bar{\mathbf{x}} = \frac{1}{N}\sum_i \mathbf{x}_i$ を引いた中心化画像 $\tilde{\mathbf{x}}_i = \mathbf{x}_i - \bar{\mathbf{x}}$ について、 共分散行列 $\mathbf{C} = \frac{1}{N}\sum_i \tilde{\mathbf{x}}_i \tilde{\mathbf{x}}_i^\top$ の固有ベクトル $\mathbf{u}_k$ を求める。 上位 $K$ 個の固有ベクトル(固有顔)で各顔画像を $\mathbf{w}_i = \mathbf{U}_K^\top \tilde{\mathbf{x}}_i$ という低次元ベクトルに射影し、 認識時には未知顔の射影と既知顔の射影のユークリッド距離 $\|\mathbf{w}_{\text{query}} - \mathbf{w}_i\|_2$ を計算して最小距離の人物 ID を返す。 言葉で読み解くと「顔画像の集合の中で『最も変動が大きい方向』を $K$ 本選び、 その軸の組み合わせで個人を表現する」手法である。 利点は計算コストが低く可視化しやすい点だが、 照明変動・表情変化・姿勢変化に弱く、 現代の深層学習手法に比べて精度は劣る。

2. LBP(Local Binary Pattern、 局所二値パターン)

LBP は 1996 年に Ojala らが提案したテクスチャ特徴量で、 顔認識では Ahonen ら(2006)が応用した。 数式は、 ピクセル $(x, y)$ を中心とする半径 $R$ の円周上 $P$ 個の点 $\{g_p\}_{p=0}^{P-1}$ の輝度値と中心輝度 $g_c$ を比較し、 $\text{LBP}_{P,R}(x, y) = \sum_{p=0}^{P-1} s(g_p - g_c) \cdot 2^p$ で計算する。 ここで $s(z) = 1$ if $z \geq 0$、 else $0$ である。 各ピクセルに 0〜255 のラベルが付き、 顔画像を $M \times N$ ブロックに分割してブロックごとに LBP ヒストグラムを作り連結すると、 顔全体の特徴ベクトル(例:8×8 ブロック × 256 bin = 16,384 次元)が得られる。 認識時にはカイ二乗距離 $\chi^2(\mathbf{h}_1, \mathbf{h}_2) = \sum_i \frac{(h_{1,i} - h_{2,i})^2}{h_{1,i} + h_{2,i}}$ で類似度を測る。 言葉で読み解くと「各ピクセル周辺の明暗パターンを 8 ビットの符号として記録し、 そのヒストグラムを顔の指紋とする」方法である。 照明変動に強く軽量で、 組み込み機器や低スペック環境で広く使われた。

3. FaceNet(深層距離学習)

FaceNet は 2015 年に Google の Schroff らが発表した深層学習ベースの顔認識手法で、 Inception 系の CNN を使い顔画像を $\mathbf{f}(\mathbf{x}) \in \mathbb{R}^{128}$ という 128 次元の埋め込みベクトル(embedding)に変換する。 学習目標は「同一人物の埋め込みは近く、 異なる人物の埋め込みは遠い」状態を作ることで、 これを Triplet Loss $\mathcal{L} = \sum_i \max\left(0, \|\mathbf{f}(\mathbf{x}_i^a) - \mathbf{f}(\mathbf{x}_i^p)\|_2^2 - \|\mathbf{f}(\mathbf{x}_i^a) - \mathbf{f}(\mathbf{x}_i^n)\|_2^2 + \alpha\right)$ で実現する。 ここで $\mathbf{x}_i^a$ はアンカー(基準顔)、 $\mathbf{x}_i^p$ は同一人物の別画像(ポジティブ)、 $\mathbf{x}_i^n$ は異なる人物の画像(ネガティブ)、 $\alpha$ はマージン(典型値 0.2)である。 認識時には埋め込み間のコサイン類似度 $\cos\theta = \frac{\mathbf{f}_1 \cdot \mathbf{f}_2}{\|\mathbf{f}_1\| \|\mathbf{f}_2\|}$ または L2 距離を計算し、 閾値判定で同一人物かを判断する。 言葉で読み解くと「同じ人の顔は引き寄せ、 別人の顔は突き放す」ように 128 次元空間を学習させる手法である。 LFW(Labeled Faces in the Wild)データセットで 99.63% の精度を達成し、 顔認証の精度を一気に引き上げた。

4. ArcFace(角度マージン損失)

ArcFace は 2019 年に Deng らが発表した SOTA 手法で、 FaceNet の改良版である。 通常の Softmax 交差エントロピー損失を $\mathcal{L} = -\log \frac{e^{s \cdot \cos\theta_{y_i}}}{e^{s \cdot \cos\theta_{y_i}} + \sum_{j \neq y_i} e^{s \cdot \cos\theta_j}}$ と表す($s$ はスケール、 典型値 64)が、 ArcFace はクラス境界に角度マージン $m$(典型値 0.5 ラジアン)を加えて $\mathcal{L} = -\log \frac{e^{s \cdot \cos(\theta_{y_i} + m)}}{e^{s \cdot \cos(\theta_{y_i} + m)} + \sum_{j \neq y_i} e^{s \cdot \cos\theta_j}}$ とする。 これにより同一クラス(同一人物)の埋め込みは超球面上で角度的にコンパクトに集まり、 異なるクラス同士は角度マージン $m$ 以上離れる。 言葉で読み解くと「正解クラスの予測角度に追加でハンディキャップ $m$ を課して、 それでも勝てるくらいキッチリ学習させる」手法である。 LFW で 99.83%、 MegaFace で 81.03% という極めて高い精度を実現し、 商用顔認証システムの多くが採用している。

5. FAR / FRR(誤受入率・誤拒否率)と性能評価

顔認証システムの評価には FAR(False Acceptance Rate、 誤受入率)と FRR(False Rejection Rate、 誤拒否率)が用いられる。 FAR は他人を本人と誤って受け入れる率で $\text{FAR} = \frac{\text{他人を本人と判定した回数}}{\text{他人ペアの総試行回数}}$、 FRR は本人を他人と誤って拒否する率で $\text{FRR} = \frac{\text{本人を他人と判定した回数}}{\text{本人ペアの総試行回数}}$ である。 閾値 $\tau$ を下げると FAR は上がり FRR は下がる(甘い判定)、 閾値を上げると逆になる(厳しい判定)というトレードオフがある。 両者が等しくなる点を EER(Equal Error Rate、 等価エラー率)と呼び、 システム全体の性能指標とする。 商用顔認証の典型値は FAR=0.001% 時に FRR=2% 程度、 EER は 0.1% 前後である。 言葉で読み解くと「FAR は『他人にだまされる確率』、 FRR は『本人を追い返す確率』で、 両方を同時に小さくはできない」ということ。 銀行やパスポート審査では FAR を極小に(他人を入れない)、 スマホロック解除では FRR を小さく(本人をスムーズに通す)チューニングする。

6. 倫理・規制(EU AI Act、 個人情報保護法)

顔認証はバイオメトリクス情報の中でも特にプライバシー影響が大きく、 規制が急速に整備されている。 EU AI Act(2024 年成立)では公共空間でのリアルタイム遠隔生体識別を原則禁止し、 違反時は全世界売上高の最大 7% の制裁金が科される。 日本の個人情報保護法(2022 年改正)では顔認証データは「個人識別符号」として明示され、 取得時の同意義務、 第三者提供制限、 漏えい時の報告義務が厳格化された。 さらに ISO/IEC 19794-5(顔画像の交換フォーマット標準)、 NIST FRVT(顔認識ベンダーテスト)等の国際標準・評価基準も整備されている。 実装上の注意点は、 (1) 取得目的の明示と同意取得、 (2) 保管期間の最小化、 (3) 暗号化保管、 (4) アクセスログの管理、 (5) 削除権の確保、 (6) アルゴリズムバイアスの定期評価(人種・性別・年齢別の精度差)である。 NIST の調査では一部のアルゴリズムが白人女性に比べて黒人女性で誤認率が 10〜100 倍高いと報告され、 公平性の確保は技術的にも倫理的にも喫緊の課題である。

散布図
図 1: FAR と FRR のトレードオフ — 閾値を横軸、 縦軸に FAR/FRR を取ると、 両者が交差する点が EER(等価エラー率)。 商用システムは用途に応じて閾値を調整する
ヒストグラム
図 2: マッチングスコア分布 — 本人ペアのスコア分布(青)と他人ペアのスコア分布(赤)の重なりが小さいほど高性能。 ArcFace 等の SOTA 手法は重なりをほぼゼロにする
箱ひげ図
図 3: アルゴリズム別性能比較 — Eigenface, LBP, FaceNet, ArcFace の LFW データセットでの精度分布。 深層学習ベースが古典手法を大きく上回る

✅ 理解度チェック

Q1. Eigenface は顔画像を低次元ベクトルに射影するが、 その「次元」はどのように選ばれるか。 100 次元と 10 次元では何が変わるか。

A1. 共分散行列の固有値の大きさ順に上位 $K$ 個の固有ベクトル(固有顔)を選ぶ。 $K$ が大きいほど元の顔画像の情報を多く保持できるが計算コストが増す。 100 次元では細かい個人特徴まで保持できるが、 10 次元では大まかな顔の形状のみ捉え、 個人識別精度は低下する。 累積寄与率が 90〜95% になる $K$ を選ぶのが実用的指針。

Q2. FAR=0.001%、 FRR=2% という顔認証システムを、 銀行 ATM とスマホロック解除のどちらに使うべきか。 理由とともに答えよ。

A2. 銀行 ATM に向く。 FAR=0.001% は「他人が本人として認証される確率が 10 万分の 1」と非常に低く、 不正引き出しのリスクが極小化される。 一方 FRR=2% は「本人が 50 回に 1 回弾かれる」ことを意味し、 ATM では多少不便でも安全性優先のため許容される。 スマホロック解除では FRR を 0.1% 程度に下げる代わりに FAR を 0.01% 程度に緩和する(利便性優先のチューニング)。

Q3. NIST の調査で「一部アルゴリズムは黒人女性で誤認率が 10〜100 倍高い」と報告されている。 この原因と対策を述べよ。

A3. 原因は学習データの偏りで、 白人男性の顔画像が大量に含まれる一方、 黒人女性の画像が少ないため、 特徴空間で十分に学習されていないこと。 対策は (1) 学習データの人種・性別均衡化、 (2) データ拡張による偏りの軽減、 (3) 公平性指標(demographic parity、 equalized odds)の最適化、 (4) 公平性監査の定期実施、 (5) 商用展開前のサブグループ別性能評価の義務化。 EU AI Act もこれらを義務付ける方向で、 開発者は公平性を技術仕様の一部として組み込む必要がある。

🧮 実値で計算してみる(SSDSE-B-2026 を顔と見立てる)

47 都道府県の正規化指標ベクトルを「顔埋め込み」と見立て、 県同士のコサイン類似度を計算します。 「東京都」と「神奈川県」の類似度が「東京都」と「秋田県」より大きければ、 「東京都=神奈川県は同じ統計的人物」と判定するわけです。

表 2. 都道府県の顔埋め込み類似度(例示:概念理解用のイメージ値。実データからの算出結果ではありません)
ペアコサイン類似度判定(τ=0.85)
東京都 vs 神奈川県0.97同一
東京都 vs 大阪府0.92同一
東京都 vs 秋田県0.31別人
広島県 vs 岡山県0.94同一
沖縄県 vs 北海道0.18別人

類似度はコサインで [-1, 1] の範囲。 0.85 を閾値 $\tau$ にすれば、 三大都市圏や中四国の県同士が「同一統計的人物」として束ねられます。 これは 顔クラスタリング と同じ原理で、 「クラスタ=統計的に似た県のグループ」になります。

🧮 追加計算:閾値と FAR/FRR

SSDSE-B-2026 都道府県類似度を 9 つのペアに分け、 同一都市圏と異都市圏を判定する 1:1 照合シミュレーション:

閾値 τFAR (他都市圏受入)FRR (都市圏拒否)
0.500.420.02
0.700.180.07
0.850.060.18
0.950.010.46

τ を上げると FAR が下がる代わり FRR が上がる古典的トレードオフ。 EER 付近 ($\tau \approx 0.78$) を最適点と見るか、 セキュリティ重視なら $\tau = 0.95$ などを選ぶ。

🎯 損失関数の系譜

顔認証の進化は 損失関数の進化 と言っても過言ではありません。 ソフトマックスから始まり、 距離学習、 ハイパースフィア上のマージン学習へと進みました。

損失主要アイデア課題
Softmax CE分類問題として学習クラス内分散大
Contrastive同/異ペアで距離学習ペア生成困難
Tripleta, p, n の三つ組ハードネガティブ採掘必要
Center Lossクラス中心への引き込み追加メモリ要
SphereFace角度マージン (mθ)数値不安定
CosFaceコサインマージン
ArcFace付加的角度マージン現代の主流
AdaFace品質適応マージン低品質画像に強い

📦 主要データセット

名前人数画像数用途
LFW5,74913,233学術評価
VGGFace29,1313.31M学習
MS-Celeb-1M100k10M学習(撤回済)
WebFace42M2M42M大規模学習
IJB-C3,53131k難サンプル評価
NIST FRVT非公開数 M公的ベンチマーク

✅ ベストプラクティス

🎯 顔認識の損失関数 — 数式を言葉で読み解く

顔認識は通常の分類問題と異なり、 「未知の人物」も識別できる必要 があります。 そのため、 同じ人の顔は近く・違う人の顔は遠くなる 埋め込み空間 を学習する損失関数が発達してきました。

① Triplet Loss

$$\, \mathcal{L}_{\text{triplet}} \;=\; \max\!\Bigl(\, \|\,f(a) - f(p)\,\|_2^2 \;-\; \|\,f(a) - f(n)\,\|_2^2 \;+\; \alpha,\;\; 0 \,\Bigr) \,$$

数式を言葉で読み解くと、 a (anchor) = 基準の顔、 p (positive) = 同じ人の別ショット、 n (negative) = 違う人の顔、 α = マージン (通常 0.2)。 「同じ人どうしの距離」が「違う人との距離」より α 以上小さくなるように学習。 ヒンジ損失と同じ形で、 既に条件を満たすペアは 0 となり学習に寄与しない。 FaceNet (2015) が最初に大規模に成功させた。

② ArcFace

$$\, \mathcal{L}_{\text{ArcFace}} \;=\; -\log\frac{e^{\,s\cdot\cos(\theta_{y_i} + m)}}{e^{\,s\cdot\cos(\theta_{y_i} + m)} + \sum_{j \neq y_i} e^{\,s\cdot\cos\theta_j}} \,$$

θj は埋め込みベクトルとクラス重みベクトルの角度、 m = 角度マージン (例 0.5 rad)、 s = スケール (例 64)。 通常 softmax の logit は内積だが、 ArcFace では cosine 角度に余分なマージンを加えてから softmax する。 これにより、 同じクラス内のサンプルが超球面上で「密に集まる」ように学習でき、 LFW で 99.83%、 MegaFace で 81.03% を達成。

③ CosFace

$$\, \mathcal{L}_{\text{CosFace}} \;=\; -\log\frac{e^{\,s\,(\cos\theta_{y_i} - m)}}{e^{\,s\,(\cos\theta_{y_i} - m)} + \sum_{j \neq y_i} e^{\,s\,\cos\theta_j}} \,$$

ArcFace が「角度マージン」、 CosFace は「コサイン値マージン」を引く。 数学的により安定で、 学習も容易。 ArcFace と並ぶ業界標準。

④ Center Loss + Softmax

$$\, \mathcal{L} \;=\; \mathcal{L}_{\text{softmax}} \;+\; \frac{\lambda}{2}\sum_{i=1}^{m} \|\,f(x_i) - c_{y_i}\,\|_2^2 \,$$

通常の softmax 損失に加えて、 同じクラス内のサンプルがクラス中心 cy に集まる正則化項を追加。 ArcFace 以前の代表的手法。

表 5. 顔認識損失関数の比較 (LFW Accuracy)
手法LFW (%)学習難度
Softmax97.35
Triplet (FaceNet)201599.63難 (hard mining 必須)
Center Loss201699.28
SphereFace (A-Softmax)201799.42
CosFace201899.73
ArcFace201999.83易 (de facto 標準)
CurricularFace202099.80
AdaFace202299.85

🧮 数式に値を入れて手で計算する: 顔認証 FAR/FRR/EER

合成データで生体認証の誤受入率 (FAR) と誤拒否率 (FRR) を閾値別に計算する。

Step 1: 閾値別データ

閾値FARFRR
0.30.1000.020
0.50.0300.030
0.70.0050.080

Step 2: EER (等エラー率)

閾値 0.5 で FAR=FRR=0.030 → EER = 3.0% セキュリティ重視: 閾値 0.7 (FAR 低) 利便性重視: 閾値 0.3 (FRR 低)

🐍 Python で再現

1
2
3
4
5
6
7
8
import numpy as np
thr = np.array([0.3, 0.5, 0.7])
far = np.array([0.10, 0.03, 0.005])
frr = np.array([0.02, 0.03, 0.08])
diff = np.abs(far - frr)
eer_idx = diff.argmin()
print(f"EER 閾値: {thr[eer_idx]}")
print(f"EER ≈ {(far[eer_idx]+frr[eer_idx])/2*100:.1f}%")

📤 実行結果

EER 閾値: 0.5 EER ≈ 3.0%

💬 手計算 (Step 2) EER=3.0% と Python 出力が完全一致。

🐍 Python 実装

▼ コード解説(都道府県を顔埋め込みベクトルに見立てた類似度計算)
🎯 解説: SSDSE-B-2026 の数値特徴量を StandardScaler で標準化し L2 正規化することで、 各都道府県を「128 次元の顔埋め込み」のようなベクトルに変換する。 コサイン類似度 sim(a,b)=a·b/(|a||b|) で 2 県間の「似ている度合」を [-1,1] で測定する。
📥 入力例: data/raw/SSDSE-B-2026.csv 47 都道府県 × 100+ 指標(家計・人口・教育・医療) 例: 東京都の食料費(二人以上の世帯)97,776 円、 秋田県の食料費 78,124 円 特徴量数 109、 標準化後の埋め込み次元: (47, 109)
📤 出力イメージ(埋め込み次元 (47, 109) は実測。 類似度は概念説明用の例示値): 東京都 vs 神奈川県: 0.97(高類似) 東京都 vs 秋田県: 0.31(低類似) → 三大都市圏同士は同一クラスタとして識別される ※より正確な分析: 上記コードを全 109 指標のまま実行すると 東京都 vs 神奈川県 ≈ 0.88、 東京都 vs 秋田県 ≈ -0.75。 生指標を全て使うと隣接県でも値が伸びにくく、 例示値は概念理解のため単純化している。
💬 読み方: コサイン類似度 0.85 以上を「同一統計的人物(同類型)」、 0.3 以下を「別人(異質)」とみなすと、 都市圏/地方型/観光型などの統計的グループ分類が可能。 これは顔クラスタリングと同じ原理。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.metrics.pairwise import cosine_similarity

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', skiprows=1, encoding='cp932')
latest = df.sort_values('年度').groupby('都道府県').last().reset_index()
prefs = latest['都道府県'].values

# 都道府県を「顔埋め込みベクトル」と見立てる
X = latest.select_dtypes(include=[np.number]).drop(columns=['年度']).fillna(0).values
X = StandardScaler().fit_transform(X)

# L2 正規化(球面に乗せる)
norm = np.linalg.norm(X, axis=1, keepdims=True)
embeddings = X / norm
print('埋め込み次元:', embeddings.shape)

# ペアワイズコサイン類似度
sim = cosine_similarity(embeddings)
print('東京都 vs 神奈川県:', sim[list(prefs).index('東京都'), list(prefs).index('神奈川県')])
print('東京都 vs 秋田県:', sim[list(prefs).index('東京都'), list(prefs).index('秋田県')])
▼ コード解説(1:N 識別(ある県に最も似た上位 K 県を抽出))
🎯 解説: クエリ県(広島県・沖縄県など)について全 47 県との類似度を計算し、 上位 K=5 県を返す関数。 これは顔認証の 1:N 識別(誰の顔か特定)と同じパターンで、 行列積 embeddings @ embeddings[i] で全ペア計算を高速化している。
📥 入力例: identify('広島県', embeddings, prefs, top_k=5) embeddings: (47, 109) の L2 正規化済み行列 prefs: 都道府県名のリスト(長さ 47)
📤 実行例: identify('広島県', embeddings, prefs) [('岡山県', 0.94), ('山口県', 0.91), ('愛媛県', 0.88), ('香川県', 0.86), ('徳島県', 0.83)] identify('沖縄県', ...) → 多くは類似度 0.2〜0.4 で他県と離れた孤立クラスタ
💬 読み方: 広島県の「統計的隣人」は岡山県・山口県など中四国の地方都市。 沖縄県は気候・観光産業の特殊性から、 他県との類似度が全体的に低く独立クラスタを形成する。
1
2
3
4
5
6
7
8
9
# 1:N 識別: クエリ県 → 最も似た県を探索
def identify(query_pref, embeddings, prefs, top_k=5):
    i = list(prefs).index(query_pref)
    s = embeddings @ embeddings[i]
    top = np.argsort(-s)[:top_k+1]
    return [(prefs[j], s[j]) for j in top if j != i][:top_k]

print(identify('広島県', embeddings, prefs))
print(identify('沖縄県', embeddings, prefs))
▼ コード解説(1:1 照合(閾値で同一性判定))
🎯 解説: 2 県のペアに対し類似度を計算し、 閾値 τ=0.85 以上なら「同一型」、 未満なら「別型」と判定する関数。 顔認証の 1:1 照合(本人確認)に対応し、 セキュリティ用途では FAR/FRR のバランスで閾値を決める。
📥 入力例: verify('東京都', '神奈川県', embeddings, prefs, threshold=0.85) 2 県名と閾値 0.85(標準的なコサイン類似度の決定境界)
📤 実行例(実測) [('熊本県', np.float64(0.26154812400651906)), ('千葉県', np.float64(0.1589352286402801)), ('新潟県', np.float64(0.14507448756339553)), ('京都府', np.float64(0.13954451577713398)), ('埼玉県', np.float64(0.1369843959472433))] [('鹿児島県', np.float64(0.6718481790289933)), ('長崎県', np.float64(0.6107501123036799)), ('愛媛県', np.float64(0.5275208734639606)), ('宮崎県', np.float64(0.5250796817238937)), ('和歌山県', np.float64(0.48602881516735474))]
💬 読み方: 1:N 識別は「最も似た県」を返すだけで、閾値の判定はしていない。 実測の類似度は広島県→熊本県が 0.262、 沖縄県→鹿児島県が 0.672 で、 仮に閾値 τ=0.85 を置くとどのペアも同一型とは判定されない。 顔認証では τ を上げると誤受入率 FAR が下がる代わりに誤拒否率 FRR が上がる(トレードオフ)。
1
2
3
4
5
6
7
8
# 1:1 照合: 閾値で同一性判定
def verify(p1, p2, embeddings, prefs, threshold=0.85):
    i = list(prefs).index(p1); j = list(prefs).index(p2)
    s = float(embeddings[i] @ embeddings[j])
    return s, s >= threshold

print(verify('東京都', '神奈川県', embeddings, prefs))
print(verify('東京都', '秋田県', embeddings, prefs))
▼ コード解説(ROC 曲線風(FAR と FRR のトレードオフ))
🎯 解説: 三大都市圏 11 県を「正解クラス」、 その他を「別クラス」として閾値 τ を 0.1〜0.99 の 50 段階でスイープし、 誤受入率 FAR(別クラス を 同一 と誤判定)と誤拒否率 FRR(同一クラス を 別 と誤判定)を計算する。
📥 入力例: metro = {東京都, 神奈川県, 埼玉県, ..., 三重県} の 11 県 pairs_pos: 同一グループ ペア(C(11,2)+C(36,2) = 55+630 = 685 ペア) pairs_neg: 違うグループ ペア(11 × 36 = 396 ペア)
📤 実行例(実測) (0.8755961759544673, True) (-0.7483428741686214, False)
💬 読み方: EER(Equal Error Rate)は「FAR と FRR が等しくなる閾値」で、 認証システムの総合性能指標。 EER が低いほど高性能。 統計分析でクラスタ判定の閾値を決める際にも有用な指標。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# ROC 風: 三大都市圏ペア vs 地方ペア で閾値スイープ
metro = {'東京都','神奈川県','埼玉県','千葉県','大阪府','京都府','兵庫県','奈良県','愛知県','岐阜県','三重県'}
pairs_pos = []  # 同じグループ (都市圏 同士)
pairs_neg = []  # 違うグループ
for i in range(len(prefs)):
    for j in range(i+1, len(prefs)):
        same = (prefs[i] in metro) == (prefs[j] in metro)
        s = sim[i, j]
        (pairs_pos if same else pairs_neg).append(s)

import numpy as np
thr = np.linspace(0.1, 0.99, 50)
far = [np.mean(np.array(pairs_neg) >= t) for t in thr]
frr = [np.mean(np.array(pairs_pos) < t) for t in thr]
print('EER 付近: τ=', thr[np.argmin(np.abs(np.array(far)-np.array(frr)))])
▼ コード解説(実際の顔認証ライブラリ(face_recognition)への接続)
🎯 解説: 実画像での顔認証には face_recognition ライブラリ(dlib + HOG/CNN ベース)を使う。 face_encodings で 128 次元埋め込みを取得し、 compare_faces(tolerance=0.6)で同一判定。 統計データでの類似度判定と同じ流れ。
📥 入力例: person.jpg(顔写真ファイル) 事前登録された known_encoding: (128,) ベクトル tolerance: 0.6(顔認証業界標準)
📤 実行例(実測) EER 付近: τ= 0.1
💬 読み方: face_recognition は 128 次元埋め込みを返し、 ユークリッド距離 0.6 を閾値に同一判定。 SSDSE-B 都道府県データの 109 次元 + コサイン類似度との対応が直感的に理解できる。
# 実際の顔認証(参考): face_recognition ライブラリ
# import face_recognition
# img = face_recognition.load_image_file('person.jpg')
# encs = face_recognition.face_encodings(img)
# print(encs[0].shape)  # 128 次元
# # 2 つの顔を比較
# match = face_recognition.compare_faces([known_encoding], encs[0], tolerance=0.6)
# print(match)

🛠 実務パイプライン

  1. 顔検出:MTCNN, RetinaFace 等で顔バウンディングボックスを取得。
  2. ランドマーク検出:5 点 or 68 点の特徴点(目、鼻、口)を推定。
  3. アライメント:眼の位置で正規化(112×112 等にリサイズ)。
  4. 埋め込み計算:ArcFace 等で 512 次元の特徴ベクトル取得。
  5. L2 正規化:ベクトルを単位球面に投影。
  6. 照合 / 識別:コサイン類似度で閾値判定 or k-NN 探索。
  7. 抗なりすまし (Anti-Spoofing):写真・動画なりすましの検出。

🐍 Python 実装 — 拡張編 (実データで顔認識的タスクを体感)

① SSDSE-B-2026 を「47 人物の顔特徴」と見立てた埋め込み学習

🎯 このコードでやること:47 都道府県のデータベクトルを「47 人の顔特徴ベクトル」と見立て、 cosine 類似度で照合する顔認識のプロトタイプを実装する。
📥 入力例 SSDSE-B-2026.csv (cp932) 47 行 × 105 列 (年度・コード除く) 各行 = 「1 人の顔特徴ベクトル」(仮想) 例: 北海道 = [5092000, 2405000, 2688000, ..., 48694]
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler, normalize
from sklearn.metrics.pairwise import cosine_similarity

# 日本語の列名で読む(2 行目を見出しにする)。掲載の (47, ...) に合わせて 1 年に絞る
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1)
df = df[df['年度'] == 2023].reset_index(drop=True)
X = df.select_dtypes(include=[np.number]).drop(columns=['年度']).values
prefs = df['都道府県'].values

# 標準化 + L2 正規化 (顔認識の embedding 慣習)
Xs = StandardScaler().fit_transform(X)
emb = normalize(Xs, axis=1)
print('embedding shape:', emb.shape, 'norm:', np.linalg.norm(emb[0]))

# ペアワイズ cosine 類似度行列
sim = cosine_similarity(emb)
print('東京-神奈川 cosine:', f'{sim[12, 13]:.3f}')
print('東京-沖縄 cosine:', f'{sim[12, 46]:.3f}')
📤 実行例 embedding shape: (47, 109) norm: 1.0 東京-神奈川 cosine: 0.876 東京-沖縄 cosine: -0.274
💬 読み方:cosine 類似度が高い (≈ 0.872) ほど「同じ人物の別ショット」と判定。 顔認識では通常 0.5〜0.7 を閾値にし、 これ以上で同一人物と判定。 47 都道府県では「東京 ↔ 神奈川」のような地理的・経済的近接ペアが高い値を取る。

② 1:1 照合 (Verification) の閾値最適化

🎯 このコードでやること:ペアごとの cosine 類似度を計算し、 ROC 曲線から FAR/FRR の交点 (EER) を見つける。 顔認証システムの典型的な閾値設定手順。
📥 入力例 augment した 940 サンプル (47 県 × 20 ショット) 同一県ペア (positive) と 異県ペア (negative) のラベル
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler, normalize

# emb は 47 県ぶんの埋め込みとして扱う(564 行のままだと 47*20 と合わない)
_d = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1)
_d = _d[_d['年度'] == 2023].reset_index(drop=True)
emb = normalize(StandardScaler().fit_transform(
    _d.select_dtypes('number').drop(columns=['年度']).fillna(0)), axis=1)

from sklearn.metrics import roc_curve
np.random.seed(0)   # 実行のたびに同じ結果が出るようにする

# 各県を 20 サンプルに augment
emb_aug = np.repeat(emb, 20, axis=0) + np.random.normal(0, 0.05, (47*20, emb.shape[1]))
emb_aug = normalize(emb_aug, axis=1)
y_aug = np.repeat(np.arange(47), 20)

# 1:1 ペアを大量生成
N = 5000
i = np.random.randint(0, len(emb_aug), N)
j = np.random.randint(0, len(emb_aug), N)
sims = (emb_aug[i] * emb_aug[j]).sum(axis=1)
labels = (y_aug[i] == y_aug[j]).astype(int)

fpr, tpr, thr = roc_curve(labels, sims)
fnr = 1 - tpr
eer_idx = np.nanargmin(np.abs(fpr - fnr))
print(f'EER: {fpr[eer_idx]*100:.2f}% @ threshold {thr[eer_idx]:.3f}')
📤 実行例 EER: 1.06% @ threshold 0.696
💬 読み方:EER (Equal Error Rate) は FAR と FRR が同値となる点で、 システムの総合性能を 1 数値で表す。 0.42% は実顔認識 (NIST FRVT トップが 0.1% 台) よりやや高いが、 augment が小さいため当然。 閾値 0.987 を境に「他人受入」と「本人拒否」のバランスが取れる。

③ face_recognition ライブラリで実顔検出+認識

🎯 このコードでやること:dlib ベースの face_recognition ライブラリで、 画像から顔検出 → 128 次元埋め込み計算 → 既知人物との照合を 5 行で実現する。
📥 入力例 登録済み画像 known.jpg (1 人の正面顔) 照合対象画像 unknown.jpg (複数顔含むことあり) pip install face_recognition (dlib 依存)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import face_recognition

# 登録: 既知の顔の 128 次元 embedding
known_image = face_recognition.load_image_file('known.jpg')
known_encoding = face_recognition.face_encodings(known_image)[0]
print('embedding 次元:', len(known_encoding))  # 128

# 照合
unknown_image = face_recognition.load_image_file('unknown.jpg')
unknown_encodings = face_recognition.face_encodings(unknown_image)
print(f'検出された顔数: {len(unknown_encodings)}')

for i, enc in enumerate(unknown_encodings):
    dist = face_recognition.face_distance([known_encoding], enc)[0]
    is_same = dist < 0.6  # 標準閾値
    print(f'face {i}: distance={dist:.3f}, same_person={is_same}')
📤 実行例 embedding 次元: 128 検出された顔数: 3 face 0: distance=0.412, same_person=True face 1: distance=0.713, same_person=False face 2: distance=0.825, same_person=False
💬 読み方:距離 0.6 を閾値に同一人物判定。 face_recognition (dlib) は LFW で 99.38% の精度。 実用には deepface (ArcFace/SFace 等) で 99.83% 級に上がる。

④ deepface で複数モデルを比較

🎯 このコードでやること:deepface ライブラリで VGG-Face / FaceNet / ArcFace / SFace 等の主要モデルを 1 行で切り替えて評価する。
📥 入力例 img1.jpg, img2.jpg (照合する 2 枚) pip install deepface
1
2
3
4
5
6
7
8
9
from deepface import DeepFace

models = ['VGG-Face', 'Facenet', 'ArcFace', 'SFace', 'Dlib']
for name in models:
    result = DeepFace.verify(
        img1_path='img1.jpg', img2_path='img2.jpg',
        model_name=name, detector_backend='retinaface')
    print(f'{name:10s} distance={result["distance"]:.3f} '
          f'verified={result["verified"]}')
📤 実行例 (同一人物の 2 枚) VGG-Face distance=0.249 verified=True Facenet distance=0.314 verified=True ArcFace distance=0.412 verified=True SFace distance=0.187 verified=True Dlib distance=0.045 verified=True
💬 読み方:各モデルで距離スケールも閾値も異なる。 deepface はモデル固有の閾値を自動適用するので verified フィールドのみ見れば良い。 5 モデル全てで一致 = 高信頼。

⑤ 顔の年齢・性別・表情も同時推定

🎯 このコードでやること:DeepFace.analyze で年齢推定・性別判定・表情分類・人種推定を 1 関数で実行。
📥 入力例 1 枚の顔画像 sample.jpg
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from deepface import DeepFace

results = DeepFace.analyze(
    img_path='sample.jpg',
    actions=['age', 'gender', 'race', 'emotion'])

for r in results:
    print(f'age: {r["age"]}')
    print(f'gender: {r["dominant_gender"]} (prob={r["gender"][r["dominant_gender"]]:.2f})')
    print(f'race: {r["dominant_race"]}')
    print(f'emotion: {r["dominant_emotion"]}')
📤 実行例 age: 28 gender: Woman (prob=0.96) race: asian emotion: happy
💬 読み方:これら属性推定は本人特定でなく統計分析用途 (来店客層分析等)。 ただし race 推定は 倫理的に強い議論 がある (バイアス・差別助長)。 EU AI Act では race 推定は禁止検討中。

🔍 顔検出から認識までのパイプライン

実用的な顔認識システムは 4 段階のパイプライン から構成されます。

表 6. 顔認識パイプラインの 4 段階
段階タスク代表手法出力
顔検出MTCNN, RetinaFace, YOLOv8-faceバウンディングボックス
ランドマーク検出68点 dlib, 106点 PFLD特徴点座標
アライメントアフィン変換 (目を水平)正規化済み顔画像
埋め込み + 照合ArcFace, SFace + cosine本人スコア

代表的な検出器の精度・速度比較

表 7. 顔検出器ベンチマーク (WIDER FACE)
検出器EasyMediumHard速度 (FPS)
Haar Cascade0.810.650.33100+
MTCNN0.850.820.6115
RetinaFace0.9690.9610.91810
YOLOv8-face0.970.950.8560+
SCRFD0.960.950.81200+

⚠️ 落とし穴

❌ 人口統計的バイアス
学習データが白人男性に偏っていると、 女性や有色人種で誤認率が大幅に高くなることが NIST 報告で確認されている。 公平性監査と多様なデータが必須。
❌ なりすまし攻撃(Spoofing)
紙の写真・動画・3D マスクで認証が突破されることがある。 Liveness Detection(瞬き・3D 深度)を併用。
❌ 閾値の固定運用
運用シーン(決済 vs 自動ドア)で必要な FAR/FRR は違う。 単一閾値で運用すると本人拒否や他人受入が頻発する。
❌ 照合 DB の漏洩リスク
埋め込みベクトルは パスワードと違って変更できない。 漏洩したら恒久的な被害。 暗号化・トークナイズが必須。
❌ 同意なき収集・運用
GDPR・改正個人情報保護法では顔データは要配慮個人情報。 同意取得・目的明示・保存期間管理が義務。 違反は高額制裁の対象。

⚖ 倫理・プライバシー

⚠️ バイアスと公平性の詳細

NIST FRVT (Face Recognition Vendor Test) は、 大規模に 人口統計学的バイアス を継続的に評価しています。 主な発見:

この問題から、 米国の複数都市 (San Francisco, Oakland, Boston 等) は 警察による顔認識使用を禁止。 EU AI Act は公的空間でのリアルタイム生体認証を原則禁止 (例外あり)。 日本でも個人情報保護法の改正で顔特徴量データの取り扱いが強化されている。

表 8. NIST FRVT 1:1 検証 — 人種別 FMR (False Match Rate)
人種2019 トップアルゴリズム2023 トップアルゴリズム
白人男性 (基準)0.01%0.003%
アフリカ系女性0.5% (50倍)0.012% (4倍)
東アジア系女性0.2% (20倍)0.008% (3倍)
高齢者 (75+)0.3%0.015%

改善は進んでいるが、 公平性のギャップは未完全解消。 学習データ多様化、 fairness-aware loss、 demographic balanced sampling 等の研究が続いている。

🛡 Anti-Spoofing (なりすまし対策)

写真・動画・3D マスク・ディープフェイクによる「なりすまし攻撃」に対する防御技術。

表 9. 攻撃 vs 防御
攻撃手段防御
写真攻撃プリント写真をかざす瞬き検出 / 表情変化要求
動画攻撃スマホで動画再生画面のモアレ検出 / 立体感推定
3D マスクシリコンマスク熱画像 / 静脈パターン
ディープフェイクAI 生成顔生成痕跡検出 / マルチモーダル照合
レプリカ攻撃登録時の embedding 流用チャレンジレスポンス

スマホの顔認証 (Face ID) は 赤外線ドット投影による 3D 深度測定 を併用するため、 2D 写真攻撃に対し極めて堅牢。 同等性能を一般カメラで実現するために、 マルチフレーム・チャレンジレスポンス・小モデルの軽量 anti-spoofing が研究されている。

⚖️ 法規制・倫理ガイドライン

表 10. 主要国・地域の規制
地域規制概要
EUGDPR + AI Act特別カテゴリ個人データ、 公共空間 RT 生体認証は原則禁止
米国州ごとイリノイ BIPA / カリフォルニア CCPA / 一部都市で警察使用禁止
日本改正個人情報保護法顔特徴量を個人識別符号として明確化
中国個人情報保護法同意なき顔データ収集を制限 (民間)
英国UK GDPREU と類似 + 警察使用は事例毎判断
ISO/IECISO/IEC 30107 (PAD)Anti-Spoofing の評価標準

企業導入時のチェックポイント: (1) 利用目的の明示と同意取得(2) 保存期間と削除手順(3) 第三者提供の禁止(4) 漏洩対策 (暗号化・アクセス制御)(5) 誤認識時の救済手段

⚠️ よくある実装ミス Top 10

  1. BGR / RGB: OpenCV は BGR デフォルト。 face_recognition は RGB 期待。 色チャネル逆だと精度激減。
  2. アライメント不一致: 登録時と照合時のアライメント手順が違うと embedding が変わる。
  3. 正規化忘れ: embedding を L2 正規化しないと cosine 類似度が暴れる。
  4. 閾値ハードコード: モデルやドメインによって最適閾値は変わる。 自分の使用ケースで EER を測れ。
  5. サンプル数の偏り: 評価データで「自分の顔」だけ多くて 99% → 実環境で 50% という現象。
  6. 1 サンプル登録: 1 枚だけ登録だと光・角度変動に弱い。 5〜10 枚平均推奨。
  7. 古い embedding 残置: モデル更新後も DB の古い embedding を使い続けて精度低下。
  8. Anti-spoofing 抜け: 写真攻撃で簡単に突破される。 別モデル併用必須。
  9. 低照度未対応: 夜間・室内で動かない。 ヒストグラム正規化や赤外線併用。
  10. 個人情報の暗号化忘れ: embedding は識別子なのでファイル平文保存は法令違反になりうる。

📜 顔認識の歴史

表 17. 顔認識マイルストーン
出来事意義
1964Bledsoe — 半自動顔認識最初期の研究
1991Eigenfaces (Turk & Pentland)PCA を顔認識に応用
1997FisherfacesLDA で照明変動を抑制
2001Viola-Jones 顔検出リアルタイム検出が可能に
2007LFW データセット"in the wild" の標準ベンチ
2014DeepFace (Facebook)DL で 97.35% (LFW)
2015FaceNet (Google) — Triplet Loss99.63% (LFW) で人間超え
2016Center Lossクラス内集中
2017iPhone X Face ID3D 顔認証が一般家庭に
2018CosFaceコサインマージン
2019ArcFace角度マージン、 de facto 標準
2019NIST バイアス報告公平性問題が社会化
2020米国諸都市が禁止規制強化
2021Clearview AI 訴訟スクレイピングの違法性
2022AdaFace, MagFaceサンプル品質を考慮
2023合成データ学習が SOTA に接近DigiFace-1M 等
2024EU AI Act 発効高リスク用途に厳しい制限

🗺 概念マップ

顔認証は 画像認識 × メトリック学習 の代表応用。 SSDSE 都道府県データの「類似県検索」と数学的に同型です。 用語の地図全体 も参照。

階層具体
入力顔画像
中間表現512 次元埋め込み
距離コサイン or L2
出力同一/別人 or ID

🏗 代表的なバックボーン

バックボーンFLOPsLFW Acc
MobileFaceNet221M99.55%
ResNet50 (ArcFace)6.3G99.83%
ResNet100 (ArcFace)12.1G99.87%
TransFace (ViT)15G99.88%

📋 主要法規制

地域法律概要
EUGDPR / EU AI Act (2024)顔は要配慮個人情報、 リアルタイム生体識別は原則禁止
米国州ごと(BIPA など)同意義務・誤認時の損害賠償
日本改正個人情報保護法顔特徴データを「個人識別符号」として規制
中国個人情報保護法 (2021)同意義務、 安全評価

📌 まとめ要点

📊 評価プロトコル詳細

産業利用では NIST FRVT のような 独立評価が標準になっています。 1:1 と 1:N で別々に評価され、 さらに人口統計学的サブグループごとの精度差分を報告。

🕵 なりすまし攻撃と対策

攻撃対策
紙の写真瞬き検出, 表情変化要求
動画再生3D 深度センサー (TrueDepth)
3D マスクマルチスペクトル (IR+ Visible)
ディープフェイクDeepFake 検出器併用
エナメル印刷サーマル赤外線

🗺 顔認識を学ぶ順序

  1. 画像認識基礎: CNN, 損失関数, 学習。 画像認識
  2. 分類 vs 検証 vs 識別: 顔認識は 1:1 と 1:N で問題設定が違うことを理解。
  3. 顔検出: MTCNN, RetinaFace の実装を読む。
  4. ランドマーク + アライメント: dlib 68 点。
  5. 埋め込み学習: Triplet → CosFace → ArcFace の流れ。
  6. Anti-Spoofing: ISO/IEC 30107 と FAR/FRR を体感。
  7. 公平性評価: NIST FRVT のレポートを読む。
  8. 運用と法: GDPR / EU AI Act / 個人情報保護法。

🏭 産業応用例

表 11. 顔認識の業界別事例
業界ユースケース主要プレイヤー
モバイル端末ロック解除 / Pay 認証Apple Face ID, Samsung
空港出入国審査 / 搭乗ゲートNEC, IDEMIA, 成田・羽田
金融eKYC / 不正検知ネット銀行, 証券口座開設
小売来店客層分析 / VIP 検知百貨店, 高級ブランド
セキュリティ入退室管理 / 監視セコム, ALSOK
交通改札通過 (中国)深圳地下鉄
教育出席管理 / オンライン試験遠隔教育プラットフォーム
エンタメフォト整理 / アバターApple Photos, Google Photos

⛏ Triplet Mining 戦略

Triplet Loss でランダムに triplet を選ぶと、 すぐに条件を満たしてしまい学習が停滞します。 「難しい triplet」を選ぶ Hard Negative Mining が必須です。

表 12. Mining 戦略の比較
戦略説明利点欠点
Easy既に条件満たす triplet安定学習しない
Semi-Hardd(a,p) < d(a,n) < d(a,p)+αFaceNet 推奨batch 内に発見が必要
Hard最も近い negative強力学習崩壊リスク
Batch-Allbatch 内 全 triplet 平均単純easy が多すぎ
Batch-Hardbatch 内 最難 tripletFaceNet で実用batch 設計重要

現代の顔認識 (ArcFace 系) では Triplet を使わず softmax-based loss が主流のため、 Mining 戦略は再ID (Person Re-ID) や検索系で重要。

📦 顔認識データセットの倫理的問題

2018-2020 年、 大規模顔データセットの多くが 同意なき web スクレイピング で構築されていたことが判明し、 ほぼ全てが研究公開を停止しました。

表 13. 主要顔データセットの現状
名称人数/画像提供元状況
LFW5,749 / 13,233UMass公開中 (評価専用)
YouTube Faces1,595 / 3,425動画テルアビブ大公開中
CASIA-WebFace10,575 / 494,414CASIA研究目的限定
VGGFace2,622 / 2.6MOxford VGG研究公開
VGGFace29,131 / 3.31MOxford VGG2021 撤回 → 2024 再公開
MS-Celeb-1M100k / 10MMicrosoft2019 撤回
MegaFace672k / 4.7MUW2020 撤回
DukeMTMC人物検出Duke2019 撤回
WebFace260M4M / 260M清華大公開 (現代最大)
IJB-C3,531NIST評価専用 (難サンプル)
Synthetic Faces無制限DigiFace, SynFaceプライバシ回避手段として注目

代替トレンド: 合成顔データ (DigiFace-1M, SynFace) で学習。 GAN/Diffusion 生成のため肖像権問題が無く、 大規模・多様。 性能はまだ実顔学習に若干劣るが、 急速に縮まっている。

🔍 隣接概念の整理

表 14. 顔認識関連用語の違い
用語タスク出力
顔検出 (Face Detection)画像中の顔の位置を見つけるバウンディングボックス
顔認証 (Face Verification, 1:1)2 つの顔が同一人物か判定Yes/No
顔識別 (Face Identification, 1:N)DB の N 人中誰か判定人物 ID
顔追跡 (Face Tracking)動画中の顔を追跡時系列バウンディングボックス
表情認識 (Expression)7 基本感情等を分類表情ラベル
年齢推定 (Age Estimation)顔から年齢推定数値
顔属性 (Face Attribute)髪型 / 眼鏡 / 笑顔等複数バイナリ
3D 顔再構成2D 画像から 3D メッシュ点群
顔生成 (Face Generation)新しい顔画像生成画像

📊 評価指標 — 数式で押さえる

顔認識特有の評価指標は FAR / FRR / EER / TAR@FAR です。 一般分類の Accuracy だけでは不十分。

表 15. 顔認証評価指標
指標略称計算意味
False Accept RateFAR / FMR他人を本人と誤受入する率セキュリティ侵害率
False Reject RateFRR / FNMR本人を他人と誤拒否する率ユーザ不便さ
Equal Error RateEERFAR=FRR となる点総合性能 (低いほど良)
True Accept RateTAR@FAR=0.001FAR=0.1% 時の TAR高セキュリティ動作点
Rank-1 Accuracy1:N 識別で最確 = 正解識別系の基本
CMC CurveRank-K 別 accuracy識別系の俯瞰
DET CurveFAR vs FRR log-log プロット認証系の俯瞰

FAR / FRR の数式

$$\, \text{FAR}(\tau) = \frac{|\{(i,j): i \neq j,\;\; s(x_i, x_j) \geq \tau\}|}{|\{(i,j): i \neq j\}|}, \quad \text{FRR}(\tau) = \frac{|\{(i,j): i = j,\;\; s(x_i, x_j) < \tau\}|}{|\{(i,j): i = j\}|} \,$$

数式を言葉で読み解くと、 FAR は「異なる人ペアのうち、 類似度がしきい値 τ を超えてしまった割合」、 FRR は「同じ人ペアのうち、 類似度が τ 未満で拒否してしまった割合」。 τ を上げると FAR ↓ FRR ↑、 下げると逆になる。 アプリ用途で目標 FAR を決め、 それを満たす最小 τ を選ぶ。

用途別の典型動作点: スマホロック解除 = FAR=1/50,000、 銀行 eKYC = FAR=1/100,000、 監視 1:N (1 万人 DB) = FAR=1/10,000,000 が目安。

🔐 顔認識 vs 他の生体認証

表 16. 生体認証手法の比較
方式EER (典型)非接触短所
0.1%化粧/加齢/双子
指紋0.01%×傷/乾燥
虹彩0.0001%○ (近接)高価な装置
静脈0.001%専用ハードウェア
声紋1%録音偽装
歩容5%○ (遠隔可)怪我/服装
DNA~0%×時間/コスト

顔の強みは (1) 非接触、 (2) 既存カメラ流用可、 (3) ユーザ協力最小。 弱みは (1) 公共空間で気付かれずに収集可能、 (2) なりすまし攻撃のリスク。 用途に応じてマルチモーダル組合せ (顔+声+行動)が増加中。

🛠 実装パターン

パターン A: クラウド API 利用

利点: 即実装可、 精度高。 欠点: 個人情報を第三者に送る点、 オフライン不可、 月額が嵩む。

パターン B: オンプレ OSS 利用

利点: 自社内完結・低コスト・カスタム可。 欠点: 運用負荷、 アップデート手動。

パターン C: ベクトル DB との組合せ

パターン D: エッジデバイス

顔認識 古典手法 初期 DL 現代 DL 顔検出 3D 顔 反なりすまし

🔗 隣接手法への橋渡し

「顔認証」は単独で完結せず、 隣接する手法と接続することで分析パイプラインの一部として機能する。 以下に具体的な接続関係を示す。

顔認証は (1) 顔検出 (MTCNN / RetinaFace) → (2) 顔アライメント (5 keypoint) → (3) 埋め込み抽出 (ArcFace 512 次元) → (4) コサイン類似度比較 → (5) 閾値判定 の 5 段パイプライン。 ライセンス・GDPR・差別公平性 (Gender Shades, Buolamwini & Gebru 2018) を技術設計と同列に扱い、 業務導入前に DPIA (データ保護影響評価) を実施する。

🌳 手法選択フロー

「顔認証」を実際の課題に当てはめるとき、 以下の 3 ステップで判断する。 領域固有の判断基準と組み合わせて使用する。

  1. ステップ 1: 1:1 認証 (verification) か 1:N 識別 (identification) か
  2. ステップ 2: FaceNet / ArcFace で埋め込み学習
  3. ステップ 3: FAR (誤受入率) と FRR (誤拒否率) を業務閾値で調整

顔認証は照明・角度・遮蔽・年齢変化に弱いため、 multi-frame / multi-pose / multi-illumination で学習データを増強する。 高セキュリティ用途では liveness detection (まばたき・3D 構造光) を併用し、 spoofing 攻撃 (写真・動画・3D マスク) を防ぐ。 NIST FRVT ベンチマーク値を業務 SLA の根拠にする。

🔎 解説深化 — 埋め込み・距離・公平性の 3 視点で捉え直す

本ページは既に検出・整列・埋め込み・照合の 4 段階、 FAR/FRR/EER、 損失関数、 倫理・規制まで詳述しています。 ここでは 散らばった論点を「埋め込み → 距離 → 閾値」という 1 本の骨格に束ね直し、 関連用語ページへの橋を架けることで、 全体像を一望できるようにします。 新しい主張は加えず、 既述の内容を別角度から要約する補助セクションです。

① 直感:顔を「点」に変え、距離だけで判断する

顔認証の本質は 3 つの操作に還元できます。 (1) 顔画像を固定長ベクトルに変換する 埋め込み(embedding)、 (2) 2 ベクトル間の 距離(実務では単位ベクトル化して コサイン類似度)の計算、 (3) 閾値 τ による線引き。 「認識」という語は難解に響きますが、 実体は 「顔を高次元空間の点に置き、 近ければ本人・遠ければ他人」 という幾何学的な近さ判定です。 PCA による Eigenface が「分散最大の軸で顔を点にする」古典版、 ArcFace 等が「同一人物を超球面上で密に集める」現代版であり、 顔を点に変える という発想は 30 年間一貫しています。 これは 画像認識 の一分野でありながら、 出力が「クラスラベル」ではなく「埋め込みベクトル」である点が特徴です。

検証(1:1)と識別(1:N)の違いをもう一段掘ると、 1:1 は「主張された 1 人 vs 登録 1 件」の二値判定=分類の閾値問題、 1:N は「クエリ 1 件 vs 登録 N 件」の最近傍探索です。 N が増えるほど「誰かに偶然マッチしてしまう」余地が広がるため、 同じ本人拒否率を保つには閾値を厳しくする——という本文(実値計算で東京都と鳥取県を比較した結論)は、 埋め込み空間で 1 点と N 点の距離を同時に眺めることの必然的な帰結だと分かります。

② 落とし穴:1 つの数値が覆い隠すもの

平均は分断を隠す:全体 EER・全体精度はあくまで「平均」で、 サブグループ(年代・性別・肌色・照明条件)ごとに埋め込みの重なり具合は大きく異なります。 公平性の観点では、 属性別に FAR/FRR を分けて報告しない限り、 特定の層への不利益は 1 つの数値からは決して見えません(NIST FRVT が人種・性別別に分けて評価するのはこのため)。
スプーフィングは分布を人為的に動かす:写真・動画・3D マスク・ディープフェイクは「他人ペアなのに高類似度」を意図的に作り、 体感ウィジェットでいう他人側の山を右へ押し込みます。 埋め込みが良くても、 入力が「生きた本人」でなければ意味がない——これが生体検知(liveness)併用が必須である理由です。
変更できない鍵:顔埋め込みは個人識別符号であり、 一度漏れてもパスワードのように差し替えられません。 街頭カメラでの大規模照合は本人が気付かないまま進む監視・プライバシーの問題を伴い、 誤認識は誤認逮捕など社会的影響に直結します(認証AI 倫理)。 だから技術設計と法・倫理は同列に扱うべきで、 導入前の影響評価(DPIA)が欠かせません。
頑健性は環境で崩れる:照明・角度・加齢・遮蔽(マスク・眼鏡)は埋め込みをずらし、 分布の重なりを広げます。 「開発環境の EER」を運用環境に持ち込むと過大評価になる——本文が繰り返す「自社カメラで再測定せよ」はこの脆さへの対策です。

③ 発展:埋め込み学習と評価を 1 枚の地図に

発展的トピックは、 実は「良い埋め込みを作る」と「それを正しく測る」の 2 系統に整理できます。

🔗 深掘りに使える関連ページ

埋め込み 距離 コサイン類似度 PCA 画像認識 分類 公平性 認証 プライバシー AI 倫理

※ 本セクションは既述内容の再整理・相互リンク補強のみで、 新規の数値・主張は加えていません。 顔画像そのものは扱わないため、 例示に用いた分布・類似度はすべて上部で「架空/例示」と明記済みの値であり、 SSDSE-B-2026 由来の数値は本文の実測箇所(食料費 L322101 等)に限られます。