tensorflowをインストールして、windowsでサクッと機械学習してみる

TAGS :

機械学習の時代

世の中は AI 全盛で、どんどん便利になっています。
会社でも、研修で AI 関連のものが増えてきています。
ここは、時代に取り残されないように、機械学習をさらっと予習しておきましょう。

機械学習の環境を作る

まずは、tensorflow のインストールです。
tensorflow の読み方ですが、"テンサーフロー"、"テンソルフロー" のどちらでもいいようです。
私は tensor だけだったら、"テンソル" と読んでます。
tensorflow を 公式ドキュメント に沿ってインストールしましょう。

Python開発環境構築

まずは、Python 開発環境の構築です。
Python をインストールしていない場合は、インストールが必要です。
私の Python の Version は 3.9.9でした。

$ python -V
Python 3.9.9

そして、Visual Studio 2015、2017、2019、および 2022用 Microsoft Visual C++ 再頒布可能パッケージ をインストールします。
ここ から、VC_redist.x86.exeVC_redist.x64.exe をダウンロードして、ダブルクリックでインストール完了させます。

Python仮想環境作成

次は、Python の仮想環境の作成です。

コマンドプロンプトを起動し、以下のコマンドで、 Python 仮想環境を作成し、有効化します。
公式ドキュメントに書かれていますが、ここにも載せておきます。

$ python -m venv --system-site-packages .\venv
$ .\venv\Scripts\activate

仮想環境で、pip をインストールします。

(venv) $ pip install --upgrade pip
(venv) $ pip list # show packages installed within the virtual environment

仮想環境の Python の Version は、仮想環境作成時に使った Python のバージョンになっています。

(venv) $ python -V
Python 3.9.9

tensorflowインストール

最後に、tensorflow のインストールです。

仮想環境下で、tensorflow をインストールして、検証しましょう。ちょっと時間がかかります。

(venv) $ pip install --upgrade tensorflow
(venv) $ python -c "import tensorflow as tf;print(tf.reduce_sum(tf.random.normal([1000, 1000])))"

機械学習してみる

データセットの取得

環境は整ったので、あとは機械学習するのみです。
このチュートリアル 通りに、mnist と呼ばれる手書き数字の画像分類をやってみます。

データセットを取得し、学習データとテストデータに分類します。
x が画像、y がラベルなので、y は 0-9 の数字です。

Python

    import tensorflow as tf

    mnist = tf.keras.datasets.mnist
    (x_train, y_train), (x_test, y_test) = mnist.load_data()
    
    print('len(x_train): {}' .format(len(x_train)))
    print('type(x_train): {}' .format(type(x_train)))
    print('x_train.shape: {}' .format(x_train.shape))
    # len(x_train): 60000
    # type(x_train): 
    # x_train.shape: (60000, 28, 28)
    
    print('len(x_test): {}' .format(len(x_test)))
    print('type(x_test): {}' .format(type(x_test)))
    print('x_test.shape: {}' .format(x_test.shape))
    # len(x_test): 10000
    # type(x_test): 
    # x_test.shape: (10000, 28, 28)
    
    print('len(y_train): {}' .format(len(y_train)))
    print('type(y_train): {}' .format(type(y_train)))
    print('y_train.shape: {}' .format(y_train.shape))
    # len(y_train): 60000
    # type(y_train): 
    # y_train.shape: (60000,)
    
    print('len(y_test): {}' .format(len(y_test)))
    print('type(y_test): {}' .format(type(y_test)))
    print('y_test.shape: {}' .format(y_test.shape))
    # len(y_test): 10000
    # type(y_test): 
    # y_test.shape: (10000,)

GPU が搭載されていない PC で実行すると、cuda の dll が見つからないエラーが出ますが、問題ないので、気にしないでください。

Could not load dynamic library 'cudart64_110.dll'; dlerror: cudart64_110.dll not found

mnist が 28x28 の白黒画像で、60,000枚の学習データと10,000枚のテストデータで構成されていることがわかりました。
何枚か画像にしてみましょう。

Python

    import matplotlib.pyplot as plt
    from PIL import Image
    
    rows = 2
    cols = 4
    fig, axes = plt.subplots(rows, cols, figsize=(6, 4))
    for r in range(rows):
        for c in range(cols):
            img = Image.fromarray(x_train[r*cols+c])
            axes[r][c].imshow(img, cmap='gray')
            axes[r][c].axis('off') # 軸目盛りを消す。
    filename = 'mnist_{}x{}_{}.png' \
        .format(rows, cols, datetime.now().strftime('%Y%m%d'))
    file_path = os.path.join(os.getcwd(), filename)
    fig.savefig(file_path)

mnist

