In [ ]:
#https://data-analysis-stats.jp/%E6%B7%B1%E5%B1%9E%E5%AD%A6%E7%BF%92/%E3%83%8B%E3%83%A5%E3%83%BC%E3%83%A9%E3%83%AB%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%AE%E3%83%97%E3%83%AB%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%EF%BC%88pruning%E3%83%BB%E6%9E%9D/
#上記記事のコードを実行してみる
In [1]:
! pip install -q tensorflow-model-optimization
     |████████████████████████████████| 213 kB 16.9 MB/s 
In [5]:
import tempfile
import os
import numpy as np
import pandas as pd
from datetime import datetime
import matplotlib.pyplot as plt 
import random

import tensorflow as tf
from tensorflow import keras
from keras.datasets import mnist

result = {}
In [6]:
output_dir = ('/content/drive/MyDrive/DNN_user/model')
if not os.path.exists(output_dir):
    os.makedirs(output_dir)
In [8]:
# Load MNIST dataset
mnist = keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

# 画像の表示
plt.rcParams['figure.figsize'] = (9,9) # Make the figures a bit bigger
for i in range(9):
    plt.subplot(3,3,i+1)
    num = random.randint(0, len(train_images))
    plt.imshow(train_images[num], cmap='gray', interpolation='none')
    plt.title("Class {}".format(train_labels[num]))
    plt.tight_layout()

# 正規化
train_images = train_images / 255.0
test_images = test_images / 255.0
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 0s 0us/step
11501568/11490434 [==============================] - 0s 0us/step
In [9]:
# MNIST without pruning
start_time = datetime.now()

# モデル構成
model = keras.Sequential([
keras.layers.InputLayer(input_shape=(28, 28)),
keras.layers.Reshape(target_shape=(28, 28, 1)),
keras.layers.Conv2D(filters=12, kernel_size=(3, 3), activation=tf.nn.relu),
keras.layers.MaxPooling2D(pool_size=(2, 2)),
keras.layers.Flatten(),
keras.layers.Dense(10)
])

# モデル設定
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])

model.summary()

# モデル学習
model.fit(train_images, train_labels, epochs=4, validation_split=0.1)

# 結果
result[('1. NN no pruning', 'fit_time')] = datetime.now() - start_time
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 reshape (Reshape)           (None, 28, 28, 1)         0         
                                                                 
 conv2d (Conv2D)             (None, 26, 26, 12)        120       
                                                                 
 max_pooling2d (MaxPooling2D  (None, 13, 13, 12)       0         
 )                                                               
                                                                 
 flatten (Flatten)           (None, 2028)              0         
                                                                 
 dense (Dense)               (None, 10)                20290     
                                                                 
=================================================================
Total params: 20,410
Trainable params: 20,410
Non-trainable params: 0
_________________________________________________________________
Epoch 1/4
1688/1688 [==============================] - 22s 13ms/step - loss: 0.3430 - accuracy: 0.9018 - val_loss: 0.1606 - val_accuracy: 0.9578
Epoch 2/4
1688/1688 [==============================] - 27s 16ms/step - loss: 0.1459 - accuracy: 0.9591 - val_loss: 0.0972 - val_accuracy: 0.9755
Epoch 3/4
1688/1688 [==============================] - 25s 15ms/step - loss: 0.0950 - accuracy: 0.9729 - val_loss: 0.0751 - val_accuracy: 0.9807
Epoch 4/4
1688/1688 [==============================] - 21s 12ms/step - loss: 0.0751 - accuracy: 0.9784 - val_loss: 0.0735 - val_accuracy: 0.9800
In [10]:
# モデル保存
model_path = (output_dir+'model1.h5')
tf.keras.models.save_model(model, model_path, include_optimizer=False)

# 検証
_, baseline_model_accuracy = model.evaluate(test_images, test_labels, verbose=0)
result[('1. NN no pruning', 'accuracy')] = baseline_model_accuracy
result[('1. NN no pruning', 'file_size_KB')] = int(os.path.getsize(model_path)/ 1024)

# 結果表示
result_df = pd.Series(result).unstack().reindex(columns=['accuracy', 'fit_time', 'file_size_KB'])
result_df
Out[10]:
accuracy fit_time file_size_KB
1. NN no pruning 0.975 0 days 00:02:22.829111 96
In [12]:
import tensorflow_model_optimization as tfmot

start_time = datetime.now()

prune_low_magnitude = tfmot.sparsity.keras.prune_low_magnitude

