데이터분석-머신러닝-AI/강의 정리

[혼자 공부하는 머신러닝+딥러닝] 18강. 심층 신경망 ▶️인공 신경망에 층을 추가하여 심층 신경망 만들어 보기 - 층을 늘리고 옵티마이저를 추가해보자

bluebamus 2023. 11. 22.

https://www.youtube.com/watch?v=JskWW5MlzOg&list=PLJN246lAkhQjoU0C4v8FgtbjOIXxSs_4Q&index=18

 

 

 - 층을 더 추가해서 성능을 높여보자.

 

 1. 데이터 로그 및 전처리

# 실행마다 동일한 결과를 얻기 위해 케라스에 랜덤 시드를 사용하고 텐서플로 연산을 결정적으로 만듭니다.
import tensorflow as tf

tf.keras.utils.set_random_seed(42)
tf.config.experimental.enable_op_determinism()

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) # 1차원으로 축 변환

# 검증세트 수동으로 분리
train_scaled, val_scaled, train_target, val_target = train_test_split(
    train_scaled, train_target, test_size=0.2, random_state=42)

 

 2. 심층 신경망 만들기 (2개 층)

   - 은닉층 (Hidden Layer)

      - 은닉층 : 입력층과 출력층 사이에 있는 모든 층이며 사용자의 요구에 따라 얼마든지 증가될 수 있다.

         - 정보손실 방지를 위해 최소한 출력층의 유닛 개수보다 많게 정의해 주어야 한다.

      - 출력층과 마찬가지로 은닉층에도 활성화함수가 적용된다.

      - 출력층보다 사용할 수 있는 함수가 비교적 자유롭다.

         - 시그모이드, 렐루 등

 

   - 심층신경망 만들기

      - 은닉층 activation은 가장 대표적인 시그모이드를 사용한다.

# 100개의 유닛을 가지고 있는 은닉층, 필수로 input_shape를 정의해줘야 한다.
dense1 = keras.layers.Dense(100, activation='sigmoid', input_shape=(784,))

# 10개의 유닛을 가지고 있는 출력층
dense2 = keras.layers.Dense(10, activation='softmax')

# 층 2개를 쌓아서 '심층 신경망' 모델을 정의한다.
model = keras.Sequential([dense1, dense2]) # 은닉층을 먼저 정의하고 출력층을 마지막에 정의한다.

 

   - 모델 정보 확인

    - .summary()를 이용해 모델의 정보를 확인할 수 있다.

         - Output Shape : (경사하강법, 출력 유닛 개수)를 보여준다.

            - 훈련을 몇개의 배치로 할지 모르니 유연하게 받을 수 있도록 None으로 설정되어 있다.

         - Param : 모델 파라미터, 즉 각 층의 가중치 & 절편의 개수를 보여준다.

            - 첫번째 층 : 784 * 100 (가중치) + 100( 절편 ) = 78,500

            - 두번째 층 : 100 * 10 (가중치) + 10(절편) = 1,010

model.summary()

Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense (Dense)               (None, 100)               78500     
                                                                 
 dense_1 (Dense)             (None, 10)                1010      
                                                                 
=================================================================
Total params: 79510 (310.59 KB)
Trainable params: 79510 (310.59 KB)
Non-trainable params: 0 (0.00 Byte)
____________________________________________

 

   - 심층 신경망 만들기 3가지 방법

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

model.summary()

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

 

   - 층마다 이름도 정의해주고 모델 전체 이름도 정의해준다.

      - name으로 정의하는 층 이름은 오직 영어로만 가능하다.

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

model.summary()

Model: "패션 MNIST 모델"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 hidden (Dense)              (None, 100)               78500     
                                                                 
 output (Dense)              (None, 10)                1010      
                                                                 
