DEEP.I - Lab

오프라인 공간의 지능화를 꿈꾸는 딥아이 연구실입니다.

Python/Python

[Python] 파이썬을 이용한 다층신경망 (Multi-Layer Perceptron: MLP) 구현하기 (XOR 문제)

Jongwon Kim 2020. 11. 28. 00:55
반응형

1986년 역전파 알고리즘 (Backpropagation)의 개념이 도입되면서 Machine Learning이 다시 주목받게 되었습니다. 기존 단층 신경망으로는 해결할 수 없었던 비선형 문제 해결이 가능한 다층 신경망은 현재 응용되고 있는 CNN(Convolutional Neural Networks)의 기반이 되고 있습니다. 이번 포스팅에서는 파이썬을 이용해서 다층 신경망을 구현해 보록 하겠습니다. 

 

 

 

그림 1. 퍼셉트론의 기본 구조

 

 

매트랩을 이용한 다층신경망 구현 포스팅과 동일한 메커니즘으로 설계했습니다. 매트랩 코드는 이전 포스팅을 참고해 주시길 바랍니다.

 

deep-eye.tistory.com/16

 

[Matlab] 매트랩을 이용한 다층신경망 (Multi-Layer Perceptron: MLP) 구현하기 (XOR 문제)

1986년 역전파 알고리즘 (Backpropagation)의 개념이 도입되면서 Machine Learning이 다시 주목받게 되었습니다. 기존 단층 신경망으로는 해결할 수 없었던 비선형 문제 해결이 가능한 다층 신경망은 현재

deep-eye.tistory.com

 

1. 샘플 코드 다운로드

 

git clone https://github.com/DEEPI-LAB/python-simple-multi-layer-neural-network-implementation.git

 

github.com/DEEPI-LAB/python-simple-multi-layer-neural-network-implementation

 

DEEPI-LAB/python-simple-multi-layer-neural-network-implementation

Python implementation of multi-layer perceptron (MLP) neural networks using only numpy and matplotlib - DEEPI-LAB/python-simple-multi-layer-neural-network-implementation

github.com

2. 학습 데이터 생성 및 파라미터 초기화 

 

import numpy as np
from matplotlib import pyplot as plt

# train data (XOR Problem)
x = np.array([[0,0],[0,1],[1,0],[1,1]])
y = np.array([0,1,1,0])

# Intialization

# input - hidden layer
w1 = np.random.randn(2,2)
b1 = np.random.randn(1,2)

# hidden - output layer
w2 = np.random.randn(1,2)
b2 = np.random.randn(1)

# epoch
ep = 20000

# learning rate
lr = 1
mse = []

 

[입력 - 은닉 - 출력]으로 구성된 MLP의 기본 구조를 사용했습니다. w1과 b1은 입력층과 은닉층의 가중치와 바이어스, w2과 b2는 은닉층과 출력층의 가중치와 바이어스입니다. 초기값은 모두 가우시안 랜덤 값으로 초기화했습니다.

 

 

3. 신경망 순전파 출력 단계

 

# Neural Networks 2-2-1
for i in range(ep):
    
    E  = np.array([])
    result = np.array([])
    
    for j in range(len(x)):
        Ha = np.array([])
        
        # feedforward
        # input - hidden layer
        for k in range(len(w1)):
            Ha = np.append(Ha,1 / (1 + np.exp(-(np.sum(x[j] * w1[k]) + b1[0][k]))))
        
        # hideen - output layer
        Hb = 1 / (1 + np.exp(-(np.sum(Ha * w2) + b2)))
        
        # error
        E = np.append(E,y[j] - Hb)
        result = np.append(result,Hb)

 

시그모이드 활성화 함수를 사용했습니다. 2차원 데이터 입력 - 2개의 은닉층 노드로 구성하여 별도의 행렬 연산 과정이 필요 없지만, 은닉층의 노드 수나 입력 데이터의 차원을 다르게 설계하면 이에 맞춰 변형해야 합니다.

 

 

