인공 신경망 모델을 훈련하는 모범 사례 필요한 도구들을 살펴보자.

이번 절에서는 케라스 API를 사용해서 모델을 훈련하는데 필요한 다양한 도구들을 살펴보자.

손실곡선

앞에서 fit()을 출력하면 마지막 출력으로

<keras.callbacks.History at 0x264150f7040>

가 출력된다.

이 코드는 훈련에서 사용한 지표, 즉 손실과 정확도 값이 저장되어 있는데, 이를 그래프로 그려보자.

 

처음부터 코드 다시짜보자.!

from tensorflow impor 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, trian_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, activation = 'softmax'))
    return model
model = model_fn()
model.summary()

Model: "sequential_1"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 flatten (Flatten)           (None, 784)               0         
                                                                 
 dense (Dense)               (None, 100)               78500     
                                                                 
 dense_1 (Dense)             (None, 10)                1010      
                                                                 
=================================================================
Total params: 79,510
Trainable params: 79,510
Non-trainable params: 0
_________________________________________________________________

이제 fit() 메소드의 결과를 history 변수에 담아 보겠다.

model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')
history = model.fit(train_scaled, train_target, epochs=5, verbose=0)
print(history.history.keys())

dict_keys(['loss', 'accuracy'])

손실과 정확도가 있는것을 확인할 수 있다.

 

이제 그림을 그려보자!!

import matplotlib.pyplot as plt
plt.plot(history.history['loss'])
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show()

 

5개의 에포크가 0~4사이에 포함되어 있다.

y축은 계산된 손실

 

이번에는 정확도를 출력 해보자.

plt.plot(history.history['accuracy'])
plt.xlabel('epochs')
plt.ylabel('accuracy')
plt.show()

에포크마다 손실이 감소하고 정확도가 올라감을 확인할 수 있다.

어?! 그러면 에포크를 ㅈㄴ 늘리면 좋은거 아닐까??

20으로 해보자.

model = model_fn()
model.compile(loss='sparse_categorical_crossentropy',metrics='accuracy')
history = model.fit(train_scaled, train_target, epochs=20, verbose=0)
plt.plot(history.history['loss'])
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show()

에포크를 늘리니까 손실이 계속 감소하는것을 볼 수 있다!!

하지만 이게 무조건 좋은것일까????

 

검증 손실

앞서 머신러닝에서, 과대/과소 적합과 에포크 횟수와의 관계를 배웠었다.

인공 신경망은 모두 경사 하강법을 사용하기 때문에 동일한 개념이 여기서도 적용된다.!

 

에포크 횟수에 따른 과대/과소 적합을 파악하려면 훈련세트에 대한 점수뿐만 아니라 검증 세트에 대한

점수도 필요하다. 따라서 앞에서처럼 훈련 세트의 손실만 그려서는 안된다.

 

에포크를 과도하게 늘리면 과대적합이 발생하고, 그렇다고 너무 적게 설정하면 과소적합이 발생한다.

 

적절한 에포크횟수를 설정하기 위해서는 크마다 검증 손실을 계산하고, 이를 확인해가며 설정하는것이 중요하다.

model = model_fn()
model.compile(loss='sparse_categorical_crossentropy',metrics='accuracy')
history = model.fit(train_scaled, train_target, epochs=20, verbose=0,
			validation_data = (val_scaled, val_target))

history 딕셔너리에 어떤 키가 들어 있는지 보자.

print(history.history.keys())

dict_keys(['loss', 'accuracy', 'val_loss', 'val_accuracy'])

그림을 그려보자 !

plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.xlabel('epochs')
plt.ylabel('loss')
plt.legend(['train'])

주황 = 검증 세트

파랑 = 훈련 세트

에포크가 증가할 수록 훈련세트의 손실은 꾸준히 감소하지만, 검증세트의 손실은 5를 기준을 증가한다!!!!