=================================================================
Total params: 79510 (310.59 KB)
Trainable params: 79510 (310.59 KB)
Non-trainable params: 0 (0.00 Byte)

 

   - 필드에서 가장 많이 사용하는 방법이다

      - 선언 사이에 if로 여러 조건을 설정할 수 있다.

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: "sequential_1"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense_2 (Dense)             (None, 100)               78500     
                                                                 
 dense_3 (Dense)             (None, 10)                1010      
                                                                 
=================================================================
Total params: 79510 (310.59 KB)
Trainable params: 79510 (310.59 KB)
Non-trainable params: 0 (0.00 Byte)

 

   - compile() 및 fit() 수행

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

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

 

 3. 활성화 함수

   - 은닉층에 활성화 함수를 적용하는 이유

      - 2개의 선형 계산식 결과 값에는 공통되는 미지수가 서로 상쇠되어 사라질 수 있다. 신경망에서 이런 계산식이 이어진다면 중간에 존재하는 은닉층들의 존재 의미가 사라져 버리게 된다.

         - 아래 식에서 b가 사라짐으로 b는 결국 하는 일이 없어지게 된다.

      - 이와 같은 문제를 해결하기 위해 은닉층의 결과값을 비선형적으로 비틀어주는 계산식이 필요하다.

         - 선형 식들이 단순히 합쳐지는 결과를 만들이 않기 위한 작업이다.

 

   - 렐루(ReLU) 함수

      - 시그모이드 함수의 단점

         - 출력값(z)이 너무 크거나 작을 경우 그래디언트 소실문제가 있다. 이 경우 기울기도 0에 가까워지면서 가중치가 매우 느리게 업데이트 되므로 학습 과정이 늦어지고 뿐만 아니라 신경망이 수렴하기 어렵게 되어 결국 층을 깊게 쌓기 힘들게 된다.

 

      - 새로운 제안, 렐루(ReLU) 함수

         - 우리말로 정류된 선형 함수라 하며 간단하게 +/-가 반복되는 신호에서 - 흐름을 차단한다는 의미이다.

         - 출력값(z)가 0보다 작으면 0으로 출력하고 0보다 크면 그대로 z를 출력한다.

         - 기울기 소실 문제가 발생하지 않는다.

 

   - 유틸리티 층 추가하기

      - Flatten() : 다차원 입력데이터를 1차원으로 펼쳐주는 유틸리티 층으로 편의를 위한 층이다.

         - summary를 이용해 출력해보면 입력값 개수를 바로 알 수 있다. 전처리 과정을 모델 내 포함시키는 것이다.

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.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: 79510 (310.59 KB)
Trainable params: 79510 (310.59 KB)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________

 

      - 새로운 모델로 재훈련 하기 

         - reshape() 사용을 더 이상 하지 않는다. 결과적으로 성능이 더 좋아지는 것을 확인할 수 있다.

(train_input, train_target), (test_input, test_target) = keras.datasets.fashion_mnist.load_data()

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

model.fit(train_scaled, train_target, epochs=5) # 점수가 조금 더 좋아졌다.

Epoch 1/5
1500/1500 [==============================] - 6s 3ms/step - loss: 0.5290 - accuracy: 0.8114
Epoch 2/5
1500/1500 [==============================] - 5s 4ms/step - loss: 0.3929 - accuracy: 0.8566
Epoch 3/5
1500/1500 [==============================] - 6s 4ms/step - loss: 0.3538 - accuracy: 0.8718
Epoch 4/5
1500/1500 [==============================] - 5s 4ms/step - loss: 0.3316 - accuracy: 0.8806
Epoch 5/5
1500/1500 [==============================] - 5s 4ms/step - loss: 0.3148 - accuracy: 0.8867

