본문 바로가기

기계학습

인공신경망 Neural Network #1

이 글의 전체 예제는 https://github.com/Kcrong/basic-neural-network 에 있습니다.

이 글은 http://blog.secmem.org/197 을 참고했으며, 모든 예제를 직접 작성하였습니다.



1. 뉴럴 네트워크란?

컴퓨터 공학에서 뉴럴 네트워크란, 인공지능 분야의 기술로 인간의 뇌 속에 있는 신경을 모델링 하여 문제를 해결하는 방법을 말합니다.


2. 뉴런이란?

뉴런은 신경망을 구성하는 신경세포 한 개를 말합니다.

뉴런 하나는 단순히 전기 신호를 전달하는 역할 밖에 없지만, 이 뉴런이 엄청 모이면 인간의 지능을 가지게 됩니다. (실제 인간은 1000억개의 뉴런을 가지고 있다 합니다.)


뉴런의 동작방식은 다음과 같습니다.


출처: 나무 위키

Cell Body    : 세포체

Nucleus    : 세포핵

Dendrites    : 가지 돌기 (수상 돌기)

Axon            : 축삭

Axon Hillock    : 축삭소구

Axon Ending    : 축삭말단

Myelin sheath    : 말이집

Nodes of Ranvier    : 랑비에 결절

Synapse        :  시냅스


뉴런은 핵을 중심으로 여러 개의 작은 가지 돌기와 한 개의 커다란 축삭이 뻗어 나와 있습니다.


가지 돌기가 다른 뉴런이 보내주는 신호를 전달 받는 곳입니다. (Input) 한 개의 뉴런은 수상 돌기를 통해 1만 ~ 10만 개 정도의 뉴런과 연결되어 있다고 합니다.


축삭 이라고 하는 커다란 돌기가 다른 뉴런에게 신호를 전달하는 역할을 합니다. (Output) 뉴런 당 하나의 축삭을 가지고 있습니다.


가지 돌기와 축삭, 각각 Input 과 Output 을 알아보았는데, 뉴런은 신호를 전달만 하는 것이 아닙니다.

따라서 연산이 가능합니다.


뉴런과 뉴런은 시냅스로 연결되어 있습니다. 시냅스는 전기신호를 화학신호로 바꾸어 전달하게 되는데, 각 시냅스 마다 연결 강도가 달라 이 화학 신호의 강도도 제각각으로 전달되게 됩니다.


뉴런은 다른 뉴런에게 받은 이 신호 강도의 합이 일정한 값 (역치값) 이상이 되면 축삭에 전기신호를 전달합니다.


정리하면,

1. 가지 돌기는 다른 여러 개의 뉴런에게 화학 신호를 받아들인다.

2. 각 연결 부의 화학 신호의 강도 (연결 강도)가 다르다

3. 받아들인 화학신호 강도의 합이 역치값 이상이면 축삭으로 전기신호를 전달한다.

4. 축삭의 전기신호가 다른 뉴런에게 전달된다.


이제 이걸 파이썬 코드로 옮기면 됩니다.


3. 기본 뉴런 만들기


우선 기본 뉴런 클래스를 만듭니다.


class Neuron:
def __init__(self, name):
# Private Var
self._next = list() # 연결된 다음 뉴런을 저장할 list 변수
self._weight = dict() # 가중치 dict 변수
self.data = None # 이 뉴런의 데이터 합을 저장할 변수
self.threshold = 0 # 역치 값 (여기선 0으로 설정)
if name is None:
name = randomkey(5)
self.name = name # 식별을 위한 이름 설정

def link_neuron(self, next_neuron, weight=None):
"""
:param next_neuron: 연결할 뉴런
:param weight: 연결할 뉴런과의 가중치
"""
self._next.append(next_neuron)
if not weight:
weight = random()
self._weight[next_neuron] = weight

def __repr__(self):
return "<Neuron %s>" % self.data

def go_next(self):
if self.data >= self.threshold: # 역치 값 비교 (역치 값보다 데이터 합이 작으면 다음 뉴런으로 전달하지 않음)
for next_neuron in self._next: # 자신과 연결된 모든 뉴런에서
next_data = self.data * self._weight[next_neuron] # 전달할 데이터 연산 (가중치 * 자신의 데이터)

if next_neuron.data: # 전달할 뉴런의 데이터가 None 이 아니면
next_neuron.data += next_data
else: # None 일 경우, 전달 데이터로 초기화
next_neuron.data = next_data
else:
pass


뉴런 네트워크는 연산 속도를 위해 객체 지향으로 작성하는 경우가 적지만, 이해를 위해 객체지향으로 작성해 보았습니다.