Macbook AirでAIやってみた

1週間ほど前にM1のMacbook Airを購入しました。
試しにMNISTで機械学習をやってみたので、やり方と結果のメモです。
MNISTは0〜9の手書き文字の画像がセットになっており、画像認識で数字をAIが数字を当てるものになっています。

## 環境構築
macOS VenturaからPythonの同梱が終了されたようなので1からPythonをインストールします。
私の場合homebrewからインストールするとパスがうまく通せなかったので[公式サイト](https://www.python.org/)からインストールしました。
今回はPython 3.9.13にしました。

Pythonをインストールしたら次はライブラリをインストールします。
以下をpipで以下をインストールしましょう。

pipのアップグレード
```
pip3 install --upgrade pip
```
Numpy
```
pip3 install numpy
```
pandas
```
pip3 install pandas
```
Tensorflow
```
pip3 install tensorflow-macos
```
matplotlib
```
pip3 install matplotlib
```

## MNISTの実行
何故かKerasを使ってmnistをインストールしようとするとエラーしたので、事前にダウンロードしてローカルで実行することにします。
MNISTのデータセットは以下のホームページで公開されています。
https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
mnist.npzがダウンロードされるので、/Username/.keras/datasetsにコピーします。

次に実行のためのプログラムですが、以下のように記述します。
今回は3層のディープラーニングを行います。

```python
import os
import pathlib
import tensorflow as tf
import numpy as np
import pandas as pd 
import matplotlib.pyplot as plt
import time

def main():
    start = time.time()
    CSV_FILE_PATH = "trainlog.csv"

    if not os.path.exists(CSV_FILE_PATH):
        pathlib.Path(CSV_FILE_PATH).touch()
    
    mnist = tf.keras.datasets.mnist
    (x_train, y_train), (x_test, y_test) = mnist.load_data()
    del mnist
    x_train, x_test = x_train/255.0, x_test/255.0
    model = tf.keras.models.Sequential([
        tf.keras.layers.Flatten(input_shape = (28, 28), name = 'input'),
        tf.keras.layers.Dense(512, name = 'fc_1'),
        tf.keras.layers.Activation(tf.nn.relu, name = 'relu_1'),
        tf.keras.layers.Dense(256, name = 'fc_2'),
        tf.keras.layers.Activation(tf.nn.relu, name = 'relu_2'),
        tf.keras.layers.Dense(256, name = 'fc_3'),
        tf.keras.layers.Activation(tf.nn.relu, name = 'relu_3'),
        tf.keras.layers.Dense(10, name = 'dense_3'),
        tf.keras.layers.Activation(tf.nn.softmax, name = 'softmax')])
    model.summary()
    model.compile(optimizer = 'adam', loss = 'sparse_categorical_crossentropy', metrics = ['accuracy'])
    callbacks = []
    callbacks.append(tf.keras.callbacks.CSVLogger(CSV_FILE_PATH))
    history = model.fit(x_train, y_train, batch_size = 100, epochs = 20, verbose = 1, validation_data = (x_test, y_test), callbacks = callbacks)
    train_loss, train_acc = model.evaluate(x_train, y_train, verbose = 1)
    print("loss(train): {:.4}".format(train_loss))
    print("accuracy(train): {:.4}".format(train_acc))
    test_loss, test_acc = model.evaluate(x_test, y_test, verbose = 1)
    print("loss(test): {:.4}".format(test_loss))
    print("accuracy(test): {:.4}".format(test_acc))
    df = pd.read_csv(CSV_FILE_PATH)
    df.head()
    print(time.time() - start)
    epochs = df["epoch"].values
    train_acc = df["accuracy"].values
    train_loss = df["loss"].values
    test_acc = df["val_accuracy"].values
    test_loss = df["val_loss"].values
    plt.plot(epochs, train_loss, label = 'train data')
    plt.plot(epochs, test_loss, label = 'test data')
    plt.xlabel("epochs")
    plt.ylabel("loss\n(categorical crossentropy)")
    plt.legend(loc = "upper right")
    plt.show()
    plt.plot(epochs, train_acc, label = 'train data')
    plt.plot(epochs, test_acc, label = 'test data')
    plt.xlabel("epochs")
    plt.ylabel("accuracy")
    plt.legend(loc = "lower right")
    plt.show()
    fig = plt.figure(figsize = (12, 8))
    ROW = 4
    COLUMN = 5

    for i in range(ROW * COLUMN):
        y_true = y_test[i]
        y_pred = model.predict(x_test[i].reshape(1, 28, 28))[0]
        
        plt.subplot(ROW, COLUMN, i + 1)
        plt.imshow(x_test[i], cmap = 'gray')
        plt.title("No.{}\ny_true: {}, y_pred: {}".format(i, y_true, y_pred))
        plt.axis("off")

    fig.tight_layout()
    fig.show()
if __name__ == '__main__': main()
```

## 実行結果
実行結果は以下のようになりました。ちゃんと学習できていることがわかります。
![mnist_accu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691433/24592871-117d-53e3-89de-05d572740b37.png)


学習の実行速度は41秒でした。
他の記事を見ると、M1 Macbook proで100秒以上かかるようです。
それに比べれば格段に早くなったようです。
今回の結果はGeForce RTX 3070 Tiと同程度のようです。
M1が出てすぐはまだTensorflowへの対応ができていなかったことが影響しているのでしょう。

M1 Macbook Airでもそれなりに機械学習ができるようになったようです。
次はもう少し負荷のかかる学習で試してみたいと思います。

参考文献
[Keras/TensorflowでMNISTデータセットの画像分類](https://www.ailab.ics.keio.ac.jp/b4_induction_training/docs/dl/mnist_notebook.html)
[機械学習環境ベンチマーク](https://take6shin-tech-diary.com/machine-learning-benchmark/)