Edited at

Python vs Ruby 『ゼロから作るDeep Learning』 2章 パーセプトロンによる論理回路

More than 1 year has passed since last update.


概要

書籍『ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装』2章のコードを参考に Python と Ruby でパーセプトロンによる論理回路

(ANDゲート, NANDゲート, ORゲート, XORゲート)を実装する。

計算処理では外部ライブラリを利用する。Python では NumPy を、Ruby では Numo::NArray を使用する。

環境構築が必要な場合はこちらを参照。

→ Python vs Ruby 『ゼロから作るDeep Learning』 1章 sin関数とcos関数のグラフ http://qiita.com/niwasawa/items/6d9aba43f3cdba5ca725


ANDゲート

重みとバイアスは、人力で適切な値を導いたもの。


Python

and_gate.py

import numpy as np

def AND(x1, x2):
x = np.array([x1, x2])
w = np.array([0.5, 0.5]) # 重み
b = -0.7 # バイアス
tmp = np.sum(w*x) + b
if tmp <= 0:
return 0
else:
return 1

if __name__ == '__main__':
for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]:
y = AND(xs[0], xs[1])
print(str(xs) + " -> " + str(y))


Ruby

and_gate.rb

require 'numo/narray'

def AND(x1, x2)
x = Numo::DFloat[x1, x2]
w = Numo::DFloat[0.5, 0.5] # 重み
b = -0.7 # バイアス
tmp = (w*x).sum + b
if tmp <= 0
0
else
1
end
end

if __FILE__ == $0
for xs in [[0, 0], [1, 0], [0, 1], [1, 1]]
y = AND(xs[0], xs[1])
puts "#{xs} -> #{y}"
end
end


実行結果

Python と Ruby の実行結果を比較する。入力が同じ値の場合は、出力も同じ値になっていることがわかる。

$ python and_gate.py

(0, 0) -> 0
(1, 0) -> 0
(0, 1) -> 0
(1, 1) -> 1

$ ruby and_gate.rb
[0, 0] -> 0
[1, 0] -> 0
[0, 1] -> 0
[1, 1] -> 1


NANDゲート

NANDゲートの実装は、重みとバイアスだけがANDゲートと異なる。


Python

nand_gate.py

import numpy as np

def NAND(x1, x2):
x = np.array([x1, x2])
w = np.array([-0.5, -0.5])
b = 0.7
tmp = np.sum(w*x) + b
if tmp <= 0:
return 0
else:
return 1

if __name__ == '__main__':
for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]:
y = NAND(xs[0], xs[1])
print(str(xs) + " -> " + str(y))


Ruby

nand_gate.rb

require 'numo/narray'

def NAND(x1, x2)
x = Numo::DFloat[x1, x2]
w = Numo::DFloat[-0.5, -0.5]
b = 0.7
tmp = (w*x).sum + b
if tmp <= 0
0
else
1
end
end

if __FILE__ == $0
for xs in [[0, 0], [1, 0], [0, 1], [1, 1]]
y = NAND(xs[0], xs[1])
puts "#{xs} -> #{y}"
end
end


実行結果

$ python nand_gate.py

(0, 0) -> 1
(1, 0) -> 1
(0, 1) -> 1
(1, 1) -> 0

$ ruby nand_gate.rb
[0, 0] -> 1
[1, 0] -> 1
[0, 1] -> 1
[1, 1] -> 0


ORゲート

ORゲートの実装も、重みとバイアスの値のみ異なる。


Python

or_gate.py

import numpy as np

def OR(x1, x2):
x = np.array([x1, x2])
w = np.array([0.5, 0.5])
b = -0.2
tmp = np.sum(w*x) + b
if tmp <= 0:
return 0
else:
return 1

if __name__ == '__main__':
for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]:
y = OR(xs[0], xs[1])
print(str(xs) + " -> " + str(y))


Ruby

or_gate.rb

require 'numo/narray'

def OR(x1, x2)
x = Numo::DFloat[x1, x2]
w = Numo::DFloat[0.5, 0.5]
b = -0.2
tmp = (w*x).sum + b
if tmp <= 0
0
else
1
end
end

if __FILE__ == $0
for xs in [[0, 0], [1, 0], [0, 1], [1, 1]]
y = OR(xs[0], xs[1])
puts "#{xs} -> #{y}"
end
end


実行結果

$ python or_gate.py

(0, 0) -> 0
(1, 0) -> 1
(0, 1) -> 1
(1, 1) -> 1

$ ruby or_gate.rb
[0, 0] -> 0
[1, 0] -> 1
[0, 1] -> 1
[1, 1] -> 1


XORゲート

XORゲートの実装では、NAND・OR・ANDのゲートを重ねた多層パーセプトロンを使う。


Python

xor_gate.py

from and_gate  import AND

from or_gate import OR
from nand_gate import NAND

def XOR(x1, x2):
s1 = NAND(x1, x2)
s2 = OR(x1, x2)
y = AND(s1, s2)
return y

if __name__ == '__main__':
for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]:
y = XOR(xs[0], xs[1])
print(str(xs) + " -> " + str(y))


Ruby

xor_gate.rb

require './and_gate'

require './or_gate'
require './nand_gate'

def XOR(x1, x2)
s1 = NAND(x1, x2)
s2 = OR(x1, x2)
y = AND(s1, s2)
return y
end

if __FILE__ == $0
for xs in [[0, 0], [1, 0], [0, 1], [1, 1]]
y = XOR(xs[0], xs[1])
puts "#{xs} -> #{y}"
end
end


実行結果

$ python xor_gate.py

(0, 0) -> 0
(1, 0) -> 1
(0, 1) -> 1
(1, 1) -> 0

$ ruby xor_gate.rb
[0, 0] -> 0
[1, 0] -> 1
[0, 1] -> 1
[1, 1] -> 0


参考資料