강의영상

imports

import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
import tensorflow.experimental.numpy as tnp
tf.config.experimental.list_physical_devices()
2022-05-06 10:37:51.868820: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:939] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
[PhysicalDevice(name='/physical_device:CPU:0', device_type='CPU'),
 PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]
import graphviz
def gv(s): return graphviz.Source('digraph G{ rankdir="LR"'+ s + ';}')

로지스틱 모형 (1): 활성화함수로 sigmoid 선택

- 기본버전은 아래와 같다

$$y_i \approx \text{sigmoid}(b + w_1 x_{1,i} + \dots + w_{784}x_{784,i})= \frac{\exp(b + w_1 x_{1,i} + \dots + w_{784}x_{784,i})}{1+\exp(b + w_1 x_{1,i} + \dots + w_{784}x_{784,i})}$$

- 벡터버전은 아래와 같다.

$${\boldsymbol y} \approx \text{sigmoid}({\bf X}{\bf W} + b) = \frac{\exp({\bf XW} +b)}{1+\exp({\bf XW} +b)}$$

- 벡터버전에 익숙해지도록 하자. 벡터버전에 사용된 차원 및 연산을 정리하면 아래와 같다.

  • ${\bf X}$: (n,784) matrix

  • ${\boldsymbol y}$: (n,1) matrix

  • ${\bf W}$: (784,1) matrix

  • $b$: (1,1) matrix

  • +, exp 는 브로드캐스팅

로지스틱 모형 (2): 활성화함수로 softmax 선택

- $y_i=0 \text{ or } 1$ 대신에 $\boldsymbol{y}_i=[y_{i1},y_{i2}]= [1,0] \text { or } [0,1]$와 같이 코딩하면 어떠할까? (즉 원핫인코딩을 한다면?)

- 활성화 함수를 취하기 전의 버전은 아래와 같이 볼 수 있다.

$$[{\boldsymbol y}_1 ~ {\boldsymbol y}_2] \propto [ {\bf X}{\bf W}_1 ~ {\bf X}{\bf W}_2] + [b_1 ~ b_2]= {\bf X} [{\bf W}_1 {\bf W}_2] + [b_1 ~ b_2]= {\bf X}{\bf W} + {\boldsymbol b}$$

여기에서 매트릭스 및 연산의 차원을 정리하면 아래와 같다.

  • ${\bf X}$: (n,784) matrix

  • ${\boldsymbol y}_1,{\boldsymbol y}_2$: (n,1) matrix

  • ${\boldsymbol y}:=[{\boldsymbol y}_1~ {\boldsymbol y}_2]$: (n,2) matrix

  • ${\bf W}_1$, ${\bf W}_2$: (784,1) matrix

  • ${\bf W}:=[{\bf W}_1~ {\bf W}_2]$: (784,2) matrix

  • $b_1,b_2$: (1,1) matrix

  • $\boldsymbol{b}:= [b_1 ~b_2] $: (1,2) matrix

  • + 는 브로드캐스팅

- 즉 로지스틱 모형 (1)의 형태를 겹쳐놓은 형태로 해석할 수 있음. 따라서 ${\bf X} {\bf W}_1 + b_1$와 ${\bf X} {\bf W}_2 + b_2$의 row값이 클수록 ${\boldsymbol y}_1$와 ${\boldsymbol y}_2$의 row값이 1이어야 함

  • ${\boldsymbol y}_1 \propto {\bf X} {\bf W}_1 + b_1$ $\to$ ${\bf X} {\bf W}_1 + b_1$의 row값이 클수록 $\boldsymbol{y}_1$의 row 값이 1이라면 모형계수를 잘 추정한것
  • ${\boldsymbol y}_2 \propto {\bf X} {\bf W}_2 + b_2$ $\to$ ${\bf X} {\bf W}_2 + b_2$의 row값이 클수록 $\boldsymbol{y}_2$의 row 값을 1이라면 모형계수를 잘 추정한것

