본문 바로가기
ML & DL/책 & 강의

[혼공머신] Chapter 07 딥러닝을 시작합니다

by 공부하는 무니 2023. 2. 19.
반응형

한빛미디어에서 모집하는 혼공학습단 활동의 일환으로 혼자 공부하는 머신러닝+딥러닝 책을 공부하고 정리한 글입니다. 책은 제 돈으로 구매했습니다. 원본 코드는 저자 박해선 님의 깃허브에서 보실 수 있습니다.

 

GitHub - rickiepark/hg-mldl: <혼자 공부하는 머신러닝+딥러닝>의 코드 저장소입니다.

<혼자 공부하는 머신러닝+딥러닝>의 코드 저장소입니다. Contribute to rickiepark/hg-mldl development by creating an account on GitHub.

github.com


Chapter 07 딥러닝을 시작합니다

07-1 인공 신경망

패션 MNIST

MNIST
머신러닝에서는 붓꽃 데이터셋이 유명한 것 처럼, 딥러닝에서는 MNIST 데이터셋이 유명하다. 
MNIST는 손으로 쓴 0~9까지의 숫자로 이루어져 있다. 
패션 MNIST는 MNIST와 크기, 개수가 동일하지만 숫자 대신 패션 아이템으로 이루어진 데이터이다.

 

from tensorflow import keras

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

print(test_input.shape, test_target.shape)

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

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

레이블 0 1 2 3 4 5 6 7 8 9
패션 아이템 티셔츠 바지 스웨터 드레스 코트 샌달 셔츠 스니커즈 가방 앵클 부츠
import numpy as np

print(np.unique(train_target, return_counts=True))

로지스틱 회귀로 패션 아이템 분류하기

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

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

인공 신경망

텐서플로와 케라스

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(
    train_scaled, train_target, test_size=0.2, random_state=42)
print(train_scaled.shape, train_target.shape)

print(val_scaled.shape, val_target.shape)

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

인공 신경망으로 패션 아이템 분류하기

model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')
print(train_target[:10])

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

model.evaluate(val_scaled, val_target)

07-2 심층 신경망

2개의 층

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, train_target, val_target = train_test_split(
    train_scaled, train_target, test_size=0.2, random_state=42)
dense1 = keras.layers.Dense(100, activation='sigmoid', input_shape=(784,))
dense2 = keras.layers.Dense(10, activation='softmax')

심층 신경망 만들기

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

층을 추가하는 다른 방법

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 = keras.Sequential()
model.add(keras.layers.Dense(100, activation='sigmoid', input_shape=(784,)))
model.add(keras.layers.Dense(10, activation='softmax'))
model.summary()

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

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

렐루 함수

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

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

model.evaluate(val_scaled, val_target)

옵티마이저

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(learning_rate=0.1)
sgd = keras.optimizers.SGD(momentum=0.9, nesterov=True)
adagrad = keras.optimizers.Adagrad()
model.compile(optimizer=adagrad, loss='sparse_categorical_crossentropy', metrics='accuracy')
rmsprop = keras.optimizers.RMSprop()
model.compile(optimizer=rmsprop, loss='sparse_categorical_crossentropy', metrics='accuracy')
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)

model.evaluate(val_scaled, val_target)

07-3 신경망 모델 훈련

손실 곡선

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, activation='softmax'))
    return model
model = model_fn()

model.summary()

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

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

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))
print(history.history.keys())

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

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('epoch')
plt.ylabel('loss')
plt.legend(['train', 'val'])
plt.show()

드롭아웃

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

model.summary()

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('epoch')
plt.ylabel('loss')
plt.legend(['train', 'val'])
plt.show()

모델 저장과 복원

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))
model.save_weights('model-weights.h5')
model.save('model-whole.h5')
!ls -al *.h5

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

model.load_weights('model-weights.h5')
import numpy as np

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)

콜백

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])
model = keras.models.load_model('best-model.h5')

