機械学習入門 - TensorFlow | オリジナル、AI翻訳
この記事はもともと中国語で書かれました。他の言語への翻訳を容易にするために英語に翻訳されました。
Python
を学習しているので、機械学習について話さないわけにはいきません。多くのライブラリがPythonで書かれています。まずインストールして試してみましょう。
TensorFlow
インストールしましょう。
$ pip install tensorflow
ERROR: Could not find a version that satisfies the requirement tensorflow
ERROR: No matching distribution found for tensorflow
$ type python
python is aliased to `/usr/local/Cellar/python@3.9/3.9.1_6/bin/python3'
しかし、TensorFlow 2
は Python 3.5–3.8
しかサポートしていません。私たちが使っているのは 3.9
です。
% type python3
python3 is /usr/bin/python3
% python3 -V
Python 3.8.2
私のシステムの python3
は 3.8.2
であることに注意してください。このPythonバージョンに対応する pip
はどこにパッケージをインストールするでしょうか?
% python3 -m pip -V
pip 21.0.1 from /Users/lzw/Library/Python/3.8/lib/python/site-packages/pip (python 3.8)
対応する pip
はここにあります。そこで、.zprofile
ファイルを修正します。最近、シェルを変更したので、.zprofile
は以前の .bash_profile
と同じです。1行追加します:
alias pip3=/Users/lzw/Library/Python/3.8/bin/pip3
これで、python3
と pip3
を使って TensorFlow
を操作できます。
% pip3 install tensorflow
...
Successfully installed absl-py-0.12.0 astunparse-1.6.3 cachetools-4.2.1 certifi-2020.12.5 chardet-4.0.0 flatbuffers-1.12 gast-0.3.3 google-auth-1.27.1 google-auth-oauthlib-0.4.3 google-pasta-0.2.0 grpcio-1.32.0 h5py-2.10.0 idna-2.10 keras-preprocessing-1.1.2 markdown-3.3.4 numpy-1.19.5 oauthlib-3.1.0 opt-einsum-3.3.0 protobuf-3.15.6 pyasn1-0.4.8 pyasn1-modules-0.2.8 requests-2.25.1 requests-oauthlib-1.3.0 rsa-4.7.2 tensorboard-2.4.1 tensorboard-plugin-wit-1.8.0 tensorflow-2.4.1 tensorflow-estimator-2.4.0 termcolor-1.1.0 typing-extensions-3.7.4.3 urllib3-1.26.3 werkzeug-1.0.1 wheel-0.36.2 wrapt-1.12.1
多くのライブラリがインストールされました。公式サイトの例を使ってみましょう。
import tensorflow as tf
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
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)),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10)
])
predictions = model(x_train[:1]).numpy()
print(predictions)
実行してみましょう。
$ /usr/bin/python3 tf.py
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 10s 1us/step
[[ 0.15477428 -0.3877643 0.0994779 0.07474922 -0.26219758 -0.03550266
0.32226565 -0.37141111 0.10925996 -0.0115255 ]]
ご覧の通り、データセットがダウンロードされ、結果が出力されました。
次に、画像分類の例を見てみましょう。
# TensorFlow and tf.keras
import tensorflow as tf
# Helper libraries
import numpy as np
import matplotlib.pyplot as plt
print(tf.__version__)
エラーが発生しました。
ModuleNotFoundError: No module named 'matplotlib'
インストールしましょう。
% pip3 install matplotlib
これで正常になりました。
$ /usr/bin/python3 image.py
2.4.1
例のコードをコピーして貼り付けます。
# TensorFlow and tf.keras
import tensorflow as tf
# Helper libraries
import numpy as np
import matplotlib.pyplot as plt
fashion_mnist = tf.keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
print(train_images.shape)
print(len(train_labels))
結果が出力されました。train_images
、train_labels
、test_images
、test_labels
があることに注意してください。これらはトレーニングデータセットとテストデータセットに分割されています。
(60000, 28, 28)
60000
次に、画像を表示してみましょう。
print(train_images[0])
結果を見てみましょう。
[[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 13 73 0
0 1 4 0 0 0 0 1 1 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 3 0 36 136 127 62
54 0 0 0 1 3 4 0 0 3]
[ 0 0 0 0 0 0 0 0 0 0 0 0 6 0 102 204 176 134
144 123 23 0 0 0 0 12 10 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 155 236 207 178
107 156 161 109 64 23 77 130 72 15]
[ 0 0 0 0 0 0 0 0 0 0 0 1 0 69 207 223 218 216
216 163 127 121 122 146 141 88 172 66]]
....
ここでは、結果の一部を抜粋しています。
print(len(train_images[0][0]))
出力は 28
です。つまり、これは幅28の行列であることがわかります。引き続き表示しましょう。
print(len(train_images[0][0][0]))
TypeError: object of type 'numpy.uint8' has no len()
これで明らかになりました。各画像は 28*28*3
の配列です。最後の次元にはRGBの値が格納されています。しかし、これは間違っている可能性があります。
print(train_images[0][1][20])
0
print(train_images[0][1])
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
これを見ると、各画像は 28*28
の配列であることがわかります。少し試行錯誤した後、ようやく秘密がわかりました。
まず、出力画像を見てみましょう。
plt.figure()
plt.imshow(train_images[0])
plt.colorbar()
plt.grid(False)
plt.show()
右側のカラーバーが見えますか?0
から 250
までです。これは2つの色の間のグラデーションであることがわかりました。しかし、どのようにして2つの色を知るのでしょうか?どこで指定したのでしょうか?
次に、2番目の画像も表示してみましょう。
plt.imshow(train_images[1])
非常に興味深いです。これは pyplot
ライブラリのデフォルトでしょうか?公式サイトが提供するコードを引き続き実行してみましょう。
plt.figure(figsize=(10,10))
for i in range(25):
plt.subplot(5,5,i+1)
plt.xticks([])
plt.yticks([])
plt.grid(False)
plt.imshow(train_images[i], cmap=plt.cm.binary)
plt.xlabel(class_names[train_labels[i]])
plt.show()
ここで、画像とその分類が表示されていることに注意してください。最終的に、cmap
パラメータの意味がわかりました。cmap
を指定しない場合、先ほど見た色のスキームがデフォルトで適用されます。
plt.imshow(train_images[i])
今度は pyplot cmap
を検索して、いくつかのリソースを見つけます。
plt.imshow(train_images[i], cmap=plt.cm.PiYG)
コードを変更しましょう。
plt.figure(figsize=(10,10))
for i in range(25):
plt.subplot(2,5,i+1) ## この行を変更
plt.xticks([])
plt.yticks([])
plt.grid(False)
plt.imshow(train_images[i], cmap=plt.cm.Blues)
plt.xlabel(class_names[train_labels[i]])
plt.show()
しかし、エラーが発生しました。
ValueError: num must be 1 <= num <= 10, not 11
これはどういう意味でしょうか?前の 5,5,i+1
は具体的にどういう意味でしょうか?2
に変更するとなぜ動作しないのでしょうか?直感的には5行5列を意味すると思いますが、なぜこのエラーが発生するのでしょうか?11
はどのように計算されるのでしょうか?num
とは何でしょうか?10
とは何でしょうか?2*5=10
に注意してください。そのため、おそらく i=11
のときにエラーが発生します。for i in range(10):
に変更すると、次の結果が得られます。
今度は簡単にドキュメントを見てみると、subplot(nrows, ncols, index, **kwargs)
について学びます。これで理解できました。
plt.figure(figsize=(10,10))
for i in range(25):
plt.subplot(5,5,i+1)
# plt.xticks([])
plt.yticks([])
plt.grid(False)
plt.imshow(train_images[i], cmap=plt.cm.Blues)
plt.xlabel(class_names[train_labels[i]])
plt.show()
0 25
のようなものは xticks
と呼ばれます。このフレームを拡大または縮小すると、表示が変わります。
拡大または縮小すると、xticks
と xlabels
の表示が変わることに注意してください。
model = tf.keras.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10)
])
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
model.fit(train_images, train_labels, epochs=10)
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print('\nTest accuracy:', test_acc)
ここでモデルの定義方法に注意してください。Sequential
クラスを使用しています。これらのパラメータに注意してください:28,28
、128
、relu
、10
。compile
と fit
が必要であることに注意してください。fit
はフィッティングを意味します。28,28
は画像のサイズに対応していることに注意してください。
Epoch 1/10
1875/1875 [==============================] - 2s 928us/step - loss: 0.6331 - accuracy: 0.7769
Epoch 2/10
1875/1875 [==============================] - 2s 961us/step - loss: 0.3860 - accuracy: 0.8615
Epoch 3/10
1875/1875 [==============================] - 2s 930us/step - loss: 0.3395 - accuracy: 0.8755
Epoch 4/10
1875/1875 [==============================] - 2s 1ms/step - loss: 0.3071 - accuracy: 0.8890
Epoch 5/10
1875/1875 [==============================] - 2s 1ms/step - loss: 0.2964 - accuracy: 0.8927
Epoch 6/10
1875/1875 [==============================] - 2s 985us/step - loss: 0.2764 - accuracy: 0.8955
Epoch 7/10
1875/1875 [==============================] - 2s 961us/step - loss: 0.2653 - accuracy: 0.8996
Epoch 8/10
1875/1875 [==============================] - 2s 1ms/step - loss: 0.2549 - accuracy: 0.9052
Epoch 9/10
1875/1875 [==============================] - 2s 1ms/step - loss: 0.2416 - accuracy: 0.9090
Epoch 10/10
1875/1875 [==============================] - 2s 1ms/step - loss: 0.2372 - accuracy: 0.9086
313/313 - 0s - loss: 0.3422 - accuracy: 0.8798
Test accuracy: 0.879800021648407
モデルはトレーニングされました。パラメータを調整してみましょう。
model = tf.keras.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(28, activation='relu'), # 128 -> 28
tf.keras.layers.Dense(10)
])
Dense
の最初のパラメータを変更します。
Epoch 1/10
1875/1875 [==============================] - 2s 714us/step - loss: 6.9774 - accuracy: 0.3294
Epoch 2/10
1875/1875 [==============================] - 1s 715us/step - loss: 1.3038 - accuracy: 0.4831
Epoch 3/10
1875/1875 [==============================] - 1s 747us/step - loss: 1.0160 - accuracy: 0.6197
Epoch 4/10
1875/1875 [==============================] - 1s 800us/step - loss: 0.7963 - accuracy: 0.6939
Epoch 5/10
1875/1875 [==============================] - 2s 893us/step - loss: 0.7006 - accuracy: 0.7183
Epoch 6/10
1875/1875 [==============================] - 1s 747us/step - loss: 0.6675 - accuracy: 0.7299
Epoch 7/10
1875/1875 [==============================] - 1s 694us/step - loss: 0.6681 - accuracy: 0.7330
Epoch 8/10
1875/1875 [==============================] - 1s 702us/step - loss: 0.6675 - accuracy: 0.7356
Epoch 9/10
1875/1875 [==============================] - 1s 778us/step - loss: 0.6508 - accuracy: 0.7363
Epoch 10/10
1875/1875 [==============================] - 1s 732us/step - loss: 0.6532 - accuracy: 0.7350
313/313 - 0s - loss: 0.6816 - accuracy: 0.7230
Test accuracy: 0.7229999899864197
Test accuracy
の前後の変化に注意してください。Epoch
ログは fit
関数によって出力されます。128
の場合、accuracy
は 0.7769
から 0.9086
になります。28
の場合、accuracy
は 0.3294
から 0.7350
になります。今回は、まずトレーニングセットを使用して loss
と accuracy
を最適化し、その後テストデータセットを使用して評価することがわかりました。train_labels
を見てみましょう。
print(train_labels)
[9 0 0 ... 3 0 5]
print(len(train_labels))
60000
これは、数字 0
から 9
がこれらのカテゴリを表すことを意味します。偶然にも、class_names
も10個のアイテムがあります。
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
もう一つ変更を加えてみましょう。
model = tf.keras.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(28, activation='relu'),
tf.keras.layers.Dense(5) # 10 -> 5
])
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
model.fit(train_images, train_labels, epochs=10)
エラーが発生しました。
tensorflow.python.framework.errors_impl.InvalidArgumentError: Received a label value of 9 which is outside the valid range of [0, 5). Label values: 4 3 2 9 4 1 6 0 7 9 1 6 5 2 3 8 6 3 8 0 3 5 6 1 2 6 3 6 8 4 8 4
[[node sparse_categorical_crossentropy/SparseSoftmaxCrossEntropyWithLogits/SparseSoftmaxCrossEntropyWithLogits (defined at /curiosity-courses/ml/tf/image.py:53) ]] [Op:__inference_train_function_538]
Function call stack:
train_function
Sequential
の3番目のパラメータ Dense
を 15
に変更すると問題は解決します。結果はそれほど変わりません。Epoch
を変更してみましょう。
model = tf.keras.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(28, activation='relu'),
tf.keras.layers.Dense(15)
])
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
model.fit(train_images, train_labels, epochs=15) # 10 -> 15
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print('\nTest accuracy:', test_acc)
Epoch 1/15
1875/1875 [==============================] - 2s 892us/step - loss: 6.5778 - accuracy: 0.3771
Epoch 2/15
1875/1875 [==============================] - 2s 872us/step - loss: 1.3121 - accuracy: 0.4910
Epoch 3/15
1875/1875 [==============================] - 2s 909us/step - loss: 1.0900 - accuracy: 0.5389
Epoch 4/15
1875/1875 [==============================] - 1s 730us/step - loss: 1.0422 - accuracy: 0.5577
Epoch 5/15
1875/1875 [==============================] - 1s 709us/step - loss: 0.9529 - accuracy: 0.5952
Epoch 6/15
1875/1875 [==============================] - 1s 714us/step - loss: 0.9888 - accuracy: 0.5950
Epoch 7/15
1875/1875 [==============================] - 1s 767us/step - loss: 0.8678 - accuracy: 0.6355
Epoch 8/15
1875/1875 [==============================] - 1s 715us/step - loss: 0.8247 - accuracy: 0.6611
Epoch 9/15
1875/1875 [==============================] - 1s 721us/step - loss: 0.8011 - accuracy: 0.6626
Epoch 10/15
1875/1875 [==============================] - 1s 711us/step - loss: 0.8024 - accuracy: 0.6622
Epoch 11/15
1875/1875 [==============================] - 1s 781us/step - loss: 0.7777 - accuracy: 0.6696
Epoch 12/15
1875/1875 [==============================] - 1s 724us/step - loss: 0.7764 - accuracy: 0.6728
Epoch 13/15
1875/1875 [==============================] - 1s 731us/step - loss: 0.7688 - accuracy: 0.6767
Epoch 14/15
1875/1875 [==============================] - 1s 715us/step - loss: 0.7592 - accuracy: 0.6793
Epoch 15/15
1875/1875 [==============================] - 1s 786us/step - loss: 0.7526 - accuracy: 0.6792
313/313 - 0s - loss: 0.8555 - accuracy: 0.6418
Test accuracy: 0.6417999863624573
15に変更してもそれほど違いはありません。tf.keras.layers.Dense(88, activation='relu')
が重要です。128
を 88
に変更すると、Test accuracy: 0.824999988079071
になります。128
の場合は 0.879800021648407
でしたが、28
の場合は 0.7229999899864197
でした。より大きな値が良い結果をもたらすのでしょうか?しかし、256
に変更すると Test accuracy: 0.8409000039100647
になります。これにより、loss
と accuracy
の意味について考えさせられます。
probability_model = tf.keras.Sequential([model,
tf.keras.layers.Softmax()])
次に、予測を行ってみましょう。Sequential
は上記と同じであることに注意してください。パラメータ model
と tf.keras.layers.Softmax()
に注意してください。
probability_model = tf.keras.Sequential([model,
tf.keras.layers.Softmax()])
predictions = probability_model.predict(test_images)
def plot_image(i, predictions_array, true_label, img):
true_label, img = true_label[i], img[i]
plt.grid(False)
plt.xticks([])
plt.yticks([])
plt.imshow(img, cmap=plt.cm.binary)
predicted_label = np.argmax(predictions_array)
if predicted_label == true_label:
color = 'blue'
else:
color = 'red'
plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
100*np.max(predictions_array),
class_names[true_label]),
color=color)
def plot_value_array(i, predictions_array, true_label):
true_label = true_label[i]
plt.grid(False)
plt.xticks(range(10))
plt.yticks([])
thisplot = plt.bar(range(10), predictions_array, color="#777777")
plt.ylim([0, 1])
predicted_label = np.argmax(predictions_array)
thisplot[predicted_label].set_color('red')
thisplot[true_label].set_color('blue')
i = 0
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions[i], test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions[i], test_labels)
plt.show()
これは、この画像が Ankle boot
である確率が99%であることを示しています。plot_image
が左のチャートを表示し、plot_value_array
が右のチャートを出力することに注意してください。
num_rows = 5
num_cols = 3
num_images = num_rows*num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))
for i in range(num_images):
plt.subplot(num_rows, 2*num_cols, 2*i+1)
plot_image(i, predictions[i], test_labels, test_images)
plt.subplot(num_rows, 2*num_cols, 2*i+2)
plot_value_array(i, predictions[i], test_labels)
plt.tight_layout()
plt.show()
これにより、さらに多くのテスト結果が表示されます。そのため、大まかな使用フローが理解できました。背後の計算方法はまだわかりませんが、使用方法は理解しています。背後には微積分があります。微積分をどのように理解するのでしょうか?
例えば、1から100の範囲で数字を当てるゲームがあるとします。あなたが数字を当てると、私はそれが低すぎるか高すぎるかを教えます。あなたが50と推測します。私は低すぎると言います。あなたが80と推測します。私は高すぎると言います。あなたが65と推測します。私は高すぎると言います。あなたが55と推測します。私は低すぎると言います。あなたが58と推測します。私は、はい、当たりですと言います。
機械学習は裏で同様のプロセスをシミュレートしていますが、より複雑です。多くの 1から100
のような範囲が関与し、一度に多くの数字を推測することができます。各推測には多くの計算が含まれ、高すぎるか低すぎるかを判断するのにも多くの計算が必要です。