model.evaluate(val_scaled, val_target) # 검증세트의 성능 확인 결과 출력층 하나보다 성능이 좋다.
375/375 [==============================] - 1s 3ms/step - loss: 0.3825 - accuracy: 0.8682
[0.38249149918556213, 0.8681666851043701]

 

 4. 옵티마이저

   - 신경망의 하이퍼파라미터

      - 신경망에는 특히 하이퍼파라미터가 많다.

         - 은닉층 뉴런 개수(100), 활성화함수(activation), 층의 종류(Dense, Flatten), 배치크기(batch_size), 반복횟수(epochs) 등이 존재한다.

    - 옵티마이저 설정

      - 옵티마이저도 하이퍼파라미터 중 하나로, 경사하강법의 종류에 대한 설정을 한다.

         - SGD(): 이름은 그냥 SGD인데 실제로는 미니배치 경사하강법을 수행한다( 기본 배치크기 = 32 )

      - 설정( compile ) 단계에서 optimizer로 정의할 수 있다.

         - ''를 사용해 문자열로 정의하거나 객체를 먼저 생성하여 파라미터에 정의해줄 수도 있다.

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

 

      - 기본 경사 하강법과 적응적 학습률 옵티마이저가 있다.

         - 상세한건 본 강의에서 다루지 않는다 상위 교재 등을 통해 학습하자.

 

         - 네스테로프 모멘텀 하강법 정의

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

 

         - 아다그라드 하강법 (적응적 학습률)

adagrad = keras.optimizers.Adagrad()
model.compile(optimizer=adagrad, loss='sparse_categorical_crossentropy', metrics='accuracy')

 

         -  RMSprop 하강법 (적응적 학습률)

adagrad = keras.optimizers.Adagrad()
model.compile(optimizer=adagrad, loss='sparse_categorical_crossentropy', metrics='accuracy')

 

   - Adam 옵티마이저를 사용한 모델을 이용해 최종 모델을 만들어 보자.

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 [==============================] - 7s 4ms/step - loss: 0.5262 - accuracy: 0.8154
Epoch 2/5
1500/1500 [==============================] - 5s 3ms/step - loss: 0.3940 - accuracy: 0.8589
Epoch 3/5
1500/1500 [==============================] - 6s 4ms/step - loss: 0.3546 - accuracy: 0.8702
Epoch 4/5
1500/1500 [==============================] - 8s 5ms/step - loss: 0.3284 - accuracy: 0.8794
Epoch 5/5
1500/1500 [==============================] - 7s 4ms/step - loss: 0.3058 - accuracy: 0.8872

model.evaluate(val_scaled, val_target)

375/375 [==============================] - 2s 3ms/step - loss: 0.3509 - accuracy: 0.8751
[0.3508651852607727, 0.875083327293396]

 

   - 추가 학습

      - 회귀 신경망 모델에서는 활성화 함수를 사용하지 않는 이유

      - 분류 모델에서 활성화 함수( sigmoid, softmax)를 사용한 이유는 확률로 출력을 하기 위해서이다. 하지만 회귀의 출력값은 임의의 숫자값이기에 필요가 없다. activation에 아무것도 정의하지 않아도 된다.

 

   - 앙상블 알고리즘과 심층 신경망의 비교

      - 이미지 출처 : https://velog.io/@simon919/7-2.-%EC%8B%AC%EC%B8%B5-%EC%8B%A0%EA%B2%BD%EB%A7%9D#-to-wrap-up

 

 

 

 - reference : 

https://velog.io/@simon919/7-2.-%EC%8B%AC%EC%B8%B5-%EC%8B%A0%EA%B2%BD%EB%A7%9D#-to-wrap-up

 

[혼공머신] 7-2. 심층 신경망

홍 선배🗣️ "오 인공신경망이 역시 좋네~ 신경망은 층 더 많이 쌓을 수도 있다며?"

velog.io

https://gooopy.tistory.com/55

 

딥러닝-3.4. 활성화함수(5)-렐루 함수(ReLU)

지금까지 계단 함수, 선형 함수, 시그모이드 함수, 소프트맥스 함수, 하이퍼볼릭 탄젠트 함수에 대해 다뤄보았다. 이들은 은닉층에서 사용해서는 안되거나, 사용할 수 있더라도 제한적으로 사용

gooopy.tistory.com

 

댓글