관리 메뉴

클라이언트/ 서버/ 엔지니어 "게임 개발자"를 향한 매일의 공부일지

케라스 3 - 단순 신경망 훈련 본문

인공지능/딥러닝

케라스 3 - 단순 신경망 훈련

huenuri 2024. 10. 26. 13:54

단순 신경망 훈련에 대해서 공부해 보겠다. 먼저 주요 용어부터 학습해 볼 것이다.


 

 

관련 용어

 

선형 회귀

회귀 분석이란 하나 이상의 독립변수들이 종속변수에 미치는 영향을 추정하는 통계 기법이다. 그중에서도 단순선형회귀 모형은 하나의 X가 Y에 미치는 영향을 추정하며 1차 함수 관계로 나타낼 수 있다.

y = ax + b

 

중학교 수학 시간에 배운 1차 함수식을 떠올려 보자. 1차 함수식의 X는 독립변수, Y는 종속변수다. 1차 함수식의 a는 기울기, b는 절편이라고 부른다. 기울기 a는 일차 함수 그래프의 기울기를 결정하고 절편 b는 그래프의 높낮이를 결정한다.

 

이번에는 텐서플로 케라스를 활용하여 단순선형회귀 모델을 직접 만들고 딥러닝을 학습한다. 이때 모델은 1차 함수식과 동일하다고 생각하면 된다. 모델의 기울기 a와 절편 b를 업데이트하면서 종속변수 Y에 가장 근사한 1차 함수식을 완성해 나간다. 딥러닝에서는 기울기 a 대신 가중치를 의미하는 w를 더 많이 사용한다.

앞으로 1차 함수식을 다음과 같이 정의한다.

y = wx + b

 

w는 가중치이고, b는 편향을 의미한다.


 

 

 

뉴런

뉴런은 인공 신경망 모델을 구성하는 하나의 신경을 의미한다. 뉴런은 노드라고도 부르며 혼용하여 사용한다. 신경망은 여러 개의 레이어를 가지며 1개 레이어는 1개 이상의 뉴런으로 구성된다. 뉴런의 내부에는 가중치가 준재하고 모델이 훈련을 진행하면서 오차 역전파를 통해 뉴런의 가중치가 업데이트된다.

 

 

Dense 레이어

Dense 레이어는 심층 신경망 모델을 구성하는 가장 기본 레이어이다. 각 레이어와 레이어 사이에 모든 뉴런이 서로 연결되어 있기 때문에 완전 연결층이라고 부른다.

다음 그림은 4개의 Dense 레이어로 구성된 모델을 나타낸다. 입력 레이어 1개, 은닉 레이어 2개, 출력 레이어 1개로 구성되어 있다. 각 레이어는 1개 이상의 뉴런으로 구성된다. 입력 레이어는 3개의 뉴런이 있고, 출력 레이어는 1개의 뉴런을 갖는다. 모든 뉴런들이 정보의 흐름을 나타내는 화살표로 연결되어 있어서 완전연결층이라고 정의한다.

 

Dense 레이어를 구성하는 노드 개수와 활성화 함수를 지정할 수 있다. 텐서플로의 layer 모듈에 있는 Dense 레이어로 쉽게 구현할 수 있다. 노드의 개수를 Dense 레이어의 첫 번째 위치 인자로 지정하면 된다. 또한 Dense 레이어의 activation 매개변수에 활성화 함수를 지정하여 적용할 수 있다.


 

 

 

 

단순 신경망 프로세스

 

1. 데이터셋 만들기

단순선형회기 모형을 지도학습 방식으로 훈련하기 위해서 s, y 데이터를 생성한다. 넘파이 arrand() 메서드를 활용하여 5개의 순차적인 x 데이터를 생성하고, 임의의 1차 함수인 y = 3x + 2 관계식에 대입하여 y 데이터 5개를 생성한다.

 

지도학습은 정답이 있는 데이터를 활용해 데이터를 활용해 데이터를 학습시키는 것이다. 모델에 주입할 입력 데이터를 피처(feature)라고 부르고 정답은 레이블이라고 부른다. 머신러닝의 학습 방법은 지도학습 외에도 비지도학습, 강화 학습, 준지도학습 등이 있다.

 

