シンプルにKeras/PythonでEXORをニューラルネットワーク学習お試し

パソコン

Pythonの機械学習に触れてみる

Python/Keras

最近、Python言語を勉強していまして、その中で機械学習をかんたんに出来るKerasというものがあることを知り、自宅PCで少し動かしてみたかったため、実験してみました。

自宅PCの Jupyter-Labを使用しました。

バージョン
Python3.9
jupyterlab3.4.5
keras2.9.0
tensorflow2.9.1
使用したバージョン

参考にしたサイト様

[https://algorithm.joho.info/machine-learning/python-keras-neural-network-xor/]

EXOR(排他的論理和 exclusive or)の計算について学習させていきます。

ソースコード

主には

  1. 入力データの設定
  2. モデル構築
  3. 学習
  4. 学習済みモデルの評価
  5. 学習済みモデルの出力確認(グラフ表示)

という流れになります。

ソースコードは以下の通りです。

import numpy as np
from keras.models import Sequential
from keras.layers.core import Dense
from tensorflow.keras import optimizers
import matplotlib.pyplot as plt
import pandas as pd
import time
import random
import tensorflow as tf

def main():
    # reproducibility
    seed = 5
    random.seed(seed)
    np.random.seed(seed)
    tf.random.set_seed(seed)

    # 訓練データの用意
    # 入力データ (EXOR train data)
    x_train = np.array([[0.0, 0.0],
                        [1.0, 0.0],
                        [0.0, 1.0],
                        [1.0, 1.0]])
    # 入力の教師データ
    y_train = np.array([0.0, 1.0, 1.0, 0.0])

    # モデル構築
    model = Sequential()
    # 入力層(2)
    model.add(Dense(2, activation='sigmoid', input_shape=(2,)))
    # 出力層(1)
    model.add(Dense(1, activation='linear'))
    # コンパイル(勾配法:RMSprop、損失関数:mean_squared_error、評価関数:accuracy)
    opt = optimizers.RMSprop(learning_rate=0.2)
    model.compile(loss='mean_squared_error', optimizer=opt, metrics=['accuracy'])
    # time counting
    start_time = time.process_time()
    # 構築したモデルで学習
    history = model.fit(x_train, y_train, batch_size=4, epochs=200, verbose=0)

    # 収束の様子プロット
    history_df = pd.DataFrame(history.history)
    history_df.plot()
    plt.show()
    model.summary()

    # テストデータの用意
    x_test = x_train
    y_test = y_train
       
    # モデルの性能評価
    score = model.evaluate(x_train, y_train, verbose=0)
    print('Score:', score[0])
    print('Accuracy:', score[1])
    end_time = time.process_time()
    # 経過時間を出力(秒)
    elapsed_time = end_time - start_time
    print("elapsed time : ", elapsed_time , " sec ")

    # 学習済みモデルを使って答えを予測
    arr = np.zeros((11, 11))
    
    # 学習済みモデルを使って分布描画
    for i in range(0, 11, 1):
      for j in range(0, 11, 1):
        x1 = (i/10)
        x2 = (j/10)
        x = np.array([[x1, x2]])
        y = model.predict(x)
        arr[i, j] = y

    plt.xlabel('Input 1 value (0.0--1.0)')
    plt.ylabel('Input 2 value (0.0--1.0)')
    plt.imshow(arr, cmap='gray')
    plt.colorbar(aspect=40, pad=0.08, orientation='vertical')

if __name__ == '__main__':
    main()

わかりにくいですが、最終的にはこんな感じの結果になりました。

縦軸、横軸は0から10の表示になっていますが、実際は 入力 0から1まで、0.1ずつ刻みのことになります。

入力(0,1)(1,0)のときは出力1.0に近く、白っぽくなっていることが分かります。

一方で入力(0,0)(1,1)のときは出力0に近く、黒っぽくなっています。まずまずの結果が得られました。

それ以外のところはなんとなくグレーな感じです。

いろいろパタメータや設定を変えることでもう少し違う結果が得られそうです。

少し設定やパラメータを変えて再度実験してみます。

import numpy as np
from keras.models import Sequential
from keras.layers.core import Dense
from tensorflow.keras import optimizers
import matplotlib.pyplot as plt
import pandas as pd
import time
import random
import tensorflow as tf

def main():
    # reproducibility
    random.seed(1)
    np.random.seed(1)
    tf.random.set_seed(1)
    
    # 訓練データの用意
    # 入力データ (EXOR train data)
    x_train = np.array([[0.0, 0.0],
                        [1.0, 0.0],
                        [0.0, 1.0],
                        [1.0, 1.0]])
    # 入力の教師データ
    y_train = np.array([0.0, 1.0, 1.0, 0.0])

    # モデル構築
    model = Sequential()
    # 入力層(2)
    model.add(Dense(5, activation='sigmoid', input_shape=(2,)))
    # 出力層(1)
    model.add(Dense(1, activation='sigmoid'))
    # コンパイル(勾配法:RMSprop、損失関数:mean_squared_error、評価関数:accuracy)
    opt = optimizers.RMSprop(learning_rate=0.1)
    model.compile(loss='mean_squared_error', optimizer=opt, metrics=['accuracy'])
    # time counting
    start_time = time.process_time()
    # 構築したモデルで学習
    history = model.fit(x_train, y_train, batch_size=4, epochs=200, verbose=0, shuffle=True)

    # 収束の様子プロット
    history_df = pd.DataFrame(history.history)
    history_df.plot()
    plt.show()
    model.summary()

    # テストデータの用意
    x_test = x_train
    y_test = y_train
       
    # モデルの性能評価
    score = model.evaluate(x_train, y_train, verbose=0)
    print('Score:', score[0])
    print('Accuracy:', score[1])
    end_time = time.process_time()
    # 経過時間を出力(秒)
    elapsed_time = end_time - start_time
    print("elapsed time : ", elapsed_time , " sec ")

    # 学習済みモデルを使って答えを予測
    predict_arr = np.zeros((11, 11))

    # 学習済みモデルを使って分布描画(0.1ずつ)
    for i in range(0, 11, 1):
      for j in range(0, 11, 1):
        x1 = (i/10)
        x2 = (j/10)
        x = np.array([[x1, x2]])
        y = model.predict(x)
        predict_arr[i, j] = y
        
    plt.xlabel('Input value 1 (0.0--1.0)')
    plt.ylabel('Input value 2 (0.0--1.0)')
    plt.imshow(predict_arr, cmap='gray')
    plt.colorbar(aspect=40, pad=0.08, orientation='vertical')

if __name__ == '__main__':
    main()

中間層を増やしてみましたが、この結果だとはっきりと結果が出るようになりました。

(0.5, 0.5)付近は教師データがなくてちょっとグレーなのですが、領域ごとにハッキリと色分けされています。個人的には最初のものよりこっちのほうが好きですね。

まとめ

今回はPythonを少し覚えたのをきっかけに、keras を使ってニューラスネットワークの簡単なお試しが出来ました。

これをベースにkerasなどに慣れていければいいなと思います。

それではまた🐧

コメント

タイトルとURLをコピーしました