직접 간단한 Artificial Neural Network 인공신경망을 만들어보며,
중요한 코드들을 여기에 정리해보았다.
ANN을 구축하는 과정을 요약하면 다음과 같다.
 
  1. Importing the libraries
  1. Data processing
    1. Importing the dataset
    2. Encoding categorical data
    3. Splitting the dataset into the Training set and Test set
    4. Feature Scaling
  1. Building the ANN
    1. Initializing the ANN
    2. Adding the input layer and the first hidden layer
    3. Adding the second hidden layer
    4. Adding the output layer
  1. Training the ANN
    1. Compiling the ANN
    2. Training the ANN on the Training set
  1. Making the predictions and evaluating the model
    1. Predicting the result of a single observation
    2. Predicting the Test set results
    3. Making the Confustion Matrix
 

0. Importing the libraries

import numpy as np import pandas as pd import tensorflow as tf
tensorflow는 google colab에 이미 설치되어 있다.
 

1. Data processing

Importing the dataset

dataset = pd.read_csv('[file]') X = dataset.iloc[:, 3:-1].values y = dataset.iloc[:, -1].values
여기서 iloc의 첫 번째 인자는 , 두 번째 인자는 이다.
즉 iloc은 필요한 부분만큼 자르는 함수이다.
위 예시에서는 모든 행, 그리고 3행부터 마지막 열 전까지이다.
 

Encoding categorical data

from sklearn.preprocessing import LabelEncoder le = LabelEncoder() X[:, 2] = le.fit_transform(X[:, 2])
LabelEncoder는 [”한국”, “중국”, “일본”] 이런 값을 [0, 1, 2]의 형태로 라벨을 붙여줄 수 있다.
하지만 주의해야할 점은, 범주 간 수치적 순서가 있다고 잘못 해석할 수 있다.
따라서 다음과 같은 상황에서 Label Encoder를 사용하면 좋을 것 같다.
  • 성별처럼 male과 female 두 개로 나눌 수 있는 경우
  • 실제로 상관관계로 라벨링할 수 있는 경우 ([Low, Medium, High])
 
범주가 3개 이상이고 수치적 순서가 없는 경우에는 바로 OneHotEncoder를 사용하면 된다.
from sklearn.compose import ColumnTransformer from sklearn.preprocessing import OneHotEncoder ct = ColumnTransformer(transformers=[('encoder', OneHotEncoder(), [0])], remainder='passthrough') X = np.array(ct.fit_transform(X))
OneHotEncoder를 사용하면 ['France', 'Spain', 'Germany'] 이런 국가 예시에서
[[1. 0. 0.] # France [0. 0. 1.] # Spain [0. 1. 0.] # Germany [1. 0. 0.]] # France
위와 같이 OneHotEncoder는 범주형 데이터를 0과 1로 이루어진 벡터로 바꿔준다.

Splitting the dataset into the Training set and Test set

from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 1)
train_test_split 은 데이터를 학습용과 테스트용으로 나눌 때 쓰인다.
주요 파라미터를 알아보면,
  • test_size
    • 전체 데이터 중에서 테스트 데이터로 사용할 비율
  • random_state
    • 데이터를 섞을 때의 랜덤 시드 역할
    • 이 값을 설정하면 항상 같은 방식으로 데이터를 나눠준다. → 결과 재현 가능성
    • 값은 아무 숫자나 가능하며, 같은 숫자를 사용하면 같은 결과가 나온다.

Feature Scaling

from sklearn.preprocessing import StandardScaler sc = StandardScaler() X_train[:, 3:] = sc.fit_transform(X_train[:, 3:]) X_test[:, 3:] = sc.transform(X_test[:, 3:])
나는 Data processing 과정에서 Feature Scaling은 왜 해야하는지 이해할 수 없었다.
Feature Scaling은 딥러닝에서 필수라고 한다. 왜 Feature Scaling이 필요할까?
  1. Feature간의 스케일 차이 때문
  1. Gradient Descent 의 효율 향상
    1. Feature 값의 스케일이 다르면 손실 함수의 모양이 찌그러진 타원형이 되어 최적점까지 가는 시간이 더 걸린다.
    2. 정규화하면 손실 함수가 대칭적인 형태가 되어 빠르게 수렴할 수 있다.
 
그러면 fit_transformtransform의 차이는 무엇일까?
메서드
역할
언제 사용?
fit
데이터의 통계값(평균, 표준편차 등) 계산만 함
처음 학습 데이터에 사용
transform
저장된 통계값을 이용해 실제 데이터를 변환함
테스트 데이터나 새 데이터에 사용
fit_transform
fit() + transform()을 한 번에 실행
학습 데이터에 사용
테스트 데이터에 fit_transform을 쓰게 되면 새로운 통계값이 계산되므로,
테스트 데이터에는 그냥 transform만 사용하자.

2. Initializing the ANN

Initializing the ANN

ann = tf.keras.models.Sequential()
Tensorflow 2.0부터는 이렇게 keras 모델을 바로 사용할 수 있다.
모델은 어떤 역할을 할까?
딥러닝에서 모델이란, 입력 데이터를 받아서 원하는 출력으로 바꾸는 일종의 함수이자, 이 함수의 구조(레이어 구조)와 학습된 가중치를 모두 포함하는 전체 시스템을 의미한다.
Sequential 모델은 딥러닝 모델 중 가장 기본적이고 단순한 형태로, 순차적으로 레이어를 쌓는 방식이다.
ex. 입력 → 레이어1 → 레이어2 → 출력
 
또 다른 모델의 종류는 표로 정리해보았다.
모델 종류
설명
장점
단점
Sequential
순차적 모델 층이 한 줄로 연결됨
간단하고 직관적
복잡한 모델 불가
Functional API
입력과 출력을 명시하여 모델 구성
유연함 (다중 입출력, 병렬 구조)
코드가 복잡해질 수 있음
Model Subclassing
Model 클래스를 상속해서 직접 모델 정의
가장 유연함. 커스터마이징 쉬움
유지보수 어려움

Adding the input layer and the first, second hidden layer

ann.add(tf.keras.layers.Dense(units=6, activation='relu'))
층을 추가하고 싶으면 add 함수를 사용하면 된다.
이 코드에서는 Dense라는 종류의 층을 추가해주었으며 당연히 다른 종류의 층도 있다.
 
일단 Dense의 파라미터를 먼저 보면,
  • units: 만들어 낼 뉴런 수
  • activation: 활성화 함수
여기서 질문이 나올 수 있다. units를 몇으로 정해야할까?
실제로 units 파라미터가 딥러닝 모델 설계에서 매우 중요하다고 한다.
정답은 없으며 경험과 실험을 통해 찾는 값이라고 한다.
units를 정하는 철학은 다른 글에서 좀 더 자세히 알아보고자 한다.
 
이제 layer에 대해서 알아보자.
layer는 뉴런들의 집합이자 입력 데이터를 처리하는 연산 단위이다.
위에서 나온 Dense layer는 이전 레이어의 모든 뉴런과 현재 레이어의 모든 뉴런의 연결된 구조이다.
다른 layer들도 많지만 그것은 계속 공부해보면서 찾아가도록 하자.

Adding the output layer

ann.add(tf.keras.layers.Dense(units=1, activation='sigmoid'))
마지막으로 output layer도 추가해주어야 한다.
이 때 hidden layer와 다른 점은 output layer의 activation 함수를 sigmoid로 한다는 것이다.
Sigmoid의 장점은 0과 1을 구분해주는 것뿐만 아니라, 1이 나올 확률도 알려준다.
예를 들어 은행에서 고객의 이탈율을 조사하고 있다면,
주어진 데이터로 고객이 이탈할지 말지만 예측해주는 것이 아니라
이탈할 확률까지 알려줄 수 있다는 장점이 있다.
 
회귀 문제의 경우, 출력값이 실수 전체 범위를 가질 수 있기 때문에 activation=None 으로 설정한다.

3. Training the ANN

Compiling the ANN

ann.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
Compile이란, 모델이 학습을 시작하기 전에 “어떻게 학습할지” 설정하는 단계이다.
optimizer는 가중치를 어떻게 업데이트할지 결정하는 알고리즘으로, adam 은 확률적 경사하강법을 이용하는 알고리즘이다.
loss는 손실함수로 이진 분류에서는 binary_crossentropy를 사용하며,
다중 클래스의 경우 categorial_crossentropy를 사용한다. 다중 클래스 상황에서는 위 예시의 출력층의 활성화 함수 simoidsoftmax로 바꿔주어야 한다.
회귀 문제는 mse (mean_squared_error)를 사용한다.
metrics는 학습 중/후에 얼마나 잘하고 있는지를 보여지는 지표로, 실제로 학습에는 사용되지 않고 모니터링 용도이다. 설정할 경우 아래 사진과 같이 결과가 출력된다.
notion image
 

Training the ANN on the Training set

ann.fit(X_train, y_train, batch_size=32, epochs = 100)
위에 설정을 다 마치고 fit 함수를 이용하면 간단하게 모델을 학습시킬 수 있다.
주요 파라미터를 알아보면,
  • batch_size
    • 한 번에 모델에 들어가는 데이터 샘플 개수로, 한 번의 가중치 업데이트마다 32개의 샘플을 사용한다는 뜻
    • 기본값은 32라고 한다.
      • 왜 2의 거듭제곱 형태로 해야할까?
        • GPU는 병렬 계산을 잘하는 장치인데, 내부에서 데이터를 2진수 블록 단위로 처리한다. 그래서 32, 64, 128 같은 2의 거듭제곱 크기가 메모리 정렬이 잘 되고, 연산이 빨라진다.
        • 꼭 2의 거듭제곱 형태가 아니어도 되지만, GPU 자원을 덜 효율적으로 쓸 수 있다.
    • 전체 학습 데이터를 너무 많이 넣으면
      • 메모리 부담
      • 업데이트 횟수 부족
    • 학습 데이터를 적게 넣으면
      • 노이즈 증가 (불안정함)
      • 시간이 오래 걸림
    • 그럼 확률적 경사하강법이 1개가 아니라 batch 단위로 가중치를 업데이트할 수 있다고 들었는데, batch_size가 optimizer에 영향을 주는 값인가? → 맞다
  • epochs
    • 전체 훈련 데이터를 몇 번 반복할 것인가
    • 너무 적으면 학습 부족
    • 너무 많으면 과적합
 

Making the predictions and evaluating the model

학습한 모델로 결과를 에측하려면 predict 함수를 사용하면 된다.

Predicting the result of a single observation

ann.predict(sc.transform([[1,0,0,600,1,40,3,60000,2,1,1,50000]]))
가장 중요한 것은 sc.transform으로 scaling을 해주어야 한다.

Predicting the Test set results

y_pred = ann.predict(X_test) y_pred = (y_pred > 0.5) print(np.concatenate((y_pred.reshape(len(y_pred), 1), y_test.reshape(len(y_test), 1)), 1))

Making the Confustion Matrix

from sklearn.metrics import confusion_matrix, accuracy_score cm = confusion_matrix(y_test, y_pred) print(cm) accuracy_score(y_test, y_pred) # Reuslt: # [[1524 71] # [ 206 199]] # 0.8615
Confusion Matrix를 이용하면 모델에 test 데이터를 넣었을 때의 결과를 보기 쉽게 요약해준다.
위 Result에서는 옳은 것을 옳다고 한 것이 1524, 틀린 것을 틀렸다고 한 것을 199개 있다는 뜻이다.