単純パーセプトロン
単純パーセプトロン
パーセプトロン とは,動物の神経細胞(ニューロン)の発火現象を数理的に表現したモデルのことです. ウォーレン・マカロック氏とウォルター・ピッツ氏が提案した 形式ニューロン を2層のネットワーク状に接続したものは 単純パーセプトロン と呼ばれます. 単純パーセプトロンの1層目のニューロンは,入力データを伝えるだけの役割であるため,実質的には1つの形式ニューロンと考えることができます.
ここでは,2入力,1出力の単純パーセプトロンを考えます. 下記の式に従って,入力された$x_1$と$x_2$から,中間出力$y$を得ます. ここで,$w_1$と$w_2$は入力に対する 重み です. また,$w_0$は バイアス と呼ばれ,出力の閾値として用いられます.
$$ y = w_1 \times x_1 + w_2 \times x_2 + w_0 $$
この中間出力$y$に対して,活性化関数 $f$と呼ばれる特殊な関数を適用して, 得られた値を最終的なニューロンの出力$z$とします.
$$ z = f(y) $$
一般に$n$入力の単純パーセプトロンは,入力${\bf x}$と重み${\bf w}$は下記のようにベクトルで表現されます. ここで,$x_0=1$はバイアス$w_0$を導入するために用いられます. パーセプトロンが多層になると,ベクトル表現が必須となりますので,慣れておきましょう.
$$
{\bf x} = (1, x_1, \cdots, x_n) \\
{\bf w} = (w_0, w_1, \cdots, w_n) \\
y = {\bf x} \cdot {\bf w} \\
z = f(y)
$$
活性化関数$f$には下記のような種類があります.
- ステップ関数
- シグモイド関数
- ReLU(Rectified Linear Unit)関数
下図はステップ関数のグラフです. ステップ関数は入力$y$が0以上なら1,0未満であれば0を出力する関数です.
下図はシグモイド関数のグラフです. シグモイド関数は,ステップ関数とは異なり滑らかに変化する連続関数であり, 0から1の範囲を出力します.
$$ f(y) = \frac{1}{1 + e^{-y}} $$
下図はReLU関数のグラフです. ReLU関数は入力$y$が0以上なら入力$y$をそのまま出力し, 0未満であれば0を出力する関数です.
単純パーセプトロンの実装
ノートブックを作成し,ノートブックのタイトルをchapter2 に設定します. それでは,単純パーセプトロンを PyTorch を利用して実装してみましょう. まずは,PyTorchをインストールし,PyTorchとNumpyをインポートします.
!pip install torch
!pip install torchvision
import torch
import torch.nn as nn
import numpy as np
単純パーセプトロンのネットワークを生成します.
nn.Sequential
は,パーセプトロンの層を追加した順番に並べます.
最初に2入力・1出力の層nn.Linear(2, 1)
を作成します.
その出力をシグモイド関数nn.Sigmoid()
に伝え,最終的な出力を得ています.
# 単純パーセプトロン
network = nn.Sequential(
nn.Linear(2, 1),
nn.Sigmoid()
)
print(network)
#出力
Sequential(
(0): Linear(in_features=2, out_features=1, bias=True)
(1): Sigmoid()
)
重みやバイアスなどのパラメータ$w$は,ランダムに初期化されています. ここでは,下記のようにパラメータを強制的に変更します.
$$ {\bf w} = (w_0, w_1, w_2) = (-0.5, 0, 1) $$
パーセプトロンの各層には,配列として参照することが可能です.
network[0]
は先程作成した2入力・1出力の層です.
重みを変更するには,network[0].weight.data
のfill_
メソッドを利用します.
# 重みの変更
network[0].weight.data[0][0].fill_(0)
network[0].weight.data[0][1].fill_(1)
print(network[0].weight)
#出力
Parameter containing:
tensor([[0., 1.]], requires_grad=True)
バイアスを変更するには,network[0].bias.data
のfill_
メソッドを利用します.
# バイアスの変更
network[0].bias.data.fill_(-0.5)
print(network[0].bias)
#出力
Parameter containing:
tensor([-0.5000], requires_grad=True)
単純パーセプトロンの入力${\bf x}=(x_1, x_2)$をテンソルとして作成します(ここではバイアスは除きます).
$$ {\bf x} = (x_1, x_2) = (1, 1) $$
# 入力
x = torch.tensor([1, 1], dtype=torch.float)
print(x)
#出力
tensor([1., 1.])
単純パーセプトロンに${\bf x}$を入力し,出力$z$を得ます.
z = network(x)
print(z)
#出力
tensor([0.6225], grad_fn=<SigmoidBackward>)
出力$z$は 0.6225 になりました. この値が正しいか確認してみましょう. 定義に従って計算すると,PyTorchで作成した単純パーセプトロンと出力が一致していることが分かります.
def sigmoid(x):
return 1 / (1 + np.exp(-1 * x))
x = np.array([1, 1, 1]) #入力
w = np.array([-0.5, 0, 1]) #重みとバイアス
y = x.dot(w) #中間出力
z = sigmoid(y) #シグモイド関数
print(z)
#出力
0.6224593312018546
課題
Google Colaboratoryで作成した chapter2.ipynb を保存し, 共有用のリンク と ノートブック(.ipynb) をダウンロードして提出してください. 提出の前に必ず下記の設定を行ってください.
- ノートブックの設定で「セルの出力を除外する」のチェックを外す
- ノートブックの変更内容を保存して固定
- 共有設定で「学校法人椙山女学園大学」を「閲覧者」に設定