- (문제) ${\bf X}{\bf W}_1 +b_1$의 값이 500, ${\bf X}{\bf W}_2 +b_2$의 값이 200 인 row가 있다고 하자. 대응하는 $\boldsymbol{y}_1, \boldsymbol{y}_2$의 row값은 얼마로 적합되어야 하는가?

(1) $[0,0]$

(2) $[0,1]$

(3) $[1,0]$ <-- 이게 답이다!

(4) $[1,1]$

Note: 둘다 0 혹은 둘다 1로 적합할수는 없으니까 (1), (4)는 제외한다. ${\bf X}{\bf W}_1 +b_1$의 값이 ${\bf X}{\bf W}_2 +b_2$의 값보다 크므로 (3)번이 합리적임

- 목표: 위와 같은 문제의 답을 유도해주는 활성화함수를 설계하자. 즉 합리적인 $\hat{\boldsymbol{y}}_1,\hat{\boldsymbol{y}}_2$를 구해주는 활성화 함수를 설계해보자. 이를 위해서는 아래의 사항들이 충족되어야 한다.

(1) $\hat{\boldsymbol{y}}_1$, $\hat{\boldsymbol{y}}_2$의 각 원소는 0보다 크고 1보다 작아야 한다. (확률을 의미해야 하니까)

(2) $\hat{\boldsymbol{y}}_1+\hat{\boldsymbol{y}}_2={\bf 1}$ 이어야 한다. (확률의 총합은 1이니까!)

(3) $\hat{\boldsymbol{y}}_1$와 $\hat{\boldsymbol{y}}_2$를 각각 따로해석하면 로지스틱처럼 되면 좋겠다.

- 아래와 같은 활성화 함수를 도입하면 어떨까?

$$\hat{\boldsymbol{y}}=[\hat{\boldsymbol y}_1 ~ \hat{\boldsymbol y}_2] = \big[ \frac{\exp({\bf X}\hat{\bf W}_1+\hat{b}_1)}{\exp({\bf X}\hat{\bf W}_1+\hat{b}_1)+\exp({\bf X}\hat{\bf W}_2+\hat{b}_2)} ~~ \frac{\exp({\bf X}\hat{\bf W}_2+\hat{b}_2)}{\exp({\bf X}\hat{\bf W}_1+\hat{b}_1)+\exp({\bf X}\hat{\bf W}_2+\hat{b}_2)} \big]$$

- (1),(2)는 만족하는 듯 하다. (3)은 바로 이해되지는 않는다

(1) $\hat{\boldsymbol{y}}_1$, $\hat{\boldsymbol{y}}_2$의 각 원소는 0보다 크고 1보다 작아야 한다. --> OK!

(2) $\hat{\boldsymbol{y}}_1+\hat{\boldsymbol{y}}_2={\bf 1}$ 이어야 한다. --> OK!

(3) $\hat{\boldsymbol{y}}_1$와 $\hat{\boldsymbol{y}}_2$를 각각 따로해석하면 로지스틱처럼 되면 좋겠다. --> ???

- 그런데 조금 따져보면 (3)도 만족된다는 것을 알 수 있다. (sigmoid, softmax Section 참고)

- 위와 같은 함수를 softmax라고 하자. 즉 아래와 같이 정의하자.

$$ \hat{\boldsymbol y} = \text{softmax}({\bf X}\hat{\bf W} + {\boldsymbol b}) = \big[ \frac{\exp({\bf X}\hat{\bf W}_1+\hat{b}_1)}{\exp({\bf X}\hat{\bf W}_1+\hat{b}_1)+\exp({\bf X}\hat{\bf W}_2+\hat{b}_2)} ~~ \frac{\exp({\bf X}\hat{\bf W}_2+\hat{b}_2)}{\exp({\bf X}\hat{\bf W}_1+\hat{b}_1)+\exp({\bf X}\hat{\bf W}_2+\hat{b}_2)} \big] $$