# 4 エポックでプルーニングモデルを作成
batch_size = 128
epochs = 4
validation_split = 0.1

num_images = train_images.shape[0] * (1 - validation_split)
end_step = np.ceil(num_images / batch_size).astype(np.int32) * epochs

# プルーニングの設定
pruning_params = {'pruning_schedule': tfmot.sparsity.keras.PolynomialDecay(initial_sparsity=0.50, final_sparsity=0.80, begin_step=0, end_step=end_step)}

model_for_pruning = prune_low_magnitude(model, **pruning_params)

# コンパイル
model_for_pruning.compile(optimizer='adam',
   loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
   metrics=['accuracy'])

model_for_pruning.summary()

logdir = tempfile.mkdtemp()

callbacks = [
   tfmot.sparsity.keras.UpdatePruningStep(),
   tfmot.sparsity.keras.PruningSummaries(log_dir=logdir),
   ]
# モデル学習
model_for_pruning.fit(train_images, train_labels,
   batch_size=batch_size, epochs=epochs, validation_split=validation_split,
callbacks=callbacks)

# 結果
result[('2. NN with pruning', 'fit_time')] = datetime.now() - start_time
/usr/local/lib/python3.7/dist-packages/tensorflow_model_optimization/python/core/sparsity/keras/pruning_wrapper.py:238: UserWarning: `layer.add_variable` is deprecated and will be removed in a future version. Please use `layer.add_weight` method instead.
  trainable=False)
/usr/local/lib/python3.7/dist-packages/tensorflow_model_optimization/python/core/sparsity/keras/pruning_wrapper.py:218: UserWarning: `layer.add_variable` is deprecated and will be removed in a future version. Please use `layer.add_weight` method instead.
  aggregation=tf.VariableAggregation.MEAN)
/usr/local/lib/python3.7/dist-packages/tensorflow_model_optimization/python/core/sparsity/keras/pruning_wrapper.py:225: UserWarning: `layer.add_variable` is deprecated and will be removed in a future version. Please use `layer.add_weight` method instead.
  aggregation=tf.VariableAggregation.MEAN)
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 prune_low_magnitude_reshape  (None, 28, 28, 1)        1         
  (PruneLowMagnitude)                                            
                                                                 
 prune_low_magnitude_conv2d   (None, 26, 26, 12)       230       
 (PruneLowMagnitude)                                             
                                                                 
 prune_low_magnitude_max_poo  (None, 13, 13, 12)       1         
 ling2d (PruneLowMagnitude)                                      
                                                                 
 prune_low_magnitude_flatten  (None, 2028)             1         
  (PruneLowMagnitude)                                            
                                                                 
 prune_low_magnitude_dense (  (None, 10)               40572     
 PruneLowMagnitude)                                              
                                                                 
=================================================================
Total params: 40,805
Trainable params: 20,410
Non-trainable params: 20,395
_________________________________________________________________
Epoch 1/4
422/422 [==============================] - 17s 34ms/step - loss: 0.0854 - accuracy: 0.9752 - val_loss: 0.0754 - val_accuracy: 0.9815
Epoch 2/4
422/422 [==============================] - 16s 39ms/step - loss: 0.0725 - accuracy: 0.9793 - val_loss: 0.0742 - val_accuracy: 0.9828
Epoch 3/4
422/422 [==============================] - 14s 33ms/step - loss: 0.0742 - accuracy: 0.9787 - val_loss: 0.0815 - val_accuracy: 0.9785
Epoch 4/4
422/422 [==============================] - 14s 33ms/step - loss: 0.0780 - accuracy: 0.9769 - val_loss: 0.0802 - val_accuracy: 0.9790
In [13]:
# モデル保存
model_path = ('temp/model2.h5')
tf.keras.models.save_model(model_for_pruning, model_path, include_optimizer=False)

# 検証
_, model_for_pruning_accuracy = model_for_pruning.evaluate(test_images, test_labels, verbose=0)
result[('2. NN with pruning', 'accuracy')] = model_for_pruning_accuracy
result[('2. NN with pruning', 'file_size_KB')] = int(os.path.getsize(model_path)/ 1024)

# 結果表示
result_df = pd.Series(result).unstack().reindex(columns=['accuracy', 'fit_time', 'file_size_KB'])
result_df
Out[13]:
accuracy fit_time file_size_KB
1. NN no pruning 0.975 0 days 00:02:22.829111 96
2. NN with pruning 0.9753 0 days 00:01:01.850907 188