<jupyter_start><jupyter_text>畳み込みニューラルネットワーク (CNN) CNN は画像認識の分野で非常によく使われています。ここでは CNNをKerasで実装して、手書き文字認識(MNIST)の問題を解いてみます。https://www.tensorflow.org/tutorials/images/cnn?hl=ja をベースにしています。<jupyter_code># Tensorflowが使うCPUの数を制限します。(VMを使う場合)
%env OMP_NUM_THREADS=1
%env TF_NUM_INTEROP_THREADS=1
%env TF_NUM_INTRAOP_THREADS=1

from tensorflow.config import threading
num_threads = 1
threading.set_inter_op_parallelism_threads(num_threads)
threading.set_intra_op_parallelism_threads(num_threads)

#ライブラリのインポート
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt<jupyter_output><empty_output><jupyter_text>MNIST データセットのインポート<jupyter_code># MNIST データセットのインポート
from tensorflow.keras.datasets import mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

train_images = train_images.reshape((60000, 28, 28, 1))
test_images = test_images.reshape((10000, 28, 28, 1))

# ピクセルの値を 0~1 の間に正規化
train_images, test_images = train_images / 255.0, test_images / 255.0<jupyter_output><empty_output><jupyter_text>`train_`は学習用データセット、`test_`はモデル評価用データセットです。`_images` は 28 x 28 ピクセルの画像データです。`_labels` はその画像の数字のラベルが入っています。  MNIST 画像の表示画像と、それに対応するラベルを見てみます。<jupyter_code>index = 0
plt.imshow(train_images[index])
plt.show()
print(f'label = {train_labels[index]}')

index = 1
plt.imshow(train_images[index])
plt.show()
print(f'label = {train_labels[index]}')

index = 2
plt.imshow(train_images[index])
plt.show()
print(f'label = {train_labels[index]}')<jupyter_output><empty_output><jupyter_text>CNN モデルの定義<jupyter_code>from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense

model = Sequential([
    Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
    MaxPooling2D((2, 2)),
    Conv2D(64, (3, 3), activation='relu'),
    MaxPooling2D((2, 2)),
    Conv2D(64, (3, 3), activation='relu'),
    Flatten(),
    Dense(64, activation='relu'),
    Dense(10, activation='softmax')
])

model.summary()<jupyter_output><empty_output><jupyter_text>トレーニングトレーニング用データは6万画像ありますが、ここでは計算時間を短くするため、6000画像だけ使ってトレーニングしてみます。<jupyter_code>model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

num_images = 6000
model.fit(
    x=train_images[:num_images],
    y=train_labels[:num_images],
    batch_size=100,
    validation_split=0.2,
    epochs=10
)<jupyter_output><empty_output><jupyter_text>性能評価性能評価用のデータセット(`test`)を使って性能評価してみましょう。`evaluate`関数を使うことで、モデルのメトリックが評価できます。<jupyter_code># モデルの性能評価
model.evaluate(
    x=test_images,
    y=test_labels,
)<jupyter_output><empty_output><jupyter_text>[]の中の1つ目が誤差関数の値、2つめがaccuracy (正答率)です。 accuracy が 95%以上と、良い精度で判別ができていると思います。間違った画像がどのようなものかも確認してみましょう。<jupyter_code>prediction = model.predict(test_images)
pred_labels = np.argmax(prediction, axis=1)
print(f'wrong image index: {np.where(test_labels != pred_labels)}')
index = 1  # 上で得られた誤った予測のindexを入れてください。 (例: 42)
plt.imshow(test_images[index])
plt.show()
print(f'label = {test_labels[index]}')
print(f'prediction = {pred_labels[index]}')<jupyter_output><empty_output><jupyter_text>CNNとMLPの比較MNIST を MLPで解くとどうなるかも調べてみましょう。<jupyter_code>from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Flatten, Reshape, Dense

