Irisの品種分類

Irisの品種分類

Irisの品種分類

 前回記事 で作成した Iris のデータを使ってニューラルネットワークに 品種分類 を学習させます。今回構築するネットワークのスペックは以下の通りです。

 ・入力層のユニット数  : 4
 ・中間層 1 のユニット数 : 10
 ・中間層 1 の活性化関数 : ReLU
 ・中間層 2 のユニット数 : 15
 ・中間層 2 の活性化関数 : ReLU
 ・出力層のユニット数  : 3
 ・バッチサイズ     : 15

 以下のコードを実行すると、エポックごとに交差エントロピー誤差を計算しながら、300 エポックまで学習を進めます。最後にネットワークにテストデータを入力して出力値とテストデータの一致率を表示します。

# リストM11-A-18
# Irisの品種分類

# ネットワークの順伝播関数
def iris_c_forward(data):
    mid_1.forward(data)
    mid_2.forward(mid_1.y_out)
    return out.forward(mid_2.y_out)

# 出力値と正解値データの一致率
def accuracy(output, data_c):
    output_class = np.argmax(output, axis = 1)
    output_class = np.identity(3, dtype = "int8")[output_class]
    argmax_1 = np.argmax(output_class, axis = 1)
    argmax_2 = np.argmax(data_c, axis = 1)
    count = np.sum(argmax_1 == argmax_2)
    acc = count * 100 / n_test
    return np.round(acc, 3)

# 乱数を初期化
np.random.seed(11)

# 学習率を設定
alpha = 0.01

# epochを設定
epoch = 300

# データの個数
n_train = data_c_train.shape[0]
n_test = data_c_test.shape[0]

# バッチサイズとバッチ数
b_size = 15
n_batch = n_train // b_size

# インデックス配列
idx = np.arange(n_train)

# 中間層と出力層を作成
mid_1 = Middle_layer(4, 10, ReLU)
mid_2 = Middle_layer(10, 15, ReLU)
out = Output_layer_c(15, 3)

# epoch配列
x = np.arange(epoch)

# 訓練誤差とテスト誤差の初期値
error_train = np.zeros(epoch)
error_test = np.zeros(epoch)

# FigureとAxesを用意
fig = plt.figure(figsize = (6, 6))
ax = fig.add_subplot(111)
ax.grid()
ax.set_xlim(0, epoch)
ax.set_ylim(0, 1.2)
ax.set_xlabel("Epochs", size = 15, labelpad = 10)
ax.set_ylabel("Cross Entropy Error", size = 15, labelpad = 10)

# エポック数だけ学習を繰り返す
for j in range(epoch):
    
    # 全訓練データを学習途中のネットワークに入力して出力を取得
    iris_c_forward(data_in_train)
    
    # 全訓練データの平均交差エントロピー誤差
    error_train[j] = cross_entropy(out.y_out, data_c_train)
    
    # 全テストデータを学習途中のネットワークに入力して出力を取得
    iris_c_forward(data_in_test)
    
    # 全テストデータの平均交差エントロピー誤差
    error_test[j] = cross_entropy(out.y_out, data_c_test)
    
    # インデックスをランダムに並べ替える
    np.random.shuffle(idx)

    # ミニバッチ学習
    for k in range(n_batch):
        batch = idx[k * b_size : (k + 1) * b_size]
        mid_1.forward(data_in_train[batch, :])
        mid_2.forward(mid_1.y_out)
        out.activate(mid_2.y_out, data_c_train[batch, :])
        mid_2.backward(out.y_back)
        mid_1.backward(mid_2.y_back)

# 全テストデータを学習途中のネットワークに入力して出力を取得
iris_c_forward(data_in_test)

# 出力値とテストデータの一致率を計算
acc = accuracy(out.y_out, data_c_test)
print("出力値とテストデータの一致率:{}%".format(acc))

ax.plot(x, error_train, color = "blue", label = "train")
ax.plot(x, error_test, color = "red", label = "test")
ax.legend()
出力値とテストデータの一致率:97.333%

 iris cross entropy error

 学習が進むにつれて、訓練データの交差エントロピー誤差は順調に下がっていきますが、テストデータの誤差は 100 エポック あたりから停滞し、その後は緩やかに上昇曲線を描きます(ネットワークが訓練データに過度に適応する「過学習」が起きています)。学習は 100 ~ 150 エポックで打ち切ったほうがよいでしょう。

 出力値とテストデータの一致率は 300 エポックで 97 % なので、未知のデータに対しても高い精度を持っていますが、ネットワークの構造やハイパーパラメータを変えることで、さらに僅かでも改善が見込めるかもしれません。色々と試してみてください。