単純パーセプトロン

Image from Gyazo

単純パーセプトロン

パーセプトロン とは,動物の神経細胞(ニューロン)の発火現象を数理的に表現したモデルのことです. ウォーレン・マカロック氏とウォルター・ピッツ氏が提案した 形式ニューロン を2層のネットワーク状に接続したものは 単純パーセプトロン と呼ばれます. 単純パーセプトロンの1層目のニューロンは,入力データを伝えるだけの役割であるため,実質的には1つの形式ニューロンと考えることができます.

Image from Gyazo

ここでは,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$には下記のような種類があります.

下図はステップ関数のグラフです. ステップ関数は入力$y$が0以上なら1,0未満であれば0を出力する関数です.

Image from Gyazo

下図はシグモイド関数のグラフです. シグモイド関数は,ステップ関数とは異なり滑らかに変化する連続関数であり, 0から1の範囲を出力します.

$$ f(y) = \frac{1}{1 + e^{-y}} $$

Image from Gyazo

下図はReLU関数のグラフです. ReLU関数は入力$y$が0以上なら入力$y$をそのまま出力し, 0未満であれば0を出力する関数です.

Image from Gyazo

単純パーセプトロンの実装

ノートブックを作成し,ノートブックのタイトルを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.datafill_メソッドを利用します.

# 重みの変更
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.datafill_メソッドを利用します.

# バイアスの変更
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) をダウンロードして提出してください. 提出の前に必ず下記の設定を行ってください.

参考書籍

愛知県名古屋市にある椙山女学園大学 文化情報学部 向研究室の公式サイトです. 専門は情報科学であり,人工知能やデータベースなどの技術要素を指導しています. この公式サイトでは,授業で使用している教材を公開すると共に, ベールに包まれた女子大教員のミステリアスな日常を4コマ漫画でお伝えしていきます. サイトに関するご意見やご質問はFacebookまたはTwitterでお問い合わせください.