機械学習入門

Home PDF

私たちがPythonを学ぶのであれば、機械学習についてもきっと話さなければなりません。なぜなら、その多くのライブラリがPythonで書かれているからです。まずはそれらをインストールして、少し遊んでみましょう。

Tensorflow

インストールしてみましょう。

$ pip install tensorflow
ERROR: Could not find a version that satisfies the requirement tensorflow
ERROR: No matching distribution found for tensorflow

このエラーメッセージは、指定されたバージョンのTensorFlowが見つからなかったことを示しています。この問題は、PythonのバージョンがTensorFlowと互換性がない場合や、利用可能なTensorFlowのバージョンが存在しない場合に発生することがあります。解決策として、Pythonのバージョンを確認し、TensorFlowがサポートしているバージョンに合わせるか、または利用可能なTensorFlowのバージョンを指定してインストールを試みることができます。

$ type python
python は `/usr/local/Cellar/python@3.9/3.9.1_6/bin/python3' のエイリアスです

しかし、Tensorflow 2Python 3.5–3.8のみをサポートしています。私たちが使用しているのは3.9です。

% type python3
python3 は /usr/bin/python3 です
% python3 -V
Python 3.8.2

私のシステム内のpython33.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)

このコマンドは、Pythonのパッケージ管理ツールであるpipのバージョンと、それがインストールされている場所を確認するものです。出力結果から、pipのバージョンが21.0.1であり、Python 3.8の環境で使用されていることがわかります。また、pip/Users/lzw/Library/Python/3.8/lib/python/site-packages/pipにインストールされていることも示されています。

対応するpipはここにあります。それでは、.zprofileファイルを変更します。最近、私はshellを変更しました。.zprofileは以前の.bash_profileに相当します。1行追加します。

alias pip3=/Users/lzw/Library/Python/3.8/bin/pip3

このコードは、pip3コマンドに対してエイリアスを設定しています。具体的には、pip3を実行すると、指定されたパス/Users/lzw/Library/Python/3.8/bin/pip3にあるpip3が実行されるようになります。これにより、システム全体のpip3ではなく、特定のユーザー環境にインストールされたpip3を使用することができます。

これで、python3pip3を使ってTensorflowを楽しむことができます。

% pip3 install tensorflow
...
成功インストール: 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

このコードは、MNISTデータセットを読み込み、訓練データとテストデータを正規化するためのものです。具体的には、x_trainx_testの各ピクセル値を255で割ることで、0から1の範囲にスケーリングしています。これにより、ニューラルネットワークの学習がより効率的になります。

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)
あなたはプロの翻訳者です。Jekyllブログ投稿用のマークダウンファイルを翻訳しています。以下のテキストを日本語に翻訳してください。英語の名前は翻訳しないでください。コードブロックに注意し、わからない場合は変更しないでください。

実行してみましょう。

$ /usr/bin/python3 tf.py
データをダウンロード中: https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 10秒 1マイクロ秒/ステップ
[[ 0.15477428 -0.3877643   0.0994779   0.07474922 -0.26219758 -0.03550266
   0.32226565 -0.37141111  0.10925996 -0.0115255 ]]

データセットがダウンロードされ、結果が出力されたことが確認できます。

次に、画像分類の例を見てみましょう。

# TensorFlowとtf.keras
import tensorflow as tf

ヘルパーライブラリ

import numpy as np import matplotlib.pyplot as plt

print(tf.__version__)

エラーが発生しました。

ModuleNotFoundError: No module named 'matplotlib'

このエラーメッセージは、Pythonがmatplotlibというモジュールを見つけられなかったことを示しています。matplotlibはデータの可視化に使用される人気のあるライブラリです。このエラーを解決するには、以下の手順でmatplotlibをインストールしてください。

  1. ターミナルまたはコマンドプロンプトを開きます。
  2. 以下のコマンドを実行してmatplotlibをインストールします。
pip install matplotlib

これでmatplotlibがインストールされ、エラーが解消されるはずです。もしpipがインストールされていない場合や、他の問題が発生した場合は、Python環境の設定を確認してください。

インストールしてみましょう。

% pip3 install matplotlib

正解です。

$ /usr/bin/python3 image.py
2.4.1

このコマンドは、Python 3を使用してimage.pyというスクリプトを実行し、その結果として2.4.1というバージョン情報を出力しています。

以下はコピー&ペーストの例コードです。

# コピー&ペーストの例
text_to_copy = "これはコピーするテキストです。"
copied_text = text_to_copy  # ここでコピーが行われます

print("コピーされたテキスト:", copied_text)

このコードは、text_to_copy 変数の内容を copied_text 変数にコピーし、それを出力します。

# TensorFlowとtf.keras
import tensorflow as tf

ヘルパーライブラリ

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シャツ/トップス', 'ズボン', 'プルオーバー', 'ドレス', 'コート',
               'サンダル', 'シャツ', 'スニーカー', 'バッグ', 'アンクルブーツ']
print(train_images.shape)
print(len(train_labels))

結果が出力されました。ここにtrain_imagestrain_labelstest_imagestest_labelsがあることに注目してください。これらは訓練データセットとテストデータセットに分かれています。

(60000, 28, 28)
60000

このコードブロックは、PythonのNumPy配列やPandasデータフレームの形状や要素数を表示する際の出力例を示しています。具体的には、以下のように解釈できます:

この出力は、機械学習のデータセット(例えば、MNISTデータセット)を扱う際によく見られる形式です。

次に、画像を印刷してみましょう。

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: 'numpy.uint8' 型のオブジェクトには len() がありません

したがって、非常に明白です。各画像は28*28*3の配列です。最後の次元の配列にはRGB値が保存されています。しかし、私たちの考えが間違っている可能性があることに気づきました。

print(train_images[0][1][20])

このコードは、train_imagesという多次元配列(またはリスト)の最初の要素の2番目の要素の21番目の要素を出力します。具体的には、train_images[0]が最初の要素、train_images[0][1]がその中の2番目の要素、そしてtrain_images[0][1][20]がその中の21番目の要素を指します。このコードは、その値を表示するために使用されます。

0
print(train_images[0][1])

このコードは、train_imagesというリスト(または配列)の最初の要素の2番目の要素を出力します。Pythonではインデックスが0から始まるため、[0]が最初の要素を指し、[1]がその中の2番目の要素を指します。

[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()

このコードは、PythonのMatplotlibライブラリを使用して、トレーニングデータセットの最初の画像を表示するものです。各コマンドの役割は以下の通りです:

tf

右側のカラーバーが見えますか。0から250まであります。これは元々、2つの色の間のグラデーションです。しかし、どうやってどの2色を選ぶのか知っているのでしょうか。私たちはどこでそれを指定したのでしょうか。

次に、2番目の図も印刷します。

plt.imshow(train_images[1])

このコードは、train_imagesというリストまたは配列の中の2番目の画像(インデックス1)を表示するために使用されます。plt.imshow()はMatplotlibライブラリの関数で、画像をプロットするために使われます。

plt

面白いですね。これは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()

このコードは、25枚の訓練画像を5x5のグリッドで表示するためのものです。各画像の下には、その画像に対応するラベルが表示されます。plt.xticks([])plt.yticks([])は、x軸とy軸の目盛りを非表示にします。plt.grid(False)は、グリッドを非表示にします。plt.imshowは、画像を表示し、plt.xlabelは、画像の下にラベルを表示します。最後にplt.show()を呼び出して、図を表示します。

tf2

ここに画像とその分類が表示されていることに気づきました。ついにcmpパラメータの正体がわかりました。もしcmpに何も指定しなければ、きっと先ほどのような色合いになるはずです。やはりその通りでした。

    plt.imshow(train_images[i])

cmap

今回はpyplot cmapを検索します。いくつかの資料が見つかりました。

    plt.imshow(train_images[i], cmap=plt.cm.PiYG)

cmap1

コードを修正します。

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()

しかし、エラーが発生しました。

ValueError: num は 1 <= num <= 10 でなければなりませんが、11 が指定されました

これは何を意味しているのでしょうか。以前の5,5,i+1は一体どういう意味だったのでしょうか。なぜ2に変更するとうまくいかないのでしょうか。直感的には5行5列という意味だとわかりますが、なぜこのエラーが発生するのでしょうか。11はどのように計算されたのでしょうか。numとは何を意味しているのでしょうか。10とは何を意味しているのでしょうか。2*5=10に気づきました。おそらくi=11のときにエラーが発生したのでしょう。for i in range(10):に変更したとき、以下の結果が得られました。

plot3

少しドキュメントを見てみると、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()

このコードは、25枚の訓練画像を5x5のグリッドで表示するためのものです。各画像の下には、その画像に対応するラベルが表示されます。plt.figure(figsize=(10,10))で図のサイズを設定し、forループを使って25枚の画像を順番に表示しています。plt.subplot(5,5,i+1)で5行5列のサブプロットを作成し、plt.imshow(train_images[i], cmap=plt.cm.Blues)で画像を表示します。plt.xlabel(class_names[train_labels[i]])で画像のラベルを表示し、plt.show()で図を表示します。

plot_xticks

0 25 のようなものを xticks と呼ぶことに注意してください。このボックスを拡大縮小すると、異なる表示が得られます。

plot_scale

拡大縮小ボックスに注目すると、xticksxlabelsが異なる表示になることがわかります。

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'])

このコードは、Kerasモデルをコンパイルするためのものです。以下に各パラメータの説明を示します:

この設定により、モデルはAdamオプティマイザを使用して訓練され、損失関数としてSparse Categorical Crossentropyが使用され、訓練中に精度が監視されます。

model.fit(train_images, train_labels, epochs=10)
test_loss, test_acc = model.evaluate(test_images,  test_labels, verbose=2)
print('\nテスト精度:', test_acc)

ここでモデルを定義する方法に注目すると、クラスSequentialが使用されています。これらのパラメータ、28,28128relu10に注意してください。compilefitが必要であることに気づきます。fitは「フィット」、つまりモデルをデータに適合させることを意味します。28,28は画像のサイズであることに気づきます。

エポック 1/10
1875/1875 [==============================] - 2s 928us/ステップ - 損失: 0.6331 - 精度: 0.7769
エポック 2/10
1875/1875 [==============================] - 2s 961us/ステップ - 損失: 0.3860 - 精度: 0.8615
エポック 3/10
1875/1875 [==============================] - 2s 930us/ステップ - 損失: 0.3395 - 精度: 0.8755
エポック 4/10
1875/1875 [==============================] - 2s 1ms/ステップ - 損失: 0.3071 - 精度: 0.8890
エポック 5/10
1875/1875 [==============================] - 2s 1ms/ステップ - 損失: 0.2964 - 精度: 0.8927
エポック 6/10
1875/1875 [==============================] - 2s 985us/ステップ - 損失: 0.2764 - 精度: 0.8955
エポック 7/10
1875/1875 [==============================] - 2s 961us/ステップ - 損失: 0.2653 - 精度: 0.8996
エポック 8/10
1875/1875 [==============================] - 2s 1ms/ステップ - 損失: 0.2549 - 精度: 0.9052
エポック 9/10
1875/1875 [==============================] - 2s 1ms/ステップ - 損失: 0.2416 - 精度: 0.9090
エポック 10/10
1875/1875 [==============================] - 2s 1ms/ステップ - 損失: 0.2372 - 精度: 0.9086
313/313 - 0s - 損失: 0.3422 - 精度: 0.8798

テスト精度: 0.879800021648407


モデルがトレーニングされました。パラメータを調整しましょう。

```shell
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の最初のパラメータを修正します。

