01 인공신경망의 구조
-01 layer + node
-02 활성함수
-03 오차함수
-04 최적화
-05 오차 역전파
-06 기울기 소실
02 실습
-01 ANN - 회귀
-02 ANN 튜닝 - batch_size, early stopping (적절한 epoch 결정)
-03 ANN - 분류
01 인공신경망의 구조
-01 layer + node
입력층 - 중간층 - 출력층 구조로 구성되어 있으며 각 층마다 여러 노드(뉴런)이 존재한다.
> 입력층 : 데이터를 전달받는 층 (노드의 수 = 피쳐 수)
> 출력층 : 최종 예측 결과를 리턴하는 층 (노드의 수 = 출력 결과)
* 회귀분석 : 1개의 target
* 분류분석 :
ex) 사망여부 -> 1개 target -> 원핫인코딩 (클래스별로 서로 다른 target 생성)* => Y_사망 Y_생존 (출력층 노드 수 2개)
ex) iris data 품종 -> 1개 target -> 원핫인코딩 => Y_1 Y_2 Y_3 (출력층 노드 수 3개)
> 중간층 : 하나의 층 구성에서부터 층을 추가하여 성능 비교 (층의 수, 노드 수 -> 사용자 결정*)
-02 활성함수 (사용자 결정*)
신호의 가중합을 다음 층에 전달할지의 여부를 결정한다.
sigmoid (0 : x < 0, 1 : x >=0), 렐루, 스텝 등
가중합의 크기가 0보다 작으면 0, 가중합의 크기가 0보다 크거나 같으면 1이다.
-03 오차함수
오차를 계산하여 오차를 줄이는 방향으로 기울기의 최적 구간을 탐색한다. (경사하강법)
* 회귀 분석 : MSE, RMSE, MAE 등
* 분류 분석 : cross entropy, binary cross entropy 등 (사용자 결정*)
-04 최적화 (사용자 결정*)
전체 데이터 수 = N
batch_size : 한 번 가중치 업데이트 시 사용하는 데이터의 수
iteration(step) : 1 epoch 동안 발생하는 업데이트 수 = N / batch_size
epochs : 전체 데이터를 1회 학습하는 단위
ex) N = 100
batch_size = 1
각 epoch마다 100건 중 단 1개의 데이터로 가중치 업데이트 100번 반복
batch_size = 100 (full batch = 배치 경사하강법)
각 epoch마다 100건 모두 사용하여 가중치 업데이트 1번 반복
batch_size = 10 (mini batch)
각 epoch마다 100/10 = 10개의 데이터로 가중치 업데이트 10번 반복
-05 오차 역전파
기울기와 오차와의 관계를 통해 기울기의 최적화를 진행한다.
중간층에서는 오차와 기울기의 관계를 파악할 수 없는 문제가 발생하며, 순전파를 통한 출력층의 오차를 이전층으로 분해하여 전달, 중간층에서도 기울기와 오차의 관계를 파악할 수 있다.
-06 기울기 소실
층이 늘어나면서 기울기가 0이 되는 현상이다.
시그모이드의 편미분값이 1보다 작아서 층마다 미분값이 곱해지는 과정에서 기울기가 0에 가까워진다.
하이퍼볼릭 탄젠트, 렐루, 소프트플러스 등으로 해결한다. (주로 렐루 사용)
02 실습
-01 ANN - 회귀
1) 데이터 로딩
import pandas as pd
boston = pd.read_csv('boston.csv')
boston.head()
Out[14]:
crim zn indus chas nox ... tax ptratio black lstat medv
0 0.00632 18.0 2.31 0 0.538 ... 296 15.3 396.90 4.98 24.0
1 0.02731 0.0 7.07 0 0.469 ... 242 17.8 396.90 9.14 21.6
2 0.02729 0.0 7.07 0 0.469 ... 242 17.8 392.83 4.03 34.7
3 0.03237 0.0 2.18 0 0.458 ... 222 18.7 394.63 2.94 33.4
4 0.06905 0.0 2.18 0 0.458 ... 222 18.7 396.90 5.33 36.2
[5 rows x 14 columns]
y = boston['medv']
X = boston.drop(columns='medv')
2) 스케일링
from sklearn.preprocessing import StandardScaler, MinMaxScaler
m_sc = StandardScaler()
X_sc = m_sc.fit_transform(X)
3) train / test 분리
from sklearn.model_selection import train_test_split
train_x, test_x, train_y, test_y = train_test_split(X_sc, y, random_state=0)
4) 모델링
(1) seed 고정 (딥러닝은 외부에서 seed를 고정)
import numpy as np
import tensorflow as tf
seed = 0
np.random.seed(seed)
tf.random.set_seed(seed)
(2) 모델 정의
from tensorflow.keras.layers import Input
from keras import Sequential
from keras.layers import Dense
model = Sequential()
model.add(Input(shape = (train_x.shape[1], ))) # 입력층은 Input 함수로 노드 구성 (노드수 = 설명변수 수)
model.add(Dense(6, activation = 'sigmoid'))
model.add(Dense(1)) # 회귀분석 출력층은 노드는 1개로 구성, 활성함수 None
* 중간층에만 activation function을 넣어준다.
(3) 오차함수, 최적화 결정
model.compile(optimizer='adam', loss='mse', metrics=['mae'])
(4) 학습
model.fit(train_x, train_y, epochs=500, batch_size = 10)
확률적 경사 하강법을 사용하며,
batch_size = 10 : 전체 데이터의 10%를 랜덤 선택하여 가중치 업데이트에 사용한다.
배치사이즈가 작아지면 속도는 빨라지나 안정성은 낮아진다. (편차가 커진다.)
epochs = 500 : 위 스텝을 500번 반복한다.
...
Epoch 498/500
38/38 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - loss: 10.2966 - mae: 2.3441
Epoch 499/500
38/38 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - loss: 10.2831 - mae: 2.3428
Epoch 500/500
38/38 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - loss: 10.2696 - mae: 2.3414
Out[42]: <keras.src.callbacks.history.History at 0x20fe69ac6e0>
379건의 10%를 사용하였기 때문에 Epoch 하단에 38이라는 숫자가 기재된다.
train_x.shape
train_x.shape
Out[43]: (379, 13)
(5) 평가
model.evaluate(test_x, test_y)[0] # loss (MSE)
model.evaluate(test_x, test_y)[0]
4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - loss: 21.1461 - mae: 3.0215
Out[45]: 21.14611053466797
model.evaluate(test_x, test_y)[1] # metrics (MAE)
model.evaluate(test_x, test_y)[1]
4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - loss: 21.1461 - mae: 3.0215
Out[46]: 3.0215461254119873
=> 500번 epoch train loss : 10.2696, test loss : 21.1461 (과적합 가능성 충분)
(6) 예측
model.predict(test_x)
test_y
test_y
Out[52]:
329 22.6
371 50.0
219 23.0
403 8.3
78 21.2
49 19.4
498 21.2
309 20.3
124 18.8
306 33.4
Name: medv, Length: 127, dtype: float64
#
model.add(Dense(52, activation = 'relu'))
model.add(Dense(26, activation = 'relu'))
model.add(Dense(13, activation = 'relu'))
다음과 같이 다층으로 구성된 경우 sigmoid가 적절하지 않다. 이러한 경우일 때는 relu를 사용하는 것이 좋다.
-02 ANN 튜닝 - batch_size, early stopping (적절한 epoch 결정)
1) 데이터 로딩
import pandas as pd
boston = pd.read_csv('boston.csv')
boston.head()
Out[14]:
crim zn indus chas nox ... tax ptratio black lstat medv
0 0.00632 18.0 2.31 0 0.538 ... 296 15.3 396.90 4.98 24.0
1 0.02731 0.0 7.07 0 0.469 ... 242 17.8 396.90 9.14 21.6
2 0.02729 0.0 7.07 0 0.469 ... 242 17.8 392.83 4.03 34.7
3 0.03237 0.0 2.18 0 0.458 ... 222 18.7 394.63 2.94 33.4
4 0.06905 0.0 2.18 0 0.458 ... 222 18.7 396.90 5.33 36.2
[5 rows x 14 columns]
y = boston['medv']
X = boston.drop(columns='medv')
2) 스케일링
from sklearn.preprocessing import StandardScaler, MinMaxScaler
m_sc = StandardScaler()
X_sc = m_sc.fit_transform(X)
3) train / test 분리
from sklearn.model_selection import train_test_split
train_x, test_x, train_y, test_y = train_test_split(X_sc, y, random_state=0)
4) 모델링
(1) seed 고정 (딥러닝은 외부에서 seed를 고정)
import numpy as np
import tensorflow as tf
seed = 0
np.random.seed(seed)
tf.random.set_seed(seed)
(2) 모델 정의
from tensorflow.keras.layers import Input
from keras import Sequential
from keras.layers import Dense
model = Sequential()
model.add(Input(shape = (train_x.shape[1], ))) # 입력층은 Input 함수로 노드 구성 (노드수 = 설명변수 수)
model.add(Dense(6, activation = 'sigmoid'))
model.add(Dense(1)) # 회귀분석 출력층은 노드는 1개로 구성, 활성함수 None
* 중간층에만 activation function을 넣어준다.
(3) 오차함수, 최적화 결정
model.compile(optimizer='adam', loss='mse', metrics=['mae'])
(4) early stopping rule
충분한 epoch로 학습, 매 스텝마다 검증 오차를 체크하여 더 이상 개선이 없을 경우 학습을 중단한다.
ex= EarlyStopping(monitor='val_loss', # 모니터링 기준
patience=10, # 10회 동안 개선이 없을 경우 중단
restore_best_weights = True) # 최적 오차 도출
# 멈춘 시점이 아닌 검증오차가 최소였던 지점의 오차 기준으로 최종 모델을 선정
(5) 학습
hist = model.fit(train_x, train_y,
validation_split = 0.25, # train 데이터의 25%를 검증용 데이터로 선택
batch_size = 10, # 전체 데이터의 10%f를 랜덤 선택하여 가중치 업데이트에 사용
epochs = 50000, # 충분히 크게 설정
callbacks = [es]) # early stopping rule 추가
...
Epoch 126/50000
29/29 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - loss: 2.3838 - mae: 1.1503 - val_loss: 6.4815 - val_mae: 1.9125
Epoch 127/50000
29/29 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - loss: 2.3591 - mae: 1.1438 - val_loss: 6.3612 - val_mae: 1.9056
Epoch 128/50000
29/29 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - loss: 2.3255 - mae: 1.1320 - val_loss: 6.4057 - val_mae: 1.9069
Epoch 129/50000
29/29 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - loss: 2.3205 - mae: 1.1334 - val_loss: 6.3793 - val_mae: 1.9044
Epoch 130/50000
29/29 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - loss: 2.3036 - mae: 1.1307 - val_loss: 6.4116 - val_mae: 1.9115
(6) 평가
hist.history['loss'] # 매 epoch 마다의 학습오차
hist.history['val_loss'] # 매 epoch 마다의 검증오차
import matplotlib.pyplot as plt
plt.plot(hist.history['loss'], label = 'train')
plt.plot(hist.history['val_loss'], label = 'val')
plt.legend()