モデルの構築と学習

Sequential モデルでネットワーク層を構築します。
https://keras.io/ja/getting-started/sequential-model-guide/

最後の層は、Dense で出力の次元を 10クラス とし、さらに活性化関数 softmax で、入力画像がどのクラスに所属するかの確率をそれぞれ出力し、すべての出力の合計が1となるようにします。
損失関数の from_logits=False にしているのは、モデルの出力が logits テンソルではなく、softmax 出力だからです。
ロジットの説明は こちら をご覧ください。
DeepL で翻訳すると、
分類モデルが生成する生の(正規化されていない)予測値のベクトルで、通常、正規化関数に渡される。モデルがマルチクラス分類問題を解く場合、ロジットは通常ソフトマックス関数への入力となる。 とのことです。

Python

    model = tf.keras.models.Sequential([
        tf.keras.layers.Flatten(input_shape=(28, 28)),
        tf.keras.layers.Dense(128, activation='relu'),
        tf.keras.layers.Dropout(0.2),
        tf.keras.layers.Dense(10, activation='softmax')
    ])

    # 損失関数
    loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(
        from_logits=False)

    # compileで、損失・メトリック、オプティマイザを指定する。
    model.compile(
        optimizer='adam',
        loss=loss_fn,
        metrics=['accuracy'],
        )

    # 学習
    history = model.fit(
        x_train,
        y_train,
        validation_split=0.2,
        epochs=10,
        batch_size=32,
        verbose=1,
        )

コマンドラインに、学習の進捗具合が出力されます。

Epoch 1/10
1500/1500 [==============================] - 3s 2ms/step - loss: 2.8785 - accuracy: 0.7364 - val_loss: 0.5680 - val_accuracy: 0.8658
Epoch 2/10
1500/1500 [==============================] - 3s 2ms/step - loss: 0.6532 - accuracy: 0.8314 - val_loss: 0.4682 - val_accuracy: 0.9018
Epoch 3/10
1500/1500 [==============================] - 3s 2ms/step - loss: 0.5234 - accuracy: 0.8605 - val_loss: 0.3451 - val_accuracy: 0.9185

学習曲線を描いてみます。
Epoch が進むにつれて、損失が収束していることがわかります。

Python

    # 学習の可視化
    plt.plot(history.history['accuracy'])
    plt.plot(history.history['val_accuracy'])
    plt.title('Model accuracy')
    plt.ylabel('Accuracy')
    plt.xlabel('Epoch')
    plt.legend(['Train', 'Test'], loc='upper left')
    filename = 'accuracy_curve_{}.png' .format(datetime.now().strftime('%Y%m%d'))
    file_path = os.path.join(os.getcwd(), filename)
    plt.savefig(file_path)
    plt.clf()
    plt.close()
    
    plt.plot(history.history['loss'])
    plt.plot(history.history['val_loss'])
    plt.title('Model loss')
    plt.ylabel('Loss')
    plt.xlabel('Epoch')
    plt.legend(['Train', 'Test'], loc='upper left')
    filename = 'loss_curve_{}.png' .format(datetime.now().strftime('%Y%m%d'))
    file_path = os.path.join(os.getcwd(), filename)
    plt.savefig(file_path)
    plt.clf()
    plt.close()

Accuracy
Loss

モデルの評価

学習に使用していないテストデータを使って、学習済みモデルが画像分類が正しくできてるか、評価します。

Python

    # 学習に使用していないテストデータで評価する。
    results = model.evaluate(x_test, y_test, verbose=2)
    print('Test loss: {:.6f}   Test accuracy: {:.6f}'
        .format(results[0], results[1]))
313/313 - 0s - loss: 0.2614 - accuracy: 0.9415 - 473ms/epoch - 2ms/step
Test loss: 0.261413 Test accuracy: 0.941500

94% くらいの精度が出ていることがわかりました。
いくつかのテストデータの、予測値と実際のラベルを見てみましょう。

Python

    # 予測
    predictions = model.predict(x_test[:3])
    # 指数表記にせず、小数点以下の桁数を指定する。
    np.set_printoptions(suppress=True, precision=2)
    print(predictions)
    print(y_test[:3])
[[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.] [0. 0. 1. 0. 0. 0. 0. 0. 0. 0.] [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]] [7 2 1]

予測は 10クラス の内、0 から 9 になる確率がそれぞれ出力されています。
y_test ラベルは、x_test 画像の正解の数字です。
確率が最も高い数字と、正解の数字が合っていることがわかります。

以上が、機械学習の環境構築と、簡単な学習例となります。
機械学習の実装は難しいということはなく、モジュールを使って、簡単に作れることを感じていただけたと思います。