tensorflowをインストールしてwindowsで機械学習してみる

TensorFlowでお困りの方へ

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 -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のpipパッケージのインストール

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

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

(venv) $ pip install --upgrade tensorflow

機械学習してみる

データセットの取得

環境は整ったので、機械学習していきます。

このチュートリアル通りに、mnistと呼ばれる手書き数字の画像分類をやってみます。

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

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): <class 'numpy.ndarray'>
# 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): <class 'numpy.ndarray'>
# 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): <class 'numpy.ndarray'>
# 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): <class 'numpy.ndarray'>
# y_test.shape: (10000,)

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

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

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

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 で翻訳すると、
分類モデルが生成する生の(正規化されていない)予測値のベクトルで、通常、正規化関数に渡される。モデルがマルチクラス分類問題を解く場合、ロジットは通常ソフトマックス関数への入力となる。とのことです。

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 が進むにつれて損失が収束していることがわかります。

# 学習の可視化
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

モデルの評価

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

# 学習に使用していないテストデータで評価する。
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% くらいの精度が出ていることがわかりました。
いくつかのテストデータの、予測値と実際のラベルを見てみましょう。

# 予測
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 画像の正解の数字です。

確率が最も高い数字と、正解の数字が合っていることがわかります。

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