エッジAI

推論(インファレンス)

学習済みモデルで結果を予測する処理。

概要

推論(インファレンス:Inference)とは、事前にデータから学習・訓練された機械学習モデルに対して新しい入力データを与え、そのモデルが持つ知識(重みパラメータ)をもとに予測・分類・検出などの結果を算出する処理のことです。

機械学習の処理フェーズは大きく「学習(トレーニング)」と「推論(インファレンス)」の二つに分かれます。

フェーズ処理内容計算リソース場所
学習(Training)大量データからパラメータを最適化大規模GPU/TPUが必要クラウド・データセンター
推論(Inference)学習済みモデルで新データに予測軽量でOKクラウド or エッジ

組み込み・IoTシステムにおけるAI活用では、学習済みモデルを用いた推論をエッジデバイス上でリアルタイムに実行することが核心的な技術課題となります。

歴史・背景

推論という概念自体は機械学習の黎明期から存在していましたが、ディープラーニング以前の時代は線形モデルやSVM(サポートベクターマシン)が主流で、推論の計算コストは比較的小さいものでした。

2012年にAlexNetが画像認識コンテストILSVRCで圧倒的な成績を収めて以降、ディープニューラルネットワーク(DNN)が主流となり、推論に必要な計算量も急増しました。初期のDNNは推論に専用GPU上でも数十msを要し、CPUでは数秒以上かかるものも多くありました。

推論高速化の歴史的流れ:

  • 2013〜2015年:CUDNNなどのGPU最適化ライブラリが登場し、クラウド推論が実用化
  • 2017年:Googleが量子化(INT8推論)をTensorFlowに統合、CPU推論速度が大幅向上
  • 2018年:TensorRT・OpenVINOなどのエッジ向け推論最適化エンジンが登場
  • 2019年:TensorFlow Lite Microでマイコン上の推論が実現
  • 2020年代:専用NPUの普及により、スマートフォンや組み込みSoCで高速かつ省電力な推論が標準化

技術仕様

ニューラルネットワークの推論計算

ディープラーニングモデルの推論は、レイヤー(層)を順番に通過するフォワードパス(順伝播)です。各レイヤーで行われる基本演算は次のとおりです。

全結合層(Fully Connected Layer):

y = W · x + b
  • x:入力ベクトル(n次元)
  • W:重み行列(m×n)
  • b:バイアスベクトル(m次元)
  • y:出力ベクトル(m次元)

この行列積(GEMM: General Matrix Multiply)が推論の主要な計算カーネルです。

たたみ込み層(Conv2D)の擬似コード:

// 4次元テンソルのたたみ込み(簡略版)
for (int oc = 0; oc < out_channels; oc++) {
    for (int oh = 0; oh < out_height; oh++) {
        for (int ow = 0; ow < out_width; ow++) {
            float sum = bias[oc];
            for (int ic = 0; ic < in_channels; ic++) {
                for (int kh = 0; kh < kernel_h; kh++) {
                    for (int kw = 0; kw < kernel_w; kw++) {
                        int ih = oh * stride + kh;
                        int iw = ow * stride + kw;
                        sum += input[ic][ih][iw] * weight[oc][ic][kh][kw];
                    }
                }
            }
            output[oc][oh][ow] = activation(sum);  // ReLUなど
        }
    }
}

推論精度とデータ型

データ型ビット幅精度メモリ速度
FP3232bit最高基準基準
FP1616bit高い1/22x
BF1616bitFP32近似1/22x
INT88bit1/44x
INT44bit低め1/88x

マイコンやNPUでの推論では主にINT8が使われます。量子化により浮動小数点モデルを整数型に変換することで、精度をわずかに犠牲にして大幅な速度・電力効率向上を実現します。

推論レイテンシの要因

推論レイテンシ = 前処理時間 + 実推論時間 + 後処理時間

実推論時間 ≈ (総演算量[FLOPS]) / (ハードウェアの実効演算性能[FLOPS/s])
要因詳細
モデルの深さ・幅レイヤー数・チャンネル数が多いほど遅い
データ型INT8はFP32の4倍以上速い場合がある
メモリ帯域パラメータのロードがボトルネックになりやすい
キャッシュ効率L1/L2キャッシュに収まるかどうか
バッチサイズエッジでは通常バッチサイズ1

動作原理

推論パイプラインの全体像

入力データ(画像/音声/センサー値)

  ① 前処理(Pre-processing)
     - リサイズ、正規化、データ型変換
     - 例:[0,255] → [0.0, 1.0]

  ② 推論実行(Inference Execution)
     - フォワードパス(レイヤー順次計算)
     - Conv2D → BN → ReLU → Pooling → ...

  ③ 後処理(Post-processing)
     - Softmax、NMS(非最大値抑制)、閾値処理

  出力結果(クラスラベル/バウンディングボックス/スコア)

デリゲーション(委譲)の仕組み

