Google Colab 上で実行する

In [1]:
%tensorflow_version 2.x
import tensorflow as tf
print(tf.__version__)
2.5.0
In [2]:
# 次のパッケージはデフォルトで使えることを確認する
!pip install matplotlib scikit-learn pandas
# 次のパッケージはインストールが必要である 
!pip install janome
Requirement already satisfied: matplotlib in /usr/local/lib/python3.7/dist-packages (3.2.2)
Requirement already satisfied: scikit-learn in /usr/local/lib/python3.7/dist-packages (0.22.2.post1)
Requirement already satisfied: pandas in /usr/local/lib/python3.7/dist-packages (1.1.5)
Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.7/dist-packages (from matplotlib) (1.3.1)
Requirement already satisfied: numpy>=1.11 in /usr/local/lib/python3.7/dist-packages (from matplotlib) (1.19.5)
Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.7/dist-packages (from matplotlib) (0.10.0)
Requirement already satisfied: python-dateutil>=2.1 in /usr/local/lib/python3.7/dist-packages (from matplotlib) (2.8.1)
Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.7/dist-packages (from matplotlib) (2.4.7)
Requirement already satisfied: scipy>=0.17.0 in /usr/local/lib/python3.7/dist-packages (from scikit-learn) (1.4.1)
Requirement already satisfied: joblib>=0.11 in /usr/local/lib/python3.7/dist-packages (from scikit-learn) (1.0.1)
Requirement already satisfied: pytz>=2017.2 in /usr/local/lib/python3.7/dist-packages (from pandas) (2018.9)
Requirement already satisfied: six in /usr/local/lib/python3.7/dist-packages (from cycler>=0.10->matplotlib) (1.15.0)
Collecting janome
  Downloading https://files.pythonhosted.org/packages/a8/63/98858cbead27df7536c7e300c169da0999e9704d02220dc6700b804eeff0/Janome-0.4.1-py2.py3-none-any.whl (19.7MB)
     |████████████████████████████████| 19.7MB 1.2MB/s 
Installing collected packages: janome
Successfully installed janome-0.4.1
In [3]:
# directory構造を可視化するtreeツールをインストールする。
!sudo apt install tree
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following package was automatically installed and is no longer required:
  libnvidia-common-460
Use 'sudo apt autoremove' to remove it.
The following NEW packages will be installed:
  tree
0 upgraded, 1 newly installed, 0 to remove and 34 not upgraded.
Need to get 40.7 kB of archives.
After this operation, 105 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu bionic/universe amd64 tree amd64 1.7.0-5 [40.7 kB]
Fetched 40.7 kB in 0s (1,027 kB/s)
debconf: unable to initialize frontend: Dialog
debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 76, <> line 1.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (This frontend requires a controlling tty.)
debconf: falling back to frontend: Teletype
dpkg-preconfigure: unable to re-open stdin: 
Selecting previously unselected package tree.
(Reading database ... 160706 files and directories currently installed.)
Preparing to unpack .../tree_1.7.0-5_amd64.deb ...
Unpacking tree (1.7.0-5) ...
Setting up tree (1.7.0-5) ...
Processing triggers for man-db (2.8.3-2ubuntu0.1) ...
In [4]:
# Google Drive をマウントする
from google.colab import drive
drive.mount('/content/drive')
Mounted at /content/drive
In [5]:
!ls /content/drive
MyDrive  Shareddrives

5.1 tf.keras.layers.Conv2DによるCNNの実装

In [6]:
# 5-01-1 Fashion-MNIST データの読み込みと前処理
# p.252
# [自分へのメモ]前処理したデータは、変数に上書きせずに、別の変数に保存する

import tensorflow as tf
from tensorflow  import keras

(x_train, t_train), (x_test, t_test) = tf.keras.datasets.fashion_mnist.load_data()

x_train_norm = x_train.astype('float32') / 255.
x_test_norm = x_test.astype('float32') / 255.

