My Data Story
[딥러닝] 인공 신경망 - 시퀀셜 API 구현 본문
◈ '인공 신경망' 목차 ◈
4. 시퀀셜 API 구현
시퀀셜 API를 통해 분류용 MLP와 회귀용 MLP 구현하는 방법에 대해 살펴보자.
1. 시퀀셜 API를 사용하여 분류기 만들기
1.1 데이터셋 적재하기
fashion_mnist = keras.datasets.fashion_mnist
(X_train_full, y_train_full), (X_test, y_test) = fashion_mnist.load_data()
X_valid, X_train = X_train_full[:5000]/255, X_train_full[5000:]/255
y_valid, y_train = y_train_full[:5000], y_train_full[5000:]
X_test = X_test/255
1.2 시퀀셜 API를 사용하여 모델 생성
step1
Sequential 모델을 만든다. 이 모델은 가장 간단한 케라스의 인공 신경망 모델이다.
순서대로 연결된 층을 일렬로 쌓아서 구성하도록 한다. 이를 시퀀셜 API 라고 부른다.
model = keras.models.Sequential()
step2
Flatten 층을 생성하여 모델에 추가한다.
Flatten 층은 입력 이미지를 1D 배열로 변환한다. 즉 입력 데이터 X를 받으면 받으면 X.reshape(-1,1) 를 계산한다.
이 층은 어떤 모델 파라미터를 가지지 않고 간단한 전처리를 수행할 뿐이다.
이때 Flatten 층은 모델의 첫번째 층이므로 input_shape 을 지정해야 한다.
input_shape 지정 시, 배치 사이즈를 제외한 샘플의 크기만 써야 한다.
또는 첫번째 층으로 input_shape=[28,28]로 지정된 keras.layers.InputLayer 층을 추가할 수도 있다.
model.add(keras.layers.Flatten(input_shape=[28,28])
step3
뉴런 300개를 가진 Dense 은닉층을 추가한다.
Dense 층마다 각자 가중치 행렬을 관리한다. 이 행렬에는 층의 뉴런과 입력 사이의 모든 연결 가중치가 포함된다.
또한 편향도 벡터로 관리한다.
model.add(keras.layers.Dense(300, activation='relu'))
model.add(keras.layers.Dense(100, activation='relu'))
step4
클래스 갯수만큼의 뉴런을 가진 Dense 출력층을 추가한다.
배타적인 클래스에 대해 소프트맥스 활성화 함수를 사용한다.
model.add(keras.layers.Dense(10, activation='softmax'))
step5
생성한 모델에 대해 확인해 볼 수 있다.
■ summary()
생성한 모델의 모든 층 출력한다.
이때 가중치 행렬의 크기는 입력의 크기에 달려 있다.
이 때문에 Sequential 모델에 첫번째 층을 추가할 때 input_shape 매개 변수를 지정한다.
케라스는 모델이 빌드되기 전에 층이 가중치를 갖지 않으면 summary() 메서드 호출이나 모델 저장 등의 작업이 불가능하다.
(실제 데이터를 주입하거나 build() 메서드 호출할 때 모델이 빌드된다.)
따라서 모델이 빌드되기 전에 입력 크기를 설정하여 가중치 갖도록 해야 한다.
■ layers
생성된 모델에 있는 층의 리스트를 출력한다.
■ get_weights()
생성된 모델에 있는 모든 가중치와 편향을 출력한다.
cf. 모델 생성하는 다른 방법
model = keras.model.Sequential([keras.layers.Flatten(input_shape=[28,28]),
keras.layers.Dense(300, activation='relu'),
keras.layers.Dense(100, activation='relu'),
keras.layers.Dense(10, activation='softmax')
])
1.3 모델 컴파일
모델을 만들고 나서 compile() 메서드를 호출하여 사용할 손실 함수와 옵티마이저를 지정한다.
부가적으로 훈련과 평가 시에 계산할 지표를 추가로 지정할 수 있다.
model.compile(loss='sparse_categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])
#위와 동일한 기능
model.compile(loss=keras.losses.sparse_categorical_crossentropy,
optimizer=kears.optimizers.SGD,
metrics=[keras.metrics.sparse_categorical_accuracy])
■ metrics
샘플마다 타킷 클래스 인덱스가 하나 있고(레이블이 한 개 이고) 각 클래스는 0~9까지 정수 중 하나를 갖을 때, 클래스는 배타적이므로 'sparse_categorical_crossentropy' 손실을 사용한다.
만약 샘플마다 클래스 별 타킷 확률을 갖고 있다면 (예를 들엉 클래스 3은 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0] 인 원-핫 벡터) 'categorical_crossentropy' 손실을 사용한다.
샘플마다 타깃 클래스 인덱스가 여러 개인 (레이블이 여러 개) 이진 분류를 수행한다면, 출력층에 'softmax' 대신 'sigmoid' 함수를 사용하고 'binary_crossentropy' 손실을 사용한다.
■ optimizer
옵티마이저에 'sgd'를 지정하면 기본 확률적 경사 하강법을 사용하여 모델을 훈련한다는 의미이다.
다른 말로 하면 케라스가 앞서 설명한 역전파 알고리즘을 수행한다. (후진 모드 자동 미분과 경사 하강법)
SGD 옵티마이저를 사용할 때 학습률 튜닝하는 것이 중요하다.
(optimizer = keras.optimizers.SGD(lr=0.01))
1.4 모델 훈련과 평가
모델 훈련과 평가를 위해 fit() 시킬 때 고려해볼 만한 매개 변수는 다음과 같다.
■ epochs
훈련할 에포크 수를 지정하지 않으면 기본값 1로 훈련되어 충분히 수렴하지 못 한다.
케라스는 매 에포크가 끝날 때마다 검증 세트를 사용해 손실과 추가적인 측정 지표를 계산한다.
■ class_weights
어떤 클래스는 많이 등장하고 다른 클래스는 조금 등장하여 훈련 세트가 편중되어 있다면, class_weight 매개 변수를 지정하는 것이 좋다. 적게 등장하는 클래스에 높은 가중치를 부여하고 많이 등장하는 클래스에 낮은 가중치를 부여한다. 케라스는 손실 계산할 때 이 가중치를 사용한다.
■ sample_weights
샘플마다 다른 가중치를 부여하고 싶다면, sample_weight 매개 변수를 지정한다.
손실 계산할 때, 각 샘플에 가중치 곱해 합한 후 전체 샘플 개수로 나눈다.
손실 뿐 아니라 다른 측정 지표에도 샘플 가중치 적용되는데, 이때는 전체 샘플 개수가 아닌 샘플 가중치 합으로 나눈다.
■ validation_data
validation_data 매개변수에 검증 세트를 직접 전달하는 대신, 검증에 사용할 훈련 세트의 비율을 지정할 수도 있다.
validation_data = 0.2 로 설정하면 섞기 전 데이터의 20%를 검증용으로 사용한다.
validation_data 튜플의 세 번째 원소로 샘플 별 가중치 지정할 수 있다. (클래스 별 가중치 설정은 못한다.)
위와 같은 매개 변수 설정 후 모델 fit() 시키면 다음과 같다.
history = model.fit(X_train, y_train, epochs=30, validation_data=(X_valid, y_valid))
생성한 history 객체는 다음과 같은 속성을 갖는다.
■ params
history.params 에는 훈련 파라미터가 포함된다.
■ epoch
history.epoch 에는 수행된 에포크 리스트가 포함된다.
■ history
history.history 에는 에포크가 끝날 때마다 훈련 세트와 검증 세트에 대한 손실과 측정 지표가 포함된다.
history 속성에 있는 내용을 바탕으로 학습 곡선을 그리면 다음과 같다.
import pandas as pd
impot matplotlib.pyplot as plt
pd.DataFrame(history.history).plot(figsize=(8,5))
plt.grid(True)
plt.gca().set_ylim(0,1) #수직축의 범위를 [0,1] 사이로 설정한다.
plt.show()
이때 검증 손실은 에포크가 끝나고 계산되고, 훈련 손실은 에포크가 진행되는 동안 계산된다는 점을 유의해야 한다.
따라서 훈련 곡선은 에포크의 절반만큼 왼쪽으로 이동해야 맞다.
학습 곡선을 살펴보았을 때, 만약 검증 손실이 여전히 감소한다면 아직 완전히 수렴되지 않았다고 볼 수 있다.
이런 경우 훈련을 계속해야 할 것이다. 케라스에서는 fit() 메서드를 다시 호출하면 중지되었던 곳에서부터 훈련을 이어갈 수 있다.
모델 성능이 만족스럽지 않으면 처음으로 되돌아가서 하이퍼파라미터를 튜닝해야 한다.
맨처음 확인할 것은 학습률이다. 학습률이 도움되지 않으면 다른 옵티마이저를 테스트해본다.
항상 다른 하이퍼파라미터를 바꾼 후에는 학습률을 다시 튜닝해야 한다.
여전히 성능이 높지 않으면 층 개수, 층에 있는 뉴런 개수, 은닉층의 활성화 함수와 같은 모델의 하이퍼파라미터를 튜닝해본다.
배치 크기와 같은 다른 하이퍼파라미터를 튜닝해볼 수 있다.
하이퍼파라미터 튜닝에 대해서는 '-----------------' 에서 더 자세히 알아보도록 하자.
모델의 검증 정확도가 만족스럽다면 모델을 상용환경으로 배포하기 전에 테스트 세트로 모델을 평가하여 일반화 오차를 추정해야 한다. 이때 evaluate() 메서드를 사용한다.
model.evaluate(X_test, y_test)
1.5 모델 사용하여 예측하기
#각 샘플에 대해 클래스 별 추정 확률 출력
model.predict(X_new)
#각 샘플에 대해 가장 높은 확률의 클래스만 출력
model.predict_classes(X_new)
2. 시퀀셜 API를 사용하여 회귀용 다층 퍼셉트론 만들기
시퀀셜 API를 사용해 회귀용 MLP를 구축, 훈련, 평가, 예측하는 방법은 분류에서 했던 것과 매우 비슷하다.
주된 차이점은 출력층이 활성화 함수가 없는 하나의 뉴런이라는 점과 손실 함수로 평균 제곱 오차를 사용한다는 점이다.
2.1 데이터 로딩 및 전처리
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
#데이터 로딩
housing = feetch_california_housing()
X_train_full, X_test, y_train_full, y_test = train_test_split(housing.data, housing.target)
X_train, X_valid, y_train, y_valid = train_test_split(X_train_full, y_train_full)
#데이터 전처리
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_valid = scaler.transform(X_valid)
X_test = scaler.transform(X_test)
2.2 시퀀셜 API 사용하여 모델 생성
#시퀀셜 API 사용하여 모델 만들기
model = keras.models.Sequential([
keras.layers.Dense(30, activation='relu', input_shape=X_train.shape[1:]),
keras.layers.Dense(1)])
2.3 모델 컴파일
#모델 컴파일
model.compile(loss='mean_squared_error', optimizer='sgd')
2.4 모델 훈련과 평가
#모델 훈련
history = model.fit(X_train, y_train, epochs=20, validation_data=(X_valid, y_valid))
#훈련 데이터와 검증 데이터에 대한 학습 곡선 확인
pd.DataFrame(history.history).plot(figsize=(8,5))
plt.grid(True)
plt.gca().set_ylim(0,1) #수직축의 범위를 [0,1] 사이로 설정한다.
plt.show()
#모델 평가
mse_test = model.evaluate(X_test, y_test)
2.5 모델 사용하여 예측하기
#모델사용하여 새로운 데이터 예측
model.predict(X_new)
'Deep Learning' 카테고리의 다른 글
[딥러닝] 인공신경망 - 서브클래싱 API 구현 (0) | 2021.09.04 |
---|---|
[딥러닝] 인공 신경망 - 함수형 API 구현 (0) | 2021.09.04 |
[딥러닝] 인공 신경망 - 케라스 API 소개 (0) | 2021.09.04 |
[딥러닝] 인공 신경망 - 다층 퍼셉트론 (0) | 2021.09.04 |
[딥러닝] 인공 신경망 - 퍼셉트론 (0) | 2021.09.04 |