sigmoid, softmax

softmax는 sigmoid의 확장형

- 아래의 수식을 관찰하자. $$\frac{\exp(\beta_0+\beta_1 x_i)}{1+\exp(\beta_0+\beta_1x_i)}=\frac{\exp(\beta_0+\beta_1 x_i)}{e^0+\exp(\beta_0+\beta_1x_i)}$$

- 1을 $e^0$로 해석하면 모형2의 해석을 아래와 같이 모형1의 해석으로 적용할수 있다.

  • 모형2: ${\bf X}\hat{\bf W}_1 +\hat{b}_1$ 와 ${\bf X}\hat{\bf W}_2 +\hat{b}_2$ 의 크기를 비교하고 확률 결정
  • 모형1: ${\bf X}\hat{\bf W} +\hat{b}$ 와 $0$의 크기를 비교하고 확률 결정 = ${\bf X}\hat{\bf W} +\hat{b}$의 row값이 양수이면 1로 예측하고 음수이면 0으로 예측

- 이항분포를 차원이 2인 다항분포로 해석가능한 것처럼 sigmoid는 차원이 2인 softmax로 해석가능하다. 즉 다항분포가 이항분포의 확장형으로 해석가능한 것처럼 softmax도 sigmoid의 확장형으로 해석가능하다.

클래스의 수가 2인 경우 softmax vs sigmoid

- 언뜻 생각하면 클래스가 2인 경우에도 sigmoid 대신 softmax로 활성화함수를 이용해도 될 듯 하다. 즉 $y=0 \text{ or } 1$와 같이 정리하지 않고 $y=[0,1] \text{ or } [1,0]$ 와 같이 정리해도 무방할 듯 하다.

- 하지만 sigmoid가 좀 더 좋은 선택이다. 즉 $y= 0 \text{ or } 1$로 데이터를 정리하는 것이 더 좋은 선택이다. 왜냐하면 sigmoid는 softmax와 비교하여 파라메터의 수가 적지만 표현력은 동등하기 때문이다.

- 표현력이 동등한 이유? 아래 수식을 관찰하자.

$$\big(\frac{e^{300}}{e^{300}+e^{500}},\frac{e^{500}}{e^{300}+e^{500}}\big) =\big( \frac{e^{0}}{e^{0}+e^{200}}, \frac{e^{200}}{e^{0}+e^{200}}\big)$$

  • $\big(\frac{e^{300}}{e^{300}+e^{500}},\frac{e^{500}}{e^{300}+e^{500}}\big)$를 표현하기 위해서 300, 500 이라는 2개의 숫자가 필요한것이 아니고 따지고보면 200이라는 하나의 숫자만 필요하다.
  • $(\hat{\boldsymbol{y}}_1,\hat{\boldsymbol{y}}_2)$의 표현에서도 ${\bf X}\hat{\bf W}_1 +\hat{b}_1$ 와 ${\bf X}\hat{\bf W}_2 +\hat{b}_2$ 라는 숫자 각각이 필요한 것이 아니고 $({\bf X}\hat{\bf W}_1 +\hat{b}_1)-({\bf X}\hat{\bf W}_2 +\hat{b}_2)$의 값만 알면 된다.

- 클래스의 수가 2개일 경우는 softmax가 sigmoid에 비하여 장점이 없다. 하지만 softmax는 클래스의 수가 3개 이상일 경우로 쉽게 확장할 수 있다는 점에서 매력적인 활성화 함수이다.

분류할 클래스가 3개 이상일 경우 신경망 모형의 설계

- y의 모양: [0 1 0 0 0 0 0 0 0 0]

- 활성화함수의 선택: softmax

- 손실함수의 선택: cross entropy

Fashion_MNIST 다중분류