エポック 1/10
1875/1875 [==============================] - 2秒 714マイクロ秒/ステップ - 損失: 6.9774 - 精度: 0.3294
エポック 2/10
1875/1875 [==============================] - 1秒 715マイクロ秒/ステップ - 損失: 1.3038 - 精度: 0.4831
エポック 3/10
1875/1875 [==============================] - 1秒 747マイクロ秒/ステップ - 損失: 1.0160 - 精度: 0.6197
エポック 4/10
1875/1875 [==============================] - 1秒 800マイクロ秒/ステップ - 損失: 0.7963 - 精度: 0.6939
エポック 5/10
1875/1875 [==============================] - 2秒 893マイクロ秒/ステップ - 損失: 0.7006 - 精度: 0.7183
エポック 6/10
1875/1875 [==============================] - 1秒 747マイクロ秒/ステップ - 損失: 0.6675 - 精度: 0.7299
エポック 7/10
1875/1875 [==============================] - 1秒 694マイクロ秒/ステップ - 損失: 0.6681 - 精度: 0.7330
エポック 8/10
1875/1875 [==============================] - 1秒 702マイクロ秒/ステップ - 損失: 0.6675 - 精度: 0.7356
エポック 9/10
1875/1875 [==============================] - 1秒 778マイクロ秒/ステップ - 損失: 0.6508 - 精度: 0.7363
エポック 10/10
1875/1875 [==============================] - 1秒 732マイクロ秒/ステップ - 損失: 0.6532 - 精度: 0.7350
313/313 - 0秒 - 損失: 0.6816 - 精度: 0.7230