에포크가 증가할수록 과대적합이 일어나는 것을 위 그래프를 통해 확인할 수 있다.

 

 

이제 Adam 옵티마이를 적용해보고 훈련손실과 검증손실을 다시 그려보자.

model= model_fn()
model.compile(optimizer='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('epochs')
plt.ylabel('loss')
plt.legend(['train','val'])
plt.show()

검증세트의 loss가 위의 SGD? 를 썼을때보다 확실히 낮은것을 볼 수 있다.

이는 Adam 옵티마이저가 이 데이터셋에 더 유용하다는것을 보여준다!!

 

규제방식에 대해서 알아보자!!

 

드롭아웃

드롭아웃은 아래 그림처럼 훈련과정에서 층에 있는 일부 뉴런을 랜덤하게 꺼서( 뉴런의 출력을 0으로 만들어)

과대 적합을 막는다.

 

말그대로 층에 있는 뉴런 한명 드롭아웃 시키는것!! (랜덤)

하이퍼파라미터 : 몇개의 뉴런을 드롭아웃 시킬건지..

 

드롭아웃이 어떻게 과적합을 막지???

----------------->

1. 이전 층의 일부 뉴런이 랜덤하게 꺼지면 (0이 되면) 특정 뉴런에 과대하게 의존하는것을 줄이고 모든 입력에 주의를 기울이는쪽으로 변함.

2. 일종의 앙상블 기법임. 랜덤하게 드롭아웃된 신경들끼리 훈련하기 때문에 다른 알고리즘끼리 학습되는 느낌.

 

Dropout을 적용해보자.

model = model_fn(keras.layers.Dropout(0.3))   # 30%를 버리기로 했다!!!
model.summary()

Model: "sequential_2"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 flatten_2 (Flatten)         (None, 784)               0         
                                                                 
 dense_4 (Dense)             (None, 100)               78500     
                                                                 
 dropout (Dropout)           (None, 100)               0         
                                                                 
 dense_5 (Dense)             (None, 10)                1010      
                                                                 
=================================================================
Total params: 79,510
Trainable params: 79,510
Non-trainable params: 0
_________________________________________________________________

 생각해보면

 Dropout() 메소드는 훈련할 때만 사용해야하고, 훈련이 끝난 후 평가, 예측을 할 때는 사용하지 말아야한다.

그러려면 모델을 훈련할때 Dropout()을 사용했다면 끝난후 층을 다시 빼야 한다.

하지만 Keras(tensorflow)는 자동으로 dropout을 적용하지 않는다. (평가/예측 시) 따라서 따로 빼줄 필요가 없다.

 

어쨌든 dropout해서 훈련한 결과를 그래프로 그려보자 !!

 

주황색 (검증세트)의 loss가 더 줄어든 모습이다.

과대적이 확실히 줄어든 모습이다.

 

모델 저장과 복원

에포크 횟수를 20에서 10으로 바꾸고 다시 훈련해보자.

model = model_fn(keras.layers.Dropout(0.3))
model.compile(optimizer='adam', loss = 'sparse_categorical_crossentropy',
			metrics='accuracy')
history = model.fit(train_scaled, train_target, epochs=10, verbose = 0,
					validation_data = (val_scaled, val_target))

케라스 모델은 훈련된 모델의 파라미터를 저장하는 간편한 메소드를 제공한다.

save_weights()을통해 저장하도록 해보자.

model.save_weights('model-weights.h5')
model.save('model-whole.h5')
!ls -al *.h5

 

모델 predict() 메소드에서 가장 큰 값을 고르기 위해 argmax() 함수를 사용하자.!

이 함수는 배열에서 가장 큰 값의 인덱스를 반환한다.

예를 들어 배열의 첫번째 원소가 가 큰 값일 경 0을 반환한다.

 

다행히 우리가 준비한 타겟값도 0부터 시작하기 때문에 비교하기 쉽다.

import numpy as np
val_labels = np.argmax(model.predict(val_scaled),axis=-1)
print(np.mean(val_labels == val_target))

argmax()함수의 axis = -1은 배열의 마지막 차원을 따라 최대값을 고릅니다.

검증 세트는 2차원 배열이기 때문에 마지막 차원은 1이 된다.

아래 사진을 통해 이해하자.

axis=1이면 열을 따라 각 행의 최대값의 인덱스를 선택하고, axis=0 이면 행을 따라 각 열의 최대값의 인덱스를 선택합니다.

 

그 다음 라인은 argmax()로 고른 index(val_labels)와 타깃(val_target)을 비교한다.

두 배열에서 각 위치의 값이 같으면 1이되고 다르면 0이 됩니다. 이를 평균하면 정확도 된다.

 

이번에는 모델 전체를 파일에서 읽은 다음 검증 세트의 정확도를 출력해보자.

 

model = keras.models.load_model('model-whole.h5')
model.evaluate(val_scaled, val_target)


375/375 [==============================] - 1s 3ms/step - loss: 0.3393 - accuracy: 0.8792
[0.33925992250442505, 0.8791666626930237]

 

콜 백

 콜백 = 훈련 과정 중에 어떤 작업을 수행할 수 있게 해주는 객체로 keras.callbacks로 사용가능

여기서는 keras.callbacks.ModelCheckpoint을 사용. 역할 = 에포크마다 모델을 저장함!!

best_only = True : 가장 낮은 검증 점수를 만드ㅊ 모델 저장 가능

model = model_fn(keras.layers.Dropout(0.3))

model.compile(optimizer='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])

왜 가장 낮은 검증점수를 저장????

 검증점수가 상승하기 시작하면 과적합이 발생해서 훈련 의미? 필요가없다.

이 때 중지한다면 상당한 시간 (자원)을 아낄 수 있다.

 

이를 조기 종료(early stopping)이라고 하는데, 딥러닝분야에서 아주 많이 쓰인다고 한다.

규제 방법중에 하나라고 생각하면 편할듯.

 

코드 = EarlyStopping 콜백 클래스

 

model = model_fn(keras.layers.Dropout(0.3))
model.compile(optimizer='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,
												  restore_best_weights=True)
history  = model.fit(train_scaled, train_target, epochs=20, verbose=0,
					validation_data=(val_scaled, val_target),
                    callbacks = [checkpoint_cb, early_stopping_cb])

훈련을 마치고나서 몇 번째 에포크에서 훈련이 중지되었는지 확인가능!!!(아래 코드)

early_stopping_cb.stopped_epoch

 

이어서 훈련 손실과 검증 손실을 출력해서 확인해보자.

plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(['train','val'])
plt.show()

 

 

배울 것 : 심층 신경망, 렐루 함수, 옵티마이저 

 

먼저 케라스에서 패션 MNIST 데이터셋을 불러오자,

from tensorflow import keras
(train_input,train_target),(test_input,test_target)=\
keras.datasets.fashion_mnists.load_data()

이미지 픽셀값 0~255을 1로 변환하고, 픽셀크기 28*28 2차원 배열을 1차원으로 펼쳐보자.

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, train_target, val_target = train_test_split(train_scaled,train_target,test_size=0.2,random_state=42

이제 인공 신경망 모델을 두개 추가해보자!!

은닉층 + 출력층

은닉층의 역할

2a + b = 4

b + 2c = 2   ------> 2a-2c=2   -> a - c = 1

b는 사라지고 a와 c에 대한 식만 남음!!  ( b가 은닉층이라고 보면 된다. )

 

dense1 = keras.layers.Dense(100,activation='sigmoid',input_shape=(784,)) #은닉층
dense2 = keras.layers.Dense(10,activation='softmax')

 

은닉층의 뉴런 수 : 100개로 설정했다.

유의사항 : 무조건 출력층의 뉴런 수 보다는 크게 설정해야함.

 

 

심층 신경망 만들기

model = keras.Sequential([dense1,dense2])

summary를 통해 요약정보 출력하기

model.summary()

Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense (Dense)               (None, 100)               78500     
                                                                 
 dense_1 (Dense)             (None, 10)                1010      
                                                                 
=================================================================
Total params: 79,510
Trainable params: 79,510
Non-trainable params: 0
_________________________________________________________________

dense 2개 모두 출력층의 shape을 보면 첫 번째가 None이 나온다.

첫 번째 차원은 샘플의 개수인데, 개수가 설정되어 있지 않기 때문에 None이 출력되는것이다.

Why?

 

케라스의 fit()은 기본적으로 데이터를 한 번에 다 사용하지 않고 여러번 나누어서 사용한다.

( 케라스의 fit은 미니배치 경사하강법을 사용하기 때문  + default 배치 사이즈 = 32)

때문에  샘플 개수를 고정하지 않고 어떤 배치 사이즈에서도 유연하게 대응할 수 있도록 None으로 설정하는것이다.

 

shape의 두번째는 각각 100,10 인데 이것은 예상하다시피 뉴런 개수이다.

마지막으로 Param에는 모델 파라미터 개수가 출력된다.

785 x 100 (픽셀 개수 x 100개의 가중치  + 100개 마다 하나의 절편)

101x10     (100개의 은닉층 x 10개의 출력층 + 10개마다 하나의 절편)

 

모델에 층을 추가하는 법: 

아래 코드는 안좋은 코드

model = keras.Sequential([
keras.layers.Dense(100,activation = 'sigmoid' , input_shape=(784,),name='hidden_layer'),
keras.layers.Dense1(10,activation = 'softmax', name='output')],
name= ' 패션 MNIST 모델')

출력해보자,

model.summary()

Model: " 패션 MNIST 모델"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 hidden_layer (Dense)        (None, 100)               78500     
                                                                 
 output (Dense)              (None, 10)                1010      
                                                                 
=================================================================
Total params: 79,510
Trainable params: 79,510
Non-trainable params: 0
_________________________________________________________________

.add() 메소드로 편하게 추가!!!

 

model = keras.Sequential()
model.add(keras.layers.Dense(100,activation='sigmoid',input_shape=(784,)))
model.add(keras.layers.Dense(10,activation='softmax'))

이제 compile하고 훈련시켜보자!

model.compile(loss='sparse_categorical_crossentropy',metrics='accuracy')
model.fit(train_scaled,train_target,epochs=5)


Epoch 1/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.4131 - accuracy: 0.8516
Epoch 2/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.3781 - accuracy: 0.8635
Epoch 3/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.3546 - accuracy: 0.8711
Epoch 4/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.3385 - accuracy: 0.8775
Epoch 5/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.3235 - accuracy: 0.8811

렐루 함수

시그모이드함수와 차이:

시그모이드 함수는 출력 값을 0~1으로 만들어주는 함수이다.

하지만 시그모이드는 오른쪽, 왼쪽 끝을 보면 누워있기 때문에, 출력을 만드는데 시간이 오래걸리는 단점이 있다.

 

특히 층이 많은 신경망일수록 단점이 극명해지기 되는데, 이를 보완하기 위해 등장한것이 렐루함수이다.

 

렐루함수

렐루함수는 음수는 무조건 0으로, 0보다 큰 값은 값 그대로를 출력하는 함수이다. 

시간적으로 절약되고, 늘어지는 모양이 없기 때문에 시그모이드보다 시간적으로 효율적이다.

 

한편, 앞서 2차원 배열 (픽셀 크기)을 1차원으로 바꿀때 reshape()을 사용했지만,

앞으로는 flatten을 사용하도록 하자.

Flatten() 메소드는 배치 차원을 제외하고 나머지 모든 차원을 모두 일렬(일차원)로 펼치는 역할을 하므로 매우 유용하다.

 

예시코드:)

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'))

summary

model.summary()

Model: "sequential_2"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 flatten (Flatten)           (None, 784)               0         
                                                                 
 dense_4 (Dense)             (None, 100)               78500     
                                                                 
 dense_5 (Dense)             (None, 10)                1010      
                                                                 
=================================================================
Total params: 79,510
Trainable params: 79,510
Non-trainable params: 0
_________________________________________________________________

Flatten() 메소드를 사용하면 위에 보다시피 입력값의 차원을 짐작할 수 있다.  (shape = 784개)

 

 

요약 --> 최종 코드 : 

(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)
model.compile(loss='sparse_categorical_crossentropy',metrics='accuracy')
model.fit(train_scaled,train_target,epochs=5)

Epoch 1/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.5312 - accuracy: 0.8117
Epoch 2/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.3926 - accuracy: 0.8591
Epoch 3/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.3544 - accuracy: 0.8710
Epoch 4/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.3306 - accuracy: 0.8810
Epoch 5/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.3158 - accuracy: 0.8880
<keras.callbacks.History at 0x2641e061b80>

model.evaluate()을 이용해서 모델을 평가해볼 수 있다.

model.evaluate(val_scaled, val_target)

375/375 [==============================] - 0s 906us/step - loss: 0.3603 - accuracy: 0.8738
[0.36031365394592285, 0.8738333582878113]

 

 

옵티마이저

옵티마이저 하이퍼 파라미터 튜닝을 쉽게 해주는 tool

compile() 메소드는 케라스의 기본 경사 하강법인 RMSprop을 사용한다.

 

하지만 RMSprop 말고도 다양한 종류의 경사하강법들이 존재하는데, 이들을 옵티마이저라고 부른다.

(하이퍼 파라미터 튜닝)

 

여기서 가장 기본적인 SGD 옵티마이저를 이용해서 하이퍼파라미터 튜닝을 해보겠다.

model.compile(optimizer='sgd', loss='sparse_categorical_crossentropy', metrics='accuracy')

learning_rate (학습률)또한 하이퍼파라미터인데, 기본값은 0.01이다.

설정하려면 다음과 같은 코드를 실행

sgd=keras.optimizers.SGD(learning_rate=0.1)

기본 / 적응적 학습률 옵티마이저

 

매개변수들 : learning_rate , momentum  ( 기본값은 각각 0.01 , 0 )

 

momentum을 0보다 크게 설정한다면 --> 이전의 그레디언트를 가속도처럼 사용하는 모멘텀 최적화를 사용한다.일반적으로 momentum은 0.9이상을 지정

 

또한 SGD 클래스의 nesterov 매개변를 기본값 False에서 True로 바꾸게 되면 네스테로프 모멘텀 최적화를 사용한다.

sgd=keras.optimizers.SGD(momentum=0.9, nesterov=True)

네스테로프 모멘텀 최적화는 일반적으로 기본적인 경사하강보다 더 나은 성능을 보여준다!!!!

 

모델이 점점 최적점에 가까이 갈수록 학습률을 낮출 수 있다.

이렇게 하면 안정적으로 최적점에 수렴할 가능성이 높다!

이런 학습률 적응적 학습률이라고 한다.

위의 이러한 방식들 학습률을 튜닝하는 수고를 덜어줄 수 있다고한다.

 

 

적응적 학습률을 사용하는 대표적인 옵티마이저는 Adagrad와 RMSprop이다.

 

Adam은 모멘텀최적화와 RMSprop의 장점을 접목시킨 옵티마이저다.

(일반적으로 Adam을 사용)

Adam optimizer를 사용해서 패션MNIST 모델을 훈련시켜보자.

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'))

model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics='accuracy')
model.fit(train_scaled, train_target, epochs=5)

Epoch 1/5
1500/1500 [==============================] - 3s 2ms/step - loss: 0.5287 - accuracy: 0.8161
Epoch 2/5
1500/1500 [==============================] - 2s 2ms/step - loss: 0.3907 - accuracy: 0.8596
Epoch 3/5
1500/1500 [==============================] - 2s 2ms/step - loss: 0.3501 - accuracy: 0.8727
Epoch 4/5
1500/1500 [==============================] - 2s 2ms/step - loss: 0.3253 - accuracy: 0.8815
Epoch 5/5
1500/1500 [==============================] - 2s 2ms/step - loss: 0.3070 - accuracy: 0.8863
<keras.callbacks.History at 0x264150f7040>

모델을 평가해보자,!!!!

model.evaluate(val_scaled, val_target)

375/375 [==============================] - 0s 1ms/step - loss: 0.3396 - accuracy: 0.8786
[0.33957886695861816, 0.8785833120346069]

RMSprop과 비슷한 성능을 보여준다..!

 

패션 MNIST 데이터셋을 통해서 머신러닝 비지도학습 (군집알고리즘)처럼 데이터를 살펴보자!!

 

딥러닝 대표 라이브러리에는 텐서플로, 케라스가 있다.

케라스 임포트해서 mnist 데이터를 다운받아 보자.

from tensorflow import keras 
(train_input , train_target), (test_input, test_target) =\
	keras.datasets.fashion_mnist.load_data()
    
    
    Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
29515/29515 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26421880/26421880 [==============================] - 1s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
5148/5148 [==============================] - 0s 0s/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4422102/4422102 [==============================] - 0s 0us/step

출력해보자

print(train_input.shape, train_traget.shape)

(60000, 28, 28) (60000,)

훈련 데이터는 60,000의 이미지로 이루어져 있고,

각 이미지는 28x28픽셀임을 알 수 있다.!!

 

타겟 데이터 또한 60,000장이다.!

 

print(test_input.shape, test_target.shape)

(10000, 28, 28) (10000,)

테스트 데이터또한 훈련 데이터와 개수,사이즈가 같다.!

 

그림으로 샘플이 무엇인지 살펴봅시다람쥐.

import matplotlib.pyplot as plt
fig, axs = plt.subplots(1, 10, figsize=(10,10))
for i in range(10):
	axs[i].imshow(train_input[i], cmap='gray_r')
    axs[i].axis('off')
plt.show()

 

리스트함축구문을 사용해서 처음 10 샘플의 타겟값을 리스트 만든 후 출력해보자.

[train_target[i] for i in range(10)]

[9, 0, 0, 3, 0, 2, 7, 2, 5, 5]

이제 unique()함수를 통해 레이블당 샘플 개수를 확인해보자.!

import numpy as np
np.unique(train_target, return_counts=True)

(array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=uint8),
 array([6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000],
       dtype=int64))