- 데이터정리

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.fashion_mnist.load_data()
tf.keras.utils.to_categorical(y_train)
array([[0., 0., 0., ..., 0., 0., 1.],
       [1., 0., 0., ..., 0., 0., 0.],
       [1., 0., 0., ..., 0., 0., 0.],
       ...,
       [0., 0., 0., ..., 0., 0., 0.],
       [1., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.]], dtype=float32)
X=x_train.reshape(-1,784)
y=tf.keras.utils.to_categorical(y_train)
XX=x_test.reshape(-1,784)
yy=tf.keras.utils.to_categorical(y_test)

- 시도1: 간단한 신경망

gv('''
splines=line
subgraph cluster_1{
    style=filled;
    color=lightgrey;
    "x1"
    "x2"
    ".."
    "x784"
    label = "Layer 0"
}
subgraph cluster_2{
    style=filled;
    color=lightgrey;
    "x1" -> "node1"
    "x2" -> "node1"
    ".." -> "node1"
    
    "x784" -> "node1"
    "x1" -> "node2"
    "x2" -> "node2"
    ".." -> "node2"
    "x784" -> "node2"
    
    "x1" -> "..."
    "x2" -> "..."
    ".." -> "..."
    "x784" -> "..."

    "x1" -> "node30"
    "x2" -> "node30"
    ".." -> "node30"
    "x784" -> "node30"


    label = "Layer 1: relu"
}
subgraph cluster_3{
    style=filled;
    color=lightgrey;

    "node1" -> "y10"
    "node2" -> "y10"
    "..." -> "y10"
    "node30" -> "y10"
    
    "node1" -> "y1"
    "node2" -> "y1"
    "..." -> "y1"
    "node30" -> "y1"
    
    "node1" -> "."
    "node2" -> "."
    "..." -> "."
    "node30" -> "."
    
    label = "Layer 2: softmax"
}
''')
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> G cluster_1 Layer 0 cluster_2 Layer 1: relu cluster_3 Layer 2: softmax x1 x1 node1 node1 x1->node1 node2 node2 x1->node2 ... ... x1->... node30 node30 x1->node30 x2 x2 x2->node1 x2->node2 x2->... x2->node30 .. .. ..->node1 ..->node2 ..->... ..->node30 x784 x784 x784->node1 x784->node2 x784->... x784->node30 y10 y10 node1->y10 y1 y1 node1->y1 . . node1->. node2->y10 node2->y1 node2->. ...->y10 ...->y1 ...->. node30->y10 node30->y1 node30->.
tf.random.set_seed(43052)
net = tf.keras.Sequential()
net.add(tf.keras.layers.Dense(30,activation='relu'))
net.add(tf.keras.layers.Dense(10,activation='softmax'))
net.compile(optimizer='adam',loss=tf.losses.categorical_crossentropy,metrics=['accuracy'])
net.fit(X,y,epochs=20,batch_size=1200)