model.evaluate(val_scaled, val_target)

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])
print(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()

model.evaluate(val_scaled, val_target)

혼공머신 미션

기본 미션 - Ch.07(07-1) 확인 문제 풀고, 풀이 과정 정리하기

1. 어떤 인공 신경망의 입력 특성이 100개이고 밀집층에 있는 뉴런 개수가 10개일 때 필요한 모델 파라미터의 개수는 몇 개인가요?

입력층과 밀집층 사이의 각 연결에는 가중치 파라미터는 100 x 10 = 1000개입니다. 

바이어스 파라미터는 10개이므로, 
모델 파라미터의 총 개수는 바이어스 파라미터 10개 + 가중치 파라미터 1000개 = 1010개입니다.

2. 케라스의 Dense 클래스를 사용해 신경망의 출력층을 만들려고 합니다. 이 신경망이 이진 분류 모델이라면 activation 매개변수에 어떤 활성화 함수를 지정해야 하나요?

이진 분류를 위해 Keras의 Dense 클래스를 사용하여 신경망의 출력층을 구축할 때, 시그모이드 활성화 함수를 사용하는 것이 일반적입니다. 시그모이드 활성화 함수는 모든 실수 값을 0과 1의 범위에 매핑하므로 이진 분류 문제에서 이진 결과(예: 예 또는 아니오, 참 또는 거짓)를 예측할 때 유용합니다.

3. 케라스 모델에서 손실 함수와 측정 지표 등을 지정하는 메서드는 무엇인가요?

Keras에서는 compil() 메서드를 사용하여 모델의 손실 함수 및 메트릭을 지정할 수 있습니다. compile 메서드를 사용하면 모델이 학습 중에 사용해야 하는 옵티마이저, 손실 함수 및 메트릭을 지정할 수 있습니다.

4.  정수 레이블을 타깃으로 가지는 다중 분류 문제일 때 케라스 모델의 compile() 메서드에 지정할 손실 함수로 적절한 것은 무엇인가요?

정수 레이블을 타깃으로 가지는 다중 클래스 분류 문제의 경우, Keras 모델의 compile() 메서드에서 지정하기에 적합한 손실 함수는 categorical cross-entropy입니다.
categorical cross-entropy는 다중 클래스 분류 문제에 일반적으로 사용되는 손실 함수로, 예측된 클래스 확률과 원핫 인코딩된 벡터로 표현되는 실제 클래스 레이블 간의 차이를 측정합니다. 

선택 미션 - Ch.07(07-2) 확인 문제 풀고, 풀이 과정 정리하기

1. 다음 중 모델의 add() 메서드 사용법이 올바른 것은 어떤 것인가요?
① model.add(keras.layers.Dense)
② model.add(keras.layers.Dense(10, activation='relu'))
③ model.add(keras.layers.Dense, 10, activation='relu')
④ model.add(keras.layers.Dense)(10, activation='relu')

② model.add(keras.layers.Dense(10, activation='relu'))
뉴런이 10개인 밀집층을 생성하고 활성화 함수를 정류된 ReLU함수로 설정합니다. add 메서드는 Dense 레이어 클래스의 인스턴스를 파라미터로 받아서 레이어를 생성합니다.

2. 크기가 300*300인 입력을 케라스 층으로 펼치려고 합니다. 다음 중 어떤 층을 사용해야 하나요?
① Plate
② Flatten
③ Normalize
④ Dense

② Flatten

Keras에서 300x300 입력을 단일 벡터로 펼치려면 평탄화 flatten을 사용해야 합니다.
flatten 레이어는 입력 텐서를 단일 벡터로 평탄화하여 밀도가 높은 레이어의 입력으로 사용할 수 있도록 하는 데 사용됩니다. 즉, flatten 레이어는 다차원 텐서를 단일 벡터의 값으로 변환합니다.

3. 다음 중에서 이미지 분류를 위한 심층 신경망에 널리 사용되는 케라스의 활성화 함수는 무엇인가요?
① linear
② sigmoid
③ relu
④ tanh

③ relu
relu는 많은 이미지 분류 문제에 잘 작동합니다. relu는 모든 음수 값을 0으로 매핑하여 심층 신경망을 훈련할 때 발생할 수 있는 소실 기울기 문제를 완화하는 데 도움이 됩니다.

4. 다음 중 적응적 학습률을 사용하지 않는 옵티마이저는 무엇인가요?
 SGD
② Adagrad
③ RMSprop
④ Adam

 SGD

SGD는 학습 중에 신경망의 가중치를 업데이트하는 기본 옵티마이저 알고리즘입니다. 이 알고리즘은 가중치에 대한 손실 함수의 기울기를 계산하고 negative 기울기 방향으로 가중치를 업데이트합니다. SGD는 적응형 학습률을 사용하지 않고 대신 사용자가 설정한 고정 학습률을 사용합니다.

반응형

댓글