일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- plot_model
- explained AI
- Neural Network
- fashion mnist
- learning_rate
- 데이터크롤링
- 뉴스웨일
- 모델평가
- OneHotEncoding
- kt에이블스쿨
- AI
- CIFAR-10
- 키워드 기반 뉴스 조회
- CNN 실습
- 데이터처리
- bias
- CRISP-DM
- CNN
- MaxPooling2D
- 인공지능
- 딥러닝
- pandas
- 데이터분석
- AWS 입문자를 위한 강의
- 크롤링
- Pooling Layer
- 머신러닝
- 데이터
- Convolution Neural Network
- NewsWhale
- Today
- Total
jjinyeok 성장일지
딥러닝 #2 - ANN 2022/09/13~2022/09/16 본문
이전 정리에서 Tensorflow와 Keras 문법을 배우고 Tensorflow와 Keras를 통한 머신러닝 과정을 진행했다. 이번엔 이것들을 사용한 딥러닝 과정을 정리하겠다. 딥러닝은 이전 정리에서 중간 Hidden Layer를 쌓는 과정이 추가된다.
1. ANN (Artificial Neural Network)
앞선 Tensorflow와 Keras를 통한 머신러닝 모델에서 Hidden Layer(은닉층)을 추가한다면 간단한 딥러닝 모델을 만들 수 있다. 이를 ANN (Artificial Neural Network) 또는 MLP (Multi Layer Perceptron)라고 한다.
Sequential 스타일의 코드에서 Hidden Layer가 2개 추가된 모델의 구현은 다음과 같다. 참고로 이전 정리의 보스턴 집값 데이터 예측 Regression 문제를 푼 것인데 단지 코드 2줄이 추가되었다. 이를 통해 rmse 값이 꽤 줄었다는 점에 유의하며 살펴보자. 이때 코드 두줄에서는 activation='relu'를 적용했다. Activation 함수란 무엇이고 ReLU란 무엇일까?
'Data: 보스턴 집 값 데이터'
print(x_train.shape, x_val.shape, y_train.shape, y_val.shape)
# (455, 13) (51, 13) (455,) (51,)
'1-1. Sequentail style 모델 생성'
model = keras.models.Sequential()
'1-2. 모델을 차곡차곡 쌓기'
model.add(keras.layers.Input(shape=(13, )))
model.add(keras.layers.Dense(32, activation='relu')) # 히든층 추가
model.add(keras.layers.Dense(32, activation='relu')) # 히든층 추가
model.add(keras.layers.Dense(1))
'1-3. 모델 컴파일하기'
model.compile(loss='mse',
optimizer='adam')
'2. 모델 학습하기'
model.fit(x_train, y_train,
epochs=1000,
verbose=1)
'3. 모델 평가하기'
pred = model.predict(x_val)
rmse = mean_squared_error(y_val, pred, squared=True)
print(f'rmse: {rmse}')
# rmse: 14.874099458862421
2. Activation Function
우선 Activation Function (활성화 함수)은 왜 필요할까? 이전 Sigmoid 함수는 -∞부터 ∞까지 있는 결과 값을 0과 1사이로 조절해 Binary Classification 문제에 활용했다. 또 Softmax 함수는 각 Class일 확률을 계산해 Multi Classification 문제에 활용했다. 그렇다면 ReLU는? 또한 Hidden Layer에서는 왜 Activation 함수가 필요하며 ReLU는 무엇일까? 먼저 ReLU함수의 그래프는 다음과 같다.
강의 내용에서 약간 벗어나긴 하지만 Activation 함수는 딥러닝에서 필수적으로 사용된다. 만일 h1 = a * x + b일때, y = c * h1 + d의 상황에서 Activation 함수가 적용되지 않는다면 y = c * (a * x + b) + d 로, y = (ca) * x + (cb + d)이다. 즉 똑같은 Linear 함수가 된다. 따라서 Activation 함수를 적용하지 않는다면 Hidden Layer를 아무리 만든다고 딥러닝 모델이 복잡해지지 않는다. 따라서 Activation 함수를 Hidden Layer에 꼭 적용해야 하고 이때 ReLU는 Sigmoid보다 Gradient Vanishing 현상이 덜 일어나기 때문에 가장 많이 쓰이는 Activation 함수 중 하나이다. Gradient Vanishing은 나중에 다시 정리하겠다.
3. Bias
앞서 y = w1 * x1 + w2 * x2 + w3 * x3 + w0를 뉴럴 네트워크로 그린적이 있다. 그렇다면 w0는 어디로 갔을까? w0 = w0 * 1 형태로 이를 나타낼 수 있고 사실 그리지 않았을 뿐 w0는 다음과 같이 그려진다. 이때 w0를 Bias라고 부른다. 당연하게도 딥러닝 과정을 통해 Bias 즉 w0도 학습된다.
4. Summary
모델을 컴파일 한 후 모델에 summary() 메서드를 적용하여 모델링이 어떻게 진행되었는지 확인할 수 있다. 앞서 2개의 Hidden Layer를 쌓은 보스턴 집값 데이터에서 모델링이 어떻게 진행되었는지 확인하는 방법은 다음과 같다.
model = keras.models.Sequential()
model.add(keras.layers.Input(shape=(13, )))
model.add(keras.layers.Dense(32, activation='relu'))
model.add(keras.layers.Dense(32, activation='relu'))
model.add(keras.layers.Dense(1))
model.compile(loss='mse', optimizer='adam')
model.summary() # 어떤식으로 모델링이 진행되었는지 알 수 있음
이 코드를 통해 나타나는 Summary는 이러하다. Param #에 집중해보자.
앞서 Bias를 정리한 이유가 있는데 여기서 Param이란 Weight이다. 따라서 Param의 개수에는 Bias가 포함된다. Densely하게 연결되어 있는 층들에서 층과 층 사이의 Param개수 즉 Weight의 개수는 (이전 층의 Node 수 + 1) * (다음 층의 Node 수) 와 같다. 당연하게도 이전 층에서 더한 1은 Bias이다. 따라서 첫번째 Param #은 (13 + 1) * 32 = 448, 두번째 Param #은 (32 + 1) * 32 = 1056, 세번째 Param #은 (32 + 1) * 1 = 33이 된 것이다. 참고로 Sequential 스타일의 모델에서는 Input Layer가 나오지 않지만 Functional 스타일의 모델에서는 Input Layer가 나오는 것도 기억하자.
5. MNIST Data
딥러닝 연습을 위한 중 가장 유명한 데이터는 역시 MNIST일 것이다. MNIST Data는 손글씨 숫자로 0부터 9까지 총 10개의 숫자 이미지로 구성되어 있다. MNIST 데이터는 tensorflow.keras.datasets.mnist의 load_data() 함수를 통해 불러올 수 있고 MNIST 데이터를 화면에 출력하여 확인하는 방법은 다음과 같다.
print(x_train.shape, y_train.shape, x_test.shape, y_test.shape)
#(60000, 28, 28) (60000,) (10000, 28, 28) (10000,)
print(f'다음 그림은 숫자 {y_train[0]} 입니다.')
plt.imshow(x_train[0], cmap='gray')
plt.show()
이때 MNIST 데이터의 Shape를 본다면 x_train은 60000개의 높이 28, 너비 28인 이미지 데이터로 구분되어 있고 y_train은 각 숫자의 값 즉 Label을 지정하고 있음을 알 수 있다. x_test와 y_test는 앞선 구성과 같지만 10000개로 Test에 사용된다는 것 또한 알 수 있다.
6. MNIST 이미지를 숫자로 판단하는 ANN 모델 만들기 - 데이터 전처리
ANN 모델을 만들기에 앞서 3가지의 전처리가 필요하다. 첫째 Reshape 과정을 통해 데이터를 1차원으로 변경한다. 높이 28, 너비 28인 2차원 이미지 데이터를 784 크기의 1차원 데이터로 변경한다. 둘째 MinMax Scaling을 진행한다. sklearn.preprocessing의 MinMaxScaler를 사용했지만 이것은 데이터 개수까지 포함해서 3차원 이상인 데이터에서는 불가능하다. Reshape를 진행하지 않은 앞선 데이터가 그러하다. 따라서 Reshape가 먼저 일어나지 않은 경우 경우 직접 데이터에 min()과 max() 메서드를 사용해 MinMax Scaling을 진행한다. 셋째 Target Feature를 One-hot Encoding으로 변경한다. 이전부터 사용하던 tensorflow.keras.utils의 to_categorical 함수를 사용해 One-hot Encoding 변경이 가능하다. 전체 전처리 과정은 다음과 같다.
'1. Reshape'
print(x_train.shape)
# (60000, 28, 28)
x_train = x_train.reshape([x_train.shape[0], 784])
x_test = x_test.reshape([x_test.shape[0], 784])
print(x_train.shape)
# (60000, 784)
'2. MinMax Scaling'
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
x_train = scaler.fit_transform(x_train)
x_test = scaler.transform(x_test)
print(f'max : {x_train.max()} / min : {x_train.min()}')
# max : 1.0 / min : 0.0
'3. Target Feature : One-hot Encoding'
from tensorflow.keras.utils import to_categorical
print(set(y_train))
# {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
len_y = len(set(y_train))
print(len_y)
# 10
y_train = to_categorical(y_train, len_y)
y_test = to_categorical(y_test, len_y)
print(y_train.shape)
# (60000, 10)
7. MNIST 이미지를 숫자로 판단하는 ANN 모델 만들기 - 모델링
Hidden Layer를 Node개수 256개로 3 층을 쌓은 모델은 다음과 같다. 앞서 지금까지 만들었던 모델과 다를 것이 없지만 Input의 shape와 각 Hidden Layer의 Node개수가 지금까지 모델보다 많아 Param #가 높은 모습을 보인다.
print(x_train.shape, y_train.shape)
# (60000, 784) (60000, 10)
keras.backend.clear_session()
model = keras.models.Sequential()
model.add(keras.layers.Input(shape=(x_train.shape[1])) )
model.add(keras.layers.Dense(256, activation='relu') )
model.add(keras.layers.Dense(256, activation='relu') )
model.add(keras.layers.Dense(256, activation='relu') )
model.add(keras.layers.Dense(10, activation='softmax') )
model.compile(loss=keras.losses.categorical_crossentropy, metrics=['accuracy'], optimizer='adam')
print(model.summary())
# Model: "sequential"
# _________________________________________________________________
# Layer (type) Output Shape Param #
# =================================================================
# dense (Dense) (None, 256) 200960
# dense_1 (Dense) (None, 256) 65792
# dense_2 (Dense) (None, 256) 65792
# dense_3 (Dense) (None, 10) 2570
# =================================================================
# Total params: 335,114
# Trainable params: 335,114
# Non-trainable params: 0
# _________________________________________________________________
# None
8. MNIST 이미지를 숫자로 판단하는 ANN 모델 만들기 - 학습 & Early Stopping
학습을 진행하는 과정 또한 지금까지 과정과 같지만 Early Stopping을 통해 성능의 개선이 없다면 모델의 학습을 종료하는 기능을 추가했다. 학습 시 Validation을 나누어 Validation 스코어를 기준으로 개선을 파악해 더이상 개선이 안된다고 판단되면 학습이 종료되는 것이다.
Early Stopping을 진행하기 위해 선행되어야 할 작업으로 tensorflow.keras.callbacks에서 EarlyStopping 객체를 만든다. 내부 parameter로 monitor로 어떤 값을 기준으로 개선이 되고 있는지 안되고 있는지 판단하고 그 기준에 대해 개선 되고 있다고 판단하는 기준을 min_delta로 지정한다. 기준을 몇번 충족할 때 Early Stopping이 실행되는지 지정하기 위해 patience를 사용하며 restore_best_weights=True로 설정해주어야 가장 성능이 좋았을 때로 복원된다.
EarlyStopping객체를 모델이 학습하는 과정에 callbacks parameter에 넣어주고 validation_split parameter를 통해 Validation 데이터의 양을 정한다. 과정은 다음과 같다.
from tensorflow.keras.callbacks import EarlyStopping
es = EarlyStopping(monitor='val_loss', # 학습 조기종료를 위해 관찰하는 항목: Loss 값
min_delta=0, # 개선되고 있다고 판단하기 위한 최소 변화량: Loss 값 변화량이 0 이상이라면 개선
patience=5, # 개선이 안되는 과정이 몇번 일어나면 종료할지: 5회 연속으로 개선이 안된다면 Early Stopping
verbose=1,
restore_best_weights=True) # 가장 성능이 좋았을 때로 복원
model.fit(x_train, y_train,
validation_split=0.2, # Train Data의 20%를 Validation Data로 사용
callbacks=[es], # EarlyStopping 적용
verbose=1, epochs=50)
val_loss를 기준으로 개선이 5회 안되었기 때문에 Epoch 10에서 학습이 종료되었고 가장 성능이 좋았던 Epoch 5때로 복원되었음을 알 수 있다.
9. MNIST 이미지를 숫자로 판단하는 ANN 모델 만들기 - 평가
Multi Class Classification 문제를 평가하는 방법은 지난 문제들의 평가 방법과 동일하다. 과정은 다음과 같다.
pred_train = model.predict(x_train)
pred_test = model.predict(x_test)
single_pred_train = pred_train.argmax(axis=1)
single_pred_test = pred_test.argmax(axis=1)
logi_train_accuracy = accuracy_score(y_train.argmax(axis=1), single_pred_train)
logi_test_accuracy = accuracy_score(y_test.argmax(axis=1), single_pred_test)
print('트레이닝 정확도 : {:.2f}%'.format(logi_train_accuracy*100))
print('테스트 정확도 : {:.2f}%'.format(logi_test_accuracy*100))
# 트레이닝 정확도 : 98.76%
# 테스트 정확도 : 97.61%
'[KT AIVLE School]' 카테고리의 다른 글
시각지능 딥러닝 #1 - CNN 개요 2022/09/19~2022/09/23 (0) | 2022.09.19 |
---|---|
딥러닝 #3 - 적용하기 2022/09/13~2022/09/16 (0) | 2022.09.16 |
딥러닝 #1 - 딥러닝 개요 Tensorflow & Keras 2022/09/13~2022/09/16 (0) | 2022.09.13 |
머신 러닝 #5 - Ensemble 기법 2022/08/22~2022/08/29 (0) | 2022.09.12 |
머신 러닝 #4 - 성능 튜닝 2022/08/22~2022/08/29 (0) | 2022.09.11 |