Epoch 1/20
50/50 [==============================] - 0s 831us/step - loss: 32.5672 - accuracy: 0.3730
Epoch 2/20
50/50 [==============================] - 0s 731us/step - loss: 2.4414 - accuracy: 0.3877
Epoch 3/20
50/50 [==============================] - 0s 881us/step - loss: 1.9154 - accuracy: 0.3809
Epoch 4/20
50/50 [==============================] - 0s 792us/step - loss: 1.7740 - accuracy: 0.4041
Epoch 5/20
50/50 [==============================] - 0s 830us/step - loss: 1.6474 - accuracy: 0.4517
Epoch 6/20
50/50 [==============================] - 0s 799us/step - loss: 1.5429 - accuracy: 0.4842
Epoch 7/20
50/50 [==============================] - 0s 738us/step - loss: 1.4649 - accuracy: 0.4992
Epoch 8/20
50/50 [==============================] - 0s 894us/step - loss: 1.4001 - accuracy: 0.5227
Epoch 9/20
50/50 [==============================] - 0s 829us/step - loss: 1.3400 - accuracy: 0.5461
Epoch 10/20
50/50 [==============================] - 0s 778us/step - loss: 1.2882 - accuracy: 0.5539
Epoch 11/20
50/50 [==============================] - 0s 883us/step - loss: 1.2506 - accuracy: 0.5612
Epoch 12/20
50/50 [==============================] - 0s 785us/step - loss: 1.2194 - accuracy: 0.5707
Epoch 13/20
50/50 [==============================] - 0s 766us/step - loss: 1.1915 - accuracy: 0.5732
Epoch 14/20
50/50 [==============================] - 0s 799us/step - loss: 1.1674 - accuracy: 0.5765
Epoch 15/20
50/50 [==============================] - 0s 732us/step - loss: 1.1453 - accuracy: 0.5808
Epoch 16/20
50/50 [==============================] - 0s 799us/step - loss: 1.1251 - accuracy: 0.5852
Epoch 17/20
50/50 [==============================] - 0s 805us/step - loss: 1.1047 - accuracy: 0.5886
Epoch 18/20
50/50 [==============================] - 0s 864us/step - loss: 1.0874 - accuracy: 0.5915
Epoch 19/20
50/50 [==============================] - 0s 830us/step - loss: 1.0716 - accuracy: 0.5944
Epoch 20/20
50/50 [==============================] - 0s 728us/step - loss: 1.0567 - accuracy: 0.5975
<keras.callbacks.History at 0x7fc80293a920>
net.evaluate(XX,yy)
313/313 [==============================] - 0s 675us/step - loss: 1.0963 - accuracy: 0.5930
[1.0962964296340942, 0.5929999947547913]

- 시도2: 더 깊은 신경망

gv('''
splines=line
subgraph cluster_1{
    style=filled;
    color=lightgrey;
    "x1"
    "x2"
    ".."
    "x784"
    label = "Layer 0"
}
subgraph cluster_2{
    style=filled;
    color=lightgrey;
    "x1" -> "node1"
    "x2" -> "node1"
    ".." -> "node1"
    
    "x784" -> "node1"
    "x1" -> "node2"
    "x2" -> "node2"
    ".." -> "node2"
    "x784" -> "node2"
    
    "x1" -> "..."
    "x2" -> "..."
    ".." -> "..."
    "x784" -> "..."

    "x1" -> "node500"
    "x2" -> "node500"
    ".." -> "node500"
    "x784" -> "node500"


    label = "Layer 1: relu"
}

subgraph cluster_3{
    style=filled;
    color=lightgrey;

    "node1" -> "node1(2)"
    "node2" -> "node1(2)"
    "..." -> "node1(2)"
    "node500" -> "node1(2)"

    "node1" -> "node2(2)"
    "node2" -> "node2(2)"
    "..." -> "node2(2)"
    "node500" -> "node2(2)"
    
    "node1" -> "...."
    "node2" -> "...."
    "..." -> "...."
    "node500" -> "...."
    
    "node1" -> "node500(2)"
    "node2" -> "node500(2)"
    "..." -> "node500(2)"
    "node500" -> "node500(2)"

    
    label = "Layer 2: relu"
}

subgraph cluster_4{
    style=filled;
    color=lightgrey;

    "node1(2)" -> "y10"
    "node2(2)" -> "y10"
    "...." -> "y10"
    "node500(2)" -> "y10"
    
    "node1(2)" -> "y1"
    "node2(2)" -> "y1"
    "...." -> "y1"
    "node500(2)" -> "y1"
    
    "node1(2)" -> "."
    "node2(2)" -> "."
    "...." -> "."
    "node500(2)" -> "."
    
    label = "Layer 3: softmax"
}
''')
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> G cluster_1 Layer 0 cluster_2 Layer 1: relu cluster_3 Layer 2: relu cluster_4 Layer 3: softmax x1 x1 node1 node1 x1->node1 node2 node2 x1->node2 ... ... x1->... node500 node500 x1->node500 x2 x2 x2->node1 x2->node2 x2->... x2->node500 .. .. ..->node1 ..->node2 ..->... ..->node500 x784 x784 x784->node1 x784->node2 x784->... x784->node500 node1(2) node1(2) node1->node1(2) node2(2) node2(2) node1->node2(2) .... .... node1->.... node500(2) node500(2) node1->node500(2) node2->node1(2) node2->node2(2) node2->.... node2->node500(2) ...->node1(2) ...->node2(2) ...->.... ...->node500(2) node500->node1(2) node500->node2(2) node500->.... node500->node500(2) y10 y10 node1(2)->y10 y1 y1 node1(2)->y1 . . node1(2)->. node2(2)->y10 node2(2)->y1 node2(2)->. ....->y10 ....->y1 ....->. node500(2)->y10 node500(2)->y1 node500(2)->.
tf.random.set_seed(43052)
net = tf.keras.Sequential()
net.add(tf.keras.layers.Dense(500,activation='relu'))
net.add(tf.keras.layers.Dense(500,activation='relu'))
net.add(tf.keras.layers.Dense(10,activation='softmax'))
net.compile(optimizer='adam',loss=tf.losses.categorical_crossentropy,metrics=['accuracy'])
net.fit(X,y,epochs=50,batch_size=1200)

