📗강의노트/핸즈온 머신러닝

[핸즈온 머신러닝] 제 10장 연습문제 풀이

728x90
반응형

Exercise Part. 10

Neural_Network


1. 초창기 인공 뉴런을 사용해 A+B(+는 XOR연산)를 계산하는 인공신경망을 그려보세요.

E

C D

A B

처럼 아래서 위로 네트워크가 진행된다고 했을 때,

(not A) and B = D

A and (not B) = C

C or D = E ( A + B (XOR) )

2. 고전적인 퍼셉트론보다 로지스틱 회귀 분류기가 일반적으로 선호되는 이유는 무엇인가요? 퍼셉트론을 어떻게 수정하면 로지스틱 회귀 분류기와 동등하게 만들 수 있나요?

고전적인 퍼셉트론은 선형적으로 구분될 때만 수렴하고 확률을 추정할 수 없다. 하지만 로지스틱은 선형적으로 구분되지 못해도 클래스 확률을 잘 출력할 수 있다. Activation은 softmax로 바꾸고, 경사 하강법을 사용하여 훈련시키면 로지스틱 분류기처럼 된다.

3. 왜 초창기의 다층 퍼셉트론을 훈련시킬 때 로지스틱 활성화 함수가 핵심 요소였나요?

경사 하강법을 적용했을 때 0인 부분이 없기에 핵심 요소였다. 기존의 활성화 함수는 계단 함수여서 기울기가 없었기에 경사 하강법이 이동할 수 없었다.

4. 유명한 활성화 함수 네 가지는 무엇인가요?

계단함수, ReLU(ELU, Leaky ReLU), tanh, Logistic

5. 10개의 통과 뉴런으로 된 입력층, 50개의 뉴런으로 된 은닉층, 그리고 3개의 뉴런으로 된 출력층으로 구성된 다층 퍼셉트론이 있다고 가정하자. 모든 뉴런은 ReLU 활성화 함수를 사용한다.

(1) 입력 행렬 X의 크기는 얼마인가요?

(None,10)

배치사이에 따라 None에 숫자가 채워진다.

(2) 은닉층의 가중치 벡터 Wh와 편향 벡터 bh의 크기는 얼마인가요?

(10,50)

(3) 출력층의 가중치 벡터 Wo와 편향 벡터 bo의 크기는 얼마인가요?

(50,3)

(4) 네트워크의 출력 행렬 Y의 크기는 얼마인가요?

3

(5) X,Wh,bh,Wo,bo의 함수로 네트워크의 출력 행렬 Y를 계산하는 식을 써보세요.

ReLU(ReLU(XWh+bh)Wo+bo)

ReLU는 행렬의 음수를 0으로 바꿔준다.

6. 스팸 메일을 분류하기 위해서는 출력층에 몇 개의 뉴런이 필요할까요? 출력층에 어떤 활성화 함수를 사용해야 할까요? MNIST 문제라면 출력층에 어떤 활성화 함수를 사용하고 뉴런은 몇 개가 필요할까요? 2장에서 본 주택 가격 예측용 네트워크에 대해 가튼 질문의 답을 찾아보세요.

스팸 메일 : 출력층 뉴런 = 1개 , 확률 추정시에는 Logistic를 활성화 함수로 이용.

MNIST : 출력층 뉴런 = 10개 , logistic에서 Softmax로 바꾸기

주택 가격 예측에는 활성화 함수 없는 출력 뉴런 하나면 된다.

7. 역전파란 무엇이고 어떻게 작동하나요? 역전파와 후진 모드 자동 미분의 차이점은 무엇인가요?

역전파는 네트워크를 학습시키는 방법중에 하나이다.

  1. 먼저 모델의 모든 파라미터에 대한 비용 함수의 그래디언트를 계산
  2. 그래디언트 사용해 경사 하강법 스텝을 수행

역전파는 그래디언트 계산과 경사 하강법 스텝을 여러 번 수행하여 인공 신경망을 훈련시키는 전체 프로세스를 의미한다. 이와 다르게 후진 모드 자동 미분은 그래디언트를 효과적으로 계산하는 하나의 기법으로 역전파에서 사용된다.

