実験日: 2026-08-24
CPU: Core i7-14700F / GPU: RTX 5070 Ti / WSL2
画像分類と聞くと、最初からCNNやVision Transformerを選びたくなるかもしれません。しかし小さな画像と限られた学習予算では、人が設計した特徴量と古典機械学習が強い場合があります。
HOGは地味な手法に見えますが、今回の条件ではCNNより高い精度になりました。
FashionMNISTの学習60,000枚・テスト10,000枚を使い、HOG特徴量+Linear SVMと、105,866パラメータのCNNを比較しました。
HOG+SVMは88.85%、3 epoch CNNは87.00%でした。古典手法が1.85ポイント上です。一方、HOG抽出とSVM fitには合計約66.2秒かかり、CNNのGPU学習は約3.59秒でした。「どちらが勝ちか」は精度だけでは決まりません。
古典手法が1.85ポイント勝った
HOG + Linear SVM
- test accuracy:88.85%
- HOG:1画像1,296次元
- 学習画像HOG抽出:13.73秒
- LinearSVC fit:50.45秒
- test HOG抽出:2.22秒
- SVM predictのみ:0.028秒
- end-to-end test処理:約2.25秒
CNN(3 epoch)
- test accuracy:87.00%
- 105,866パラメータ
- GPU学習:3.59秒
- test inference:0.142秒
10,000テスト画像の関係
- 両方正解:8,293枚
- SVMだけ正解:592枚
- CNNだけ正解:407枚
- 両方誤り:708枚
- 予測label一致率:88.29%

