ImageBind と OpenVINO を使用したマルチモーダル・データのバインド#

この Jupyter ノートブックは、ローカルへのインストール後にのみ起動できます。

GitHub

周囲の世界を探索するとき、人々は、にぎやかな通りを見たり、車のエンジン音を聞いたりするなど、複数の感覚から情報を得ます。ImageBind は、さまざまな形式の情報から同時に、総合的に、直接的に学習する人間の能力にマシンを一歩近づけるアプローチを導入します。ImageBind は、明示的な監視 (生データを整理してラベル付けするプロセス) を必要とせずに、6 つのモダリティーからのデータを一度にバインドできる最初の AI モデルです。この画期的な技術は、画像とビデオ、音声、テキスト、深度、熱、慣性計測装置 (IMU) などのモダリティー間の関係を認識することで、マシンがさまざまな形式の情報をより適切に分析できるようにし、AI の進歩に貢献します。

ImageBind

ImageBind#

このチュートリアルでは、OpenVINO を使用して ImageBind モデルを変換して実行する方法について説明します。

このチュートリアルは次のステップで構成されます:

  1. 事前トレーニングされたモデルをダウンロードします。

  2. 入力データの例を準備します。

  3. モデルを OpenVINO 中間表現形式 (IR) に変換します。

  4. モデル推論を実行し、結果を分析します。

ImageBind について#

2023 年 5 月に Meta Research によってリリースされた ImageBind は、画像とビデオ、テキスト、オーディオ、熱画像、深度、加速度計や方向モニターなどのセンサーを含む IMU の 6 つのモダリティーからのデータを組み合わせる埋め込みモデルです。ImageBind を使用すると、オーディオなどの 1 つのモダリティーでデータを提供して、ビデオや画像などのさまざまなモダリティーで関連するドキュメントを見つけることができます。

ImageBind はデータのペアを使用してトレーニングされました。各ペアは、ビデオを含む画像データを別のモダリティーにマッピングし、結合されたデータを使用して埋め込みモデルをトレーニングしました。ImageBind は、トレーニングに使用した画像データを使用して、さまざまなモダリティーの特徴を学習できることを発見しました。ImageBind からの注目すべき結論は、画像を別のモダリティーとペアリングし、その結果を同じ埋め込み空間で組み合わせるだけで、マルチモーダル埋め込みモデルを作成できることです。モデルの詳細については、モデル・リポジトリー論文、Meta AI ブログ投稿をご覧ください。

すべての埋め込みモデルと同様に、ImageBind には、情報検索、ゼロショット分類、下流のタスク (画像生成など) の入力として ImageBind 表現によって作成された使用例など、多数の潜在的な使用例があります。下の画像に示されている潜在的な使用例の一部は次のとおりです:

ユースケース

ユースケース#

このチュートリアルでは、マルチモーダル・ゼロショット分類に ImageBind を使用する方法について説明します:

目次:

必要条件#

import platform 

%pip install -q "torch>=2.0.1" "torchvision>=0.15.2,<0.17.0" "torchaudio>=2.0.2" --extra-index-url https://download.pytorch.org/whl/cpu 
%pip install -q datasets regex librosa soundfile pytorchvideo ftfy "timm>=0.6.7" einops fvcore "openvino>=2024.0.0" "nncf>=2.9.0" numpy scipy --extra-index-url https://download.pytorch.org/whl/cpu 

if platform.system() != "Windows":
     %pip install -q "matplotlib>=3.4" 
else:
     %pip install -q "matplotlib>=3.4,<3.7"
from pathlib import Path 

repo_dir = Path("ImageBind") 

if not repo_dir.exists():
     !git clone https://github.com/facebookresearch/ImageBind.git 

%cd {repo_dir}

PyTorch モデルをインスタンス化#

モデルでの作業を開始するには、PyTorch モデルクラスをインスタンス化する必要があります。imagebind_model.imagebind_huge(pretrained=True) はモデルの重みをダウンロードし、ImageBind 用の PyTorch モデル・オブジェクトを作成します。現在、ダウンロード可能な ImageBind モデルは imagebind_huge のみです。詳細については、モデルカードをご覧ください。

インターネット接続速度によっては、モデルのダウンロード処理に時間がかかる場合があります。また、モデル・チェックポイントを保存するには、ディスク上に少なくとも 5 GB の空き容量が必要です。