6000개씩 10종류가 있음을 확인할 수 있다.

 

 

로지스틱 회귀로 분류하기

앞서 배운 SGDClassifier (확률적)경사하강법을 사용할 때 처럼 표준화 전처리를 해야함.

흑백 이미지의 경우 0~255의 값을 가지므로, 255으로 나누면 0~1로 표현가능하다.

 

우선 reshape()을 통해 3차원->2차원으로 배열을 바꿔보자,

train_scaled = train_input / 255.0
train_scaled = train_sclaed.reshape(-1, 28*28)

잘 됐는지 확인해보자.

print(train_scaled.shape)

(60000, 784)

 

교차 검증을 통해서 성능을 확인해보자!!!

from sklearn.model_selection import cross_validate
from sklearn.linear_model import SGDClassifier
sc = SGDClassifier(loss='log', max_iter=5, random_state=42)
scores = cross_validate(sc, train_scaled, train_target, n_jobs=-1)
print(np.mean(scores['test_score']))

0.8192833333333333

높지가 않다!!!

 

 

로지스틱 회귀 공식 떠올려보자,,,!

픽셀 784개에 대해서 각각 가중치를 다르게 매겨서 소프트맥수 함수 통과~ 출력 :0~1사이!!

 

뉴런 = z값 ( 출력층의 값) == 유닛

