1
1
生成AIに関する記事を書こう!
Qiita Engineer Festa20242024年7月17日まで開催中!

1.56ビットニューラルネットワークモデル。

Last updated at Posted at 2024-07-09

faa7dd4f-41e0-4c52-bc59-6b347d917c49.png

通常のニューラルネットワークモデルと1.56ビットニューラルネットワークモデルの両方を構築し、それぞれをMNISTデータセットで訓練します。エポックごとの訓練および検証ロスをプロットすることで、モデルの性能を視覚的に比較できます。
1.56ビットネットの解説

1.56ビットネットは、ニューラルネットワークの重みを-1, 0, 1の3つの値に量子化する技術です。この手法の利点は、重みの表現が非常に効率的であり、メモリ使用量の削減や計算の高速化が期待できる点です。具体的には、重みをビット表現する際に3つの状態(-1, 0, 1)を持つため、理論上の情報量はlog2(3) ≈ 1.56ビットとなります。

このアプローチは、ディープラーニングモデルの軽量化を目指すものであり、特にリソースが限られた環境(モバイルデバイスなど)で有用です。

1.56ビットネットのアイデアは、0、1、-1の値を取ることができるバイナリニューラルネットワーク(BNN)の一種です。これはモデルの計算効率を向上させる可能性がありますが、精度に対する影響を比較する必要があります。

以下のコードでは、MNISTデータセットを使用して、通常のニューラルネットワークと1.56ビットネットの精度を比較します。具体的には、各ネットワークのトレーニングとテストを行い、精度を出力します。

#####実行結果。
通常モデルの精度: 97.76%
1.56ビットモデルの精度: 97.81%

image.png

Normal Model Accuracy: 97.46%
1.56-bit Model Accuracy: 97.84%

import numpy as np
import tensorflow as tf
from tensorflow.keras.datasets import mnist
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten, BatchNormalization, Activation
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.losses import SparseCategoricalCrossentropy
from tensorflow.keras.metrics import SparseCategoricalAccuracy
import matplotlib.pyplot as plt

# MNISTデータセットの読み込みと前処理
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

# 通常のニューラルネットワークモデルを定義
def build_normal_model():
    model = Sequential([
        Flatten(input_shape=(28, 28)),
        Dense(128, activation='relu'),
        BatchNormalization(),
        Dense(64, activation='relu'),
        BatchNormalization(),
        Dense(10)
    ])
    return model

# 1.56ビットニューラルネットワークモデルを定義
def build_156bit_model():
    model = Sequential([
        Flatten(input_shape=(28, 28)),
        Dense(128),
        BatchNormalization(),
        Activation('relu'),
        Dense(64),
        BatchNormalization(),
        Activation('relu'),
        Dense(10)
    ])
    return model

# 重みを{-1, 0, 1}に量子化する関数
def quantize_weights(weights):
    return np.round(np.clip(weights, -1, 1))

# エポックごとに重みを量子化するカスタムコールバック
class QuantizeWeightsCallback(tf.keras.callbacks.Callback):
    def on_epoch_end(self, epoch, logs=None):
        for layer in self.model.layers:
            if hasattr(layer, 'kernel'):
                weights = layer.get_weights()
                weights[0] = quantize_weights(weights[0])
                layer.set_weights(weights)

# モデルのコンパイルと訓練
def train_model(model, epochs=5):
    model.compile(optimizer=Adam(),
                  loss=SparseCategoricalCrossentropy(from_logits=True),
                  metrics=[SparseCategoricalAccuracy()])
    # 1.56ビットモデルの場合、量子化コールバックを追加
    if isinstance(model, Sequential) and model.layers[-1].name == 'dense_2':
        callbacks = [QuantizeWeightsCallback()]
    else:
        callbacks = []
    history = model.fit(x_train, y_train, epochs=epochs, callbacks=callbacks, validation_data=(x_test, y_test))
    return history

# 両方のモデルを作成して訓練
normal_model = build_normal_model()
normal_history = train_model(normal_model)

bit156_model = build_156bit_model()
bit156_history = train_model(bit156_model)

# 両方のモデルを評価
normal_model_accuracy = normal_model.evaluate(x_test, y_test, verbose=0)[1]
bit156_model_accuracy = bit156_model.evaluate(x_test, y_test, verbose=0)[1]

print(f"通常モデルの精度: {normal_model_accuracy * 100:.2f}%")
print(f"1.56ビットモデルの精度: {bit156_model_accuracy * 100:.2f}%")

# 両方のモデルのロスをプロット
plt.figure(figsize=(12, 6))
plt.plot(normal_history.history['loss'], label='loss')
plt.plot(normal_history.history['val_loss'], label='val_loss')
plt.plot(bit156_history.history['loss'], label='1.56 loss')
plt.plot(bit156_history.history['val_loss'], label='1.56 val_loss')
plt.xlabel('エポック')
plt.ylabel('ロス')
plt.legend()
plt.title('Training and validation losses for the regular and 1.56-bit models')
plt.show()

コードの各部分の計算内容を詳細に解説します。
  1. ライブラリのインポート
    必要なライブラリをインポートしています。これには、NumPy、TensorFlow、Keras、Matplotlibが含まれます。これらのライブラリはデータの処理、モデルの構築、訓練、評価、そして結果のプロットに使用されます。

  2. データの読み込みと前処理
    MNISTデータセットを読み込みます。このデータセットには、手書き数字の画像とその対応するラベルが含まれています。各ピクセルの値を0から255の範囲から0から1の範囲に正規化することで、モデルの学習を効率的に行います。

  3. 通常のニューラルネットワークモデルの定義
    通常のニューラルネットワークモデルを構築します。モデルの各層は以下の通りです:

Flatten: 28x28の画像を一列の784次元ベクトルに変換。
Dense(128, activation='relu'): 128ユニットの全結合層、ReLU活性化関数を使用。
BatchNormalization: バッチ正規化を適用し、学習を安定化。
Dense(64, activation='relu'): 64ユニットの全結合層、ReLU活性化関数を使用。
BatchNormalization: バッチ正規化を適用。
Dense(10): 10ユニットの全結合層(出力層)。

  1. 1.56ビットニューラルネットワークモデルの定義
    1.56ビットニューラルネットワークモデルを構築します。このモデルは通常のモデルと似ていますが、Dense層において、明示的に活性化関数を分けて定義しています。これにより、重みを量子化する際の柔軟性が増します。

  2. 重みの量子化関数の定義
    重みを-1, 0, 1に量子化する関数です。np.clipを使って重みを-1から1の範囲に制限し、その後にnp.roundを使用して最も近い整数(-1, 0, 1)に丸めます。

  3. カスタムコールバックの定義
    エポックの終了時に各層の重みを量子化するカスタムコールバックです。これは1.56ビットモデルに適用されます。

  4. モデルのコンパイルと訓練
    モデルをコンパイルし、訓練します。コンパイル時には、Adamオプティマイザとスパースカテゴリカルクロスエントロピー損失関数を使用します。1.56ビットモデルの場合、量子化コールバックを追加します。

  5. 両方のモデルを作成して訓練
    通常のモデルと1.56ビットモデルの両方を作成し、それぞれを訓練します。

  6. モデルの評価
    訓練された両方のモデルをテストデータで評価し、その精度を表示します。

  7. ロスのプロット
    両方のモデルの訓練および検証ロスをプロットします。これにより、モデルの学習過程を視覚的に比較できます。

このコードにより、通常のニューラルネットワークと1.56ビット量子化ニューラルネットワークの性能を比較することができます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1