model.evaluate(train_x, train_y)
model.evaluate(train_x, train_y)
12/12 ━━━━━━━━━━━━━━━━━━━━ 0s 2ms/step - loss: 3.5405 - mae: 1.4057
Out[90]: [3.540541172027588, 1.405723214149475]
model.evaluate(test_x, test_y)
model.evaluate(test_x, test_y)
4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 7ms/step - loss: 16.4689 - mae: 2.9572
Out[91]: [16.468944549560547, 2.957167625427246]
## ** 참고 : 위 그래프 출력 시 폰트 에러가 발생하는 경우 -> 기본 폰트 깨짐 현상 -> 폰트 캐시 재생성
import matplotlib
import shutil, os
cache_dir = matplotlib.get_cachedir()
print(ache_dir)
shutil.rmtree(cache_dir)
(7) batch size 튜닝
bs = [10, 20, 50, train_x.shape[0]]
for i in bs :
seed = 0
np.random.seed(seed)
tf.random.set_seed(seed)
# 모델 정의
model = Sequential()
model.add(Input(shape=(train_x.shape[1], )))
model.add(Dense(6, activation='relu'))
model.add(Dense(1))
# 오차함수, 최적화 결정
model.compile(optimizer='adam', loss='mse', metrics=['mae','r2_score'])
# early stopping rule
es = EarlyStopping(monitor='val_loss',
patience=10,
restore_best_weights = True)
# 학습
hist = model.fit(train_x, train_y,
validation_split=0.25, verbose= 0,
batch_size = i,
epochs=50000,
callbacks=[es])
# 최적 반복수 확인
be = np.argmin(hist.history['val_loss']) + 1
print(f'batch_size : {i}, 최적 반복수 : {be}')
# 평가
print(model.evaluate(train_x, train_y)[0])
print(model.evaluate(test_x, test_y)[0])
batch_size : 10, 최적 반복수 : 1673
12/12 ━━━━━━━━━━━━━━━━━━━━ 0s 2ms/step - loss: 8.2063 - mae: 2.0459 - r2_score: 0.9038
8.206317901611328
4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 6ms/step - loss: 21.7978 - mae: 3.0250 - r2_score: 0.7332
21.797828674316406
batch_size : 20, 최적 반복수 : 974
12/12 ━━━━━━━━━━━━━━━━━━━━ 0s 2ms/step - loss: 8.5905 - mae: 2.1381 - r2_score: 0.8993
8.590462684631348
4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 6ms/step - loss: 20.6176 - mae: 3.0851 - r2_score: 0.7476
20.617616653442383
batch_size : 50, 최적 반복수 : 2302
12/12 ━━━━━━━━━━━━━━━━━━━━ 0s 2ms/step - loss: 8.3724 - mae: 2.1259 - r2_score: 0.9019
8.372426986694336
4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - loss: 20.5260 - mae: 3.0028 - r2_score: 0.7488
20.525999069213867
batch_size : 379, 최적 반복수 : 5407
12/12 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - loss: 13.3568 - mae: 2.6968 - r2_score: 0.8434
13.356831550598145
4/4 ━━━━━━━━━━━━━━━━━━━━ 0s 5ms/step - loss: 25.5050 - mae: 3.6179 - r2_score: 0.6878
25.504959106445312
-03 ANN - 분류
회귀분석과는 다르게 출력층에서 반드시 가중합을 학습된 Y의 형태 (0 or 1)로 변환하는 장치 필요 --> 활성함수 (sigmoid)
출력층의 유닛(노드)의 수가 1개가 아닐 수 있음*
(1) 데이터 로딩
cancer = pd.read_csv('cancer.csv')
y = cancer['diagnosis']
X = cancer.drop(columns=['id','diagnosis'])
(2) 라벨링
y = (y == 'Malignant').astype('int') # 출력층 노드 수 1개로 설정 필요
y2 = pd.get_dummies(y, prefix='Y').astype('int') # 출력층 노드 수 2개로 설정 필요
(3) 스케일링
from sklearn.preprocessing import MinMaxScaler
m_sc = MinMaxScaler()
X_sc = m_sc.fit_transform(X)
(4)train / test 분리
from sklearn.model_selection import train_test_split
train_x, test_x, train_y, test_y = train_test_split(X_sc, y2, random_state=0)
(5) 모델링
# 1) seed 고정
import numpy as np
import tensorflow as tf
seed = 0
np.random.seed(seed)
tf.random.set_seed(seed)
# 2) 모델 정의
from tensorflow.keras.layers import Input
from keras import Sequential
from keras.layers import Dense
model = Sequential()
model.add(Input(shape=(train_x.shape[1], )))
model.add(Dense(15, activation='relu'))
model.add(Dense(2, activation='sigmoid'))
# 3) 오차함수, 최적화 결정
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# 4) early stopping rule
from tensorflow.keras.callbacks import EarlyStopping
es = EarlyStopping(monitor='val_loss',
patience=10,
restore_best_weights = True)
# 5) 학습
hist = model.fit(train_x, train_y,
validation_split=0.25,
batch_size = 10,
epochs=50000,
callbacks=[es])
# 6) 평가
hist.history['loss'] # 매 epoch 마다의 학습오차
hist.history['val_loss'] # 매 epoch 마다의 검증오차
hist.history['accuracy'] # 매 epoch 마다의 학습 정확도
hist.history['val_accuracy'] # 매 epoch 마다의 검증 정확도
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1,2)
ax[0].plot(hist.history['loss'], label = 'train')
ax[0].plot(hist.history['val_loss'], label = 'val')
ax[0].legend()
ax[1].plot(hist.history['accuracy'], label = 'train')
ax[1].plot(hist.history['val_accuracy'], label = 'val')
ax[1].legend()
model.evaluate(train_x, train_y) # accuracy: 0.9883 - loss: 0.0310
model.evaluate(test_x, test_y) # accuracy: 0.9441 - loss: 0.2931
'아이티윌_데이터 분석 55기 > 강의내용_딥러닝' 카테고리의 다른 글
| #5 5일차_감성 분석 (나이브베이즈, RNN) (0) | 2026.07.29 |
|---|---|
| #4 4일차_CNN, 얼굴 사진 분류하기, 쇼핑몰 후기 감성 분석 (0) | 2026.07.28 |
| #3 3일차_ANN(다중 분류), 이미지 분석(PCA+KNN, ANN, CNN) (0) | 2026.07.27 |
| #1 1일차_tensorflow, keras 설치하기 (0) | 2026.07.23 |