推論の実行

特殊なハードウェアを備えたモバイルおよびエッジデバイスでモデルを実行することは、参照環境での実行とは異なる場合があります。たとえば、PyTorch 実装がfloat32精度で推論を実行する一方で、ターゲットハードウェアはfloat16またはint8を使用して計算を行う場合があります。これにより、数値の不一致やアンダーフローおよびオーバーフローの可能性が生じることがあります。これが結果に悪影響を与えるかどうかは、モデルとデータの分布に依存します。

推論ジョブは、入力データをアップロードし、実際のハードウェアで推論を実行し、出力結果をダウンロードする方法を提供します。これらの結果を参照実装と直接比較することで、最適化済みモデルが期待通りに動作するかどうかを判断できます。推論は最適化済みモデルにのみ対応しています。PyTorch や ONNX などのソース形式のモデルは、submit_compile_job() または類似の方法でコンパイルする必要があります。

推論ジョブでは、--qairt_version オプションを使用して特定の Qualcomm® AI Runtime バージョンを指定できます。指定しない場合は、バージョン選択 に従ってバージョンが選択されます。

TensorFlow Lite モデルでの推論の実行

この例では、TensorFlow Lite モデル SqueezeNet10.tflite を使用して推論を実行します。

import numpy as np

import qai_hub as hub

sample = np.random.random((1, 224, 224, 3)).astype(np.float32)


inference_job = hub.submit_inference_job(
    model="SqueezeNet10.tflite",
    device=hub.Device("Samsung Galaxy S23 (Family)"),
    inputs=dict(x=[sample]),
)

assert isinstance(inference_job, hub.InferenceJob)
inference_job.download_output_data()
  • 推論の入力はディクショナリでなければならず、キーは特徴の名前、値はテンソルです。テンソルはnumpy配列のリスト、または単一のデータポイントの場合は単一のnumpy配列であることができます。

  • inference_jobInferenceJob のインスタンスです。

複数の推論ジョブは、submit_inference_job() APIに Device オブジェクトのリストを提供することで同時に開始できます。

QNNモデルライブラリ、DLC、およびコンテキストバイナリを使用した推論の実行

この例では、TorchScript モデル (mobilenet_v2.pt) をQNNモデルライブラリ、QNN DLC、またはQNNコンテキストバイナリ形式にコンパイルします。その後、コンパイルされたターゲットモデルでデバイス上で推論を実行します。

import numpy as np

import qai_hub as hub

sample = np.random.random((1, 3, 224, 224)).astype(np.float32)

compile_job = hub.submit_compile_job(
    model="mobilenet_v2.pt",
    device=hub.Device("Samsung Galaxy S23 (Family)"),
    options="--target_runtime qnn_lib_aarch64_android",
    input_specs=dict(image=(1, 3, 224, 224)),
)
assert isinstance(compile_job, hub.CompileJob)

inference_job = hub.submit_inference_job(
    model=compile_job.get_target_model(),
    device=hub.Device("Samsung Galaxy S23 (Family)"),
    inputs=dict(image=[sample]),
)
assert isinstance(inference_job, hub.InferenceJob)
import numpy as np

import qai_hub as hub

sample = np.random.random((1, 3, 224, 224)).astype(np.float32)

compile_job = hub.submit_compile_job(
    model="mobilenet_v2.pt",
    device=hub.Device("Samsung Galaxy S23 (Family)"),
    options="--target_runtime qnn_dlc",
    input_specs=dict(image=(1, 3, 224, 224)),
)
assert isinstance(compile_job, hub.CompileJob)

inference_job = hub.submit_inference_job(
    model=compile_job.get_target_model(),
    device=hub.Device("Samsung Galaxy S23 (Family)"),
    inputs=dict(image=[sample]),
)
assert isinstance(inference_job, hub.InferenceJob)
import numpy as np

import qai_hub as hub

input_shape = (1, 3, 224, 224)
sample = np.random.random(input_shape).astype(np.float32)

compile_job = hub.submit_compile_job(
    model="mobilenet_v2.pt",
    device=hub.Device("Samsung Galaxy S24 (Family)"),
    options="--target_runtime qnn_context_binary",
    input_specs=dict(image=input_shape),
)
assert isinstance(compile_job, hub.CompileJob)

inference_job = hub.submit_inference_job(
    model=compile_job.get_target_model(),
    device=hub.Device("Samsung Galaxy S24 (Family)"),
    inputs=dict(image=[sample]),
)
assert isinstance(inference_job, hub.InferenceJob)

推論ジョブを使用してオンデバイスでモデルの精度を検証する

この例では、オンデバイスでQNNモデルライブラリモデルの数値を検証する方法を示します。

