Tensor Flow
구글에서 만든 딥러닝 프로그램을 쉽게 구현할 수 있도록 기능을 제공하는 라이브러리
모델 구축과 서비스에 필요한 다양한 도구를 제공, 신경망 모델을 빠르게 구성 가능한 Keras를 핵심 API로 채택
- 가능한 요소 : 필기 숫자 판별, 이미지 인식, 단어 임베딩, 반복 신경망, 시퀀스 투 시퀀스 모델 자연어 처리, 신경망 학습
- Colab에서 딥러닝 라이브러리를 사용할 때는 그래픽 처리 장치인 GPU를 사용하여 인공 신경망 훈련하기
- GPU : 벡터와 행렬 연산에 매우 최적화되어 있기에, 덧셈과 곱셈이 많이 수행되는 인공 신경망에 큰 도움이 됨
인공 신경망(ANN; Artificial Neural Network)
: 기존 머신러닝 알고리즘으로 다루기 어려웠던 이미지, 음성, 텍스트 분야에서 뛰어난 성능을 발휘하는 딥러닝
* 딥러닝(DeepLearning) : 인공신경망과 동의어로 사용되는 경우가 多, 혹은 심층 신경망을 딥러닝이라고 함.
○ 용어
● 출력층(Output layer) : 신경망의 최종 값
● 뉴런(Neuron = Unit) : z 값을 계산하는 단위, 뉴런에서 일어나는 일은 선형 계산이 전부
● 입력층(Input layer) : 픽셀값 그 자체, 특별한 계산을 하지는 않음
○ 인공신경망으로 모델 만들기
● 신경망 모델 생성
* Sequential 클래스의 객체를 만들 때 만든 밀집층의 객체 dense를 전달
* 아래 코드의 경우 model 객체가 신경망 모델
* 모델 그림을 그릴 때 입력층과 출력층 사이에 연결선만 나타내고 가중치는 표시하지 않는 경우가 多
* 절편의 경우 아예 선을 그리지 않는 경우가 많음 하지만 절편이 뉴런마다 더해진다는 사실은 기억할 것
* 소프트맥스 함수 : 뉴런의 선형 방정식 계산 결과에 적용되는 함수로 활성화 함수(Activation Function)라고 부름
import tensorflow as tf
from tensorflow import keras
from sklearn.model_selection import train_test_split
train_scaled, val_scaled, train_target, val_target = train_test_split(tran_scaled, train_target, test_size = 0.2, random_state = 42)
# (뉴런 개수, 뉴런 출력에 사용할 함수, 입력 크기)
dense = keras.layers.Dense(10, activation="softmax", input_shape=(784, ))
model = keras.Sequential(dense)
● 케라스 모델을 훈련하기 전 손실 함수 종류 설정 단계(필수)
- 이진 분류 손실 함수 : loss = 'binary_crossentropy'
- 이진 분류 활성화 함수 : 시그모이드 함수
- 다중 분류 손실 함수 : loss = 'categorical_crossentroy'
- 다중 분류 활성화 함수 : 소프트맥스 함수
* 아래 코드에서 sparse를 붙인 이유?
이진 크로스 엔트로피 손실을 위해 아래와 같이 계산했음
양성일 경우 : - log(a) X 타깃값(=정답)
음성일 경우 : -log(1-a) X (1 - 타깃값)
이진 분류에서는 출력층의 뉴런이 하나.
이 뉴런이 출력하는 확률값 a(시그모이드 함수의 출력값)를 사용해 양성/음성 클래스에 대한 크로스 엔트로피를 계산
model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')
● 원-핫 인코딩
- 타깃값을 해당 클래스만 1이고 나머지는 모두 0인 배열로 만드는 방법
- 변환해 주는 이유
: 다중 분류에서 크로스 엔트로피 손실 함수를 사용하려면 0, 1, 2와 같이 정수로 된 타깃 값을 변환해야 함
● 스파스 범주형 교차 엔트로피(sparse_categorical_crossentropy)
: 텐서플로에서 정수로 된 값을 원-핫 인코딩으로 바꾸지 않고 바로 사용 가능
● 모델 훈련 및 성능 평가
model.fit(train_scaled, train_target, epochs = 5)
model.evaluate(val_scaled, val_target)
○ SGDClassifier와 Keras Sequential 클래스 사용법 비교
● 사이킷런 모델
# 모델
sc = SGDBlassifier(loss='log_loss', max_iter = 5) # loss= 손실함수 , max_iter = 반복 횟수
# 훈련
sc.fit(train_scaled, train_target)
# 평가
sc.score(val_scaled, val_target)
● 케라스 모델
dense = keras.layers.Dense(10, activation='softmax', input_shape=(784,)) # Dense = 층생성
# 모델
model = keras.Ssequential(dense)
model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')
# 훈련
model.fit(train_scaled, train_target, epochs=5)
# 평가
model.evaluate(val_scaled, val_target)
○ 심층 신경망(Deep neural network; DNN)
: 2개 이상의 층을 포함한 신경망(종종 다층 인공 신경망, 심층 신경망, 딥러닝을 같은 의미로 사용)
● 데이터 불러오기(패션 MNIST 데이터 셋 사용)
from tensorflow import keras
(train_input, train_target), (test_input, test_target) =\ keras.datasets.fashion_mnist.load_data()
from sklearn.model_selection import train_test_split
train_scaled = train_input / 255.0
train_scaled = train_scaled.reshape(-1, 28*28)
train_scaled, val_scaled, tarin_target, val_target = train_test_split(train_scaled, train_target, test_size=0.2, random_state=42)
● 층 추가 방법 1 : 출력층을 케라스의 Dense 클래스로 생성하기
* 시그모이드 활성화 함수를 사용
* 시그모이드 함수 (활성화 함수) : 뉴런의 출력 z 값을 0 ~ 1 사이로 압축
# 은닉층 : 100개의 뉴런을 가진 밀집층
dense1 = keras.layers.Dense(100, activation='sigmoid', input_shape=(784,))
# 출력층 : 10개의 클래스를 분류하므로 10개의 뉴런을 설정
dense2 = keras.layers.Dense(10, activation='softmax')
● 층 추가 방법 2 : Sequential 클래스의 생성자 안에서 바로 Dense 클래스의 객체를 만들기
model = keras.sequential([
keras.layers.Dense(100, activation='sigmoid', input_shape(784,)), name='hidden'),
keras.layers.Dense(10, activation='softmax', name='output')
], name='fashion MNIST model')
● 층 추가 방법 3 : add() 메서드 사용
model = keras.Sequential()
model.add(keras.layers.Dense(100, activation='sigmoid', input_shape=(784,))
model.add(keras.layers.Dense(10, activation='softmax'))
model.summary()
● 모델 생성 및 훈련
# 생성
model = kears.Sequential([dense1, dense2])
model.summary()
# 훈련
model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')
model.fit(train_scaled, train_target, epochs=5)
○ 렐루 함수
: 입력이 양수일 경우 활성화 함수가 없는 것처럼 입력을 pass 하고 음수일 경우 0으로 만듦
● 시그모이드 함수의 단점 : 오른쪽과 왼쪽 끝으로 갈수록 그래프가 누워있음
So, 올바른 출력을 만드는 데 신속한 대응 불가
특히 층이 많은 심층 신경망일수록 누적되어 학습을 어렵게 만듦
model = keras.Sequential()
model.add(keras.layers.Flatten(input_shape=(28,28)))
model.add(keras.layers.Dense(100, activation='relu'))
model.add(keras.layers.Dense(10, activation='softmax'))
(train_input, train_target), (test_input, test_target) =\
keras.datasets.fashion_mnist.load_data()
train_scaled = tarin_input / 255.0
train_scaled, val_scaled, train_taraget, val_target = train_test_split(
train_scaled, train_target, test_size = 0.2, random_state = 42)
model.compile(loss = 'sparse_categorical_crossentropy', metrics = 'accuracy')
model.fit(train_scaled, train_target, epochs = 5)
○ 옵티마이저(optimizer)
: 신경망의 가중치와 절편을 학습하기 위한 알고리즘 또는 방법
케라스의 경우 경사 하강법 알고리즘이 구현되어 있으며, 대표적으로 SGD, 네스테로프 모멘텀, RMSprop, Adam 등
* SGD : 기본 경사 하강법 옵티마이저 클래스
- 매개변수
1. learning_rate : 학습률 지정(default : 0.01)
2. momentum : 매개변수에 0 이상 값 지정하면 모멘텀 최적화 수행
3. nesterov : True로 설정하면 네스테로프 모멘텀 최적화 수행
* Adagrad
- 매개변수
1. learning_rate : defaut = 0.001
2. Adagrad : 그레디언트 제곱을 누적해 학습률을 나눔
* RMSprop
- 매개변수
1. learning_rate : default = 0.001
2. Adagrad처럼 그레디언트 제곱으로 학습률을 나누지만 최근의 그레디언트를 사용하기 위해 지수 감소를 사용
* Adam
- 매개변수
1. learning_rate : default = 0.001
2. beta_1 : 모멘텀 최적화의 그레디언트 지수 감소 평균 조절(default : 0.9)
3. beta_2 : RMSprop의 그레디언트 제곱 지수 감소 평균 조절(default : 0.999)
신경망 모델 훈련
○ 손실 곡선
● 모델 생성(훈련 + 검증 세트로 나누고 모델 생성)
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 = train_input / 255.0
train_scaled, val_scaled, train_target, val_target = train_test_split(
train_scaled, train_target, test_size=0.2, random_state=42)
# 모델 생성
def model_fn(a_layer = None):
model = keras.Sequential()
model.add(keras.layers.Flatten(input_shape=(28, 28)))
model.add(keras.layers.Dense(100, activation='relu'))
if a_layer:
model.add(a_layer)
model.add(keras.layers.Dense(10, adctivation('softmax'))
return model
● 그래프로 표현
* fit() 메서드 결과에는 손실과 정확도가 들어있음
(현재 history 객체에 훈련 측정값이 담긴 history 딕셔너리가 들어있음)
model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')
# history 변수에 fit() 결과 담기
history = model.fit(train_scaled, train_target, epochs=5, verbose=0)
# 출력
# print(history.history.keys())
# 맷플로리를 통한 시각화
import matplotlib.pyplot as plt
# 손실 출력
plt.plot(history.history['loss'])
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show()
# 정확도 출력
plt.plot(history.history['accuracy'])
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.show()
○ 검증손실
: 인공 신경망은 모두 일종의 경사 하강법을 사용하기 때문에 에포크 사이의 관계와 과대/과소 적합이 동일하게 적용됨
따라서 에포크에 따른 과대/과소 적합을 파악하려면 훈련 세트 점수와 검증 세트에 대한 점수가 필요
* 인공 신경망 모델이 최적화하는 대상은 정확도가 아니라 손실 함수
So, 모델 훈련이 잘 되었는지 판단하려면 손실 함숫값을 확인하는 것이 더 좋음
● 에포크마다 검증 손실을 계산하기
model = model_fn()
model.compile(loss='sparse_categorical_crossentropy', metrics = 'accuracy')
# fit() 메서드에 검증 데이터를 전달하여 에포크마다 검증 손실을 계산
history = model.fit(train_scaled, train_target, epochs=20, verbose=0,
validation_data =(val_scaled, val_target)
# 검증 세트에 대한 손실 = 'val_loss', 정확도 = 'val_accuracy'
# 과대/과소 적합 문제 조사를 위한 훈련/검증 손실 그래프 그리기
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(['train', 'val'])
plt.show()
● 옵티마이저 하이퍼파라미터 조정을 통해 과대적합 완화
- Adam 옵티마이저 사용
: Adam의 경우 적응적 학습률을 적용 So, 에포크가 진행되면서 학습률의 크기 조정 가능
* 적응적 학습률(adaptive learning rate)
: 모델이 최적점에 가까이 갈수록 안정적으로 수렴하도록 학습률을 낮추도록 조정하는 방법
학습률 매개변수를 튜닝하는 수고를 덜 수 있는 장점
model = model_fn()
model.compile(optimize = 'adam', loss='sparse_categorical_crossentropy', metrics='accuracy')
history = model.fit(train_scaled, train_target, epochs=20, verbose=0,
validation_data=(val_scaled, val_target))
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(['train', 'val'])
plt.show()
○ 드롭아웃(dropout)
: 훈련 과정에서 층에 있는 일부 뉴런을 랜덤 하게 꺼서(뉴런 출력을 0으로 만들어서) 과대적합 방지
왼쪽은 두 번째 뉴런이 드롭아웃되어 h2 출력이 없고, 오른쪽은 첫 번째 뉴런이 드롭아웃되어 h1 출력이 없음
드롭아웃이 과대적합을 왜 막을까?
- 이전 층의 일부 뉴런이 랜덤 하게 꺼지면 특정 뉴런에 과대 의존을 줄이고 모든 입력에 대해 주의를 기울여야 함
일부 뉴런의 출력이 없을 수 있다는 점을 감안하면 이 신경망은 더 안정적인 예측을 만들 수 있음
- 드롭아웃을 적용해 훈련하는 것은 마치 2개의 앙상블 하는 것처럼 생각할 수 있음(앙상블 = 과대적합을 막아줌)
* 앙상블 = 더 좋은 예측 결과를 만들기 위해 여러 개의 모델을 훈련하는 머신러닝 알고리즘
● 케라스로 드롭아웃 객체를 전달하여 층을 추가
* 훈련이 끝난 뒤에 평가 or 예측을 수행할 때는 드롭아웃 적용하면 안 됨!
* 케라스(텐서플로)는 모델을 평가와 예측을 사용할 때는 자동으로 드롭아웃을 적용하지 않음
# 30% 정도를 드롭아웃
model = model_fn(keras.layers.Dropout(0.3))
# 출력 결과를 보면 은닉층 뒤에 추가된 드롭아웃 층은 훈련되는 모델 파라미터가 없음
model.summary()
model.compile(optimize = 'adam', loss='sparse_categorical_crossentropy', metrics='accuracy')
history = model.fit(train_scaled, train_target, epochs=20, verbose=0,
validation_data=(val_scaled, val_target))
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(['train', 'val'])
plt.show()
모델 저장과 복원
○ save_weights() 메서드 (in keras)
: 텐서플로의 체크포인트 포맷으로 저장하지만 파일 확장자가 '. h5'일 경우 HDF5 포맷으로 저장
○ save() 메서도
: 모델 구조와 모델 파라미터를 함께 저장. 기본적으로 SavedModel 포맷으로 하지만 '. h5'일 경우 HDF5 포맷으로 저장
model.compile(optimize = 'adam', loss='sparse_categorical_crossentropy', metrics='accuracy')
history = model.fit(train_scaled, train_target, epochs=20, verbose=0,
validation_data=(val_scaled, val_target))
model.save_weights('model-weights.h5')
model.save('model_whole.h5')
# 확인
!ls -al *.h5
○ 실습
1. 새로운 모델을 만들고 저장된 파일(model_whole.h5)에서 훈련된 모델 파라미터 읽어 사용하기
● load_weights() 메서드를 사용하려면 저장한 모델과 정확히 똑같은 구조를 가져야 함
So, model_fn() 함수를 사용하여 동일한 모델을 사용(모듈화의 중요성)
● evaluate() 메서드
: 모델 파라미터를 읽은 후 정확도를 출력 가능하지만 손실을 계산하기 위해 complie() 메서드를 먼저 실행해야 함
load_model() 함수를 실행한 후에는 모델 파라미터, 구조, 옵티마이저 상태까지 복원하여 사용 가능
model = model_fn(keras.layers.Dropout(0.3))
model.load_weights('model-weights.h5')
# 정확도 계산
import numpy as np
# predict() 메서드 결과에서 가장 큰 값을 고르기 위해 넘파이의 argmax() 함수 사용
# argmax() : 배열에서 가장 큰 값의 인덱스를 반환
val_labels = np.argmax(model.predict(val_scaled), axis=1)
print(np.mean(val_labels == val_target))
# 정확도 출력
model = keras.models.load_model('model-whole.h5')
model.evaluate(val_scaled, val_target)
2. 콜백(callback) : model_whole.h5 파일에서 새로운 모델을 만들어 바로 사용하기
: 훈련 과정 중간에 어떤 작업을 수행할 수 있는 객체
keras.callbacks 패키지 아래에 있는 클래스
fit() 메서드의 callbacks 매개변수에 리스트로 전달하여 사용
* 사용하는 ModelCheckpoint 콜백은 기본적으로 에포크마다 모델을 저장
So, save_best_only = True 매개변수 지정으로 가장 낮은 검증 손실을 만드는 모델을 저장 가능
model = model_fn(keras.layers.Dropout(0.3))
model.compile(optimize = 'adam', loss='sparse_categorical_crossentropy', metrics='accuracy')
checkpoint_cb = keras.callbacks.ModelCheckpoint('best-model.h5', save_best_only = True)
model.fit(train_scaled, train_target, epochs=20, verbose=0,
validation_data=(val_scaled, val_target),
callbacks=[checkpoint_cb])
# 모델 예측 수행
model = keras.models.load_model('best-model.h5')
model.evaluate(val_scaled, val_target)
○ 조기 종료 : 과대적합이 커지기 전에 훈련을 미리 중지하는 것
● EarlyStopping 콜백
- patience 매개변수 : 검증 점수가 향상되지 않더라도 참을 에포크 횟수로 지정
e.g. patience=2 → 2번 연속 검증 점수가 향사오디지 않으면 훈련 중지
- restore_best_weights = True : 가장 낮은 검증 손실을 낸 모델 파라미터로 돌림
model = model_fn(keras.layers.Dropout(0.3))
model.compile(optimize = 'adam', loss='sparse_categorical_crossentropy', metrics='accuracy')
checkpoint_cb = keras.callbacks.ModelCheckpoint('best-model.h5', save_best_only = True)
early_stopping_cb = keras.callbacks.EarlyStopping(patience=2, restotr_bbest_weights=True)
model.fit(train_scaled, train_target, epochs=20, verbose=0,
validation_data=(val_scaled, val_target),
callbacks=[checkpoint_cb, early_stopping_cb])
# 훈련/검증 손실 출력
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(['train', 'val'])
ptl.show()
# 모델 성능 확인
model.evaluate(val_scaled, val_target)
'Networks > 데이터 분석 및 AI' 카테고리의 다른 글
SK networks AI Camp - 딥러닝 추가 조사 자료 (2) | 2024.09.04 |
---|---|
SK networks AI Camp - Deep learning 기초 (2) | 2024.09.04 |
SK networks AI Camp - 비지도 학습 (0) | 2024.08.31 |
SK networks AI Camp- 회귀 (0) | 2024.08.30 |
SK networks AI Camp - 평가 지표 (0) | 2024.08.26 |