혼자 공부하는 머신러닝 + 딥러닝의 Chapter 7을 공부하면서 정리한 내용을 기반으로 작성하였다.
7-3 미완
07-1. 인공신경망
인공 신경망(ANN;artificial neural network)
- 가장 기본적인 인공 신경망은 확률적 경사 하강법을 사용하는 로지스틱 회귀와 같다.
- 이미지 분류 문제에는 인공 신경망이 잘 맞는다.
- 출력층 z값을 계산하는 단위를 유닛(unit)이라고 부른다. (예전에는 뉴런이라고 부름)
- 기존의 머신러닝 알고리즘이 잘 해결하지 못했던 문제에서 높은 성능을 발휘하는 새로운 종류의 머신러닝 알고리즘일 뿐이다.
- GPU(그래픽 처리장치)는 벡터와 행렬 연산에 매우 최적화 되어 있어 곱셈/덧셈이 많이 수행되는 인공 신경망에 큰 도움이 된다.
- 인공 신경망에서는 교차 검증을 살 사용하지 않고, 검증 세트를 별도로 덜어내어 사용한다.
케라스(Keras)
- Tensorflow의 직관적이고 사용하기 편한 고수준 API
- 멀티 - 백엔드 케라스 : 케라스의 백엔드로 텐서플로, 씨아노, CNTK와 같은 여러 딥러닝 라이브러리를 사용할 수 있다.
- 단, 2.3.1버전 이후로 더 이상 개발되지 않는다. 그렇기에, 케라스와 텐서플로는 거의 동의어인 셈이다.
- 케라스는 텐서플로의 핵심 API가 되었다.
데이터셋 인공 신경망에 맞게 처리하자
→ 머신러닝에서는 붓꽃 데이터셋이 유명하지만, 딥러닝에서는 MNIST 데이터셋이 유명하다.
- 패션 MNIST dataset 받기
- 검증세트 20%정도를 빼두기
- 각 픽셀이 0~255사이의 정숫값을 가지므로 0~1 사이의 값으로 정규화한다. (표준화 아님!)
- 2차원 배열을 1차원 배열로
- 여기선 reshape()를 썼지만, 이후 모델에 keras.layers.Flatten()을 이용해서 펼쳐주는 층을 추가할 수 있다.
import tensorflow as tf
from tensorflow import keras
from sklearn.model_Selection import train_test_split
(train_input, train_target), (test_input, test_target) =\
keras.datasets.fashion_mnist.load_data()
train_scaled, val_scaled, train_target, val_target =
train_test_split(train_scaled, train_target, test_size = 0.2)
train_scaled = train_input / 255.0
train_scaled = train_scaled.reshape(-1, 28*28)
코드 - 1
인공 신경망 모델을 만들어 보자
- Dense 클래스 : 밀집층 객체를 만들 수 있고, 매개변수로는 다음과 같은 사항을 필요로 한다
- 뉴런 개수,
- activation = 뉴런의 출력에 적용할 활성화 함수
- input_shape = 입력의 크기
- Sequential 클래스
- compile() : 모델 훈련하기 전 설정 단계 손실 함수의 종류를 지정해야 한다.
- 이진분류 : loss = 'binary_crossentropy'
- 다중분류 : loss = 'categorical_crossentropy'
- fit()
- epochs로 반복횟수를 정하고, 훈련한다.
- verbose로 훈련과정을 어떻게 나타낼지 지정할 수 있다
- 0: 훈련 과정 나타내지 않는다.
- 1 (기본값) : 에포크마다 진행막대와 지표를 보여준다
- 2 : 진행 막대 빼고 훈련결과 출력
- evaluate() : keras에서 모델의 성능을 평가하는 메서드로, 반드시 이전에 compile()이 실행되어야 한다.
- predict() : 새로운 데이터에 대해 예측하는 메서드로, 각 샘플마다 10개의 클래스에 대한 확률을 반환한다.
(7-3장 참조)
- compile() : 모델 훈련하기 전 설정 단계 손실 함수의 종류를 지정해야 한다.
import tensorflow as tf
from tensorflow import keras
dense = keras.layers.Dense(10, activation = 'softmax', input_shape=(784,))
model = keras.Sequential(dense)
model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')
model.fit(train_scaled, train_target, ephochs = 5)
model.evaluate(val_scaled, cal_target)
코드 - 2
- 원-핫 인코딩 (one-hot encoding)
- 신경망은 손실을 낮추기 위해서 뉴런의 활성화 함수를 거친 출력값이 가능한 1에 가깝게 만들어야 한다.
- 원-한 인코딩은 타깃값을 해당 클래스만 1이고, 나머지는 모두 0인 배열로 만드는 것을 말한다.
- 하지만, 정수로 된 타깃값을 가지고 있다면, 원-핫 인코딩없이 크로스 엔트로피 손실을 계산할 수 있다. 그 때 쓰는 손실함수가 'sparse_categorical_crossentropy'이다.
07-2. 심층 신경망
활성화 함수
- 출력층의 활성화 함수는 다소 정해져 있다.
- 이진 분류일 경우 시그모이드 함수를 사용
- 다중 분류일 경우, 소프트맥스 함수를 사용
- 은닉층의 활성화 함수는 자유롭다.
- 모든 은닉층에는 활성화 함수가 있다
- 시스모이드 함수, 볼 렐수(ReLU)함수가 대표적!
- 은닉층에서 활성화 함수를 쓰는 이유는 뭘까
- a에서 b를 거쳐 c라는 최종값을 얻고자하는 식이 있다고 생각하자. : a * 3 + 2 = b → b * 3 - 5 = c
- 위 식에서 b는 전달책에 지나지 않아 필요 없어 보인다. 그냥 (a * 3 +2) * 3 - 5 = c로 계산하면, b는 필요 없는 셈이다.
- 그렇기에, 중간의 b에 log를 씌워 전달하는 등 비선형적으로 비틀어줄 필요가 있다.
- 회귀를 위한 신경망에서는 활성화 함수를 적용하지 않는다.
- 인공신경망 그림으로 표현할 때, 활성화 함수를 별개의 층이 아니라 층에 포함된 것으로 간주하기에, 생략하는 경우가 많다.
시그모이드 함수
- 활성화 함수 중 하나로, x값을 0과 1사이로 압축할 수 있다.
- 함수가 양끝으로 갈 수록 완만해지기 때문에, 올바른 출력을 만드는데 신속하게 대응하지 못한다.
렐루 함수(ReLU)
- 시그모이드 함수보다 신속한 대응가능하게 한다. 성능 좋다.
- ReLU(z) = max(0, z)
- 음수는 0으로 만든다.
- 양수는 변동없이 그대로 출력된다.
심층 신경망 (DNN;deep neural network)을 만들자
Dense() 할 때 주의사항
- 신경망의 첫번째 층은 입력의 크기(input_shape)를 꼭 지정해줘야 한다.
- 은닉층의 뉴런의 개수 > 출력층의 뉴런의 개수
- 출력층을 가장 마지막에 두어야 한다.
2차원 배열 → 1차원 배열
- 모델에 데이터를 넣기 전, reshape()을 써서 미리 처리해두기
- keras.layers.Flatten()을 이용해, 일렬로 펼치는 층을 입력층 바로 뒤에 추가한다. [코드 - 3]
층 추가 방법
코드 - 2 처럼dense로 따로 저장해 리스트로 주는 방법 [코드 - 3의 flatten]- Sequential 생성하면서 같이 생성 [코드 - 3의 relu]
- add() 함수 사용 [코드 - 3의 softmax]
import tensorflow as ts
from tensorflow import keras
(train_input, train_target), (test_input, test_target) = keras.datasets.fashion_mnist.load_data()
train_scaled = train_input / 255.0
'''
2차원 -> 1차원 : Flatten ()
add dense : list, add()
'''
# make_model : 모델 생성 함수
def make_model(aLayer = None) :
flatten = keras.layers.Flatten(input_shape=(28, 28), name = 'flatten')
model = keras.Sequential([flatten,keras.layers.Dense(100, activation = 'relu', name = 'relu')])
if(aLayer)
model.add(aLayer)
model.add(keras.layers.Dense(10, activation = 'softmax', name ='softmax'))
return model
model = make_model()
model.summary()
코드 - 3
Optimizer(옵티마이저)
▷ 모델 환경설정(compile())할 때 매개변수 optimazer에 지정할 수 있다 (default : rmsprop)
▷ keras.optimizers 클래스 객체 만들 때의 매개변수
- learning_rate : 학습률을 지정할 수 있다 (default : 0.01)
- momentum : 0보다 큰 값을 지정하면 momentum optimization을 사용한다 (보통 0.9 이상을 지정함) (default : 0)
- nesterov : nesterov momentum optimization을 사용여부 지정(default : False)
1. SGD(Stochastic Gradient Descent)
- 확률적 경사하강법, 가장 기본적인 옵티마이저
- learning_rate : (default : 0.01)
2. Adam(추천!)
- 적응적 학습률(adaptive learning rate; 모델이 최적점에 가까워질수록 학습률을 낮춰 안정적으로 최적점에 수렴하도록 함)을 사용한다.
- momentum optimization과 RMSprop의 장점을 접목한 것
- learning_rate : (default : 0.001)
3. Adagrad
- 적응적 학습률을 사용한다.
- learning_rate : (default : 0.001)
4. RMSprop(Root Mean Square Propagation)
- 적응적 학습률을 사용한다.
- learning_rate : (default : 0.001)
'''
keras.optimizer 클래스 객체 만들기
- 매개변수 바꾸고 싶을 때
keras.optimizers.SGD()
Keras.optimizers.Adagrad()
keras.optimizers.RMSprop()
keras.optimizers.Adam()
'''
sgd = keras.optimizer.SGD(learning rate = 0.1, momentum = 0.9, nesterov = True)
model.compile(optimizer = sgd, loss = 'sparse_categorical_crossentropy', metrics = 'accuracy')
'''
compile()의 optimizer 매개변수에 지정
sgd
adam
adagrad
rmsprop
'''
model.compile(optimizer = 'adam', loss = 'sparse_categorical_crossentropy', metrics = 'accuracy')
model.fit(train_scaled, train_target, epoches = 5)
model.evaluate(val_scaled, val_target)
코드 - 4
07-3. 신경망 모델 훈련
검증 손실
손실 곡선과 정확도 곡선
- history 객체에는 훈련 측정 값이 담겨 있는 history 딕셔너리가 들어 있다.
print(history.history.keys())
#dict_keys(['loss', 'accuracy'])
- matplotlib.pyplot의 plot() 함수를 통해서 손실, 정확도 그래프를 그릴 수 있다.
- y축 : history.history['loss'] 혹은 history.history['accuracy']
- x축 : epoch
검증 손실
- 인공 신경망은 모두 일종의 경사 하강법을 사용하기 때문에, 과대/과소적합을 막기 위해서는 훈련세트와 검증세트에 대한 손실을 모두 확인해야 한다.
- 모델이 잘 훈련되었는지 판단하려면 정확도보다는 손실 값을 확인해야 하고, 손실 함수가 최적화 되어야 한다.
- fit() 함수의 validation_data에 튜플로 검증세트를 전달할 수 있고, 검증세트에 대한 손실과 정확도는 각각 val_loss와 val_accuracy에 들어 있다.
model.fit(train_scaled, train_target, expochs = 20, verbose = 0,
validation_data = (val_scaled, val_target))
import matplotlib.pyplot as plt
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.xlabel('epoch')
plt.ylabel('loss')
ply.legend(['train', 'val'])
plt.show()
과대적합 확인
인공 신경망 최적화
- 과대적합 막는 방법
- 앞서 검증 손실 부분에서 훈련세트와 테스트세트에 대해서 에포크 당 손실 그래프를 그렸다. 이는 과대적합 확인할 수 있는 방법으로, 이번엔 과대적합을 막는 여러 방법을 정리해보자.
1) Optimizer (Adam, RMSprop 등)를 이용해보자
- compile()로 모델 설정할 때, optimizer를 지정해주면 된다.
2) Early Stopping(조기 종료)
- epoch 매개변수를 이용해 학습률을 학습률을 조정해보자
- fit()에 epoch를 지정해주는데, optimizer를 지정해주면 된다.
- keras.callbacks.EarlyStopping() : 조기 종료 콜백함수
- 매개변수 patience에 횟수를 지정하여, 그 횟수만큼 검증 손실이 줄어들지 않으면 훈련을 중지한다.
- early_stopping_cb.stopped_epoch로 훈련이 중지된 게 몇 번째 에포크인지 확인할 수 있다.
- 예를들어, patience를 2로 지정했고, 에포크 12번째 때 중지되었다면, 최적의 모델은 2 에포크 전의 모델인 셈이다.
3) Drop Out(드롭아웃)
- WHAT 뉴런이 랜덤하게 드롭아웃되는데, 드롭할 뉴런의 개수는 우리가 지정할 수 있다. (하이퍼파라미터임)
- WHY 랜덤하게 뉴런을 드롭시켜, 일부 뉴런의 출력을 0으로 막아 특정 뉴런에 과하게 의존하는 경향을 줄일 수 있다. 그렇기에, 드롭아웃을 통해 과대적합을 줄이고 보다 안정적인 예측을 만들 수 있는 것이다.
- 일부 뉴런의 출력을 0으로 만들지만 전체 출력 배열의 크기는 바뀌지 않는다.
- 훈련이 끝난 뒤에는 훈련된 모든 뉴런을 사용해야 예측을 잘 할 수 있기에, 훈련이 끝난 뒤에는 드롭아웃을 적용해서는 안된다.
- 다행히 텐서플로와 케라스는 모델을 평가하고 모델을 가지고 예측할 때는 자동으로 드롭아웃을 적용하지 않는다.
4) Callback(콜백)
- fit()의 훈련 중간에 특정 작업들을 수행할 수 있게 한다.
- fit()의 하이퍼 파라미터 callbacks에 리스트형태로 지정해주면 된다.
- keras.callbacks.ModelCheckpoint() : 모델 저장 콜백함수
- 매개변수 best_only= True로 두면, 가장 검증 손실이 낮은 모델을 저장할 수 있다.
- 기본적으로는 에포크마다 모델을 저장한다.
- keras.callbacks.EarlyStopping() : 조기 종료 콜백함수
# 드롭아웃
model.add(keras.layers.Dropout(0.3))
# 콜백
modelCheck = keras.callbacks.ModelCheckpoint('best-model.h5', save_best_only = True)
model.fit( ... , callbacks = [modelCheck]
모델 저장과 복원
1. 모델 저장
- save_weights() : 모델 파라미터를 체크포인트 포맷으로 저장한다.
- save() : 모델구조와 모델 파라미터를 SavedModel 포맷으로 저장한다.
- 인자로 전달하는 파일의 확장자가 .h5라면 HDF5 포맷으로 저장한다
2. 모델 복원
- load_weights()
- 이전에 저정했던 모델 파라미터를 복원하여, 새로운 모델에 해당 모델 파라미터를 적재할 수 있다.
- save_weights()의 쌍으로 저장된 모델과 정확히 같은 구조를 가지지 않으면 에러가 발생한다.
- load_model()
- 모델 파라미터, 모델구조, 옵티마이저 상태까지 모두 복원한다.
- save()로 저장된 모델을 load_model()로 복원할 수 있다.
# 모델 저장
model.save_weights('model-parameters.h5')
model.save('model-whole.h5')
# 모델 복원
new_model = make_model() #코드3 의 make_model() 함수로 모델 생성함
model_parameter.load_weights('model-parameters.h5')
model_whole = keras.model.load_model('model-whole.h5')
predict()
import numpy as np
val_labels = np.argmax(model.predict(val_scaled), axis = -1)
print(np.mean(val_labels == val_target))
**참고
1. 표준화(Nomalization) → 값의 최대-최소 범위를 벗어나지 않고, 공통 척도를 기준으로 변경하는 것 → 보통 0~1사이의 고정된 범위로 조정된다. → Min-Max scaling을 Normalization이라고 부르기도 한다. → Xnorm = ( X − Xmin ) / ( Xmax − Xmin ) |
2. 정규화(Standardization) → feature들이 표준 정규 분포 특성을 가지게 하는 것 → z = ( x- μ ) / σ |
[epoche와 batch size] 1 epoch = 100 / batch size = 10 iteration → epoches : 전체 데이터셋에 대해서 한 번 학습을 완료한 상태 → batch size : 한번 전달되는 데이터셋의 샘플 사이즈 길게 늘어뜨려서 이해해보자. 전체 데이터셋 중 batch size만큼의 일부가 전달되고 학습되는 과정이 반복(iteration)된다. 여러 반복이 후, 전체 데이터셋이 한 번 학습이 완료된다. 이 총 과정을 몇 번 반복할지 epoche로 정한다. |
[tuple] ex ) (1,) → 값이 중복될 수 있지만, 내부 값을 특정해서 변경하거나 삭제할 수 없다. 물론, 튜플 자체 삭제는 가능하다. |
[np.argmax()] 가장 큰값의 인덱스 반환 - axis = -1 : 마지막 차원을 따라 최댓값의 인덱스 반환 - axis = 0 : row를 따라 column 별 최댓값의 인덱스 반환 - axis = 1 : column을 따라 row 별 최대값의 인덱스 반환 |
'딥러닝 > 혼공머신' 카테고리의 다른 글
[혼공머신] chapter 9. 텍스트를 위한 인공 신경망 (0) | 2023.03.27 |
---|---|
[혼공머신] chapter 8. 이미지를 위한 인공 신경망 (0) | 2023.03.13 |