HOGは画像の何を特徴量にするのか
HOGはHistogram of Oriented Gradients、つまり「勾配方向のhistogram」です。画素の明るさそのものより、局所的なedgeがどの方向を向いているかを表します。
まず横・縦方向の差分からgradientを求めます。
gx = 横方向の明るさ変化
gy = 縦方向の明るさ変化
magnitude = sqrt(gx² + gy²)
angle = atan2(gy, gx)
gradientが大きい場所はedgeです。衣服の袖、胴体、靴底、bagの輪郭などが反応します。
次に画像を小さなcellへ分け、cell内のgradient方向をhistogramへ投票します。今回の設定です。
features = hog(
image,
orientations=9,
pixels_per_cell=(4, 4),
cells_per_block=(2, 2),
block_norm="L2-Hys",
)
scikit-image公式のHistogram of Oriented Gradientsでは、gradient計算、cell内の方向histogram、block正規化、feature vector化という流れが解説されています。
なぜ1,296次元になるのか
28×28画像を4×4 pixelのcellへ分けると、縦横7 cellです。
2×2 cellを1 blockにし、1 cellずつずらすので、block位置は縦横6個あります。
1 blockには次の値があります。
2 × 2 cells × 9 orientations = 36 values
全体では次の通りです。
6 × 6 blocks × 36 values = 1,296 dimensions
元画像は28×28=784画素なので、HOGは次元削減ではなく1,296次元へ増やしています。同じcellが複数blockで正規化されるため重複がありますが、局所的なcontrast変化へ強くなる利点があります。
学習60,000枚をfloat32で保持すると、HOG行列だけで約296.6 MiBです。特徴抽出は計算時間だけでなくRAMも使います。
Linear SVMは1,296次元空間に境界を引く
HOGを抽出した後、LinearSVCへ入力しました。
svm = LinearSVC(
C=1.0,
dual="auto",
max_iter=5000,
random_state=42,
)
svm.fit(hog_train, y_train)
prediction = svm.predict(hog_test)
classごとに概念的には次のscoreを計算します。
score_k(x) = w_k · x + b_k
HOG vector xとweight w_kの内積が大きいclassを選びます。境界はfeature空間でlinearです。
今回使ったのはRBF kernelのSVCではなくLinearSVCです。60,000 sampleに対して計算量を現実的にし、HOG表現がlinear boundaryでどこまで分類できるかを見ています。
CNNは特徴量そのものを学習する
CNNへは0~1へ変換した画素をそのまま入力しました。
1×28×28
→ Conv 1→16 → ReLU → MaxPool
→ Conv 16→32 → ReLU → MaxPool
→ Linear 1568→64 → ReLU
→ Linear 64→10
HOGのcell sizeや方向binは人が決めます。CNNではconvolution kernelのweightを誤差逆伝播で更新し、分類に役立つedgeやtexture、部品の組み合わせをdataから学びます。
ただし今回のCNNは小さく、3 epoch、data augmentationなしです。HOG+SVMより精度が低かったことは「CNNの上限が87%」という意味ではありません。比較しているのは、この具体的な学習budgetのbaselineです。
実験条件を揃えた部分と揃わない部分
共通条件です。
- FashionMNIST公式train 60,000 / test 10,000
- 同じlabelと画像
- test setでmodel選択をしない
- 全体精度、class別精度、confusion matrixを保存
HOG+SVM条件です。
- CPUでHOG抽出
- 1,296次元float32
- LinearSVC C=1
- feature extraction、fit、predictを別計時
CNN条件です。
- RTX 5070 Tiで学習
- batch 256、Adam、learning rate 0.001
- 3 epoch
- DataLoader workers=4、pin memory
- GPU/library warm-upを時間外に実施
- warm-upでweightを変えた後、初期modelを再生成してから本学習
CPU SVMとGPU CNNの時間は、algorithmだけでなくhardwareも違います。精度と、このPCで実際に待つ時間の両方を示す比較です。
古典手法が1.85ポイント上だった
HOG+Linear SVMは8,885/10,000正解、CNNは8,700/10,000正解でした。
FashionMNISTは背景がほぼ黒く、衣服が中央へ揃った28×28画像です。輪郭方向を固定gridで集計するHOGの仮定と相性がよいdataです。
一方、CNNは3 epochしか学習していません。小型modelでもepochを増やす、正規化する、augmentationを使う、architectureを調整する余地があります。
ここから言えるのは、「簡単な画像taskで古典baselineを省略してはいけない」ということです。HOG+SVMはdeep learning実験の妥当性を測る強いbaselineになります。
class別に見ると違いが大きい
| class | HOG+SVM | CNN | 差(SVM-CNN) |
|---|---|---|---|
| T-shirt/top | 85.3% | 89.4% | -4.1 pt |
| Trouser | 96.9% | 97.3% | -0.4 pt |
| Pullover | 83.1% | 84.5% | -1.4 pt |
| Dress | 87.7% | 84.9% | +2.8 pt |
| Coat | 84.1% | 73.5% | +10.6 pt |
| Sandal | 96.7% | 95.5% | +1.2 pt |
| Shirt | 65.8% | 58.8% | +7.0 pt |
| Sneaker | 95.5% | 97.3% | -1.8 pt |
| Bag | 98.0% | 95.5% | +2.5 pt |
| Ankle boot | 95.4% | 93.3% | +2.1 pt |
最大差はCoatの10.6ポイントです。CNNはCoat 1,000枚のうちPulloverへ122、Shirtへ110誤分類しました。HOG+SVMではPulloverへ64、Shirtへ54です。
一方、T-shirt/topではCNNが4.1ポイント上です。HOGが常に優れた特徴ではなく、classごとに得意・苦手が違います。
Shirtは両方に難しい
両modelで最低精度はShirtでした。
- HOG+SVM:65.8%
- CNN:58.8%
HOG+SVMはShirtをT-shirtへ130、Pulloverへ82、Coatへ82誤分類しました。CNNはT-shirtへ211、Pulloverへ106、Coatへ70です。
28×28のgrayscaleでは、上半身衣類の局所edgeが似ています。全体accuracyだけではこの弱点を見落とします。実用systemなら「衣類10分類で89%」ではなく、重要classごとのrecallを確認すべきです。
速度はCNNが圧倒的だった
HOG+SVMの学習側costです。
train HOG extraction 13.73 s
LinearSVC fit 50.45 s
合計 64.18 s
test側です。
test HOG extraction 2.22 s
SVM predict 0.028 s
合計 約2.25 s
SVMの内積計算だけなら速いのですが、毎回HOGを作る必要があります。特徴抽出がinferenceの約99%を占めました。
CNNは3 epoch学習3.59秒、10,000枚推論0.142秒です。このPCではCNN推論がHOG+SVM end-to-endより約15.8倍速くなりました。
ただしCNNはGPUを使用し、SVM/HOGはCPUです。GPUなしの環境、少量data、モデル説明、実装依存を含めれば選択は変わります。
誤りの集合が同じではない
両modelが同じ予測labelを出した割合は88.29%でした。
SVMだけが正解した592枚と、CNNだけが正解した407枚があります。仮に「正解する方を必ず選ぶoracle」があれば、8,293+592+407=9,292枚、92.92%まで正解できます。
もちろん実際には正解labelを知らないのでoracleは作れません。しかし2 modelが異なる情報を使っている証拠であり、次の研究テーマになります。
- decision scoreをcalibrationしてensembleする
- CNN特徴をSVMへ入力する
- HOGをCNN入力channelへ追加する
- disagreement sampleを人が調べる
- 両方が誤る708枚のannotationや画質を確認する
単純な多数決は2 modelではtieになるため、validation setで重みやmeta-classifierを学ぶ必要があります。test setで重みを調整してはいけません。
再現方法
cd /mnt/c/Users/user/Documents/Codex/2026-08-24/ko/work/ai_lab
/opt/ai-lab/venv/bin/python experiment_hog_svm_vs_cnn.py \
--data-dir /opt/ai-lab/data \
--output results/hog_svm_vs_cnn.json \
--figure ../../outputs/hog-svm-vs-cnn.png
JSONにはHOG設定、1,296次元、各処理時間、class別精度、2つのconfusion matrix、正誤集合、予測一致率を保存しています。
比較実験で確認すること
- 同じtrain/test splitを使う
- feature extraction時間をfit時間から隠さない
- inferenceも前処理込みで測る
- GPU/CPUなどhardware差を明記する
- 全体accuracyだけでなくclass別metricを見る
- deep learningのepochとtuning budgetを明記する
- baselineが勝っても失敗扱いにしない
- test setをhyperparameter調整に使わない
- disagreement sampleを次の仮説へつなげる
まとめ
FashionMNISTでは、HOG+Linear SVMが88.85%で3 epoch CNNの87.00%を上回りました。背景が単純で中央揃えの小画像では、局所edge方向という手設計biasが強いbaselineになりました。
一方、HOG抽出+SVM fitは約64.2秒、CNN GPU学習は3.59秒でした。test前処理込みでもCNNが約15.8倍高速です。また両modelの正解集合は異なり、SVMだけ正解592枚、CNNだけ407枚でした。
古典MLとdeep learningは、単純な新旧の関係ではありません。精度、前処理、計算資源、class別誤り、運用速度を同じ表へ置いて比較することが重要です。次からはこのPCの16GB VRAMでローカルLLMを4B・8B・12Bと段階的に動かし、model sizeと生成速度・memoryを測ります。