テスト精度: 0.7229999899864197


`Test accuracy`の前後で変化が確認できます。`Epoch`というのは`fit`関数が出力するログです。バッチサイズが`128`の場合、`accuracy`は`0.7769`から`0.9086`に変化しました。一方、バッチサイズが`28`の場合、`accuracy`は`0.3294`から`0.7350`に変化しました。ここで注目すべきは、まずトレーニングセットを使用して`loss`と`accuracy`を最適化し、その後テストデータセットでテストを行っていることです。まずは`train_labels`を見てみましょう。

```python
print(train_labels)
[9 0 0 ... 3 0 5]
print(len(train_labels))
60000

上記のコードは、train_labelsというリストの内容とその長さを表示しています。train_labelsには、訓練データのラベルが格納されており、その長さは60,000です。

これは、これらのカテゴリを0から9の数字で表すことを意味します。ちょうどclass_namesも10個あります。

class_names = ['Tシャツ/トップス', 'ズボン', 'プルオーバー', 'ドレス', 'コート',
               'サンダル', 'シャツ', 'スニーカー', 'バッグ', 'アンクルブーツ']

もう一度修正してみましょう。

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'])

このコードは、Kerasモデルをコンパイルするためのものです。以下に各パラメータの説明を示します:

この設定により、モデルはAdamオプティマイザを使用して訓練され、損失関数としてSparse Categorical Crossentropyが適用され、精度が評価指標として使用されます。

model.fit(train_images, train_labels, epochs=10)

エラーが発生しました。

tensorflow.python.framework.errors_impl.InvalidArgumentError:  ラベル値として9を受け取りましたが、これは有効な範囲[0, 5)の外です。ラベル値: 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]

関数呼び出しスタック: train_function


`Sequential`の3番目のパラメータである`Dense`のパラメータを`15`に変更すればOKです。結果に大きな違いはありません。`Epoch`を変更してみてください。

```python
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'])

