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

 

먼저 케라스에서 패션 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과 비슷한 성능을 보여준다..!

 

+ Recent posts