ようこそ。
今日は、基本的なシングルパーセプトロンニューラルネットワークの作り方を取り上げます。
CNNや転移学習など、あらゆることを深く掘り下げる連載記事の第一回にしたいと思いますので、ぜひこのサイトをブックマークしてチェックしておいてください。
また、この記事には数学も含まれますので、どうぞお付き合いください。
パーセプトロンとは
ニューラルネット(NN)の最も基本的な単位です。
複雑なNNでは、すべてのデータはこれらのいくつかを通過し、しばしば同時に、異なる役割を果たす。
しかし、それについては後で説明します。
さて、パーセプトロンとは何でしょうか?
教師あり学習では、パーセプトロンは線形分類器の一種です。
つまり、一本の直線で分けられるデータセットであれば、パーセプトロンを使って分類することができます。
つまり、次のようなデータセットです。
import pandas as pd
import numpy as np
import random
|
最後のものは、近似的にデータベースを分けることができる一本の直線ではないので、線形分離可能とは言えません。
#Dataset df = pd.DataFrame()
df[ 'x' ] = [random.randint( 1 , 20 ) for x in range ( 10 )]
df[ 'y' ] = [random.randint( 1 , 20 ) for x in range ( 10 )]
df.head() |
Single Perceptron Neural Networkを構築する
それでは、今日最初のシングルパーセプトロンニューラルネットワークを構築してみましょう。
そのために、まずはデータを作成します。
1. データセットの作成
まず、データセットが必要です。
この例では2次元配列です。
コードエディター、Jupyterノートブック、Google Colabを開いてください。
label = []
for i in range (df.shape[ 0 ]):
if df.iloc[i, 0 ] < df.iloc[i, 1 ]:
label.append( 1 )
else :
label.append( - 1 )
df[ 'label' ] = label
df |
データを作ってみましょう。
この例では、結果を小さく簡潔にするために、20*20の平面を考えています。
#weights and bias weights = [np. round (random.uniform( - 0.99 , 0.99 ), 2 ) for i in range ( 2 )]
|
さて、これらにラベルを付ける必要があります。
そこで、線(私はy=xと考えた)を基準にフィルタリングします。
つまり、線より下の点はすべてyxという意味です。
w = weights.copy()
X = [[df.iloc[i, 0 ],df.iloc[i, 1 ]] for i in range (df.shape[ 0 ])]
wx = [X[i][ 0 ] * w[ 0 ] + X[i][ 1 ] * w[ 1 ] for i in range (df.shape[ 0 ])]
|
for i in range (df.shape[ 0 ]):
if wx[i]< = 0 :
pred = 0
else :
pred = 1
|
この記事もチェック:Pythonでデータセットから別のデータセットへピボットテーブルを作成する
2. 値の重みを初期化する
さて、重みを初期化することができます。
0は使えないので、一様分布のランダムな重みにします。
for i in range (df.shape[ 0 ]):
if wx[i]< = 0 :
pred = - 1
else :
pred = 1
if pred ! = df[ 'label' ][i] :
err = df[ 'label' ][i] - pred
w[ 0 ] = w[ 0 ] + err
w[ 1 ] = w[ 1 ] + err
|
そして、重みを入力データ点と掛け合わせ、合計します。
for i in range (df.shape[ 0 ]):
print ( 'wx : ' ,wx[i])
if wx[i]< = 0 :
pred = - 1
else :
pred = 1
print ( 'label=' ,df[ 'label' ][i])
print ( 'pred = ' ,pred)
if pred ! = df[ 'label' ][i] :
err = df[ 'label' ][i] - pred
print ( 'err' ,err)
print ( 'before' , w[ 0 ],w[ 1 ])
w[ 0 ] = w[ 0 ] + err
w[ 1 ] = w[ 1 ] + err
print ( 'after' ,w[ 0 ],w[ 1 ])
else :
print ( 'w_i' , w[ 0 ],w[ 1 ])
|
これで、各ポイントの重みと入力の合計が求まりました。
これらの値を1つずつ活性化関数に代入し、出力に基づいて重みを修正する、という手順です。
3. 活性化関数の作成
さて、次は活性化関数です。
パーセプトロンは和を処理してラベルを出し、それを元のラベルと比較して正しいかどうかを判断します。
正しくない場合は誤差を求め、解が元の方向へ向くように重みを調整します。
ここではsignum関数を使用します。
wx <=0 ならば出力は0、そうでなければ出力は1です。
#Test Dataset new_df = pd.DataFrame()
new_df[ 'x' ] = [random.randint( 1 , 20 ) for x in range ( 100 )]
new_df[ 'y' ] = [random.randint( 1 , 20 ) for x in range ( 100 )]
new_df.head() |
ここで、入力はxとyの2つだけで、データフレーム全体ではないことに注意してください。
そこで、この活性化関数を拡張して、一度に1つのデータポイントを取り込み、誤差を求め、その誤差を調整することにします。
label_text = []
for i in range (new_df.shape[ 0 ]):
if new_df.iloc[i, 0 ] < new_df.iloc[i, 1 ]:
label_text.append( 1 )
else :
label_text.append( - 1 )
new_wX = w[ 0 ] * new_df[ 'x' ] + w[ 1 ] * new_df[ 'y' ]
|
これで完璧に動作するようになりました。
出力を明確に見るために、printステートメントをたくさん入れてみましょう。
new_df[ 'given label' ] = label_text
pred_label_text = []
for i in range (new_df.shape[ 0 ]):
if new_wX[i]> = 0 :
pred_label_text.append( - 1 )
else :
pred_label_text.append( 1 )
new_df[ 'predicted labels' ] = pred_label_text
|
そして、これを実行すると
単純なプリント・フォーマット文が最終的な重みを与えてくれます。
4. 別のデータベースでモデルをテストする
訓練とテストの分割と同様に、ここでは別のデータベースを使用してテストします。
そして、y=xの線と、weights*inputsの和からラベルを生成します。
これが私のものです。
さて、いよいよ活性化関数を適用して、与えられたラベルと予測されたラベルを比較します。
見ての通り、かなりうまくいったと思います。
まとめ
このチュートリアルを終えることができ、おめでとうございます。
パーセプトロン」についての理解を深めていただけたでしょうか。
今後のチュートリアルを読むために、私たちと連絡を取り合ってください。