8. 다층 퍼셉트론에서 조정할 수 있는 하이퍼파라미터를 모두 나열해보세요. 훈련 데이터에 다층 퍼셉트론이 과대적합되었다면 이를 해결하기 위해 하이퍼파라미터를 어떻게 조정해야 할까요?

은닉층 수, 각 은닉층의 뉴런 수, 활성화 함수(이진분류:로지스틱, 다중분류:소프트맥스)

9. 깊은 다중 퍼셉트론을 MNIST 데이터셋에 훈련시키고 98% 정확도를 얻을 수 있는지 확인해보세요. 9장의 마지막 연습문제에서와 같이 모든 부가 기능을 추가해보세요. ( 체크포인트 저장, 중지시 체크포인트 복원, 서머리 추가, 텐서보드를 통한 학습 곡선 그리기)

In [111]:
# MNIST 데이터 불러오기
import tensorflow as tf
(X_train,y_train),(X_test,y_test) = tf.keras.datasets.mnist.load_data()
In [112]:
# preprocessing
import numpy as np
X_train = X_train.astype(np.float32).reshape(-1,28*28) / 255.0
X_test = X_test.astype(np.float32).reshape(-1,28*28) / 255.0

y_train = y_train.astype(np.int32)
y_test = y_test.astype(np.int32)
In [113]:
X_train, X_valid = X_train[5000:], X_train[:5000]
y_train, y_valid = y_train[5000:], y_train[:5000]
In [119]:
tf.reset_default_graph()
n_inputs = 28*28  # MNIST
n_hidden1 = 300
n_hidden2 = 100
n_outputs = 10
In [120]:
X = tf.placeholder(tf.float32, shape=(None,n_inputs),name='X')
y = tf.placeholder(tf.int32, shape=(None),name='y')
In [121]:
with tf.name_scope('dnn'):
    hidden1 = tf.layers.dense(X,n_hidden1,activation=tf.nn.relu,name='hidden1')
    hidden2 = tf.layers.dense(hidden1,n_hidden2,activation=tf.nn.relu,name='hidden2')
    logits = tf.layers.dense(hidden2,n_outputs,name='outputs')
In [122]:
with tf.name_scope('loss'):
    xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits,labels=y)
    loss = tf.reduce_mean(xentropy,name='loss')
    loss_summary = tf.summary.scalar('log_loss',loss)
In [123]:
lr = 0.01
with tf.name_scope('train'):
    optimizer = tf.train.GradientDescentOptimizer(lr)
    training_op = optimizer.minimize(loss)
In [124]:
with tf.name_scope('eval'):
    correct = tf.nn.in_top_k(logits,y,1)
    accuracy = tf.reduce_mean(tf.cast(correct,tf.float32))
    accuracy_summary = tf.summary.scalar("accuracy",accuracy)
In [125]:
# 텐서보드

from datetime import datetime

def log_dir(prefix=""):
    now = datetime.utcnow().strftime("%Y%m%d%H%M%S")
    root_logdir = "tf_logs"
    if prefix:
        prefix += "-"
    name = prefix + "run-" + now
    return "{}/{}/".format(root_logdir, name)
In [126]:
logdir = log_dir("mnist_dnn")
In [127]:
file_writer = tf.summary.FileWriter(logdir, tf.get_default_graph())
In [128]:
m,n = X_train.shape
In [129]:
def shuffle_batch(X, y, batch_size):
    rnd_idx = np.random.permutation(len(X))
    n_batches = len(X) // batch_size
    for batch_idx in np.array_split(rnd_idx, n_batches):
        X_batch, y_batch = X[batch_idx], y[batch_idx]
        yield X_batch, y_batch
In [130]:
saver = tf.train.Saver()
In [131]:
import os



n_epochs = 1001
batch_size = 50
total_batch = int(np.ceil(m / batch_size))

checkpoint_path = "/tmp/my_deep_mnist_model.ckpt"
checkpoint_epoch_path = checkpoint_path + ".epoch"
final_model_path = "./my_deep_mnist_model"