このコードは、Kerasモデルをコンパイルするための設定を行っています。以下に各パラメータの説明を日本語で示します。

この設定により、モデルはAdamオプティマイザを使用して訓練され、損失関数としてSparse Categorical Crossentropyが適用され、精度が評価指標として使用されます。

model.fit(train_images, train_labels, epochs=15)  # 10 -> 15

このコードは、ニューラルネットワークモデルを訓練するためのものです。train_imagestrain_labelsはそれぞれ訓練データの画像とそのラベルを表しています。epochs=15は、モデルを15回繰り返し訓練することを指定しています。以前は10回だったのが、15回に増やされています。

test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print('\nテスト精度:', test_acc)
エポック 1/15
1875/1875 [==============================] - 2s 892us/ステップ - 損失: 6.5778 - 精度: 0.3771
エポック 2/15
1875/1875 [==============================] - 2s 872us/ステップ - 損失: 1.3121 - 精度: 0.4910
エポック 3/15
1875/1875 [==============================] - 2s 909us/ステップ - 損失: 1.0900 - 精度: 0.5389
エポック 4/15
1875/1875 [==============================] - 1s 730us/ステップ - 損失: 1.0422 - 精度: 0.5577
エポック 5/15
1875/1875 [==============================] - 1s 709us/ステップ - 損失: 0.9529 - 精度: 0.5952
エポック 6/15
1875/1875 [==============================] - 1s 714us/ステップ - 損失: 0.9888 - 精度: 0.5950
エポック 7/15
1875/1875 [==============================] - 1s 767us/ステップ - 損失: 0.8678 - 精度: 0.6355
エポック 8/15
1875/1875 [==============================] - 1s 715us/ステップ - 損失: 0.8247 - 精度: 0.6611
エポック 9/15
1875/1875 [==============================] - 1s 721us/ステップ - 損失: 0.8011 - 精度: 0.6626
エポック 10/15
1875/1875 [==============================] - 1s 711us/ステップ - 損失: 0.8024 - 精度: 0.6622
エポック 11/15
1875/1875 [==============================] - 1s 781us/ステップ - 損失: 0.7777 - 精度: 0.6696
エポック 12/15
1875/1875 [==============================] - 1s 724us/ステップ - 損失: 0.7764 - 精度: 0.6728
エポック 13/15
1875/1875 [==============================] - 1s 731us/ステップ - 損失: 0.7688 - 精度: 0.6767
エポック 14/15
1875/1875 [==============================] - 1s 715us/ステップ - 損失: 0.7592 - 精度: 0.6793
エポック 15/15
1875/1875 [==============================] - 1s 786us/ステップ - 損失: 0.7526 - 精度: 0.6792
313/313 - 0s - 損失: 0.8555 - 精度: 0.6418