TensorFlow Liteなどの推論ランタイムは、演算ごとに最適なハードウェアへ処理を委ねるデリゲーション機能を持ちます。

import tflite_runtime.interpreter as tflite

# NNAPIデリゲート(AndroidのNPU/DSP活用)
delegate = tflite.load_delegate('libnnapi.so')
interpreter = tflite.Interpreter(
    model_path='model.tflite',
    experimental_delegates=[delegate]
)

C言語での組み込み推論実装例(TFLite Micro)

#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/micro/micro_mutable_op_resolver.h"
#include "model_data.h"  // モデルをC配列として埋め込み

// テンソルアリーナ(RAM領域)
constexpr int kTensorArenaSize = 32 * 1024;
uint8_t tensor_arena[kTensorArenaSize];

// オペレータ登録
tflite::MicroMutableOpResolver<5> resolver;
resolver.AddConv2D();
resolver.AddDepthwiseConv2D();
resolver.AddFullyConnected();
resolver.AddSoftmax();
resolver.AddReshape();

// インタープリタ生成
tflite::MicroInterpreter interpreter(
    tflite::GetModel(g_model_data),
    resolver,
    tensor_arena,
    kTensorArenaSize
);
interpreter.AllocateTensors();

// 推論実行
TfLiteTensor* input = interpreter.input(0);
memcpy(input->data.f, input_data, sizeof(float) * input_size);
interpreter.Invoke();

// 結果取得
TfLiteTensor* output = interpreter.output(0);
float result = output->data.f[0];

用途・ユースケース

リアルタイム推論が要求される場面

用途要求レイテンシ典型的モデル
自動車の物体検出10ms以下YOLOv8n
音声ウェイクワード50ms以下DS-CNN
外観検査100ms以下MobileNetV2
振動異常検知500ms以下1D-CNN
スマートメーター数秒以内LSTM

バッチ vs リアルタイム推論

エッジデバイスでは通常、1サンプルずつ処理するオンライン推論(バッチサイズ=1)が一般的です。クラウドではバッチ処理でスループットを最大化しますが、エッジでは遅延を優先します。

実装・開発のポイント

ベンチマーク手法

推論性能を正確に測定するには以下のツールを使用します。

# TFLite Benchmarkツール
adb shell /data/local/tmp/benchmark_model \
  --graph=/data/local/tmp/model.tflite \
  --num_threads=4 \
  --use_nnapi=true \
  --num_runs=100

# 出力例
# Inference timings: Init: 5000 us, First inference: 12000 us,
# Warmup (avg): 11500 us, Inference (avg): 10800 us

メモリ最適化

組み込みシステムでは、テンソルアリーナのサイズをできるだけ小さくする必要があります。

# モデルのメモリ使用量を確認
import tflite_runtime.interpreter as tflite
interpreter = tflite.Interpreter('model.tflite')
interpreter.allocate_tensors()
print("テンソルの詳細:")
for detail in interpreter.get_tensor_details():
    shape = detail['shape']
    dtype = detail['dtype']
    size = 1
    for s in shape:
        size *= s
    print(f"  {detail['name']}: shape={shape}, dtype={dtype}, "
          f"size={size * dtype.itemsize} bytes")

精度劣化の確認

量子化や変換後に精度が落ちていないかを確認することが重要です。

# 元のFP32モデルとINT8量子化モデルの精度比較
def evaluate_model(interpreter, test_data, test_labels):
    correct = 0
    for data, label in zip(test_data, test_labels):
        interpreter.set_tensor(input_idx, data[np.newaxis])
        interpreter.invoke()
        pred = np.argmax(interpreter.get_tensor(output_idx))
        if pred == label:
            correct += 1
    return correct / len(test_data)

fp32_acc = evaluate_model(fp32_interpreter, test_data, test_labels)
int8_acc = evaluate_model(int8_interpreter, test_data, test_labels)
print(f"FP32精度: {fp32_acc:.4f}, INT8精度: {int8_acc:.4f}")
print(f"精度低下: {(fp32_acc - int8_acc) * 100:.2f}%")

他技術との比較

推論ランタイムの比較

ランタイム対応ハードウェア対象ユースケース特徴
TensorFlow LiteARM, x86, DSP, NPUモバイル〜MCUGoogleエコシステム、豊富なサポート
TFLite MicroCortex-Mマイコン数十KB動作、C++実装
ONNX RuntimeCPU, GPU, NPUクロスプラットフォーム多様なフレームワーク対応
TensorRTNVIDIA GPU高性能エッジ最高速、NVIDIA専用
OpenVINOIntel CPU/GPU/VPUIntel製品Intel最適化
ArmNNArm CPU/GPU/NPUArm製品Arm純正

推論処理はエッジAIの核心であり、推論アクセラレータ量子化TensorFlow LiteONNXなどの関連技術と組み合わせることで、最適なエッジAIシステムを構築できます。

関連用語

参考リンク