NeuroWhAI의 잡블로그

[Rust] 퍼셉트론 - '밑바닥부터 시작하는 딥러닝' 2장 본문

개발 및 공부/알고리즘

[Rust] 퍼셉트론 - '밑바닥부터 시작하는 딥러닝' 2장

NeuroWhAI 2018. 7. 14. 14:07


1장은 건너뛰고 책에서 미리 준비된 코드를 사용해서 진행하는 실습도 건너뛰었습니다.
남은건 퍼셉트론 뿐...
예제는 퍼셉트론으로 AND, OR, NAND 그리고 이를 조합하여 XOR 게이트를 구현한 코드입니다.

코드:
use rulinalg::matrix::BaseMatrix;

pub fn and_gate(x1: f32, x2: f32) -> f32 {
	let x = matrix![x1, x2];
	let w = matrix![0.5, 0.5];
	let b = -0.7;
	
	let out = x.elemul(&w).sum() + b;
	
	if out > 0.0 {
		1.0
	}
	else {
		0.0
	}
}

pub fn or_gate(x1: f32, x2: f32) -> f32 {
	let x = matrix![x1, x2];
	let w = matrix![0.5, 0.5];
	let b = -0.2;
	
	let out = x.elemul(&w).sum() + b;
	
	if out > 0.0 {
		1.0
	}
	else {
		0.0
	}
}

pub fn nand_gate(x1: f32, x2: f32) -> f32 {
	let x = matrix![x1, x2];
	let w = matrix![-0.5, -0.5];
	let b = 0.7;
	
	let out = x.elemul(&w).sum() + b;
	
	if out > 0.0 {
		1.0
	}
	else {
		0.0
	}
}

pub fn xor_gate(x1: f32, x2: f32) -> f32 {
	let s1 = nand_gate(x1, x2);
	let s2 = or_gate(x1, x2);
	and_gate(s1, s2)
}
fn test_gate(name: &str, gate: fn(f32, f32) -> f32) {
	let input = [
		[0.0, 0.0],
		[0.0, 1.0],
		[1.0, 0.0],
		[1.0, 1.0],
	];
	
	println!("{}", name);
	
	for x in input.iter() {
		let x1 = x[0];
		let x2 = x[1];

		println!("({}, {}) -> {}", x1, x2, gate(x1, x2));
	}
}

pub fn tests() {
	test_gate("AND", perceptron::and_gate);
	test_gate("OR", perceptron::or_gate);
	test_gate("NAND", perceptron::nand_gate);
	test_gate("XOR", perceptron::xor_gate);
}

결과:
AND
(0, 0) -> 0
(0, 1) -> 0
(1, 0) -> 0
(1, 1) -> 1
OR
(0, 0) -> 0
(0, 1) -> 1
(1, 0) -> 1
(1, 1) -> 1
NAND
(0, 0) -> 1
(0, 1) -> 1
(1, 0) -> 1
(1, 1) -> 0
XOR
(0, 0) -> 0
(0, 1) -> 1
(1, 0) -> 1
(1, 1) -> 0


이 챕터에서 중요한건 각 게이트 코드에서 바뀐건 w와 b뿐이라는거죠.
하나의 아키텍쳐를 가지고 여러 작업에 특화시킬 수 있다는걸 보여줍니다.
다만 단층 퍼셉트론으론 선형분리 문제만 해결할 수 있으며 XOR같은 비선형 문제를 해결하려면 조합을 하여 다층으로 구성해야 합니다.


전체 소스코드는 GitHub에서 보실 수 있습니다.



Comments