입력층 = 픽셀값 그잡채

 

 

텐서플로와 케라스는 원래 별도의 라이브러리와 같은 개념이였는데,

텐서플로는 구글이 개발, 오픈소스로 공개한 라이브러리 이고, 케라스는 프랑소와라는 사람이 만들었다.

프랑소와가 구글에 합류하고, 케라스 api를 텐서플로에 넣은 후, 텐서플로는 케라스api만 사용하게 되었고,

이후 사실상 tensorflow=keras 같은 개념이라고 볼 수 있을것 같다.

 

 

1. 인공 신경망 만들기

from sklearn.model_selectoin import train_test_split
train_scaled, val_scaled, train_target, val_target
= train_test_split(train_scaled,train_target,test_size=0.2, random_state=42)

인공 신경망 (딥러닝) 에서는 머신러닝 했을때와 다르게 교차 검증 하지 않는다!!!!!!!!!!!!!!

1. 데이터셋 충분히 크기 때문에 교차검증 효과적 X

2. 시간이 너~무 오래걸림

훈려세트에서 20%를 검증세트로 따로 떼어냈다 .  ( test_size= 0.2 )

print(train_scaled.shape, train_target.shape)
(48000, 784) (48000,)

60,000 - ( 60,000 x 0.2 ) = 48,000 정상적으로 나눠졌다.

 