4. 신경망 역전파 업데이트 단계

 

        # back-propagation
        # output - hidden layer
        alpha_2 = E[j] * Hb * (1-Hb)
        
        # hidden - input layer
        alpha_1 = alpha_2 * Ha * (1-Ha) * w2
        
        # update
        w2 = w2 + (lr * alpha_2 * Ha)
        b2 = b2 + lr * alpha_2
        
        w1 = w1 + np.ones((2,2)) * lr * alpha_1 * x[j]
        b1 = b1 +  lr * alpha_1

 

신경망 학습 알고리즘의 핵심, 역전파 단계입니다. 자세한 설명은 생략하겠습니다. 추후 머신러닝 관련 포스팅을 통해 자세히 다루어보도록 하겠습니다. 자료와 코드는 쌓여있는데 이걸 정리하기가 쉽지 않네요 ㅠ

 

 

5. 최종 코드

 

# -*- coding: utf-8 -*-
"""
Neural Network Multi-Layer Perseptron (XOR Problem)
@author: Deep.I Inc. @Jongwon Kim
Revision date: 2020-11-28
See here for more information :
    https://deep-eye.tistory.com/16
    https://deep-i.net
"""

import numpy as np
from matplotlib import pyplot as plt

# train data (XOR Problem)
x = np.array([[0,0],[0,1],[1,0],[1,1]])
y = np.array([0,1,1,0])

# Intialization

# input - hidden layer
w1 = np.random.randn(2,2)
b1 = np.random.randn(1,2)

# hidden - output layer
w2 = np.random.randn(1,2)
b2 = np.random.randn(1)

# epoch
ep = 20000
# learning rate
lr = 1
mse = []

# Neural Networks 2-2-1
for i in range(ep):
    
    E  = np.array([])
    result = np.array([])
    
    for j in range(len(x)):
        Ha = np.array([])
        
        # feedforward
        # input - hidden layer
        for k in range(len(w1)):
            Ha = np.append(Ha,1 / (1 + np.exp(-(np.sum(x[j] * w1[k]) + b1[0][k]))))
        
        # hideen - output layer
        Hb = 1 / (1 + np.exp(-(np.sum(Ha * w2) + b2)))
        
        # error
        E = np.append(E,y[j] - Hb)
        result = np.append(result,Hb)
        
        # back-propagation
        # output - hidden layer
        alpha_2 = E[j] * Hb * (1-Hb)
        
        # hidden - input layer
        alpha_1 = alpha_2 * Ha * (1-Ha) * w2
        
        # update
        w2 = w2 + (lr * alpha_2 * Ha)
        b2 = b2 + lr * alpha_2
        
        w1 = w1 + np.ones((2,2)) * lr * alpha_1 * x[j]
        b1 = b1 +  lr * alpha_1
        
    print('EPOCH : %05d MSE : %04f RESULTS : 0 0 => %04f 0 1 => %04f 1 0 => %04f 1 1 => %04f'
          %(i,np.mean(E**2),result[0],result[1],result[2],result[3]))
    
    mse.append(np.mean(E**2))

    # plot graph
    
    # if i%100 == 0:
    #     plt.xlabel('EPOCH')
    #     plt.ylabel('MSE')
    #     plt.title('MLP TEST')
    #     plt.plot(mse)
    #     plt.show()

 

 

 

 

역전파와 시그모이드 함수 이외 다른 기술적인 테크닉이 전혀 없는 코드입니다. 따라서 단순한 XOR 역시 초기값에 따라 학습이 되지 않는 경우도 많이 발생합니다. 모멘텀이나, 적응형 학습률 등의 다양한 방법으로 응용해보시길 바랍니다.

 

 

# 머신러닝 프로젝트 제작, 상담 및 컨설팅  / 머신러닝 접목 졸업작품 컨설팅

# 데이터 가공, 수집, 라벨링 작업 / C, 파이썬 프로그램 제작

# email : deepi.contact.us@gmail.com

# site : www.deep-i.net

반응형