プロファイリングの例 the profiling example (mobilenet_v2.pt) からモデルを再利用します。

import torch

import qai_hub as hub

device_s23 = hub.Device(name="Samsung Galaxy S23 (Family)")
compile_job = hub.submit_compile_job(
    model="mobilenet_v2.pt",
    device=device_s23,
    input_specs={"x": (1, 3, 224, 224)},
    options="--target_runtime qnn_lib_aarch64_android",
)

assert isinstance(compile_job, hub.CompileJob)
on_device_model = compile_job.get_target_model()

この最適化された .so モデルを使用し、特定のデバイスで入力データを使用して推論を実行できます。この例で使用される入力画像は input_image1.jpg からダウンロードできます。

https://qaihub-public-assets.s3.us-west-2.amazonaws.com/apidoc/input_image1.jpg
import numpy as np
from PIL import Image

# Convert the image to numpy array of shape [1, 3, 224, 224]
image = Image.open("input_image1.jpg").resize((224, 224))
img_array = np.array(image, dtype=np.float32)

# Ensure correct layout (NCHW) and re-scale
input_array = np.expand_dims(np.transpose(img_array / 255.0, (2, 0, 1)), axis=0)

# Run inference using the on-device model on the input image
inference_job = hub.submit_inference_job(
    model=on_device_model,
    device=device_s23,
    inputs=dict(x=[input_array]),
)
assert isinstance(inference_job, hub.InferenceJob)

このオンデバイスのraw出力を使用してクラス予測を生成し、参照実装と比較できます。これにはimagenetクラスが必要です - imagenet_classes.txt

# Get the on-device output
on_device_output: dict[str, list[np.ndarray]] = inference_job.download_output_data()  # type: ignore

# Load the torch model and perform inference
torch_model = torch.jit.load("mobilenet_v2.pt")
torch_model.eval()

# Calculate probabilities for torch model
torch_input = torch.from_numpy(input_array)
torch_output = torch_model(torch_input)
torch_probabilities = torch.nn.functional.softmax(torch_output[0], dim=0)

# Calculate probabilities for the on-device output
output_name = list(on_device_output.keys())[0]
out = on_device_output[output_name][0]
on_device_probabilities = np.exp(out) / np.sum(np.exp(out), axis=1)

# Read the class labels for imagenet
with open("imagenet_classes.txt") as f:
    categories = [s.strip() for s in f.readlines()]

# Print top five predictions for the on-device model
print("Top-5 On-Device predictions:")
top5_classes = np.argsort(on_device_probabilities[0], axis=0)[-5:]
for c in reversed(top5_classes):
    print(f"{c} {categories[c]:20s} {on_device_probabilities[0][c]:>6.1%}")

# Print top five prediction for torch model
print("Top-5 PyTorch predictions:")
top5_prob, top5_catid = torch.topk(torch_probabilities, 5)
for i in range(top5_prob.size(0)):
    print(
        f"{top5_catid[i]:4d} {categories[top5_catid[i]]:20s} {top5_prob[i].item():>6.1%}"
    )

上記のコードは次のような結果を生成します:

Top-5 On-Device predictions:
968 cup                   71.3%
504 coffee mug            16.4%
967 espresso               7.8%
809 soup bowl              1.3%
659 mixing bowl            1.2%

Top-5 PyTorch predictions:
968 cup                   71.4%
504 coffee mug            16.1%
967 espresso               8.0%
809 soup bowl              1.4%
659 mixing bowl            1.2%

オンデバイスの結果はリファレンス実装とほぼ同等です。これは、モデルが正確性の低下を経験していないことを示しており、デプロイ後に期待通りに動作することを確認できます。

この信頼を強化するために、これを複数の画像に拡張し、KLダイバージェンスの測定や精度の比較(ラベルが既知の場合)などの定量的な要約を使用することを検討してください。これにより、ターゲットデバイス全体での検証が容易になります。

事前にアップロードされたデータセットとモデルを使用して推論を実行する

モデルと同様に、AI Hubは再利用可能なデータをアップロードするためのAPIを公開しています。

import numpy as np

import qai_hub as hub

data = dict(
    x=[
        np.random.random((1, 224, 224, 3)).astype(np.float32),
        np.random.random((1, 224, 224, 3)).astype(np.float32),
    ]
)
hub_dataset = hub.upload_dataset(data)

アップロードされたデータセットを使用して推論ジョブを実行できます。この例では SqueezeNet10.tflite を使用します。

# Submit job
job = hub.submit_inference_job(
    model="SqueezeNet10.tflite",
    device=hub.Device("Samsung Galaxy S23 (Family)"),
    inputs=hub_dataset,
)