best_loss = np.infty
epochs_without_progress = 0
max_epochs_without_progress = 50

with tf.Session() as sess:
    if os.path.isfile(checkpoint_epoch_path):
        with open(checkpoint_epoch_path,"rb") as f:
            start_epoch = int(f.read())
            print("이전 훈련이 중지되었습니다. 에포크 {}에서 시작합니다".format(start_epoch))
            saver.restore(sess, checkpoint_path)
    else:
        start_epoch = 0
        sess.run(tf.global_variables_initializer())
        
    for epoch in range(start_epoch,n_epochs):
        for X_batch, y_batch in shuffle_batch(X_train,y_train,batch_size):
            sess.run(training_op,feed_dict={X:X_batch,y:y_batch})
            
        accuracy_val, loss_val, accuracy_summary_str, loss_summary_str = \
        sess.run([accuracy,loss,accuracy_summary,loss_summary],feed_dict={X:X_val,y:y_val})
        file_writer.add_summary(accuracy_summary_str, epoch)
        file_writer.add_summary(loss_summary_str, epoch)

        if epoch % 5 == 0:
            print("에포크:", epoch,
                  "\t검증 세트 정확도: {:.3f}%".format(accuracy_val * 100),
                  "\t손실: {:.5f}".format(loss_val))
            saver.save(sess, checkpoint_path)
            with open(checkpoint_epoch_path, "wb") as f:
                f.write(b"%d" % (epoch + 1))
            if loss_val < best_loss:
                saver.save(sess, final_model_path)
                best_loss = loss_val
            else:
                epochs_without_progress += 5
                if epochs_without_progress > max_epochs_without_progress:
                    print("조기 종료")
                    break
에포크: 0 	검증 세트 정확도: 90.040% 	손실: 0.35835
에포크: 5 	검증 세트 정확도: 94.920% 	손실: 0.18239
에포크: 10 	검증 세트 정확도: 96.220% 	손실: 0.13295
에포크: 15 	검증 세트 정확도: 96.920% 	손실: 0.10980
에포크: 20 	검증 세트 정확도: 97.180% 	손실: 0.09520
에포크: 25 	검증 세트 정확도: 97.520% 	손실: 0.08463
에포크: 30 	검증 세트 정확도: 97.660% 	손실: 0.08015
에포크: 35 	검증 세트 정확도: 97.900% 	손실: 0.07535
에포크: 40 	검증 세트 정확도: 97.840% 	손실: 0.07380
에포크: 45 	검증 세트 정확도: 97.940% 	손실: 0.07149
에포크: 50 	검증 세트 정확도: 98.080% 	손실: 0.07061
에포크: 55 	검증 세트 정확도: 97.920% 	손실: 0.07060
에포크: 60 	검증 세트 정확도: 98.000% 	손실: 0.07052
에포크: 65 	검증 세트 정확도: 97.980% 	손실: 0.07162
에포크: 70 	검증 세트 정확도: 98.000% 	손실: 0.07191
에포크: 75 	검증 세트 정확도: 98.140% 	손실: 0.07105
에포크: 80 	검증 세트 정확도: 98.060% 	손실: 0.07157
에포크: 85 	검증 세트 정확도: 98.060% 	손실: 0.07134
에포크: 90 	검증 세트 정확도: 98.000% 	손실: 0.07244
에포크: 95 	검증 세트 정확도: 98.180% 	손실: 0.07229
에포크: 100 	검증 세트 정확도: 98.140% 	손실: 0.07292
에포크: 105 	검증 세트 정확도: 98.140% 	손실: 0.07414
에포크: 110 	검증 세트 정확도: 98.060% 	손실: 0.07486
에포크: 115 	검증 세트 정확도: 98.140% 	손실: 0.07569
조기 종료
In [132]:
os.remove(checkpoint_epoch_path)
In [133]:
with tf.Session() as sess:
    saver.restore(sess, final_model_path)
    accuracy_val = accuracy.eval(feed_dict={X: X_test, y: y_test})
INFO:tensorflow:Restoring parameters from ./my_deep_mnist_model
In [134]:
accuracy_val
Out[134]:
0.9794


728x90
반응형