print(val_scaeld.shape, var_target.shape)

(12000, 784) (12000,)

 60,000 x 0.2 = 12,000 정상적으로 나눠짐 !

 

 

이제 인공 신경망을 만들어보자.

dense=밀집한 ==> 입력층의 수많은 784개의 픽셀등을 뜻한다고 생각하면 편하다.

케라스의 Dense클래스를 이용해서 밀집층을 만들자. 매개변수는 뉴런수,함수,입력크기이다.

 

dense = keras.layers.Dense(10, activation = 'softmax', input_shape=(784,))

activation = 출력층에 적용할 함수 (이진분류이면 시그모이드, 다중 분류 소프트맥스)

input_shape = 입력의 크기

 

model = keras.Sequential(dense)

이제 신경망을 만들었다.

MNIST 데이터셋을 분류해보자.

 

훈련하기전 마지막 설정 단계 : model.compile()

손실함수

이진분류 : loss = 'binary_crossentropy'

다중분류 : loss  = 'categoricail_crossentropy'

 

sparse_binary / categoricail_crossentropy => 원-핫 인코딩 안해도 될때 sparse 사용!

 

model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')

 

metrics에 대해 알아보자.

케라스는 모델이 훈련할 때 기본으로 에포크마다 손실값을 출력한다.

손실이 줄어드는 것을 보고 훈련이 잘 되는것을 볼 수 있지만 정확도까지 출력해주면 더 좋을것이다.

이를 위해 accuracy를 지정!

 

이제 다 끝났으니 훈련시켜보자.

model.fit(train_scaled, train_target, epochs = 20)

Epoch 1/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.3956 - accuracy: 0.8672
Epoch 2/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.3956 - accuracy: 0.8666
Epoch 3/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.3945 - accuracy: 0.8680
Epoch 4/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.3942 - accuracy: 0.8679
Epoch 5/5
1500/1500 [==============================] - 2s 1ms/step - loss: 0.3929 - accuracy: 0.8688

 

이제 검증세트 모델의 성능을 확인해보자 !!

model.evaluate(val_scaled, val_target)

375/375 [==============================] - 0s 882us/step - loss: 0.4426 - accuracy: 0.8518

검증세트 모델도 훈련데이터세트와 비슷한 accuracy를 나타냄을 볼 수 있다.

 

+ Recent posts