Epoch 1/50
50/50 [==============================] - 0s 1ms/step - loss: 21.6114 - accuracy: 0.6873
Epoch 2/50
50/50 [==============================] - 0s 985us/step - loss: 1.9374 - accuracy: 0.8032
Epoch 3/50
50/50 [==============================] - 0s 948us/step - loss: 1.2284 - accuracy: 0.8216
Epoch 4/50
50/50 [==============================] - 0s 959us/step - loss: 0.9360 - accuracy: 0.8339
Epoch 5/50
50/50 [==============================] - 0s 1ms/step - loss: 0.7526 - accuracy: 0.8436
Epoch 6/50
50/50 [==============================] - 0s 986us/step - loss: 0.6205 - accuracy: 0.8538
Epoch 7/50
50/50 [==============================] - 0s 973us/step - loss: 0.5437 - accuracy: 0.8615
Epoch 8/50
50/50 [==============================] - 0s 984us/step - loss: 0.5181 - accuracy: 0.8644
Epoch 9/50
50/50 [==============================] - 0s 918us/step - loss: 0.4379 - accuracy: 0.8750
Epoch 10/50
50/50 [==============================] - 0s 948us/step - loss: 0.3880 - accuracy: 0.8852
Epoch 11/50
50/50 [==============================] - 0s 992us/step - loss: 0.3627 - accuracy: 0.8872
Epoch 12/50
50/50 [==============================] - 0s 917us/step - loss: 0.3536 - accuracy: 0.8899
Epoch 13/50
50/50 [==============================] - 0s 920us/step - loss: 0.3106 - accuracy: 0.9006
Epoch 14/50
50/50 [==============================] - 0s 939us/step - loss: 0.3013 - accuracy: 0.8997
Epoch 15/50
50/50 [==============================] - 0s 945us/step - loss: 0.2864 - accuracy: 0.9043
Epoch 16/50
50/50 [==============================] - 0s 998us/step - loss: 0.2813 - accuracy: 0.9067
Epoch 17/50
50/50 [==============================] - 0s 950us/step - loss: 0.2551 - accuracy: 0.9124
Epoch 18/50
50/50 [==============================] - 0s 920us/step - loss: 0.2427 - accuracy: 0.9155
Epoch 19/50
50/50 [==============================] - 0s 992us/step - loss: 0.2200 - accuracy: 0.9227
Epoch 20/50
50/50 [==============================] - 0s 931us/step - loss: 0.2154 - accuracy: 0.9240
Epoch 21/50
50/50 [==============================] - 0s 954us/step - loss: 0.2073 - accuracy: 0.9267
Epoch 22/50
50/50 [==============================] - 0s 932us/step - loss: 0.1962 - accuracy: 0.9300
Epoch 23/50
50/50 [==============================] - 0s 1ms/step - loss: 0.2138 - accuracy: 0.9255
Epoch 24/50
50/50 [==============================] - 0s 934us/step - loss: 0.1958 - accuracy: 0.9303
Epoch 25/50
50/50 [==============================] - 0s 1ms/step - loss: 0.1906 - accuracy: 0.9326
Epoch 26/50
50/50 [==============================] - 0s 1ms/step - loss: 0.1725 - accuracy: 0.9372
Epoch 27/50
50/50 [==============================] - 0s 981us/step - loss: 0.1792 - accuracy: 0.9355
Epoch 28/50
50/50 [==============================] - 0s 957us/step - loss: 0.1658 - accuracy: 0.9400
Epoch 29/50
50/50 [==============================] - 0s 978us/step - loss: 0.1527 - accuracy: 0.9444
Epoch 30/50
50/50 [==============================] - 0s 931us/step - loss: 0.1600 - accuracy: 0.9418
Epoch 31/50
50/50 [==============================] - 0s 1ms/step - loss: 0.1428 - accuracy: 0.9473
Epoch 32/50
50/50 [==============================] - 0s 924us/step - loss: 0.1442 - accuracy: 0.9466
Epoch 33/50
50/50 [==============================] - 0s 948us/step - loss: 0.1478 - accuracy: 0.9452
Epoch 34/50
50/50 [==============================] - 0s 998us/step - loss: 0.1489 - accuracy: 0.9457
Epoch 35/50
50/50 [==============================] - 0s 1ms/step - loss: 0.1353 - accuracy: 0.9502
Epoch 36/50
50/50 [==============================] - 0s 953us/step - loss: 0.1290 - accuracy: 0.9526
Epoch 37/50
50/50 [==============================] - 0s 1ms/step - loss: 0.1279 - accuracy: 0.9530
Epoch 38/50
50/50 [==============================] - 0s 932us/step - loss: 0.1202 - accuracy: 0.9556
Epoch 39/50
50/50 [==============================] - 0s 953us/step - loss: 0.1151 - accuracy: 0.9571
Epoch 40/50
50/50 [==============================] - 0s 977us/step - loss: 0.1089 - accuracy: 0.9601
Epoch 41/50
50/50 [==============================] - 0s 948us/step - loss: 0.1085 - accuracy: 0.9596
Epoch 42/50
50/50 [==============================] - 0s 963us/step - loss: 0.1139 - accuracy: 0.9583
Epoch 43/50
50/50 [==============================] - 0s 969us/step - loss: 0.1051 - accuracy: 0.9609
Epoch 44/50
50/50 [==============================] - 0s 1ms/step - loss: 0.1138 - accuracy: 0.9582
Epoch 45/50
50/50 [==============================] - 0s 961us/step - loss: 0.1255 - accuracy: 0.9532
Epoch 46/50
50/50 [==============================] - 0s 914us/step - loss: 0.1059 - accuracy: 0.9614
Epoch 47/50
50/50 [==============================] - 0s 947us/step - loss: 0.1127 - accuracy: 0.9583
Epoch 48/50
50/50 [==============================] - 0s 921us/step - loss: 0.1059 - accuracy: 0.9608
Epoch 49/50
50/50 [==============================] - 0s 935us/step - loss: 0.1201 - accuracy: 0.9572
Epoch 50/50
50/50 [==============================] - 0s 1ms/step - loss: 0.1042 - accuracy: 0.9622
<keras.callbacks.History at 0x7fc8014a3fa0>
net.evaluate(XX,yy)
313/313 [==============================] - 0s 697us/step - loss: 0.7534 - accuracy: 0.8623
[0.7533721923828125, 0.8622999787330627]

숙제

- 시도1,2에서 사용된 모형에서 각각 추정해야할 파라메터의 수를 구하고 비교하라.

hint: net.summary() 이용