ニューラルネットワークの実装5 単一ニューロンによる分類

ニューラルネットワークの実装5 単一ニューロンによる分類

こんにちは、アーキテクトの深山です^o^。久々にブログを更新できて嬉しいです。

前回の記事ではニューラルネットワークの実装について解説をしました。

今回の記事では、続きからやっていきたいと思います。ニューラルネットワークを実装し、そのアルゴリズムをなるべくわかりやすく解説します。

まず初めに、コードだけのっけます。コピペしたい方はどうぞ(^。^)。

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets

iris = datasets.load_iris()
iris_data = iris.data
sl_data = iris_data[:100, 0] 
sw_data = iris_data[:100, 1] 


sl_ave = np.average(sl_data)  # 平均値
sl_data -= sl_ave  # 平均値を引く
sw_ave = np.average(sw_data)
sw_data -= sw_ave

# 入力をリストに格納
input_data = []
for i in range(100):  # iには0から99までが入る
    input_data.append([sl_data[i], sw_data[i]])

def sigmoid(x):
    return 1.0 / (1.0 + np.exp(-x))

# ニューロン
class Neuron:
    def __init__(self):  
        self.input_sum = 0.0
        self.output = 0.0

    def set_input(self, inp):
        self.input_sum += inp

    def get_output(self):
        self.output = sigmoid(self.input_sum)
        return self.output

    def reset(self):
        self.input_sum = 0
        self.output = 0

# ニューラルネットワーク
class NeuralNetwork:
    def __init__(self):  
        self.neuron = Neuron()  #ニューロンの生成
        self.w = [0.5, -0.2]
        self.bias = 0.0

    def commit(self, input_data):  
        self.neuron.reset()

        self.neuron.set_input(input_data[0] * self.w[0])
        self.neuron.set_input(input_data[1] * self.w[1])
        self.neuron.set_input(self.bias)
        return self.neuron.get_output()

# ニューラルネットワーク
neural_network = NeuralNetwork()


st_predicted = [[], []]  # セトサ
vc_predicted = [[], []]  # バージカラー
for data in input_data:
    if neural_network.commit(data) < 0.5:
        st_predicted[0].append(data[0]+sl_ave)
        st_predicted[1].append(data[1]+sw_ave)
    else:
        vc_predicted[0].append(data[0]+sl_ave)
        vc_predicted[1].append(data[1]+sw_ave)


plt.scatter(st_predicted[0], st_predicted[1], label="Setosa")
plt.scatter(vc_predicted[0], vc_predicted[1], label="Versicolor")
plt.legend()

plt.xlabel("Sepal length (cm)")
plt.ylabel("Sepal width (cm)")
plt.title("Predicted")
plt.show()

# 比較用に元の分類を散布図で表示
st_data = iris_data[:50]  # セトサ
vc_data = iris_data[50:100]  # バージカラー
plt.scatter(st_data[:, 0], st_data[:, 1], label="Setosa")
plt.scatter(vc_data[:, 0], vc_data[:, 1], label="Versicolor")
plt.legend()

plt.xlabel("Sepal length (cm)")
plt.ylabel("Sepal width (cm)")
plt.title("Original")
plt.show()

ニューラルネットワークの実装

ニューラルネットワークを実装するときは必ずこの図↑を意識してください。こう行ったものを作り上げることをやっていきます。

ただし今回の記事では、ニューラルネットワークに組み込む単一ニューロンについての解説になります。上の図よりも、こちらの図をメインに扱います。

アルゴリズムを説明する用の図を用意しました。

黒枠の中では入力データを取得して、元データから平均値を差し引いています。なぜ平均値で差し引くのかというと、元データが正のデータと負のデータと両方向に散らばるような形になるからです。

正と負の、両方に散らばると、ニューラルネットワークの学習をするのに適した形になります。

こちらに関しては前回の記事で詳しく解説しています。

まず黄枠をみてください。ここでニューラルネットワークインスタンスを生成しています。

青枠の中で、初期化をします。ニューロンインスタンスの生成と初期化も行なっています。青枠の中で重み関数とバイアスの初期化を行なっていますね。重みとバイアスについて忘れた方はこちらを参考にしてください。

重み関数とバイアスをこんな風に設定しています。どうしてこんな値にしたのかは、気にしないでください。
self.w = [0.5, -0.2]
self.bias = 0.0

続いて赤枠の中の処理が始まります。input_data の中のデータを 1 行ずつ取り出しています。input_data の中には、オレンジ枠で計算したセトサとバージカラーのデータが入っています。セトサとバージカラーとは、アイリスの品種のことです。

赤枠の中で、 if 分の中で neural_network.commit メソッドが実行されます。このメソッドの帰り値が 0.5 より大きければ上段の処理を、そうでなければ下段の処理をすることになります。

neural_network.commit メソッドとは緑枠の中になります。緑枠の中の処理を行うたびに self.neuron.reset メソッドが行われ、ニューロンが初期化されます。

緑枠の中で重み関数と入力データが掛け合わされていますね。バイアスもプラスされています。return 文の中で self.neuron.get_output メソッドが実行されています。

続いて水枠の中の処理が始まります。この中でシグモイド関数による出力が出てきます。

一度赤枠に戻ります。if 文で、シグモイド関数によって吐き出された出力が 0.5 より大きいか小さいかの判断がされています。

赤枠の中の計算に注目してください。

for data in input_data:
    if neural_network.commit(data) < 0.5:
        st_predicted[0].append(data[0]+sl_ave)
        st_predicted[1].append(data[1]+sw_ave)
    else:
        vc_predicted[0].append(data[0]+sl_ave)
        vc_predicted[1].append(data[1]+sw_ave)

このような計算になっています。この計算、意味わかりますかね?

ニューロンの出力が0.5以下ならセトサという品種と判断し、0.5以上ならバージカラーという品種と判断して、それぞれ st_predicted と vc_predicted に代入しています。代入するときに、ちゃんと平均値を足し戻しているのがわかると思います。こうすることで元データの値を st_predicted と vc_predicted に格納しているのです。

そして最後に灰枠の中で散布図として表示させています。比較用に答えとなる散布図も表示させます。↓の上図は単一ニューロンで分類した散布図です。下図は答えの散布図です。

高い確率でセトサとバージカラーを分類できているのがわかるかと思います。


どうですか、簡単にですが分類問題を解くアルゴリズムを実装してみました。

コードを理解するには、一つ一つのメソッドの意味を理解することです。ここを疎かにすると、すぐに理解不能に陥ってしまいます。

次回はニューラルネットワークにもう一歩踏み込んだところをやっていきます。

疲れたでしょうが、頑張りましょう!

関連記事

コメント

この記事へのコメントはありません。

TOP