생성한 데이터를 matplotlib 시각화 라이브러리를 활용하여 그래프를 출력해 보겠다. 이렇게 만들어진 x, y 데이터는 기울기 3을 갖는 직선 그래프로 그려진다.

 

1차 함수 그래프가 잘 그려졌다면, 이제 모델을 입력할 데이터의 준비가 끝난 것이다.


 

 

 

 

2. Sequential API

텐서플로 테라스는 세 가지 방식으로 모델을 생성할 수 있다. 그중 케라스의 Squential API를 사용하면 매우 간결하게 딥러닝 모델을 만들 수 있다. 이 방식은 층을 이어 붙이듯 시퀀스에 맞게 일렬로 연결하는 방식이다. 따라서 입력 레이어부터 출력 레이어까지 순서를 갖는다.

입력 데이터는 시퀀스의 가장 앞에 위치한 층에 투입되고, 순서대로 각 층을 하나씩 통과하면서 딥러닝 연산을 수행한다.

 

이처럼 직관적으로 구조를 이해할 수 있기 때문에, 케라스 모델을 생성하고 훈련하는 가장 간단한 방법이라고 말할 수 있다. 다만, 2개 이상의 다중 입력이나 다중 출력을 갖는 복잡한 다중 입력이나 다중 출력을 갖는 구조를 만들 수 없다는 단점이 있다.


 

 

 

모델 구조

Squential API를 사용하여 모델 생성 시 다음과 같은 두 가지 방법으로 모델을 구성할 수 있다. 리스트형 정의로 Sequential 클래스 함수에 파이썬 리스트 형태로 여러 개의 층을 입력한다. 대괄호 안에 쉼표로 구분하여 층을 쌓는다. 앞에 위치한 층부터 연산을 먼저 처리하고 순차적으로 다음 층의 연산을 수행하게 된다.

 

 

다음은 add 함수로 레이어 추가로 Sequential 클래스 객체를 먼저 만들 뒤에, 생성된 모델 인스턴스에 층을 추가하는 방식이다. add() 메서드 함수를 사용하여 1개 층을 추가할 수 있다. 따라서 여러 개의 층을 추가하려면 add 함수를 반복해서 여러 번 사용해야 한다.

앞의 코드와 동일 구조의 모델을 만들기 위해 add 함수를 3번 사용했다.


 

 

 

입력 데이터 형태

Sequential API를 사용하여 모델을 구성할 때 반드시 첫 번째 층은 input_shape 매개변수를 지정해야 한다. input_shape 매개변수는 주입할 데이터셋의 shape을 튜플 혹은 리스트로 지정할 수 있다.

예를 들어 데이터셋의 shape이 (150, 4)로 구성되었다고 가정한다면 input_shapejgs (4,) 혹은 [4]로 지정할 수 있다.


 

 

 

단순선형회귀 모델 정의

단순선형회귀 모델을 만들기 위해서는 1개의 뉴런을 가지는 Dense 레이어 한 개를 사용한다. 여기에 정의한 1개의 뉴런은 기울기에 해당하는 w와 상수항에 해당하는 b를 매개변수로 갖는다. 1개의 뉴런을 갖는 Dense 레이어는 1개의 출력 값을 가지므로, 출력 값은 y에 대한 모델의 예측 값이다.

 


 

 

 

 

3. 모델 요약

Sequential API로 모델을 만들었다면 model.summary()로 모델의 요약을 확인할 수 있다. 모델의 요약 내용은 노트 셀에서 출력값으로 확인이 가능하다. 모델의 구조를 확인할 수 있으며 층별 노드의 개수가 표기된다. 요약의 하단에는 훈련 시 업데이트할 파라미터의 개수가 표시된다.

 

단순선형회귀 모델에서는 업데이트 파라미터가 가중치 w와 편향 b 두 개다. 따라서 요약에서도 총 파라마미터의 개수가 2개로 표기되는 것을 확인할 수 있다.


 

 

 

4. 컴파일

컴파일 단계에서는 모델의 훈련 과정에서 적용할 옵티마이저, 손실함수, 그리고 평가지표 등을 정의한다. 클래스인스턴스, 함수 혹은 사전 정의된 문자열이다.

클래스 인스턴스로 지정할 경우 학습률, 모멘텀 등의 하이퍼파라미터를 사용자가 직접 지정할 수 있다. 하지만 문자열로 지정하는 경우 기본값으로 설정된 하이파파라미터를 사용하며, 하이퍼파라미터 수정은 어렵다는 한계가 있다.

 

 

앞에서 정의한 단순선형회귀 모델을 훈련시키기 위해서 옵티마이저는 확률적 경사하강법 알고리즘인 'sgs', 손실함수로는 확률제곱오차인 'mse', 평가지표는 평균절대오차인 'mae'를 지정한다.


 

 

 

 

5. 훈련

생성한 모델 인스턴스에 fit() 메소드를 적용하면, 데이터를 입력하여 모델을 훈련할 수 있다. fit() 메서드에는 훈련용 데이터셋의 입력(x)과 정답에 해당하는 출력(y), 그리고 반복 훈련할 epoch 수를 지정한다. 매 epoch가 끝날 때마다 훈련 데이터셋에 대한 손실과 평가지표를 출력한다.

fit() 메서드에 검증 데이터셋(validation_data) 옵션을 지정했다면 검증 셋에 대한 손실과 평가지표도 함께 출력한다.

 

컴파일 단계에서 손실함수로 평균제곱오차를 지정했기 때문에 8.6414는 평균제곱오차를 나타낸다. 매 epoch당 loss값을 보면 손실함수, 즉 모델의 예측 오차가 점점 줄어드는 것을 볼 수 있다. 모델이 잘 학습되고 있는 것을 알 수 있다. 하지만 반복 훈련 횟수가 충분하지 않아 학습이 덜 되었다고 볼 수 있다. epoch를 늘려서 추가 학습을 하면 손실을 더욱 낮출 수 있을 것으로 보인다. 모델은 현재 과소적합 상태이다.

 

이번에는 epoch에 1200을 지정하여 충분히 훈련할 수 있도록 한다. 모델 인스턴스를 새로 생성하고 컴파일한다. history 변수를 생성하고 fit() 메서드에 대한 반환값을 대입한다. fit() 메서드가 반환하는 history 변수는 epoch별 훈련 손실과 평가지표가 딕셔너리 형태로 저장된다.

 

 

 

충분한 epoch 동안 훈련한 후 mse, mae 모두 개선되었음을 확인할 수 있다. 훈련에 대한 결과를 history 변수를 사용하여 시각화해 보겠다.

 

첫 10 epoch까지 손실이 감소되는 것을 확인할 수 있다. 10 epoch를 넘어가면 감소 폭이 둔화되면서 조금씩 감소하는 것을 확인할 수 있다. 즉, 모델 훈련 초기 단계에서는 학습이 매우 빠른 속도로 진행되다가 일정 epoch 이후에는 학습 속도가 느려지는 패턴을 보이고 있다.


 

 

 

 

6. 검증

모델 인스턴스의 evalute() 메서드로 모델의 성능을 검증할 수 있다. 일반적으로 검증 데이터셋을 입력하여 검증한다. 별도의 검증 셋을 만들어 두지 않았으므로 훈련 데이터셋의 x, y를 대입하여 반환되는 결과를 확인한다.

 

모델 훈련 단계에서 1200번 epoch를 종료한 상태에서 출력된 값과 같다. 검증 단계에서는 모델이 훈련을 마친 상태의 가중치를 그대로 적용하여 손실과 평가지표를 계산하기 때문이다.


 

 

 

7. 예측

훈련이 완료된 모델 인스턴스의 predict() 메서드에 새로운 입력 데이터를 넣어 주면 모델의 예측 값을 얻을 수 있다. 다음과 같이 예측을 위한 입력 x를 pridict()의 인자로 지정한다. 

 

모델이 예측 결과로 출력하는 값은 32.0431이다. 

 


 

 

 

학습을 마치고

오늘은 공부가 하기 싫어 놀면서 빈둥거리고 낮잠도 실컷 자면서 하고 있어서 학습 시간이 평소보다 3배 이상 걸리는 것 같다. 그래도 이런 식으로 하다 보면 제대로 공부하고 싶어 진다. 그래도 지난 8월부터는 단 하루도 공부를 쉰 적이 없다. 

조금 어려웠지만 단순신경망 훈련에 대해서 배울 수 있었다. 모든 혼공책에서 공부한 내용이었으나 그때는 잘 이해하지 못했었다.