# モデルの定義
model_dnn = Sequential([
    Flatten(input_shape=(28, 28, 1)),  # 画像を1次元のベクトルに変換
    Dense(128, activation='relu'),  # ノード数が128の層を追加。活性化関数はReLU。
    Dense(128, activation='relu'),  # ノード数が128の層を追加。活性化関数はReLU。
    Dense(128, activation='relu'),  # ノード数が128の層を追加。活性化関数はReLU。
    Dense(128, activation='relu'),  # ノード数が128の層を追加。活性化関数はReLU。
    Dense(128, activation='relu'),  # ノード数が128の層を追加。活性化関数はReLU。
    Dense(10, activation='softmax')
])

model_dnn.compile(optimizer='adam',
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])

model_dnn.summary()

num_images = 6000
model_dnn.fit(
    x=train_images[:num_images],
    y=train_labels[:num_images],
    batch_size=100,
    validation_split=0.2,
    epochs=10,
    verbose=0
)

# モデルの性能評価
model_dnn.evaluate(
    x=test_images,
    y=test_labels
)<jupyter_output><empty_output><jupyter_text>どのくらいの精度が出たでしょうか？ 次は、画像のピクセルのシャッフルをしてみます。<jupyter_code># 全ての画像に対して、同じルールでピクセルのシャッフルをしています。
permute = np.random.permutation(28 * 28)
train_images_shuffle = train_images.reshape([-1, 28 * 28, 1])[:, permute, :].reshape([-1, 28, 28, 1])
test_images_shuffle = test_images.reshape([-1, 28 * 28, 1])[:, permute, :].reshape([-1, 28, 28, 1])<jupyter_output><empty_output><jupyter_text>これを画像としてプロットすると、人間には理解不能なものになっていることがわかります。<jupyter_code>plt.imshow(train_images_shuffle[0])
plt.show()<jupyter_output><empty_output><jupyter_text>これをCNN, MLPで学習させると、どうなるでしょうか？<jupyter_code># CNN の学習
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense

model_cnn = Sequential([
    Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
    MaxPooling2D((2, 2)),
    Conv2D(64, (3, 3), activation='relu'),
    MaxPooling2D((2, 2)),
    Conv2D(64, (3, 3), activation='relu'),
    Flatten(),
    Dense(64, activation='relu'),
    Dense(10, activation='softmax')
])

model_cnn.compile(
    optimizer='adam',
    loss='sparse_categorical_crossentropy',
    metrics=['accuracy']
)

num_images = 6000
model_cnn.fit(
    x=train_images_shuffle[:num_images],
    y=train_labels[:num_images],
    batch_size=100,
    validation_split=0.2,
    epochs=10,
    verbose=0
)

# モデルの性能評価
model_cnn.evaluate(
    x=test_images_shuffle,
    y=test_labels
)
# DNN の学習
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Flatten, Reshape, Dense

# モデルの定義
model_dnn = Sequential([
    Flatten(input_shape=(28, 28, 1)),  # 画像を1次元のベクトルに変換
    Dense(128, activation='relu'),  # ノード数が128の層を追加。活性化関数はReLU。
    Dense(128, activation='relu'),  # ノード数が128の層を追加。活性化関数はReLU。
    Dense(128, activation='relu'),  # ノード数が128の層を追加。活性化関数はReLU。
    Dense(128, activation='relu'),  # ノード数が128の層を追加。活性化関数はReLU。
    Dense(128, activation='relu'),  # ノード数が128の層を追加。活性化関数はReLU。
    Dense(10, activation='softmax')
])
model_dnn.compile(
    optimizer='adam',
    loss='sparse_categorical_crossentropy',
    metrics=['accuracy']
)

num_images = 6000
model_dnn.fit(
    x=train_images_shuffle[:num_images],
    y=train_labels[:num_images],
    batch_size=100,
    validation_split=0.2,
    epochs=10,
    verbose=0
)

# モデルの性能評価
model_dnn.evaluate(
    x=test_images_shuffle,
    y=test_labels
)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13587039584288552, 'fraction_numerical': 0.04126547455295736, 'mean_word_length': 6.582850521436848, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 45, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '334475', 'license': 'Apache-2.0', 'n_tokens_mistral': 3384, 'n_tokens_neox': 3109, 'n_words': 356, 'path': 'advanced/CNN.ipynb', 'repo_name': 'saitoicepp/ppcc2021_DeepLearning', 'size': '6543'}