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

前回の記事では単一のニューロンの実装を行いました。重み関数とバイアスを導入して、入力データを処理してから、シグモイド関数(活性化関数)で出力するというところまでやったと思います。
今回の記事は単一ニューロンからなるニューラルネットワークを使って、アイリスデータを2品種に分類することをやってみようかと思います。
今回の記事を読む前に、外部データの取り込み方や散布図のプロットの仕方をきちんと理解する必要があります。もし、理解が不十分だと思われる方はこちらを先に読んでください。
きちんと読み込んだ前提でアルゴリズムを解説していきます。基本的なことを理解できていなかったら置いてきぼりになってしまいます。必ず読み込むようにしてください。
先に貼り付け用のコードを載せておきます。
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()
単一ニューロンによる分類のアルゴリズム
まず青枠の中をみてください。
sl_data = iris_data[:100, 0] sw_data = irisdata[:100, 1] となってますね。
sl_data にはセトサとバージカラーの、萼の長径データを取り込ませます。同様に sw_data には萼の短径データを取り込ませてあります。

青枠の中で
sl_ave = np.average(sl_data) sw_ave = np.average(sw_data)
となっていますね。np.average というのは numpy の機能の一つです。一番最初で numpy をインポートしていなかったらここでエラーが出ます。
Python だと、平均値の計算が非常に楽でいいですね。C なんかだと、平均値を計算するためにわざわざ配列を宣言して、for 文を回したりしなくちゃいけないので、めっちゃ大変です(^^;;。
青枠において sl_data -= sl_ave sw_data -= sw_ave
こんな計算がされてます。元データから平均値を差し引いています。
なぜ平均値で差し引くのかというと、元データが正のデータと負のデータと両方向に散らばるような形になるからです。
正と負の、両方に散らばると、ニューラルネットワークの学習をするのに適したデータになります。
sl_data -= sl_ave は sl_data = sl_data - sl_ave と同じ計算になります。 x += 10 は x = x + 10 と同じ計算になります。x に 10 を加えるだけの演算です。 こういう計算の書き方も覚えるようにしてください。今後多用します。 プログラミングにおいて、= は「右辺のものを左辺にぶち込む」という意味になります。
input_data = []
for i in range(100): # iには0から99までが入る
input_data.append([sl_data[i], sw_data[i]])
この↑コードでは sl_data と sw_data に入っているデータを一つずつ取り出して、input_data という配列に格納しています。for 文の中で range(100) となっているのは、0 から始めて、for 文が一回回るたびに i に 1 が追加され、i が 100 になるまで for 文を回すという感じになります。
sl_data と sw_data に入っていたデータが全て input_data のなかに格納されます。100 行 2 列の データ構造になります。
ところで、ぶっちゃけていうと 0~49 番目のデータは全てセトサですし、50~99 番目のデータは全てバージカラーです。ある程度整理された格好になっているのですが、バージカラーとセトサのデータがごちゃ混ぜになっていると考えてください。
いかがですか。
今回は下準備なので、ここまでにします。
次回は本格的にアルゴリズムを解説していこうと思います。バージカラーとセトサがごちゃ混ぜになったと仮定して解説していきます。
ニューラルネットワークを実装して、分類をしていこうかと思います。
コメント