목록rust (50)
NeuroWhAI의 잡블로그
※ 실제로 동작하는 전체 소스코드는 GitHub에서 보실 수 있습니다. (가중치 초기화 방법들(Xavier, He)은 코드로 구현은 하였지만 글은 넘어갑니다.) 드롭아웃은 오버피팅(과적합)을 방지하기 위해서 순전파시 일정 확률로 특정 출력값을 0으로 만들고 역전파시에도 기울기의 해당 부분들을 0으로 만들어서 보냅니다. 보통 일정 확률로 신경망의 뉴런을 비활성화한다 혹은 끈다고 설명합니다. 학습이 좀 느려진다는 단점은 있지만 쉽게 과적합을 어느정도 이겨낼 수 있습니다. 비슷하게 배치정규화라는 놈도 과적합을 방지해주지만 이건 학습 속도가 훨씬 빠릅니다. 아래 코드는 드롭아웃 계층을 어떻게 구현했는지만 넣어놨습니다. 코드: impl Layer for Dropout { fn forward(&mut self, x..
https://stackoverflow.com/questions/28519997/what-are-rusts-exact-auto-dereferencing-rules 위 글을 공부하여 정리한 글입니다. Rust에서 x.bar()처럼 메소드를 호출하는건 T::bar(x)와 같은데 이때 bar의 self와 x가 일치하지 않으면 auto-dereferencing rules이 수행됩니다. 설명하기 전에 단어, 문자 용어 정리하고 하겠습니다. Receiver type : 메소드의 self 타입 (Self가 Foo이고 fn bar(&self);라면 &Foo가 됩니다. Self가 &Foo이고 fn bar(self);여도 &Foo.) x : 메소드의 self로 들어갈 값 T : x의 타입 U : 각 역참조 단계에서의 타입..
Rust. Change mutable reference to immutable. &mut T 형식으로 받았는데 원하는 메소드가 &T에만 구현된 경우가 있었습니다.(C++ 사용자는 뭔소리야 싶겠지만 Rust는 타입이 사용된 상태?마다 다르게 메소드를 구현할 수 있습니다.)아래는 그 오류를 재연한 예제입니다. https://ideone.com/YeENwm trait FooPow { fn pow(&self) -> i32; } struct Foo(i32); impl i32 { self.0 * self.0 } } /*impl i32 { self.0 * self.0 } }*/ fn test1(x: &Foo) { println!("{}", x.pow()); } fn test2(x: &mut Foo) { println..
※ 실제로 동작하는 전체 소스코드는 GitHub에서 보실 수 있습니다. 매개변수라 함은 학습시 손실을 줄이기 위해 조절하는 변수들을 말합니다. 가중치나 편향 등을 매개변수라고 할 수 있습니다. 이때까지는 매개변수를 단순히 학습률과 기울기의 곱으로 빼서 갱신했지만 그것보다 더 잘할 수 있는 방법이 많습니다. 참고로 이때까지 사용한 방법은 SGD(확률적 경사 하강법)로 볼 수 있습니다. 아래 코드는 5장에서 구현했던 신경망을 살짝 수정해서 여러 매개변수 갱신법을 사용해 MNIST 학습을 진행하는 예제입니다. 코드: use std::collections::HashMap; use rulinalg::matrix::{Matrix, BaseMatrix, BaseMatrixMut}; use common::utils; ..
※ 실제로 동작하는 전체 소스코드는 GitHub에서 보실 수 있습니다. 5장의 마지막입니다. ReLU, Affine 등의 레이어를 잘 구현해서 쌓아올리기만 하면 학습이 가능한 신경망을 만들 수 있습니다.이게 가능한 이유는 체인룰 덕분이고 이전 글에서 계산 그래프를 통해 설명되었습니다. forward, backward 메소드에 주목하셔야 하는데 forward는 흔히 아시는 순전파에 역전파에 사용할 값을 기억해두는 역할도 합니다. backward가 역전파이고 뒷 계층의 기울기(dout)를 받아 현재 계층의 기울기를 구하여 저장한 뒤 앞 계층으로 넘겨줍니다. 아래 코드는 Affine - ReLU - Affine - Softmax 순서로 계층을 쌓아 만든 신경망으로 MNIST를 학습하는 예제입니다. 이전에 수치..
※ 실제로 동작하는 전체 소스코드는 GitHub에서 보실 수 있습니다. 5장에서는 계산 그래프라는 방법을 통해 순전파, 역전파를 가르쳐줍니다. 연쇄 법칙(Chain rule) 덕분에 각 층의 자체(?) 기울기를 곱하면서 역전파하면 각 층의 최종 기울기를 얻을 수 있습니다. 아래 코드는 간단하게 덧셈, 곱셈 레이어를 만들고 이를 사용하여 사과, 오렌지의 가격을 순전파로 계산한 다음 역전파로 각 요소가 최종 가격에 끼치는 기울기를 계산하는 예제입니다. 코드: pub struct MulLayer { x: f32, y: f32, } impl MulLayer { pub fn new() -> Self { MulLayer { x: 0.0, y: 0.0 } } pub fn forward(&mut self, x: f32..
※ 실제로 동작하는 전체 소스코드는 GitHub에서 보실 수 있습니다. 이번에는 이때까지 구현한 기능을 조합하여 2층 신경망을 만들어봅니다. 다만 수치 미분을 사용했기에 매우 느려 학습이 잘 되는지는 확인하지 못했으니 대충 흐름만 보시면 되겠습니다. 코드에서 MNIST 데이터셋과 관련된 부분은 포함하지 않았으니 관심있으신 분은 GitHub에서 보시면 되겠습니다.또한 속도를 높히기 위하여 데이터셋의 일부만 학습에 사용하였고테스트를 위해 사용했던 해석적 미분을 이용한 부분은 주석 처리 해두었습니다. 코드: use std::f32; use rulinalg::matrix::{Matrix, BaseMatrix, BaseMatrixMut}; use rand; use ch03::activation; use commo..
※ 실제로 동작하는 전체 소스코드는 GitHub에서 보실 수 있습니다. 이전에 신경망의 학습은 손실 함수의 값을 최소화하는 방향으로 파라미터를 조정한다고 했습니다. 그럼 파라미터를 어떻게 조절해야 손실이 줄어드는지 알 수 있을까요? 저는 미적분을 제대로 배우지 않았지만 미분은 값의 변화와 관련이 있다는건 압니다. 그러니까 L = f(x)이고 x가 d만큼 변했을때 L은 d의 몇 배만큼 변하는지가 미분이라고 대충 알고 있습니다. 여기서 L을 손실, f를 손실 함수 + 신경망, x를 파라미터라고 하면 대충 윤곽이 보이죠. 우리는 f 함수를 미분하여 기울기를 구해 x를 올바른 방향으로 조절할 수 있습니다. 그런데 저 같은 수포자에게 함수를 미분하라는건 힘든 일입니다. 그러나 수치 미분이란 방법을 쓰면 해석적 미..
※ 실제로 동작하는 전체 소스코드는 GitHub에서 보실 수 있습니다. 손실 함수는 신경망의 학습 정도를 수치화하는데 사용되는 함수입니다. 손실 함수의 값을 최소화하는 방향으로 신경망의 파라미터들을 조정하는게 학습입니다. 여러 종류가 있는데 보통은 어떤 문제를 푸느냐에 따라 다른 함수를 사용하는 것 같습니다. 아래 코드는 대표적인 손실 함수인 MSE와 Cross entropy를 구현하고 손실값을 계산해보는 예제입니다. 코드: use rulinalg::matrix::{Matrix, BaseMatrix, BaseMatrixMut}; pub fn mean_squared_error(y: &Matrix, t: &Matrix) -> f32 { let mut err = y - t; err = err.apply(&|v..
※ 실제로 동작하는 전체 소스코드는 GitHub에서 보실 수 있습니다. 활성화 함수는 뉴런에서 입력을 받아 합산한 값을 출력으로 내보낼때 거치는 함수입니다. 어떤 활성화 함수를 사용하느냐도 학습에 중요한 요소로 작용합니다. 책에서는 계단 함수, 시그모이드, ReLU(렐루?)를 소개하고 있습니다. 코드: use rulinalg::matrix::{Matrix, BaseMatrixMut}; pub fn step_function(x: Matrix) -> Matrix { x.apply(&|value| if value > 0.0 { 1.0 } else { 0.0 }) } pub fn sigmoid(x: Matrix) -> Matrix { x.apply(&|value| 1.0 / (1.0 + (-value).exp(..