テスト精度: 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`の意味について考えさせられます。

```python
probability_model = tf.keras.Sequential([model, 
                                         tf.keras.layers.Softmax()])

このコードは、Kerasを使用して確率モデルを作成しています。probability_modelは、既存のmodelSoftmax層を追加したシーケンシャルモデルです。Softmax層は、モデルの出力を確率分布に変換するために使用されます。

次に予測を行います。Sequentialが上記と同じであることに注意してください。パラメータmodeltf.keras.layers.Softmax()に注目してください。

probability_model = tf.keras.Sequential([model, 
                                         tf.keras.layers.Softmax()])
predictions = probability_model.predict(test_images)

このコードは、TensorFlowとKerasを使用して、モデルの出力にSoftmax層を追加し、テスト画像に対する予測を行うものです。以下に日本語で説明します。

  1. probability_model という名前の新しいシーケンシャルモデルを作成します。このモデルは、既存の model と、その後に追加される Softmax 層で構成されています。Softmax層は、モデルの出力を確率分布に変換します。

  2. predictions 変数には、probability_model を使用して 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)

このコードは、Matplotlibのxlabel関数を使用して、X軸のラベルを設定しています。ラベルは、予測されたクラス名、その予測確率(パーセンテージ)、および実際のクラス名を含むフォーマット文字列です。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)

この関数は、指定されたインデックス i の予測結果 predictions_array と正解ラベル true_label を使用して、予測値の配列を棒グラフとしてプロットします。グラフのX軸には0から9までの数字が表示され、Y軸の目盛りは非表示になります。棒グラフの色は灰色(#777777)で、Y軸の範囲は0から1に設定されます。最後に、predictions_array の中で最も高い値を持つインデックスを predicted_label として取得します。

thisplot[predicted_label].set_color('red')
thisplot[true_label].set_color('blue')

このコードは、thisplotというオブジェクトの特定のインデックス(predicted_labeltrue_label)に対応する要素の色を変更しています。predicted_labelに対応する要素の色を赤に、true_labelに対応する要素の色を青に設定しています。

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()

pred

これは、この画像が99%の確率でAnkle bootであることを示しています。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()

このコードは、指定された行数 (num_rows) と列数 (num_cols) に基づいて、画像とその予測結果をプロットするためのものです。num_images は行数と列数を掛け合わせた総画像数を表します。plt.figure で図のサイズを設定し、for ループ内で各画像とその予測結果をサブプロットとして配置します。plot_image 関数は画像を表示し、plot_value_array 関数は予測結果の配列を表示します。最後に plt.tight_layout() でレイアウトを整え、plt.show() で図を表示します。

pred1

ここでは、より多くのテスト結果を表示しているだけであることに気づきました。したがって、使用の流れはおおよそ理解しています。しかし、背後でどのように計算されているかはまだわかりません。それらがどのように使用されるかはわかっていますが、その背後には微積分があります。では、微積分をどのように理解すればよいのでしょうか。

例えば、1から100までの数字を当てるゲームがあるとします。毎回あなたが数字を推測し、私が「小さい」か「大きい」かを教えます。あなたが50と推測したら、私は「小さい」と言います。次にあなたが80と推測したら、私は「大きい」と言います。あなたが65と推測したら、私は「大きい」と言います。あなたが55と推測したら、私は「小さい」と言います。最後にあなたが58と推測したら、私は「当たり」と言います。

機械学習は、このようなプロセスを背後でシミュレートするものです。ただし、より複雑です。多くの「1から100」の範囲があり、多くの数を推測する必要があります。同時に、毎回の推測には多くの計算が必要です。そして、大きいか小さいかを判断するたびに、多くの計算を行います。

PyTorch

PyTorchは、Python向けのオープンソースの機械学習ライブラリです。FacebookのAI研究チームによって開発され、柔軟性と使いやすさが特徴です。PyTorchは、動的な計算グラフを採用しており、これによりモデルのデバッグや変更が容易になります。また、GPUを活用した高速な計算が可能で、深層学習モデルの開発や研究に広く利用されています。PyTorchは、研究者や開発者にとって強力なツールであり、最新のAI技術を迅速に実装するためのプラットフォームとして人気を集めています。

インストールしてみましょう。これは3.9バージョンのPythonをサポートしています。

$ pip install torch torchvision
Collecting torch
  Downloading torch-1.8.0-cp39-none-macosx_10_9_x86_64.whl (120.6 MB)
     |████████████████████████████████| 120.6 MB 224 kB/s
Collecting torchvision
  Downloading torchvision-0.9.0-cp39-cp39-macosx_10_9_x86_64.whl (13.1 MB)
     |████████████████████████████████| 13.1 MB 549 kB/s
Requirement already satisfied: numpy in /usr/local/lib/python3.9/site-packages (from torch) (1.20.1)
Collecting typing-extensions
  Downloading typing_extensions-3.7.4.3-py3-none-any.whl (22 kB)
Requirement already satisfied: pillow>=4.1.1 in /usr/local/lib/python3.9/site-packages (from torchvision) (8.0.1)
Installing collected packages: typing-extensions, torch, torchvision
Successfully installed torch-1.8.0 torchvision-0.9.0 typing-extensions-3.7.4.3

確認してみましょう。

import torch
x = torch.rand(5, 3)
print(x)

エラーが発生しました。

Traceback (most recent call last):
  File "torch.py", line 1, in <module>
    import torch
  File "torch.py", line 2, in <module>
    x = torch.rand(5, 3)
AttributeError: 部分的に初期化されたモジュール 'torch' には 'rand' 属性がありません(おそらく循環インポートが原因です)

このエラーメッセージをGoogleで検索してみました。原因は、私たちのファイルもtorchという名前だったためです。名前が重複していました。名前を変更したら、正しく動作しました。

tensor([[0.5520, 0.9446, 0.5543],
        [0.6192, 0.0908, 0.8726],
        [0.0223, 0.7685, 0.9814],
        [0.4019, 0.5406, 0.3861],
        [0.5485, 0.6040, 0.2387]])

このコードブロックは、PyTorchのテンソルを表示しています。テンソルは、5行3列の行列で、各要素は浮動小数点数です。具体的には、以下のような値を持っています:

このテンソルは、機械学習モデルの重みや入力データなど、さまざまな用途で使用されることがあります。

例を見つけました。

# -*- coding: utf-8 -*-
import torch
import math
dtype = torch.float
device = torch.device("cpu")
# device = torch.device("cuda:0") # GPUで実行する場合はこの行のコメントを解除してください

ランダムな入力と出力データを作成

x = torch.linspace(-math.pi, math.pi, 2000, device=device, dtype=dtype) y = torch.sin(x)

重みをランダムに初期化

a = torch.randn((), device=device, dtype=dtype) b = torch.randn((), device=device, dtype=dtype) c = torch.randn((), device=device, dtype=dtype) d = torch.randn((), device=device, dtype=dtype)

learning_rate = 1e-6
for t in range(2000):
    # 順伝播: 予測値 y を計算
    y_pred = a + b * x + c * x ** 2 + d * x ** 3
# 損失を計算して表示
loss = (y_pred - y).pow(2).sum().item()
if t % 100 == 99:
    print(t, loss)

# 損失に対するa, b, c, dの勾配を計算するためのバックプロパゲーション
grad_y_pred = 2.0 * (y_pred - y)
grad_a = grad_y_pred.sum()
grad_b = (grad_y_pred * x).sum()
grad_c = (grad_y_pred * x ** 2).sum()
grad_d = (grad_y_pred * x ** 3).sum()

# 勾配降下法を使用して重みを更新
a -= learning_rate * grad_a
b -= learning_rate * grad_b
c -= learning_rate * grad_c
d -= learning_rate * grad_d print(f'結果: y = {a.item()} + {b.item()} x + {c.item()} x^2 + {d.item()} x^3') ```

実行してみましょう。

99 1273.537353515625
199 849.24853515625
299 567.4786987304688
399 380.30291748046875
499 255.92752075195312
599 173.2559814453125
699 118.2861328125
799 81.72274780273438
899 57.39331817626953
999 41.198158264160156
1099 30.41307830810547
1199 23.227672576904297
1299 18.438262939453125
1399 15.244369506835938
1499 13.113286972045898
1599 11.690631866455078
1699 10.740333557128906
1799 10.105220794677734
1899 9.6804780960083
1999 9.39621353149414
結果: y = -0.011828352697193623 + 0.8360244631767273 x + 0.002040589228272438 x^2 + -0.09038365632295609 x^3

numpyライブラリだけを使ったコードを見てみましょう。

# -*- coding: utf-8 -*-
import numpy as np
import math

ランダムな入力と出力データを作成する

x = np.linspace(-math.pi, math.pi, 2000) y = np.sin(x)

重みをランダムに初期化

a = np.random.randn() b = np.random.randn() c = np.random.randn() d = np.random.randn()

learning_rate = 1e-6
for t in range(2000):
    # 順伝播: 予測値 y を計算
    # y = a + b x + c x^2 + d x^3
    y_pred = a + b * x + c * x ** 2 + d * x ** 3
# 損失を計算して表示
loss = np.square(y_pred - y).sum()
if t % 100 == 99:
    print(t, loss)

# 損失に対するa, b, c, dの勾配を計算するためのバックプロパゲーション
grad_y_pred = 2.0 * (y_pred - y)
grad_a = grad_y_pred.sum()
grad_b = (grad_y_pred * x).sum()
grad_c = (grad_y_pred * x ** 2).sum()
grad_d = (grad_y_pred * x ** 3).sum()

# 重みの更新
a -= learning_rate * grad_a
b -= learning_rate * grad_b
c -= learning_rate * grad_c
d -= learning_rate * grad_d
print(f'結果: y = {a} + {b} x + {c} x^2 + {d} x^3')

これは2つの計算方法であることに注意してください。

これらの例では、まず一連のxとyを生成しています。次に、三次方程式を仮定します。その後、いくつかの方法を使用して係数を反復計算します。これらのアルゴリズムはどのようなものなのでしょうか。2000回ループしていることに注意してください。各反復でより正確にフィットさせています。ここでは詳細には触れません。

最後に

現在のところ、私たちは機械学習の背後にある計算方法を理解していません。しかし、それは今のところ重要ではありません。上記のような知識を使って、私たちはすでに多くのことを行うことができます。また、機械学習を使ってテキストやオーディオなどを処理することもできます。数十の例を試してみてから、その原理を学ぶのも遅くはありません。

練習


Back 2025.01.18 Donate