import imagebind.data as data 
import torch 
from imagebind.models import imagebind_model 
from imagebind.models.imagebind_model import ModalityType 

# モデルのインスタンス化 
model = imagebind_model.imagebind_huge(pretrained=True) 
model.eval();
/home/ea/work/my_optimum_intel/optimum_env/lib/python3.8/site-packages/torchvision/transforms/functional_tensor.py:5: UserWarning: The torchvision.transforms.functional_tensor module is deprecated in 0.15 and will be removed in 0.17. Please don't rely on it. You probably just need to use APIs in torchvision.transforms.functional or in torchvision.transforms.v2.functional. 
  warnings.warn( 
/home/ea/work/my_optimum_intel/optimum_env/lib/python3.8/site-packages/torchvision/transforms/_functional_video.py:6: UserWarning: The 'torchvision.transforms._functional_video' module is deprecated since 0.12 and will be removed in the future. Please use the 'torchvision.transforms.functional' module instead. 
  warnings.warn( 
/home/ea/work/my_optimum_intel/optimum_env/lib/python3.8/site-packages/torchvision/transforms/_transforms_video.py:22: UserWarning: The 'torchvision.transforms._transforms_video' module is deprecated since 0.12 and will be removed in the future. Please use the 'torchvision.transforms' module instead. 
  warnings.warn(

入力データを準備#

ImageBind は 6 つの異なるモダリティーにわたるデータを処理します。それぞれに前処理の手順が必要です。data モジュールは、各モダリティーのデータの読み取りと前処理を担当します。

  • data.load_and_transform_text は、テキストラベルのリストを受け取り、トークン化します。

  • data.load_and_transform_vision_data は、入力画像へのパスを受け入れ、それを読み取り、小さい辺サイズ 224 でアスペクト比を保存するようにサイズを変更して、中央の切り取りを実行し、データを [0, 1] 浮動小数点範囲に正規化します。

  • data.load_and_transofrm_audio_data は、指定されたパスからオーディオファイルを読み取り、サンプルごとに分割し、メル・スペクトログラムを計算します。

# Prepare inputs 

text_list = ["A car", "A bird", "A dog"] 
image_paths = [ 
    ".assets/dog_image.jpg", 
    ".assets/car_image.jpg", 
    ".assets/bird_image.jpg", 
] 
audio_paths = [ 
    ".assets/dog_audio.wav", 
    ".assets/bird_audio.wav", 
    ".assets/car_audio.wav", 
] 

inputs = { 
    ModalityType.TEXT: data.load_and_transform_text(text_list, "cpu"), 
    ModalityType.VISION: data.load_and_transform_vision_data(image_paths, "cpu"), 
    ModalityType.AUDIO: data.load_and_transform_audio_data(audio_paths, "cpu"), 
}

モデルを OpenVINO 中間表現 (IR) 形式に変換#

OpenVINO は、モデル・トランスフォーメーション API を通じて PyTorch をサポートします。モデルを IR 形式に変換するには、モデル変換 Python API を使用します。ov.convert_model 関数は、デバイスにロードする準備が整った OpenVINO モデル・クラス・インスタンスを返すか、ov.save_model を使用して次回ロードするためにディスクに保存します。

ImageBind は、さまざまなモダリティーを同時に任意の組み合わせで表すデータを受け入れますが、それらの処理は互いに独立しています。データの受け渡しの柔軟性が失われないよう、各モダリティー・エンコーダーを独立したモデルとしてエクスポートします。以下のコードは、単一モダリティーの埋め込みのみを取得するためのモデルのラッパーを定義します。

class ModelExporter(torch.nn.Module): 
    def __init__(self, model, modality): 
        super().__init__() 
        self.model = model 
        self.modality = modality 

    def forward(self, data): 
        return self.model({self.modality: data})
import openvino as ov 

core = ov.Core()

推論デバイスの選択#

OpenVINO を使用して推論を実行するためにドロップダウン・リストからデバイスを選択します

import ipywidgets as widgets 

device = widgets.Dropdown( 
    options=core.available_devices + ["AUTO"], 
    value="AUTO", 
    description="Device:", 
    disabled=False, 
) 

device
Dropdown(description='Device:', index=3, options=('CPU', 'GPU.0', 'GPU.1', 'AUTO'), value='AUTO')
ov_modality_models = {} 

modalities = [ModalityType.TEXT, ModalityType.VISION, ModalityType.AUDIO] 
for modality in modalities: 
    export_dir = Path(f"image-bind-{modality}") 
    file_name = f"image-bind-{modality}" 
    export_dir.mkdir(exist_ok=True) 
    ir_path = export_dir / f"{file_name}.xml" 
    if not ir_path.exists(): 
        exportable_model = ModelExporter(model, modality) 
        model_input = inputs[modality] 
        ov_model = ov.convert_model(exportable_model, example_input=model_input) 
        ov.save_model(ov_model, ir_path) 
    else: 
        ov_model = core.read_model(ir_path) 
    ov_modality_models[modality] = core.compile_model(ov_model, device.value)

ImageBind と OpenVINO を使用したゼロショット分類#

ゼロショット分類では、データの一部が埋め込まれ、モデルに入力されて、データの内容に対応するラベルが取得されます。ImageBind では、音声、画像、その他のサポートされているモダリティーの情報を分類できます。CLIP モデルを使用してゼロショット画像分類を実行する方法についてはすでに説明しました (詳細についてはこのノートブックを確認してください)。ImageBind では、サポートされているモダリティーの任意の組み合わせを分類に使用できるため、このタスクに対する ImageBind の機能はより広範囲にわたります。

ImageBind を使用してゼロショット分類を実行するには、次の手順を実行する必要があります:

  1. 要求されたモダリティーのデータバッチを前処理します (この場合、1 つのモダリティーはデータソースとして扱われ、他のモダリティーはラベルとして扱われます)。

  2. 各モダリティーの埋め込みを計算します。

  3. 埋め込みベクトル間のドット積を求めて確率行列を取得します。

  4. ソースをラベル空間にマッピングするため最も高い確率を持つラベルを取得します。

前のステップですでにデータを前処理したので、埋め込みを取得するためにモデル推論を実行する必要があります。

embeddings = {} 
for modality in modalities: 
    embeddings[modality] = ov_modality_models[modality](inputs[modality])
[ov_modality_models[modality].output(0)]

確率行列は、ソース埋め込みとラベル埋め込みの対応を示します。これは 2D 行列であり、x 次元はラベル・モダリティー・データを表し、y 次元はソース・モダリティー・データを表します。これは埋め込みベクトル間のドット積として計算でき、softmax を使用して [0,1] の範囲に正規化できます。次に、x ラベルと y ラベルの交差部分のスコアが高くなると、それらが同じオブジェクトを表す信頼性が高くなります。

import matplotlib.pyplot as plt 
import numpy as np 
from scipy.special import softmax 

def visualize_prob_matrix(matrix, x_label, y_label): 
    fig, ax = plt.subplots() 
    ax.matshow(matrix, cmap="winter") 

    for (i, j), z in np.ndenumerate(matrix): 
        ax.text(j, i, "{:0.3f}".format(z), ha="center", va="center") 
        ax.set_xticks(range(len(x_label)), x_label) 
        ax.set_yticks(range(len(y_label)), y_label) 

image_list = [img.split("/")[-1] for img in image_paths] 
audio_list = [audio.split("/")[-1] for audio in audio_paths]

テキスト画像分類#

text_vision_scores = softmax(embeddings[ModalityType.VISION] @ embeddings[ModalityType.TEXT].T, axis=-1) 

visualize_prob_matrix(text_vision_scores, text_list, image_list)
../_images/image-bind-with-output_20_0.png

テキスト音声分類#

text_audio_scores = softmax(embeddings[ModalityType.AUDIO] @ embeddings[ModalityType.TEXT].T, axis=-1) 

visualize_prob_matrix(text_audio_scores, text_list, audio_list)
../_images/image-bind-with-output_22_0.png

画像音声の分類#

audio_vision_scores = softmax(embeddings[ModalityType.VISION] @ embeddings[ModalityType.AUDIO].T, axis=-1) 

visualize_prob_matrix(audio_vision_scores, image_list, audio_list)
../_images/image-bind-with-output_24_0.png

これらすべてを組み合わせることで、データのテキスト、画像、音声を一致させることができます。

import IPython.display as ipd 
from PIL import Image 

text_image_ids = np.argmax(text_vision_scores, axis=0) 
text_audio_ids = np.argmax(text_audio_scores, axis=0) 
print( 
    f"Predicted label: {text_list[0]} \nprobability for image - {text_vision_scores[text_image_ids[0], 0]:.3f}\nprobability for audio - {text_audio_scores[0, text_audio_ids[0]]:.3f}" 
) 
display(Image.open(image_paths[text_image_ids[0]])) 
ipd.Audio(audio_paths[text_audio_ids[0]])
Predicted label: A car 
probability for image - 1.000 
probability for audio - 1.000
../_images/image-bind-with-output_26_1.png
print( 
    f"Predicted label: {text_list[1]} \nprobability for image - {text_vision_scores[text_image_ids[1], 1]:.3f}\nprobability for audio - {text_audio_scores[1, text_audio_ids[1]]:.3f}" 
) 
display(Image.open(image_paths[text_image_ids[1]])) 
ipd.Audio(audio_paths[text_audio_ids[1]])
Predicted label: A bird 
probability for image - 0.986 
probability for audio - 1.000
../_images/image-bind-with-output_27_1.png
print( 
    f"Predicted label: {text_list[2]} \nprobability for image - {text_vision_scores[text_image_ids[2], 2]:.3f}\nprobability for audio - {text_audio_scores[2, text_audio_ids[2]]:.3f}" 
) 
display(Image.open(image_paths[text_image_ids[2]])) 
ipd.Audio(audio_paths[text_audio_ids[2]])
Predicted label: A dog 
probability for image - 0.984 
probability for audio - 1.000
../_images/image-bind-with-output_28_1.png

NNCF を使用した ImageBind モデルのトレーニング後の量子化#

このチュートリアルは、NNCF(Neural Network Compression Framework) から 8 ビットのトレーニング後の量子化を適用してモデルを高速化し、OpenVINO™ ツールキットを介して量子化されたモデルを推論する方法を示します。

最適化プロセスには次の手順が含まれます。

  1. 量子化データセット 2 を準備します。
  2. NNCF を使用して OpenVINO モデルを量子化します。
  3. 入力データの例について、変換されたモデルと量子化されたモデルの間で確率行列を比較します。
  4. 変換および量子化されたモデルのモデルサイズを比較します。
  5. 変換および量子化されたモデルのパフォーマンスを比較します。
modalities = [ModalityType.TEXT, ModalityType.VISION, ModalityType.AUDIO] 
fp_model_paths = {modality: Path(f"image-bind-{modality}") / f"image-bind-{modality}.xml" for modality in modalities} 
int8_model_paths = {modality: Path(f"image-bind-{modality}") / f"image-bind-{modality}_int8.xml" for modality in modalities}

データセットの準備#

Conceptual Captions データセットは、キャプションの注釈が付けられた約 330 万枚の画像で構成されています。データセットは、画像およびテキストモデルを量子化するために使用されます。

import imagebind.data as data 
import os 
import requests 
import tempfile 

from requests.packages.urllib3.exceptions import InsecureRequestWarning 

requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 

def check_text_data(data): 
    """ 
    Check if the given data is text-based.
    """ 
    if isinstance(data, str): 
        return True 
    if isinstance(data, list): 
        return all(isinstance(x, str) for x in data) 
    return False 

def collate_fn(examples, image_column="image_url", text_column="caption"): 
    """ 
    Collates examples into a batch for processing. 
    Preprocesses each example by loading and transforming image and text data. 
    Checks if the text data in the example is valid by calling the `check_text_data` function. 
    Downloads the image specified by the URL in the image_column of the example dictionary. 
    Constructs and returns a dictionary representing the collated batch with the following keys: 
        - "pixel_values": The pixel values of the preprocessed example. 
        - "input_ids": The transformed text data of the preprocessed example.
    """ 
    assert len(examples) == 1 
    example = examples[0] 
    if not check_text_data(example[text_column]): 
        raise ValueError("Text data is not valid") 

    url = example[image_column] 
    with tempfile.TemporaryDirectory() as tempdir: 
        f_name = os.path.join(tempdir, "image.jpg") 
        try: 
            response = requests.get(url, verify=False, timeout=20) 
            with open(f_name, "wb") as file: 
                file.write(response.content) 
            pixel_values = data.load_and_transform_vision_data([f_name], "cpu") 
        except Exception: 
            print(f"Can't load image from url: {url}") 
            return None 

text = data.load_and_transform_text([example[text_column]], "cpu") 

return {"pixel_values": pixel_values, "input_ids": text}
from datasets import load_dataset 
import itertools 
import torch 
from tqdm.notebook import tqdm 

def collect_vision_text_data(dataloader, init_steps): 
    """ 
    This function collects vision and text data from a dataloader for a specified number of initialization steps. 
    It iterates over the dataloader, fetching batches and storing the relevant vision and text data. 
    Returns a tuple containing the collected vision_data and text_data lists.
    """ 
    text_data = [] 
    vision_data = [] 
    print(f"Fetching {init_steps} for the initialization...") 
    counter = 0 
    for batch in tqdm(dataloader): 
        if counter == init_steps: 
            break 
        with torch.no_grad(): 
            if batch: 
                counter += 1 
                text_data.append(batch["input_ids"].to("cpu")) 
                vision_data.append(batch["pixel_values"].to("cpu")) 
    return vision_data, text_data 

def prepare_vision_text_dataset(opt_init_steps=50): 
    """ 
    Prepares a vision-text dataset for quantization by collecting vision and text data.
    """ 
    dataset = load_dataset("google-research-datasets/conceptual_captions", streaming=False, trust_remote_code=True) 
    train_dataset = dataset["train"].shuffle(seed=0) dataloader = torch.utils.data.DataLoader(train_dataset, collate_fn=collate_fn, batch_size=1) 
    vision_data, text_data = collect_vision_text_data(dataloader, opt_init_steps) 
    return vision_data, text_data

ESC-50 データセットは、ImageBind モデルのオーディオ・モダリティーを量子化するために使用されます。データセットは、環境音分類のベンチマーク方法に適した 2000 件の環境音声録音のラベル付きコレクションです。データセットは、50 のセマンティック・クラスに編成された 5 秒間の録音で構成されています。

import numpy as np 
import torchaudio 

def collect_audio_data(dataloader, init_steps=300): 
    """ 
    This function collects audio data from a dataloader for a specified number of initialization steps. 
    It iterates over the dataloader, fetching batches and storing them in a list.
    """ 
    audio_data = [] 
    for _, batch in tqdm(zip(range(init_steps), itertools.islice(dataloader, 0, init_steps))): 
        with torch.no_grad(): 
            audio_data.append(batch) 
    return audio_data 

def prepare_audio_dataset(): 
    """ 
    Prepares an "ashraq/esc50" audio dataset for quantization by collecting audio data. 
    Collects audio data from the dataloader by calling the `collect_audio_data` function. 
    Returns a list containing the collected calibration audio data batches.
    """ 
    audio_dataset = load_dataset("ashraq/esc50", streaming=True, trust_remote_code=True) 
    train_dataset = audio_dataset["train"].shuffle(seed=42, buffer_size=1000) 

    def collate_fn(examples): 
        assert len(examples) == 1 
        with tempfile.TemporaryDirectory() as tempdir: 
            f_name = os.path.join(tempdir, "audio.wav") 
            audio_data = examples[0]["audio"]["array"] 
            sample_rate = examples[0]["audio"]["sampling_rate"] 
            audio_data = torch.from_numpy(audio_data).to(torch.float32).unsqueeze(0) 
            torchaudio.save(f_name, audio_data, sample_rate) 
            return data.load_and_transform_audio_data([f_name], "cpu") 

dataloader = torch.utils.data.DataLoader(train_dataset, collate_fn=collate_fn, batch_size=1) 
calibration_data = collect_audio_data(dataloader) 
return calibration_data
vision_data, text_data = [], [] 

if not int8_model_paths[ModalityType.TEXT].exists() or not int8_model_paths[ModalityType.VISION].exists(): 
    vision_data, text_data = prepare_vision_text_dataset()

量子化を適用#

import logging 
import nncf 
import openvino as ov 

nncf.set_log_level(logging.ERROR) 

core = ov.Core() 

def quantize_openvino_model(modality, calibration_data): 
    model_path = fp_model_paths[modality] 
    model = core.read_model(model_path) 
    quantized_model = nncf.quantize( 
        model=model, 
        calibration_dataset=calibration_data, 
        model_type=nncf.ModelType.TRANSFORMER, 
    ) 
    ov.save_model(quantized_model, int8_model_paths[modality]) 
    return quantized_model
INFO:nncf:NNCF initialized successfully.Supported frameworks detected: torch, tensorflow, onnx, openvino

視覚モダリティー用の ImageBind モデルを量子化#

: 量子化は時間とメモリーを消費する操作です。以下の量子化コードを実行すると、時間がかかる場合があります。

if not int8_model_paths[ModalityType.VISION].exists(): 
    if len(vision_data) == 0: 
        raise RuntimeError("Calibration dataset is empty.Please check internet connection and try to download images manually from the URLs above.") 

    vision_dataset = nncf.Dataset(vision_data) 
    vision_quantized_model = quantize_openvino_model(modality=ModalityType.VISION, calibration_data=vision_dataset)

テキスト・モダリティー用の ImageBind モデルを量子化#

if not int8_model_paths[ModalityType.TEXT].exists(): 
    text_dataset = nncf.Dataset(text_data) 
    text_quantized_model = quantize_openvino_model(modality=ModalityType.TEXT, calibration_data=text_dataset)

オーディオ・モダリティー用の ImageBind モデルを量子化#

if not int8_model_paths[ModalityType.AUDIO].exists(): 
    audio_calibration_data = prepare_audio_dataset() 
    audio_dataset = nncf.Dataset(audio_calibration_data) 
    audio_quantized_model = quantize_openvino_model(modality=ModalityType.AUDIO, calibration_data=audio_dataset)

NNCF は、量子化対応トレーニングや量子化以外のアルゴリズムもサポートしています。詳細については、NNCF リポジトリーの NNCF ドキュメントを参照してください。

OpenVINO FP16 モデルと量子化モデルの結果を比較#

FP16INT8 モデルの確率行列を比較します。

# 入力を準備 

text_list = ["A car", "A bird", "A dog"] 
image_paths = [ 
    ".assets/dog_image.jpg", 
    ".assets/car_image.jpg", 
    ".assets/bird_image.jpg", 
] 
audio_paths = [ 
    ".assets/dog_audio.wav", 
    ".assets/bird_audio.wav", 
    ".assets/car_audio.wav", 
] 

inputs = { 
    ModalityType.TEXT: data.load_and_transform_text(text_list, "cpu"), 
    ModalityType.VISION: data.load_and_transform_vision_data(image_paths, "cpu"), 
    ModalityType.AUDIO: data.load_and_transform_audio_data(audio_paths, "cpu"), 
}

推論デバイスの選択#

OpenVINO を使用して推論を実行するためにドロップダウン・リストからデバイスを選択します

device
Dropdown(description='Device:', index=3, options=('CPU', 'GPU.0', 'GPU.1', 'AUTO'), value='AUTO')
embeddings = {} 
for modality in modalities: 
    ov_model = core.compile_model(fp_model_paths[modality], device.value) 
    embeddings[modality] = ov_model(inputs[modality])[0] 

quantized_embeddings = {} 
for modality in modalities: 
    model = core.compile_model(int8_model_paths[modality], device.value) 
    quantized_embeddings[modality] = model(inputs[modality])[0]
def visualize_prob_matrices(fp_matrix, int_matrix, x_label, y_label): 
    fig, ax = plt.subplots(1, 2) 
    for i, matrix in enumerate([fp_matrix, int_matrix]): 
        ax[i].matshow(matrix, cmap="winter") 

        for (k, j), z in np.ndenumerate(matrix): 
            ax[i].title.set_text("FP16 probs" if i == 0 else "INT8 probs") 
            ax[i].text(j, k, "{:0.3f}".format(z), ha="center", va="center") 
            ax[i].set_xticks(range(len(x_label)), x_label) 
            ax[i].set_yticks(range(len(y_label)), y_label) 
    fig.tight_layout() 

image_list = [img.split("/")[-1] for img in image_paths] 
audio_list = [audio.split("/")[-1] for audio in audio_paths]
fp_text_vision_scores = softmax(embeddings[ModalityType.VISION] @ embeddings[ModalityType.TEXT].T, axis=-1) 
int_text_vision_scores = softmax( 
    quantized_embeddings[ModalityType.VISION] @ quantized_embeddings[ModalityType.TEXT].T, 
    axis=-1, 
) 

visualize_prob_matrices(fp_text_vision_scores, int_text_vision_scores, text_list, image_list)
../_images/image-bind-with-output_52_0.png
fp_text_audio_scores = softmax(embeddings[ModalityType.AUDIO] @ embeddings[ModalityType.TEXT].T, axis=-1) 
int_text_audio_scores = softmax( 
    quantized_embeddings[ModalityType.AUDIO] @ quantized_embeddings[ModalityType.TEXT].T, 
    axis=-1, 
) 

visualize_prob_matrices(fp_text_audio_scores, int_text_audio_scores, text_list, image_list)
../_images/image-bind-with-output_53_0.png
fp_audio_vision_scores = softmax(embeddings[ModalityType.VISION] @ embeddings[ModalityType.AUDIO].T, axis=-1) 
int_audio_vision_scores = softmax( 
    quantized_embeddings[ModalityType.VISION] @ quantized_embeddings[ModalityType.AUDIO].T, 
    axis=-1, 
) 

visualize_prob_matrices(fp_audio_vision_scores, int_audio_vision_scores, text_list, image_list)
../_images/image-bind-with-output_54_0.png

ファイルサイズの比較#

def calculate_compression_rate(modality): 
    fp16_ir_model_size = Path(fp_model_paths[modality]).with_suffix(".bin").stat().st_size / 1024 
    quantized_model_size = Path(int8_model_paths[modality]).with_suffix(".bin").stat().st_size / 1024 
    print(f"Modality: {modality}") 
    print(f" * FP16 IR model size: {fp16_ir_model_size:.2f} KB") 
    print(f" * INT8 model size: {quantized_model_size:.2f} KB") 
    print(f" * Model compression rate: {fp16_ir_model_size / quantized_model_size:.3f}") 

for modality in modalities: 
    calculate_compression_rate(modality)
Modality: text 
* FP16 IR model size: 691481.69 KB 
* INT8 model size: 347006.66 KB 
* Model compression rate: 1.993 
Modality: vision 
* FP16 IR model size: 1235995.15 KB 
* INT8 model size: 620132.79 KB 
* Model compression rate: 1.993 
Modality: audio 
* FP16 IR model size: 168429.15 KB 
* INT8 model size: 84818.40 KB 
* Model compression rate: 1.986

FP16 IR と量子化モデルの推論時間を比較#

FP16INT8 モデルの推論パフォーマンスを測定するには、キャリブレーション・データセットの推論時間の中央値を使用します。したがって、動的量子化モデルの速度向上を見積もることができます。

: 最も正確なパフォーマンス推定を行うには、他のアプリケーションを閉じた後、ターミナル/コマンドプロンプトで benchmark_app を実行することを推奨します。

import time 

def calculate_inference_time(model_path, calibration_data): 
    model = core.compile_model(model_path) 
    output_layer = model.output(0) 
    inference_time = [] 
    for batch in calibration_data: 
        start = time.perf_counter() 
        _ = model(batch)[output_layer] 
        end = time.perf_counter() 
        delta = end - start 
        inference_time.append(delta) 
    return np.median(inference_time)

ビジョンモデル#

fp16_latency = calculate_inference_time(fp_model_paths[ModalityType.VISION], vision_data) 
int8_latency = calculate_inference_time(int8_model_paths[ModalityType.VISION], vision_data) 
print(f"Performance speed up: {fp16_latency / int8_latency:.3f}")
Performance speed up: 2.375

テキストモデル#

fp16_latency = calculate_inference_time(fp_model_paths[ModalityType.TEXT], text_data) 
int8_latency = calculate_inference_time(int8_model_paths[ModalityType.TEXT], text_data) 
print(f"Performance speed up: {fp16_latency / int8_latency:.3f}")
Performance speed up: 1.492

オーディオモデル#

fp16_latency = calculate_inference_time(fp_model_paths[ModalityType.AUDIO], audio_calibration_data) 
int8_latency = calculate_inference_time(int8_model_paths[ModalityType.AUDIO], audio_calibration_data) 
print(f"Performance speed up: {fp16_latency / int8_latency:.3f}")
Performance speed up: 5.770