コンテンツにスキップ

第3章 あやめの分析

1 データの準備

では実際にディープラーニングで学習と予測を行っています。まずは機械学習でも行った「あやめ」(iris)のデータを読み込んでみます。

import pandas as pd
df =  pd.read_csv("iris.csv")
df.head()

このデータには以下の列があります。

  • SepalLength 花がくの長さ
  • SepalWidth 花がくの幅
  • PetalLength 花びらの長さ
  • PetalWidth 花びらの幅
  • Name 種類

SepalLength、SepalWidth、PetalLength、PetalWidthが特徴量、Nameが正解ラベルになります。

学習データと教師データに分けます。今回は教師データは数値である必要があるため、ngroup() で0~2にします、そして、学習用とテスト用に分割します。

# 学習データ
x = df[["SepalLength", "SepalWidth", "PetalLength", "PetalWidth"]]

# # 教師データ
y = df.groupby(['Name']).ngroup()

# 学習用とテスト用の分割
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, random_state=0)

2 モデルの構築

ディープラーニングにはKerasというライブラリを使用します。 KerasのSequentialモデル(単純に層を重ねるモデル)をまず生成します。

import keras

model = keras.models.Sequential()

これにaddで層を追加していきます。

from keras import layers

model.add(layers.Dense(10, activation="relu", input_shape=(4,)))
model.add(layers.Dense(8, activation="relu"))
model.add(layers.Dense(3, activation="softmax"))

layers.Denseは全てのニューロンを単純に全結合する層です。最初の層では10個のニューロンがあります。そして、入力層(input_shape)が4個です。これはSepalLength、SepalWidth、PetalLength、PetalWidth の4つです。4個から入力したデータを10個に拡大します。

activationでは活性化関数を指定します。reluは現在最も一般的に使われている活性化関数です。

次の層では8個のニューロンを持つ層を追加します。10個から8個に絞ります。

最後に3個のニューロンになる層を追加します。これが出力層です。この出力層が3個なのは最終的に0~2のどの数値であるかを予測するためです。0番目の数値が一番大きいなら0と予測されたことになります。

出力層の活性化関数にはsoftmax関数を指定します。これは全ての合計が1.0になるようにします。ということはこれは確率を表すことになります。

例:3個の配列のうち、1番目が0.1、2番目が0.8、3番目が0.1だった場合、80%の確率で「2」と予測されたことになります。

model.summary()

model.summary() ではモデルの概要を表示します。 「Param #」はパラメータ数です。これは重み付けの数(入力数×ニューロン数)とバイアスの数(ニューロン数)の合計です。このパラメータを決めていく作業が学習です。パラメータが多いほど学習に時間がかかります。

最初の層は入力が4個で10個に接続しますので、40個の重み付け数が必要です。これに、各10個のニューロンがバイアス値が必要ですので計50個になります。

3 学習と評価

学習前にcompileを行います。optimizerで最適化関数を指定します。lossには損失関数を指定します。

損失関数とは損失、つまり誤差(予測値と正解値との差)をどう計算するかの計算方法です。 今回はsparse_categorical_crossentropyを指定します。

最適化関数は、この誤差をどうやって少なくするかを計算するための方法を指定します。今回はadamを指定します。

metricsには性能評価指標を指定します。今回はaccuracy(正解率)を指定します。

model.compile(optimizer="adam",
              loss="sparse_categorical_crossentropy",
              metrics=["accuracy"])

学習にはfitを使用します。epochsで学習の回数を指定します。今回は200回です。validation_dataには検証用データを指定します。

history = model.fit(x_train, y_train, epochs=200, 
        validation_data=(x_test, y_test))

戻り値には学習の履歴が入ります。後でグラフ化してみようと思いますので、変数historyに格納します。

学習する毎にaccuracy(訓練データでの正解率)が上昇していきます。また、val_accuracy(テストデータでの正解率)は過学習を起こすと下がっていきます。

model.evaluateで評価を得ます。戻り値は損失率と正解率です。

test_loss, test_acc = model.evaluate(x_test, y_test)

print(f"テストデータの正解率は{test_acc:.2%}です。")

4 正解率と誤差

正解率を学習回数毎にグラフで表示してみます。accuracyが訓練データの正解率、val_accuracyがテストデータの正解率です。

import matplotlib.pyplot as plt
import seaborn as sns
sns.set(font=["Meiryo"])

plt.title("正解率")
plt.xlabel("学習回数")
plt.plot(history.history["accuracy"])
plt.plot(history.history["val_accuracy"])
plt.legend(["訓練","テスト"])
plt.show()

誤差を学習回数毎にグラフで表示してみます。lossが訓練データの正解率、val_lossがテストデータの正解率です。

import matplotlib.pyplot as plt
import seaborn as sns
sns.set(font=["Meiryo"])

plt.title("誤差")
plt.xlabel("学習回数")
plt.plot(history.history["loss"])
plt.plot(history.history["val_loss"])
plt.legend(["訓練","テスト"])
plt.show()

5 推論

実際に値を与えて推論(予測)してみます。x_test のデータを推論させます。

pre = model.predict(x_test)

その0番目の推論結果を表示してみましょう。

p = pre[0] # 推論結果をp にいれる

for i in range(3):
    print(f"{i}番目 {p[i]:.8f}")
print("正解:" , y_test.iloc[0])

このよう何番目の確率が何かが表示されます。