x_train_rs = x_train_norm.reshape(-1, 28, 28, 1)
x_test_rs = x_test_norm.reshape(-1, 28, 28, 1)
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
32768/29515 [=================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26427392/26421880 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
8192/5148 [===============================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4423680/4422102 [==============================] - 0s 0us/step
In [7]:
# 5-01-2 CNN モデルを生成するクラス
# p.259

class CNN(tf.keras.Model):
    
    def __init__(self, output_dim):
        super().__init__()
        weight_decay = 1e-4
        self.c1 = tf.keras.layers.Conv2D(
            filters=64,
            kernel_size=(3,3),
            padding='same',
            input_shape=x_train[0].shape,
            kernel_regularizer=tf.keras.regularizers.l2(weight_decay),
            activation='relu'
        )
        self.c2 = tf.keras.layers.Conv2D(
            filters=32,
            kernel_size=(3,3),
            padding='same',
            kernel_regularizer=tf.keras.regularizers.l2(weight_decay),
            activation='relu'
        )
        self.p1 = tf.keras.layers.MaxPooling2D(
            pool_size=(2,2)
        )
        self.c3 = tf.keras.layers.Conv2D(
            filters=16,
            kernel_size=(3,3),
            padding='same',
            kernel_regularizer=tf.keras.regularizers.l2(weight_decay),
            activation='relu'
        )
        self.p2 = tf.keras.layers.MaxPooling2D(
            pool_size=(2,2)
        )
        self.d1 = tf.keras.layers.Dropout(0.4)
        self.f1 = tf.keras.layers.Flatten()
        self.l1 = tf.keras.layers.Dense(
            128,
            activation='relu'
        )
        self.l2 = tf.keras.layers.Dense(
            output_dim,
            activation='softmax'
        )
        self.ls = [ self.c1, self.c2, self.p1, self.c3, self.p2, self.d1, self.f1, self.l1, self.l2 ]
        
    def call(self, x):
        for layer in self.ls:
            x = layer(x)
        return x
In [8]:
# 5-01-3 損失関数の定義
# p.263

cce = keras.losses.SparseCategoricalCrossentropy()

def loss(t, y):
    return cce(t,y)
In [9]:
# 5-01-4 Stochastic Gradient Descend を使用するオプティマイザー
# p.263

optimizer = keras.optimizers.SGD(learning_rate=0.1)

# 損失を記録するオブジェクト
train_loss = keras.metrics.Mean()

# 精度を記録するオブジェクト
train_acc = keras.metrics.SparseCategoricalAccuracy()

# validationの損失を記録するオブジェクト
val_loss = keras.metrics.Mean()

# validationの精度を記録する
val_acc = keras.metrics.SparseCategoricalAccuracy()
In [10]:
import tensorflow as tf
# p.264
def train_step(x, t):
    '''
    学習を1回行う
    
    Parameters:
      x (ndarray(float32)): 訓練データ
      t (ndarray(float32)): 正解ラベル
      
    Returns:
      ステップごとのクロスエントロピー誤差
      
      '''
    
    with tf.GradientTape() as tape:
        outputs = model(x)
        tmp_loss = loss(t, outputs)
    grads = tape.gradient(tmp_loss, model.trainable_variables)
    optimizer.apply_gradients(zip(grads, model.trainable_variables))
    # 損失と精度を記録
    train_loss(tmp_loss)
    train_acc(t, outputs)
In [11]:
# 5-01-5 検証データによる評価を行う
# p.265
def val_step(x, t):
    preds = model(x)
    tmp_loss = loss(t, preds)
    val_loss(tmp_loss)
    val_acc(t, preds)
In [12]:
# 5-01-6 訓練データを検証データを用意する
# p.266
from sklearn.model_selection import train_test_split

x_tr, x_val, t_tr, t_val = train_test_split(x_train_rs, t_train, test_size=0.2)
In [13]:
print(x_tr.shape)
print(x_val.shape)
print(t_tr.shape)
print(t_val.shape)
(48000, 28, 28, 1)
(12000, 28, 28, 1)
(48000,)
(12000,)
In [14]:
# 5-01-7 モデルを生成して学習する
# p.266
from sklearn.utils import shuffle

epochs = 100
batch_size = 64
steps = x_tr.shape[0] // batch_size
steps_val = x_val.shape[0] // batch_size

model = CNN(10)
In [15]:
# 学習を行う
# p.267
# [自分へのメモ] バグだと思われる部分を変更している。

for epoch in range(epochs):
    x_, t_ = shuffle(x_tr, t_tr, random_state=1)
    
    for step in range(steps):
        start = step * batch_size
        end = start + batch_size
        train_step(x_[start:end], t_[start:end])
        
    for step_val in range(steps_val):
        start = step_val * batch_size
        end = start + batch_size
        #val_step(x_[start:end], t_[start:end])   ### !!! Bug
        val_step(x_val[start:end], t_val[start:end])
        
    print(f'epoch: {(epoch+1)} '
          f'train_loss: {train_loss.result():.4f} '
          f'train_acc:{train_acc.result():.4f} '
          f'val_loss: {val_loss.result():.4f} '
          f'val_acc: {val_acc.result():.4f}')
epoch: 1 train_loss: 0.6417 train_acc:0.7622 val_loss: 0.3914 val_acc: 0.8580
epoch: 2 train_loss: 0.5082 train_acc:0.8126 val_loss: 0.3666 val_acc: 0.8666
epoch: 3 train_loss: 0.4444 train_acc:0.8364 val_loss: 0.3495 val_acc: 0.8721
epoch: 4 train_loss: 0.4035 train_acc:0.8516 val_loss: 0.3364 val_acc: 0.8768
epoch: 5 train_loss: 0.3737 train_acc:0.8624 val_loss: 0.3263 val_acc: 0.8804
epoch: 6 train_loss: 0.3504 train_acc:0.8709 val_loss: 0.3176 val_acc: 0.8837
epoch: 7 train_loss: 0.3313 train_acc:0.8778 val_loss: 0.3111 val_acc: 0.8859
epoch: 8 train_loss: 0.3151 train_acc:0.8837 val_loss: 0.3063 val_acc: 0.8878
epoch: 9 train_loss: 0.3009 train_acc:0.8890 val_loss: 0.3026 val_acc: 0.8892
epoch: 10 train_loss: 0.2882 train_acc:0.8938 val_loss: 0.3003 val_acc: 0.8903
epoch: 11 train_loss: 0.2766 train_acc:0.8981 val_loss: 0.2988 val_acc: 0.8913
epoch: 12 train_loss: 0.2660 train_acc:0.9020 val_loss: 0.2990 val_acc: 0.8921
epoch: 13 train_loss: 0.2561 train_acc:0.9058 val_loss: 0.2998 val_acc: 0.8927
epoch: 14 train_loss: 0.2468 train_acc:0.9093 val_loss: 0.3021 val_acc: 0.8931
epoch: 15 train_loss: 0.2380 train_acc:0.9126 val_loss: 0.3081 val_acc: 0.8928
epoch: 16 train_loss: 0.2297 train_acc:0.9156 val_loss: 0.3123 val_acc: 0.8931
epoch: 17 train_loss: 0.2219 train_acc:0.9185 val_loss: 0.3182 val_acc: 0.8932
epoch: 18 train_loss: 0.2146 train_acc:0.9213 val_loss: 0.3261 val_acc: 0.8931
epoch: 19 train_loss: 0.2078 train_acc:0.9238 val_loss: 0.3335 val_acc: 0.8930
epoch: 20 train_loss: 0.2014 train_acc:0.9262 val_loss: 0.3417 val_acc: 0.8928
epoch: 21 train_loss: 0.1953 train_acc:0.9284 val_loss: 0.3506 val_acc: 0.8925
epoch: 22 train_loss: 0.1896 train_acc:0.9305 val_loss: 0.3570 val_acc: 0.8927
epoch: 23 train_loss: 0.1843 train_acc:0.9324 val_loss: 0.3652 val_acc: 0.8924
epoch: 24 train_loss: 0.1791 train_acc:0.9343 val_loss: 0.3741 val_acc: 0.8925
epoch: 25 train_loss: 0.1744 train_acc:0.9360 val_loss: 0.3801 val_acc: 0.8926
epoch: 26 train_loss: 0.1700 train_acc:0.9377 val_loss: 0.3875 val_acc: 0.8926
epoch: 27 train_loss: 0.1657 train_acc:0.9392 val_loss: 0.3936 val_acc: 0.8927
epoch: 28 train_loss: 0.1615 train_acc:0.9408 val_loss: 0.4016 val_acc: 0.8928
epoch: 29 train_loss: 0.1577 train_acc:0.9421 val_loss: 0.4078 val_acc: 0.8929
epoch: 30 train_loss: 0.1541 train_acc:0.9434 val_loss: 0.4153 val_acc: 0.8929
epoch: 31 train_loss: 0.1504 train_acc:0.9448 val_loss: 0.4207 val_acc: 0.8932
epoch: 32 train_loss: 0.1469 train_acc:0.9461 val_loss: 0.4254 val_acc: 0.8936
epoch: 33 train_loss: 0.1436 train_acc:0.9473 val_loss: 0.4312 val_acc: 0.8940
epoch: 34 train_loss: 0.1406 train_acc:0.9484 val_loss: 0.4364 val_acc: 0.8942
epoch: 35 train_loss: 0.1376 train_acc:0.9495 val_loss: 0.4425 val_acc: 0.8943
epoch: 36 train_loss: 0.1347 train_acc:0.9506 val_loss: 0.4482 val_acc: 0.8946
epoch: 37 train_loss: 0.1320 train_acc:0.9516 val_loss: 0.4534 val_acc: 0.8948
epoch: 38 train_loss: 0.1294 train_acc:0.9525 val_loss: 0.4581 val_acc: 0.8951
epoch: 39 train_loss: 0.1268 train_acc:0.9535 val_loss: 0.4637 val_acc: 0.8952
epoch: 40 train_loss: 0.1242 train_acc:0.9544 val_loss: 0.4689 val_acc: 0.8954
epoch: 41 train_loss: 0.1220 train_acc:0.9553 val_loss: 0.4747 val_acc: 0.8955
epoch: 42 train_loss: 0.1198 train_acc:0.9561 val_loss: 0.4793 val_acc: 0.8957
epoch: 43 train_loss: 0.1177 train_acc:0.9569 val_loss: 0.4843 val_acc: 0.8960
epoch: 44 train_loss: 0.1155 train_acc:0.9576 val_loss: 0.4890 val_acc: 0.8962
epoch: 45 train_loss: 0.1135 train_acc:0.9584 val_loss: 0.4940 val_acc: 0.8964
epoch: 46 train_loss: 0.1114 train_acc:0.9592 val_loss: 0.5008 val_acc: 0.8965
epoch: 47 train_loss: 0.1095 train_acc:0.9599 val_loss: 0.5058 val_acc: 0.8967
epoch: 48 train_loss: 0.1077 train_acc:0.9605 val_loss: 0.5121 val_acc: 0.8967
epoch: 49 train_loss: 0.1059 train_acc:0.9612 val_loss: 0.5169 val_acc: 0.8968
epoch: 50 train_loss: 0.1043 train_acc:0.9618 val_loss: 0.5221 val_acc: 0.8970
epoch: 51 train_loss: 0.1028 train_acc:0.9624 val_loss: 0.5267 val_acc: 0.8971
epoch: 52 train_loss: 0.1012 train_acc:0.9630 val_loss: 0.5324 val_acc: 0.8972
epoch: 53 train_loss: 0.0996 train_acc:0.9635 val_loss: 0.5379 val_acc: 0.8974
epoch: 54 train_loss: 0.0983 train_acc:0.9640 val_loss: 0.5427 val_acc: 0.8974
epoch: 55 train_loss: 0.0969 train_acc:0.9646 val_loss: 0.5475 val_acc: 0.8975
epoch: 56 train_loss: 0.0955 train_acc:0.9651 val_loss: 0.5528 val_acc: 0.8976
epoch: 57 train_loss: 0.0942 train_acc:0.9656 val_loss: 0.5573 val_acc: 0.8977
epoch: 58 train_loss: 0.0929 train_acc:0.9661 val_loss: 0.5614 val_acc: 0.8978
epoch: 59 train_loss: 0.0916 train_acc:0.9665 val_loss: 0.5656 val_acc: 0.8980
epoch: 60 train_loss: 0.0904 train_acc:0.9670 val_loss: 0.5703 val_acc: 0.8981
epoch: 61 train_loss: 0.0892 train_acc:0.9674 val_loss: 0.5748 val_acc: 0.8983
epoch: 62 train_loss: 0.0880 train_acc:0.9679 val_loss: 0.5796 val_acc: 0.8985
epoch: 63 train_loss: 0.0868 train_acc:0.9683 val_loss: 0.5833 val_acc: 0.8986
epoch: 64 train_loss: 0.0857 train_acc:0.9688 val_loss: 0.5891 val_acc: 0.8986
epoch: 65 train_loss: 0.0846 train_acc:0.9692 val_loss: 0.5938 val_acc: 0.8987
epoch: 66 train_loss: 0.0836 train_acc:0.9695 val_loss: 0.5987 val_acc: 0.8986
epoch: 67 train_loss: 0.0826 train_acc:0.9699 val_loss: 0.6035 val_acc: 0.8987
epoch: 68 train_loss: 0.0817 train_acc:0.9703 val_loss: 0.6071 val_acc: 0.8988
epoch: 69 train_loss: 0.0807 train_acc:0.9706 val_loss: 0.6112 val_acc: 0.8989
epoch: 70 train_loss: 0.0798 train_acc:0.9710 val_loss: 0.6146 val_acc: 0.8989
epoch: 71 train_loss: 0.0788 train_acc:0.9713 val_loss: 0.6202 val_acc: 0.8990
epoch: 72 train_loss: 0.0779 train_acc:0.9717 val_loss: 0.6239 val_acc: 0.8991
epoch: 73 train_loss: 0.0770 train_acc:0.9720 val_loss: 0.6282 val_acc: 0.8991
epoch: 74 train_loss: 0.0761 train_acc:0.9723 val_loss: 0.6323 val_acc: 0.8992
epoch: 75 train_loss: 0.0753 train_acc:0.9726 val_loss: 0.6361 val_acc: 0.8992
epoch: 76 train_loss: 0.0744 train_acc:0.9729 val_loss: 0.6411 val_acc: 0.8992
epoch: 77 train_loss: 0.0736 train_acc:0.9732 val_loss: 0.6451 val_acc: 0.8993
epoch: 78 train_loss: 0.0728 train_acc:0.9735 val_loss: 0.6485 val_acc: 0.8993
epoch: 79 train_loss: 0.0721 train_acc:0.9738 val_loss: 0.6528 val_acc: 0.8994
epoch: 80 train_loss: 0.0713 train_acc:0.9741 val_loss: 0.6573 val_acc: 0.8995
epoch: 81 train_loss: 0.0706 train_acc:0.9744 val_loss: 0.6618 val_acc: 0.8995
epoch: 82 train_loss: 0.0698 train_acc:0.9746 val_loss: 0.6654 val_acc: 0.8996
epoch: 83 train_loss: 0.0692 train_acc:0.9749 val_loss: 0.6695 val_acc: 0.8996
epoch: 84 train_loss: 0.0685 train_acc:0.9751 val_loss: 0.6740 val_acc: 0.8996
epoch: 85 train_loss: 0.0678 train_acc:0.9754 val_loss: 0.6779 val_acc: 0.8997
epoch: 86 train_loss: 0.0673 train_acc:0.9756 val_loss: 0.6814 val_acc: 0.8997
epoch: 87 train_loss: 0.0667 train_acc:0.9758 val_loss: 0.6849 val_acc: 0.8997
epoch: 88 train_loss: 0.0660 train_acc:0.9760 val_loss: 0.6893 val_acc: 0.8997
epoch: 89 train_loss: 0.0656 train_acc:0.9762 val_loss: 0.6919 val_acc: 0.8998
epoch: 90 train_loss: 0.0650 train_acc:0.9765 val_loss: 0.6950 val_acc: 0.8999
epoch: 91 train_loss: 0.0643 train_acc:0.9767 val_loss: 0.6984 val_acc: 0.9000
epoch: 92 train_loss: 0.0637 train_acc:0.9769 val_loss: 0.7016 val_acc: 0.9001
epoch: 93 train_loss: 0.0632 train_acc:0.9771 val_loss: 0.7054 val_acc: 0.9002
epoch: 94 train_loss: 0.0626 train_acc:0.9773 val_loss: 0.7095 val_acc: 0.9002
epoch: 95 train_loss: 0.0622 train_acc:0.9775 val_loss: 0.7124 val_acc: 0.9003
epoch: 96 train_loss: 0.0616 train_acc:0.9777 val_loss: 0.7152 val_acc: 0.9003
epoch: 97 train_loss: 0.0611 train_acc:0.9779 val_loss: 0.7182 val_acc: 0.9004
epoch: 98 train_loss: 0.0606 train_acc:0.9781 val_loss: 0.7213 val_acc: 0.9004
epoch: 99 train_loss: 0.0600 train_acc:0.9783 val_loss: 0.7245 val_acc: 0.9005
epoch: 100 train_loss: 0.0595 train_acc:0.9785 val_loss: 0.7277 val_acc: 0.9006
In [16]:
# 5-01-8 テストデータによるモデルの評価
# p.269

test_loss = keras.metrics.Mean()
test_acc = keras.metrics.SparseCategoricalAccuracy()

def test_step(x, t):
    '''
    Parameters:
      x (ndarray(float32)): test data
      t (ntarray(float32)): label
    '''
    preds = model(x)
    tmp_loss = loss(t, preds)
    test_loss(tmp_loss)
    test_acc(t, preds)
In [17]:
test_step(x_test_rs, t_test)

print(f'test_loss: {test_loss.result():.4f} '
      f'test_acc: {test_acc.result():.4f}')
test_loss: 1.0892 test_acc: 0.9055
In [17]: