[딥러닝] 심층학습 시작 : 인공 신경망과 MLP (+ 신경망 모델 만들어보기)
심층학습의 시작 : 퍼셉트론과 MLP(Multi-layer Perceptron)
이번 포스팅에서는 기존의 전통적인 머신러닝의 단점을 극복하고 딥러닝의 시작을 알렸던 퍼셉트론 및 MLP에 대해서 알아보려고 한다.
1. 딥러닝의 역사 : 과거에서부터 현재까지 딥러닝이 어떻게 발전해 왔고 주요한 기술적 변화가 무엇이 있었는지 확인해보자
2. 인공 신경망 : 기본적인 단층 퍼셉트론의 개념과 구조, 그리고 풀이할 수 있는 문제를 알아보려고 한다.
3. MLP(다층 퍼셉트론) : MLP의 구조와 벡터 및 구성요소의 수학적 표현방법, 그리고 학습 과정에 대해서 알아보자
4. Python에서 인공 신경망 모델 훈련시키기 : 우선 Numpy로 MLP를 직접 구현해보고, 이후에는 Tensorflow를 사용해서 모델을 훈련시켜볼 것이다.
5. 딥러닝의 장단점
딥러닝의 역사
심층학습의 출현은 인공지능 역사에 있어 매우 큰 전환점이다.
기존의 머신러닝에서는 데이터의 특징 중 어떤 특징을 추출할지를 사람이 분석하고 판단해야만 했다. 하지만 딥러닝에서는 기계가 자동으로 학습하려는 데이터에서 특징을 추출하여 학습할 수 있게 되었다. 마치 주입식 교육과 자기주도적 학습의 느낌이랄까?
자동으로 대규모 데이터에서 중요한 패턴 및 규칙을 학습할 수 있다는 측면은 복잡한 데이터, 비정형 데이터와 같은 높은 수준의 학습이 가능하게 되었다.
1. McCulloch & Pitts(1943) :뉴런 구조를 수학적으로 근사하는 모델에 대한 개념 제시
2. Hebb(1949) :시냅스의 연결 강도 조정을 위한 학습 규칙을 기술
3. Rosenblatt(1958) :Perceptron, 최초의 인공 신경망 모델 발표, 단층 모델의 한계
4. Minsky & Papert(1969) :퍼셉트론의 XOR 문제 제기 -> 연결주의 인공지능의 한계
5. Rumelhart(1986) : 은닉층, 다층 퍼셉트론(MLP), 역전파(Backpropogation) 개념 도입, 복잡한 구조로 인한 학습의 어려움(Gradient Vanishing)
6. LeCun(1998) : CNN 모델을 처음 제안, 필기체 인식에 탁월한 성능
7. Hinton(2006) : Deep Learning 연구의 시작
* Deep Belief Network(DBN) : RBM을 여러 층으로 배치한 모델
8. Alex Krizhevsky & Hinton(2012)
* Deep CNN : 심층 구조를 가진 CNN, Convolution -> Pooling의 단순 구조 반복, 2개의 GPU 이용
9. Ian Goodfellow(2015)
* GAN : 생성자와 판별자의 대립을 통해 학습, 영상을 생성하는 최초의 인공 신경망 모델
10. Transformer(2017) : Google에서 발표한 자연어 처리 모델, 기존의 RNN와 LSTM을 뛰어넘는 성능. 언어 지능 뿐 아니라 시각 지능에서도 사용됨
11. 2020년대 : 시각지능, 언어지능, 데이터지능 등 다양한 분야
퍼셉트론과 MLP 인공 신경망의 개념은 이런 심층학습 연구에 불을 지핀 시발점이다. CNN은 이미지 처리와 패턴 인식 분야에서 효과적으로 사용되어온 모델로서 역할을 하고 있다.
더 나아가 GAN과 같은 생성형 모델과, ChatGPT와 같이 자연어를 처리하는 Transformer 모델과 같은 진보된 형태의 모델의 출현은 인공지능 시대를 열게 하였다.
인공 신경망과 퍼셉트론
인공 신경망은 인간의 뇌 구조에서 영감을 받아 만들어진 모델이다.
뉴런이 모여 연결된 구조를 가지고 있으며, 이 연결된 구조를 통해 학습하고 예측을 수행한다.
퍼셉트론(Perceptron)은 인공신경망 모델 중 하나이다.
퍼셉트론 (Perceptron)
단층 퍼셉트론이라고 불리는 인공신경망의 가장 기본적인 형태 중 하나로, 입력과 출력 사이에 하나의 계층이 있는 모델.
구조
- 입력 (Input): 단층 퍼셉트론의 입력은 벡터로 표현, 이 벡터는 입력 특징(Feature)을 나타낸다.
- 입력층의 노드 수는 Feature의 수와 일치한다.
- 𝑥𝑇 = (𝑥1, 𝑥2, … 𝑥𝑛)
- 가중치 (Weight): 각 입력 특성에 대해 가중치가 할당. 가중치는 모델이 학습하는 매개변수로, 특징의 중요도를 나타낸다.
- 𝑤𝑇 = (𝑤1, 𝑤2, … 𝑤𝑛)
- 𝑤0 = 𝑏 (bias(편향값)), 활성화 함수의 결정 경계를 조정하여 모델이 더 유연하게 데이터를 학습할 수 있도록 역할을 한다.
- 가중합 (Weighted Sum): 입력과 가중치의 곱을 모두 합한 값
- \(\sum_{i=1}^N wi xi \) + 𝑤0 => 𝑤1⋅𝑥1 + 𝑤2⋅𝑥2 + 𝑤3⋅𝑥3... + 𝑤n⋅𝑥n + 𝑤0⋅1
- 활성함수 (Activation Function): 가중합을 입력으로 받아 출력을 생성하는 함수. 단층 퍼셉트론에서는 계단 함수 사용
- \(g(z) = \begin{cases} 1 & \text{if } z \geq 0 \\ 0 & \text{else} \end{cases} \)
- 출력: 입력과 가중치의 선형 조합을 계산하고, 그 결과에 대해 활성함수를 적용하여 출력을 생성 (가중합 + 활성 함수)
- 출력층의 노드 수는 예측하고자 하는 타겟 값(Label)의 수와 일치한다.
- 𝑓(𝑥) = 𝑓(𝑤𝑇𝑥 + 𝑤0)
동작 방식
1. 가중합 구하기 : 입력치와 가중치를 서로 곱하여 모두 합한다.
2. 가중합을 활성함수가 가지고 있는 임계치와 비교
3. 값이 임계치보다 크면 뉴런은 활성화, 작으면 비활성화
퍼셉트론의 활용 예시
단층 퍼셉트론은 선형 결정 경계를 사용한다. 따라서 선형 분류의 용도로 사용이 가능하다.
가장 대표적인 예시로 AND Gate와 OR Gate의 구현이 있다. 두 개의 논리회로는 대표적으로 선형 분류가 가능한 친구들이다.
다음 그림을 보면 두 개의 입력인 특징(x1, x2)에 대해서 True와 False를 단순 선형 분류가 가능하다는 것을 할 수 있다.
입력으로는 (0, 0), (0, 1), (1, 0), (1, 1)이 들어올 수 있으며, 출력으로는 0 또는 1이 나올 것이다.
AND Gate
위 그림과 같은 단층 퍼셉트론이 있다고 생각해보자.
- 입력 : 두 개의 입력값, 각각의 입력에는 0 또는 1의 값이 들어올 것이다.
- 가중치 : 우리가 Gate를 구현하기 위해서 계산해야 하는 값이다.
- 활성화 함수 : 계단 함수를 사용하여 if(z>0)일 때 1을, else일 때 0으로 출력을 생성할 것이다.
따라서 우리는 AND Gate를 구현하기 위해서 가중치의 값을 결정해야 하고, 이것이 인공 신경망의 관점에서는 학습시켜야 하는 대상이다.
가중치를 각각 -0.7, 0.5, 0.5로 결정한다면 입력의 경우에 수에 따라서 AND Gate의 규칙에 따라서 출력이 나오게 되는 것을 알 수 있다. 만약 인공 신경망이 해당 가중치를 스스로 결정했다면 이는 성공적으로 학습된 것이다.
OR Gate
마찬가지로 OR Gate를 구현하기 위해서 가중치 값을 결정한 것이다.
한계
단층 퍼셉트론은 비선형적인 결정 경계를 필요로 하는 문제에는 성능이 제한되는 한계가 있다. 가장 대표적인 문제의 사례가 XOR Gate의 구현이다.
XOR 게이트의 출력은 그림으로 보는 것과 같이 선형적으로 분리될 수 없다.
단층 퍼셉트론의 이런 한계점은 이는 단일층의 제약으로 인한 것으로 복잡한 함수나 다양한 특징을 표현할 수 없다는 점을 알 수 있다.
MLP (다층 퍼셉트론, Multi-layer Perceptron)
위에서 언급한 XOR 문제를 해결할 수 있는 수단으로서 다층 퍼셉트론(MLP)과 같은 심층 신경망이 등장하였다.
MLP는 퍼셉트론의 개념에서 은닉층을 추가하여 다양한 종류의 복잡한 패턴과 특징을 인식이 가능해졌다.
입력층 (Input Layer) : 퍼셉트론과 마찬가지로 입력 데이터를 받아들이는 Layer. 입력 데이터의 특징(Feature)에 해당한다.
은닉층 (Hidden Layer) : 입력층과 출력층 사이에 위치한 층으로, MLP의 성능을 높이는 중요한 역할을 한다.
- 은닉층의 노드 수는 사용자가 설정하며, 여러 개의 Layer를 가질 수 있다. (그렇기에 Deep Learning이다.)
- 현재 Layer의 노드는 이전 Layer의 모든 노드의 출력과 연결되며, 각 연결은 가중치를 가진다.
- 즉 현재 Hidden Layer의 입력값은 이전 Hidden Layer의 출력값들의 가중합이다.
- 은닉층의 노드도 마찬가지로 활성화 함수를 사용하여 입력 신호를 변환한다.
출력층 (Output Layer) : 은닉층의 출력 결과를 받아 최종 출력을 생성하는 Layer. 출력은 해당 입력에 대한 결과값(Label)에 해당한다.
다층 퍼셉트론의 표현
입력 벡터 : \(\mathbf{x} = [x_1, x_2, \ldots, x_m]\)
가중치 행렬 : \(\mathbf{W}^{(l)}\)
→ \(l\)은 Layer을 의미한다.
가중치 : 각각의 가중치는 \(w_{ji}^{(l-1)}\)로 나타낼 수 있다.
→ \(i\)는 다음 Layer의 i번째 노드를 의미한다.
→ \(j\)는 이전 Layer의 j번째 노드를 의미한다.
→ 즉 이전 Layer의 \(j\)번째 노드에서 다음 Layer의 \(i\)번째 노드로의 가중치를 의미한다.
\( l \)번째 은닉층의 \( i \)번째 노드의 입력값
→ \( z_i^{(l)} = \sum_{j=0}^{n_{l-1}} w_{ji}^{(l-1)} a_j^{(l-1)} \)
\( l \)번째 은닉층의 \( i \)번째 노드의 출력값
→ \( a_i^{(l)} = \sigma(z_i^{(l)}) \)
→ \( \sigma \)는 활성 함수이다.
\( l \)번째 Layer의 입력 벡터
- \( [ z^{(l)} = [z_1^{(l)}, z_2^{(l)}, \ldots] ] \)
- → \( [ w_1^{(l^T)} a^{(l)}, w_2^{(l^T)} a^{(l)}, \ldots] \)
- → \( [ w_1^{(l^T)}, w_2^{(l^T)}, \ldots] \cdot a^{(l)} \)
- \( T \)는 전치 연산을 의미한다.
\( l \)번째 Layer의 출력 벡터
- \(\mathbf{a}^{(l)} = [a_1^{(l)}, a_2^{(l)}, \ldots, a_{n_{l}}^{(l)}]\)
- \( a_i^{(l)} = \sigma(z_i^{(l)}) \)
출력층 (Output Layer): 출력층은 최종 예측을 생성한다. 최종 \( L \)번째 Layer의 출력 벡터가 출력이 된다.
활성함수 (Activation Function) : 가중합을 활성함수를 통과시켜 값을 출력 시키는 역할
주로 사용되는 활성화 함수로는 시그모이드 함수, ReLU 함수, Leaky ReLU 함수 등을 사용한다.
학습 과정
다층 퍼셉트론은 학습 알고리즘을 사용하여 모델을 훈련한다. 앞에서 말했듯 모델을 훈련한다는 것은 적절한 가중치를 찾아가는 과정이다.
이때 사용되는 손실 함수는 모델의 예측과 실제 값 간의 차이를 측정. 역전파(backpropagation) 알고리즘이 사용, 경사하강법과 같은 최적화 알고리즘을 통해 손실 함수를 최소화한다.
1. Forward Propagation (순전파)
우리는 앞에서 살펴보았듯 입력층에서부터 여러 은닉층을 거쳐 예측 결과인 출력을 내는 과정을 살펴보았었다. 해당 과정을 Forward Propagation이라고 한다.
- 입력층: 훈련 데이터(Feature)의 입력
- 가중치 및 활성화 함수 적용: 각 은닉층과 출력층은 가중합을 계산, 그 결과에 활성화 함수를 적용. 해당 과정을 입력층에서부터 출력층까지 반복한다.
- 출력층: 모델의 예측 결과를 얻어낸다.
2. Loss 계산
Loss는 예측한 결과와 실제 결과간의 차이를 나타내주는 지표이다. 기계학습의 목표는 학습을 통해서 Loss를 최소화하는 것이다.
실제값과 모델의 예측값 사이의 차이를 나타내는 손실 함수(MSE, Cross Entropy Loss 등)를 사용하여 계산한다.
출력의 개수와 손실 함수
Foward Propagation은 입력 벡터로부터 예측값을 도출하는 과정이다.
출력의 개수는 예측해야 하는 값의 차원을 나타낸다. 즉 예측해야 하는 Class(Label)의 수 만큼의 출력 뉴련이 필요하다.
- 1개의 출력: 일반적으로 맞다/틀리다의 이진 분류 문제에서 사용된다. 이진 분류에서는 하나의 출력으로 충분하기 때문이다.
- 예를 들어 스팸 메시지인지, 아닌지 예측하는 문제에서는 스팸 OK, 스팸 X로만 분류하면 되기 때문이다.
- Binary Cross-entropy(BCE)와 같은 손실 함수를 사용하여 Loss를 계산한다.
- 여러 개의 출력: 다중 클래스 분류나 회귀 문제 등은 여러 개의 특징들이 필요하다.
- 예를 들면 동물을 분류해야 한다고 생각하면, 강아지, 고양이, 사자 등 여러개의 클래스들 중 예측해야 할 것이다.
- 클래스 분류 문제에서는 각 클래스에 대한 확률 값을 출력하여 가장 가능성 있는 클래스를 선택하는 방식을 사용한다.
- Categorical Cross-entropy(CCE)와 같은 손실 함수를 사용하여 Loss를 계산한다.
3. Backpropagation (역전파)
역전파 알고리즘
출력층에서 입력층으로 거꾸로 진행하면서 각각의 Hidden Layer의 각각의 가중치들을 업데이트 시켜주는 작업을 진행한다.
1. Gradient 계산: 손실 함수의 값을 각각의 가중치로 편미분하여 Gradient를 구한다. 연쇄 법칙(Chain rule)을 사용하여 구할 수 있다.
- 위의 그림은 \(w_{1, 1}^{(2)}\)에 대한 Gradient를 구하는 방법이다. 미분의 연쇄법칙에 따라서 아래의 결과가 나온다.
2. 가중치 업데이트: 출력층에서 입력층으로 거꾸로 진행하며 경사 하강법 등의 Optimizer을 사용하여 각각의 Hidden Layer의 가중치를 역방향으로 업데이트한다.
Optimizer
경사 하강법(Gradient Descent)
- 손실 함수의 기울기를 사용하여 매개변수를 조정하여 손실을 줄이는 방향으로 학습하는 가장 기본적인 방식
- 옵티마이저는 손실 함수를 최소화하기 위해 모델의 매개변수(가중치와 편향)를 업데이트하는 알고리즘이며 경사하강법을 기본으로 하며, 파생된 방법들이 있다.
Gradient Descent의 문제점과 Optimizer
- 시간 : 학습 데이터가 너무 많은 경우 시간이 오래 걸림
- SGD : 확률적 경사하강법. 학습 데이터 전체를 사용하지 않고 Batch Size만큼 학습하며 업데이트 -> 학습 속도를 높이고 메모리 사용량을 줄일 수 있음
- Local Minimum : Global Minimum을 찾아야 하는데 Local Minimum에 수렴하여 멈출 수 있음.
- Momentum : Local Minumum 문제를 극복하기 위해서 관성 적용. 이전 기울기 방향과 같은 방향이라면 속도를 가속한다.
- NAG : Momentum과 비슷하지만 예상을 먼저 진행한다. (먼저 관성에 따라서 갈 곳의 기울기값을 판단 → 실제로 이동)
- Gradient Vanishing : 기울기가 점점 작아져 0에 가까워지는 현상. 딥러닝에서는 초기 Layer의 가중치가 거의 업데이트되지 않아 학습이 어려워지는 문제가 발생할 수 있다.
- Gradient Exploding : 기울기가 너무 커져서 수렴하지 못하는 현상. 딥러닝에서는 가중치가 급격하게 변동하는 현상이 발생하여 불안정을 초래한다.
- 각 변수별 Gradient의 크기가 다름 : 학습 속도 차이 -> 특정 변수의 수렴이 이루어지지 않을 수 있음
- AdaGrad : 각 단계, 각 파라미터 마다 학습률을 다르게 적용
- 드물게 등장하는 변수에 대해서 Step size를 크게 해줌
- 자주 등장하는 변수에 대해서 Step size를 작게 해줌 -> 그렇지만 학습률이 너무 적어져 Gradient Vanishing이 발생할 수 있음
- RMSProp : AdaGrad의 학습률 감소 문제 해결 → 최근 그래디언트만을 고려하여 학습률을 조정
- Adam : AdaGrad와 RMSProp을 결합한 방식.
4. 학습 반복
해당과정을 여러 번 반복하여 모델의 가중치를 조정하고 손실을 최소화한다.
Python에서 인공 신경망 모델 훈련시키기
이제 우리가 살펴보았던 것들을 직접 해봐야 한다. 우선 파이썬 진영에는 딥러닝과 관련하여 Tensorflow나 PyTorch와 같은 강력한 라이브러리들이 있다.
그렇지만 우리는 딥러닝에 첫 발을 디딘 입장이므로 우선 한번은 Numpy로 한땀한땀 MLP를 작성해보려고 한다. 앞에서 열심히 보았던 훈련 과정들을 그대로 코드로 구현해보면서 과정을 다시 복기해보다.
Numpy로 직접 MLP 모델 작성해서 훈련시키기
ScikitLearn에서 제공하는 데이터셋인 당뇨 데이터(diabetes)에 대해서 MLP를 직접 Numpy로 작성한 내용이다.
해당 문제는 다변량 회귀 문제에 속한다.
import numpy as np
class SimpleMLP:
# 활성화 함수
def relu(self, x):
return np.maximum(0, x)
def linear(self, x):
return x
# 입력값의 차원, Hidden layer의 개수, 출력값의 차원을 기반으로 Weight와 Bias를 생성하고 초기화
def __init__(self, input_size, hidden_size, output_size):
self.hidden_W = np.random.randn(input_size, hidden_size) * 0.01
self.hidden_b = np.zeros((1, hidden_size))
self.output_W = np.random.randn(hidden_size, output_size) * 0.01
self.output_b = np.zeros((1, output_size))
# Forward Propagation
def forward(self, X):
self.hidden_Z = np.dot(X, self.hidden_W) + self.hidden_b # 은닉층의 입력 Z : 가중합(입력과 가중치의 내적에 편향을 더한다)
self.hidden_A = self.relu(self.hidden_Z) # 은닉층의 출력 A : ReLu 활성 함수 적용
self.output_Z = np.dot(self.hidden_A, self.output_W) + self.output_b # 출력층의 입력 Z : 가중합(은닉층의 출력과 가중치의 내적에 편향을 더한다)
self.output_A = self.linear(self.output_Z) # 출력층의 출력 A : Linear 활성 함수 적용
return self.output_A
# Backward Propagation
def backward(self, X, y, output, learning_rate):
m = y.shape[0]
# 출력층의 Gradient 계산 : Loss에 대한 출력의 Gradient 계산
d_oZ = output - y.reshape(-1, 1)
# 출력층 가중치 Gradient 계산 : 출력층의 Gradient와 (이전 Layer에서 들어온)은닉층의 출력(A)을 사용하여 출력층의 가중치를 갱신하기 위한 Gradient를 계산한다
d_oW = (1/m) * np.dot(self.hidden_A.T, d_oZ)
d_ob = (1/m) * np.sum(d_oZ, axis=0, keepdims=True)
# 은닉층의 Gradient 계산
d_hA = np.dot(d_oZ, self.output_W.T) # 출력층의 그래디언트를 은닉층의 출력에 대한 그래디언트로 변환
d_hZ = d_hA * (self.hidden_Z > 0).astype(float) # ReLU의 미분
# 은닉층의 가중치 Gradient 계산 : 은닉층의 Gradient와 (이전 Layer에서 들어온)입력층의 출력을 사용하여 은닉층의 가중치를 갱신하기 위한 Gradient를 계산한다.
d_hW = (1/m) * np.dot(X.T, d_hZ)
d_hb = (1/m) * np.sum(d_hZ, axis=0, keepdims=True)
# 역전파를 통해 구한 Gradient를 통해 가중치와 편향을 갱신한다.
self.hidden_W -= learning_rate * d_hW
self.hidden_b -= learning_rate * d_hb
self.output_W -= learning_rate * d_oW
self.output_b -= learning_rate * d_ob
# MLP 학습
def train(self, X, y, epochs, learning_rate):
for epoch in range(epochs):
output = self.forward(X) # 1. Forward Propagation
loss = np.mean((output - y.reshape(-1, 1)) ** 2) # 2. Loss 계산
self.backward(X, y, output, learning_rate) # 3. Backward Propagation
if epoch % 10 == 0:
print(f"Epoch {epoch}, Loss: {loss}") # 4. epochs만큼 반복
def predict(self, X):
return self.forward(X)
앞에서 살펴보았던 내용들이 모델에 적용되어 있는지 확인해보자.
1. 학습 과정
- forward() -> loss 계산 -> backward() -> epochs 만큼 반복한다는 것이 위에서 설명한 내용과 동일하다.
2. Forward Propagation 과정
- 다변량 선형 회귀이므로 은닉층에서 ReLU를 활성화 함수로 사용하였다.
- 입력층 -> 은닉층 -> 출력층의 순서로 연산이 진행된다.
3. Loss 구하기
- MSE Loss 함수를 사용해서 Loss를 계산하였다.
4. Backpropagation 과정
- Loss부터 시작하여 출력층 -> 은닉층 -> 입력층의 역순으로 역전파 알고리즘을 진행한다.
- 출력층과 은닉층의 가중치에 대한 Gradient를 계산하여 가중치를 업데이트한다.
from sklearn.datasets import load_diabetes
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
# 데이터 로드 및 전처리
diabetes = load_diabetes()
X = diabetes.data
y = diabetes.target
# 데이터 스케일링 (특성 표준화)
scaler = StandardScaler()
X = scaler.fit_transform(X)
# 데이터셋을 훈련 세트와 테스트 세트로 분리
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 모델 초기화 및 학습
input_size = X_train.shape[1]
hidden_size = 10
output_size = 1
model = SimpleMLP(input_size, hidden_size, output_size)
model.train(X_train, y_train, epochs=300, learning_rate=0.001)
# 예측 및 성능 평가
predictions = model.predict(X_test)
mse = np.mean((predictions.flatten() - y_test) ** 2)
print(f"Test MSE: {mse}")
Tensorflow로 MLP 모델 훈련시키기
이번에는 TensorFlow의 Sequential API를 사용하여 다층 퍼셉트론을 구현하고, scikit-learn의 내장 데이터셋 중 하나인 붓꽃(iris) 데이터셋을 학습시켜볼 것이다. 붓꽃 데이터는 Classfication 문제이다.
import tensorflow as tf
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
# 데이터 로드
iris = load_iris()
X, y = iris.data, iris.target
# 데이터 전처리
scaler = StandardScaler() # 특성 표준화를 위한 StandardScaler 객체 생성
X_scaled = scaler.fit_transform(X) # 데이터 표준화
# 훈련 세트와 테스트 세트로 분할
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)
# 모델 정의
# Sequential 모델 생성: 층을 순차적으로 쌓아나가는 신경망 모델
model = tf.keras.Sequential([
# 입력층 및 첫 번째 은닉층: 64개의 뉴런과 ReLU 활성화 함수 사용
tf.keras.layers.Dense(64, activation='relu', input_shape=(X_train.shape[1],)),
# 두 번째 은닉층: 64개의 뉴런과 ReLU 활성화 함수 사용
tf.keras.layers.Dense(64, activation='relu'),
# 출력층: 3개의 뉴런(클래스 수)과 softmax 활성화 함수 사용
tf.keras.layers.Dense(3, activation='softmax')
])
# 모델 컴파일: Adam 옵티마이저, 손실 함수는 sparse_categorical_crossentropy(다중 클래스 분류 -> CCE를 사용해야 한다고 하였다)
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# 모델 학습: 50 에포크 동안, 배치 크기는 32로 설정, 테스트 세트를 검증 데이터로 사용하여 학습 진행
model.fit(X_train, y_train, epochs=50, batch_size=32, validation_data=(X_test, y_test))
# 모델 평가
test_loss, test_acc = model.evaluate(X_test, y_test) # 테스트 데이터를 사용하여 모델 평가
print("Test Accuracy:", test_acc) # 테스트 정확도 출력
데이터 로드 및 전처리
- 사이킷런에서 붓꽃 데이터를 불러온 후 Feature(X)와 Label(y)을 분리한다.
- 표준화 : Feature들을 비슷한 스케일로 맞추어 학습 효율을 높일 수 있도록 전처리를 해준다.
- Train / Test Set으로 분리해주어 각각 학습 데이터와 검증 데이터로 사용한다.
모델 생성
- Tensorflow에서 제공하는 Sequential 모델은 Layer를 순차적으로 쌓을 수 있는 인공 신경망 모델이다.
- 각 Layer들에 대해서 출력층의 차원과, 활성 함수를 지정해주었다. 붓꽃은 3개의 Class로 분류되므로 Output Layer의 차원은 3으로 지정해야 한다.
모델 설정 및 컴파일
- 모델을 컴파일 할 때 옵티마이저, 손실 함수 등을 지정해줄 수 있다.
- 앞에서 언급했듯 다중 클래스 분류 문제는 손실 함수로 Categorical Cross Entropy를 주로 사용한다.
모델 학습
- Train Set을 사용해서 모델의 학습을 진행한다.
- Epoch : 데이터셋을 모델에 한 번 돌리는 단위이다.
- Batch Size: 모델을 훈련할 때 한 번에 모든 데이터를 사용하는 대신, 데이터를 작은 배치로 나누어 사용하는 단위이며 계산 효율성과 GPU 효율을 향상시키는 데 도움이 된다.
- 모델을 학습시키는 도중 Test Set(validation_data)을 사용하여 훈련 중의 모델의 성능을 검증한다.
모델 평가
- Test Set을 사용해서 모델의 성능을 최종적으로 검증한다.
딥러닝의 장단점
1. 장점
- 특징을 자동으로 추출한다. 이는 복잡한 데이터에 유리하며 모델 확장성이 뛰어나다.
- 대규모 데이터셋 처리에 특화되어 있다.
- 이미지, 음성, 자연어 등 복잡한 패턴을 인식하고 처리하는 능력이 뛰어나다.
2. 단점
- 모델의 파라미터가 많기 때문에 전통적인 머신러닝 모델에 비해 상대적으로 많은 학습 데이터가 필요하다.
- 모델 훈련을 위한 시간과 비용(=데이터의 양)이 많이 든다.
- 설정 파라미터가 많아서 최적의 모델과 훈련 방법을 찾기 위해서 힘내야 한다.
- Black-box : 오류를 파악하거나 디버깅이 어렵다
3. 한계(극복하지 못한 점)
- Overfitting : 모델이 데이터를 암기하는 과적합 현상
- Gradient Vanishing : 학습이 중단되는 현상
'Data Science > 머신러닝 & 딥러닝' 카테고리의 다른 글
[딥러닝] CNN : ResNet 모델로 동물 이미지 분류하기(CIFAR 이미지셋) (0) | 2024.06.08 |
---|---|
[딥러닝] CNN : 이미지 학습을 위한 신경망 (+ MNIST 손글씨 분류해보기) (1) | 2024.06.08 |
[머신러닝] 앙상블 모델 : Boosting / Stacking 적용해보기 (0) | 2023.08.30 |
[머신러닝] 앙상블 모델 : Voting / Bagging / Random Forest 적용해보기 (0) | 2023.08.30 |
[머신러닝] 비지도 학습 : 연관 규칙 분석 / 차원 축소 (0) | 2023.08.30 |