728x90
반응형

Computer Vision Footprint

1998 - LeNet 5

 

2012 - AlexNet

- Gradient vanishin문제를 해결하는 ReLU를 사용 - LRN 사용 안했음

- Overlapping Pooling(영향력이 크진 않음)

- Dropout(Overfitting 방지)

 

2013 - ZFNet

- AlexNet을 Visualization통해 insight를 제공

- HyperParameter tuning 방법론 제시

- Network in Network

- 1x1 Convolution 도입 (1. 차원 조절 2. non-linear 특성 부여 3. fully connected 처럼 사용)

- Flatten 대신 사용하는 방법인 Global Average Pooling 도입

- 같은 형태를 반복하고 겹쳐서 사용하는 Stacking 도입

 

2014 - GoogLeNet v1 (1등)

- 1x1 convolution 활용

- Inception module stacking

- Global average pooling 활용

- VGG (2등)

 

2016 - GoogLeNet v4

GoogLeNet

ReLU와 같은 기법 덕에 Layer를 깊게 쌓을 수 있는 확신이 있었던 배경 때문에 Layer를 어떻게 깊게 쌓는지 여부가 중요한 포인트였다

GoogLeNet 특징

1. 1x1 convolution

- 차원 축소 효과

- nonlinearity 특징 부여

2. Inception module

- 9 inception module로 구성되어 있다

- Inception moddule은 Hebbian rule에 의해 영향력이 가장 부분이 연결성이 강화된다(weight가 커진다)

- 실제 구현에서는 차원을 조절하여 inception module을 적용하였다

3. Global average pooling

4. Auxiliary classifier

- relu로 gradient vanishing 문제를 해결한듯 했으나 layer가 기존에 8 layer였던것에 비해 22 layer로 급격하게 늘었기 때문에 gradient vanishing 가능성이 생겼다

- 따라서 네트워크 중간에 auxiliary classifier를 추가하여 중간 중간 결과를 낸다

Inception module

import tensorflow as tf 

(X_train, y_train), (X_test, y_test) = tf.keras.datasets.cifar10.load_data()

# Inception module, naive version
input_ = tf.keras.Input((32,32,3))
conv1x1 = tf.keras.layers.Conv2D(3,1, padding='same', name='1x1')(input_) 
conv3x3 = tf.keras.layers.Conv2D(3,3, padding='same', name='3x3')(input_) 
conv5x5 = tf.keras.layers.Conv2D(3,3, padding='same', name='5x5')(input_) 
maxpool = tf.keras.layers.MaxPool2D(3,1, padding='same', name='pool')(input_) # unoverlapping 
concatenate = tf.keras.layers.Concatenate()([conv1x1,conv3x3,conv5x5,maxpool]) # 합치기 위해서 구조를 맞추어야 한다 

model = tf.keras.models.Model(input_, concatenate)
model.summary()
# Model: "model_13"
# __________________________________________________________________________________________________
# Layer (type)                    Output Shape         Param #     Connected to                     
# ==================================================================================================
# input_24 (InputLayer)           [(None, 32, 32, 3)]  0                                            
# __________________________________________________________________________________________________
# 1x1 (Conv2D)                    (None, 32, 32, 3)    12          input_24[0][0]                   
# __________________________________________________________________________________________________
# 3x3 (Conv2D)                    (None, 32, 32, 3)    84          input_24[0][0]                   
# __________________________________________________________________________________________________
# 5x5 (Conv2D)                    (None, 32, 32, 3)    84          input_24[0][0]                   
# __________________________________________________________________________________________________
# pool (MaxPooling2D)             (None, 32, 32, 3)    0           input_24[0][0]                   
# __________________________________________________________________________________________________
# concatenate_15 (Concatenate)    (None, 32, 32, 12)   0           1x1[0][0]                        
#                                                                  3x3[0][0]                        
#                                                                  5x5[0][0]                        
#                                                                  pool[0][0]                       
# ==================================================================================================
# Total params: 180
# Trainable params: 180
# Non-trainable params: 0
# __________________________________________________________________________________________________
tf.keras.utils.plot_model(model, show_shapes=True)

 

 

# Inception module with dimension reductions
input_ = tf.keras.Input((32,32,3))
conv1x1 = tf.keras.layers.Conv2D(3,1, padding='same', name='1x1')(input_) 
conv1x1_reduc3x3 = tf.keras.layers.Conv2D(2,1, padding='same', name='1x1_3x3')(input_) 
conv3x3 = tf.keras.layers.Conv2D(2,3, padding='same', name='3x3')(conv1x1_reduc3x3) 
conv1x1_reduc5x5 = tf.keras.layers.Conv2D(2,1, padding='same', name='1x1_5x5')(input_) 
conv5x5 = tf.keras.layers.Conv2D(2,3, padding='same', name='5x5')(conv1x1_reduc5x5) 
maxpool = tf.keras.layers.MaxPool2D(2,1, padding='same', name='pool')(input_) 
conv1x1_reduc_mp = tf.keras.layers.Conv2D(2,1, padding='same', name='1x1_pool')(maxpool) 
concatenate = tf.keras.layers.Concatenate(axis=-1)([conv1x1,conv3x3,conv5x5,conv1x1_reduc_mp]) # 합치기 위해서 구조를 맞추어야 한다 
# concatenate = tf.keras.layers.Concatenate([conv1x1,conv3x3,conv5x5,conv1x1_reduc_mp]) # 옵션을 주지 않을때 

model = tf.keras.models.Model(input_, concatenate)
model.summary()
# Model: "model_14"
# __________________________________________________________________________________________________
# Layer (type)                    Output Shape         Param #     Connected to                     
# ==================================================================================================
# input_25 (InputLayer)           [(None, 32, 32, 3)]  0                                            
# __________________________________________________________________________________________________
# 1x1_3x3 (Conv2D)                (None, 32, 32, 2)    8           input_25[0][0]                   
# __________________________________________________________________________________________________
# 1x1_5x5 (Conv2D)                (None, 32, 32, 2)    8           input_25[0][0]                   
# __________________________________________________________________________________________________
# pool (MaxPooling2D)             (None, 32, 32, 3)    0           input_25[0][0]                   
# __________________________________________________________________________________________________
# 1x1 (Conv2D)                    (None, 32, 32, 3)    12          input_25[0][0]                   
# __________________________________________________________________________________________________
# 3x3 (Conv2D)                    (None, 32, 32, 2)    38          1x1_3x3[0][0]                    
# __________________________________________________________________________________________________
# 5x5 (Conv2D)                    (None, 32, 32, 2)    38          1x1_5x5[0][0]                    
# __________________________________________________________________________________________________
# 1x1_pool (Conv2D)               (None, 32, 32, 2)    8           pool[0][0]                       
# __________________________________________________________________________________________________
# concatenate_16 (Concatenate)    (None, 32, 32, 9)    0           1x1[0][0]                        
#                                                                  3x3[0][0]                        
#                                                                  5x5[0][0]                        
#                                                                  1x1_pool[0][0]                   
# ==================================================================================================
# Total params: 112
# Trainable params: 112
# Non-trainable params: 0
# __________________________________________________________________________________________________
tf.keras.utils.plot_model(model, show_shapes=True, rankdir="BT", show_dtype=True) # wide하게 분포되어 있기 때문에 parameter operator가 엄청 많다 / 이중에서 영향력 있는 것만 강한 연결성을 띄게 된다

in3 = tf.keras.applications.InceptionV3()

tf.keras.utils.plot_model(in3)

Visual Geometry Group

Very Deep Convolutional Networks for large-scale image recognition

Layer가 깊어지면 깊어질 수 록 성능이 좋아진다

Abliation study 방식으로 모델 성능을 비교한다

 

1. AlexNet vs AlexNet + LRN

- LRN 기법은 성능 개선은 없고 메모리 사용량 및 연산 시간만 늘어났기에 사용을 하지 않는다

2. AlexNet vs AlexNet + conv layer 2개 추가

- 성능 좋아짐

3. AlexNet + conv layer 2개 vs AlexNet + conv layer 2개 + 1x1 convolution 3개

- Nonlinearity만 추가 시켜 성능향상을 하는지 확인 => activation이 더 많아서 성능 더 좋아짐 (UAT)

4. AlexNet + conv layer 2개 + 1x1 convolution 3개 vs AlexNet + conv layer 5개

- 성능 좋아짐

5. AlexNet + conv layer 5개 vs AlexNet + conv layer 8개

- 성능 좋아짐

결국 Layer가 늘어나면 늘어날 수록 성능이 좋아졌다

 

 

 

model을 불러와 사용하는 두 가지 방식

1. applications => Computer vision 분야에서 지원되는 모델을 지원한다

2. tensorflow hub

import tensorflow as tf 

vgg16 = tf.keras.applications.VGG16() # ImageNet 대회서 2등, 학습된 모델을 그대로 사용할 수 있다  

vgg16.summary()
# Model: "vgg16"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# input_2 (InputLayer)         [(None, 224, 224, 3)]     0         
# _________________________________________________________________
# block1_conv1 (Conv2D)        (None, 224, 224, 64)      1792      
# _________________________________________________________________
# block1_conv2 (Conv2D)        (None, 224, 224, 64)      36928     
# _________________________________________________________________
# block1_pool (MaxPooling2D)   (None, 112, 112, 64)      0         
# _________________________________________________________________
# block2_conv1 (Conv2D)        (None, 112, 112, 128)     73856     
# _________________________________________________________________
# block2_conv2 (Conv2D)        (None, 112, 112, 128)     147584    
# _________________________________________________________________
# block2_pool (MaxPooling2D)   (None, 56, 56, 128)       0         
# _________________________________________________________________
# block3_conv1 (Conv2D)        (None, 56, 56, 256)       295168    
# _________________________________________________________________
# block3_conv2 (Conv2D)        (None, 56, 56, 256)       590080    
# _________________________________________________________________
# block3_conv3 (Conv2D)        (None, 56, 56, 256)       590080    
# _________________________________________________________________
# block3_pool (MaxPooling2D)   (None, 28, 28, 256)       0         
# _________________________________________________________________
# block4_conv1 (Conv2D)        (None, 28, 28, 512)       1180160   
# _________________________________________________________________
# block4_conv2 (Conv2D)        (None, 28, 28, 512)       2359808   
# _________________________________________________________________
# block4_conv3 (Conv2D)        (None, 28, 28, 512)       2359808   
# _________________________________________________________________
# block4_pool (MaxPooling2D)   (None, 14, 14, 512)       0         
# _________________________________________________________________
# block5_conv1 (Conv2D)        (None, 14, 14, 512)       2359808   
# _________________________________________________________________
# block5_conv2 (Conv2D)        (None, 14, 14, 512)       2359808   
# _________________________________________________________________
# block5_conv3 (Conv2D)        (None, 14, 14, 512)       2359808   
# _________________________________________________________________
# block5_pool (MaxPooling2D)   (None, 7, 7, 512)         0         
# _________________________________________________________________
# flatten (Flatten)            (None, 25088)             0         
# _________________________________________________________________
# fc1 (Dense)                  (None, 4096)              102764544 
# _________________________________________________________________
# fc2 (Dense)                  (None, 4096)              16781312  
# _________________________________________________________________
# predictions (Dense)          (None, 1000)              4097000   
# =================================================================
# Total params: 138,357,544
# Trainable params: 138,357,544
# Non-trainable params: 0
# _________________________________________________________________
vgg16.weights

vgg16.__class__
# keras.engine.functional.Functional

3x3을 쓰는 이유

(X_train, y_train), (X_test, y_test) = tf.keras.datasets.cifar10.load_data()

input_ = tf.keras.Input((32,32,3))
x = tf.keras.layers.Conv2D(2,5)(input_) # filter 2개 5x5 
model = tf.keras.models.Model(input_, x)

model.summary()
# Model: "model"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# input_4 (InputLayer)         [(None, 32, 32, 3)]       0         
# _________________________________________________________________
# conv2d (Conv2D)              (None, 28, 28, 2)         152       
# =================================================================
# Total params: 152
# Trainable params: 152
# Non-trainable params: 0
# _________________________________________________________________
input_ = tf.keras.Input((32,32,3))
x = tf.keras.layers.Conv2D(2,3)(input_) 
x = tf.keras.layers.Conv2D(2,3)(x) 
model = tf.keras.models.Model(input_, x)

model.summary() # 3x3이 더 좋다 / 5x5일 때와 shape은 같지만 activation을 여러개 사용했고 파라미터 수가 줄어들었기 때문에 성능이 더 좋아졌다 
# Model: "model_15"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# input_27 (InputLayer)        [(None, 32, 32, 3)]       0         
# _________________________________________________________________
# conv2d_221 (Conv2D)          (None, 30, 30, 2)         56        
# _________________________________________________________________
# conv2d_222 (Conv2D)          (None, 28, 28, 2)         38        
# =================================================================
# Total params: 94
# Trainable params: 94
# Non-trainable params: 0
# _________________________________________________________________
input_ = tf.keras.Input((32,32,3))
x = tf.keras.layers.Conv2D(2,3)(input_) 
x = tf.keras.layers.Conv2D(2,3)(x)
x = tf.keras.layers.Conv2D(2,3)(x) 
model = tf.keras.models.Model(input_, x)

model.summary() # 3x3으로 더 큰 receptive field를 대체 할 수 있다 

# Model: "model_24"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# input_36 (InputLayer)        [(None, 32, 32, 3)]       0         
# _________________________________________________________________
# conv2d_243 (Conv2D)          (None, 30, 30, 2)         56        
# _________________________________________________________________
# conv2d_244 (Conv2D)          (None, 28, 28, 2)         38        
# _________________________________________________________________
# conv2d_245 (Conv2D)          (None, 26, 26, 2)         38        
# =================================================================
# Total params: 132
# Trainable params: 132
# Non-trainable params: 0
# _________________________________________________________________

보통 첫번째 layer는 5x5 또는 7x7 filter를 사용하고

(처음부터 3x3을 사용하면 메모리를 너무 많이차지 하기 때문에 오히려 성능 저하가 될 수 있다)

그 다음 layer 부터는 3x3을 사용하면 성능이 좋다

Deep Residual Learning for Image Recognition

ResNet은 인간을 뛰어넘은 첫번째 모델
Residual => 실제값 - 예측값 (잔차)

layer가 56개로 깊어지면서 gradient vanishing문제가 다시 떠오르기 시작했다

(relu로 해결되지 못하는 문제가 발생) underfitting

처음에 학습했던 것들을 점차 잊게되면서 목표로 부터 멀어지게 되는 현상이 생겼다

그래서 해결책으로 Short cut 즉, residual block을 도입하게 되었다

 

LSTM에서 아이디어를 얻어 자신의 값을 더함으로써 값을 유지시키고 목표를 잃지 않고 지속적으로 학습하게 된다

 

기존의 신경망은 입력값 x를 타겟값 y로 매핑하는 함수 H(x)를 얻는 것이 목적이었다.

그러나 ResNet은 F(x) + x를 최소화하는 것을 목적으로 한다.

x는 현시점에서 변할 수 없는 값이므로 F(x)를 0에 가깝게 만드는 것이 목적이 된다.

F(x)가 0이 되면 출력과 입력이 모두 x로 같아지게 된다.

F(x) = H(x) - x이므로 F(x)를 최소로 해준다는 것은 H(x) - x를 최소로 해주는 것과 동일한 의미를 지닌다.

여기서 H(x) - x를 잔차(residual)라고 한다.

즉, 잔차를 최소로 해주는 것이므로 ResNet이란 이름이 붙게 된다.

 

Batch Normalization 사용 => underfitting을 막아주면서 dropout을 사용하지 않고 좋은 성능을 얻게 되었다

vgg19와 34-layer plain을 비교했을 때 34-layer는 가장 앞 layer에서 7x7 filter를 적용했고 레이어 수를 두 배 가까이 늘렸다

그리고 맨마지막에 flatten을 쓰지 않고 average pooling을 사용했더니 34-layer가 성능이 더 좋았다

더 나아가 34-layer에서 residual block을 추가한 결과 추가하지 않은 것보다 오차율이 감소한 것을 확인할 수 있었다

Residual block과 Batch Normalization의 조합으로 훨씬 더 깊은 layer가 가능해졌다

결국 총 152 layer를 쌓을 수 있게 되었다

반응형
728x90
반응형

Visualizing and Understanding Convolutional Networks

CNN을 제대로 이해하기 위한 논문
CNN을 시각화 하여 왜 성능이 향상되었는지를 탐구하는 논문
과거의 관점으로 AlexNet에 대한 '통찰'과 '진단'을 제공한다

Convolutional layer를 통과하고나서 Max pooling을 거칠때 가장 영향력 있는 값들로 축약되기 때문에 큰 특징만 남게 된다

따라서 반대로 pooling을 거치기 전으로 복원시킨다면 큰 특징만 남아 있기 때문에 Detail한 특징들은 사라지게 될 것이다

AlexNet의 네트워크 구조대로 통과시킨 데이터들을 레이어 별로 복원시키게 되면

가장 중요한 특징들만 남도록 복원된다는 것을 시각적으로 확인 있다

 

시각화된 결과를 보면 AlexNet의 구조는 처음 레이어에서 간단한 특징들을 뽑아내다가

레이어가 깊어지면 깊어질 수록 '복잡한 특징' 구분할 있도록 학습이 되는 것을 있다

기존 AlexNet의 첫번째 Layer에서 filter 11x11, stride 4를 filter 7x7, stride 2로 바꾸었다

두번째 layer에서는 stride 1, zero-padding 2에서 stride 2로 바꾸었다

=> 기존에는 filter가 컸기 때문에 작은 것들의 특징을 잘 못잡는다는 문제가 있었다

 

결과 => 파라미터가 줄어들었고, 좀 더 디테일한 특징을 알아낼 수 있도록 학습하게되었다

receptive field를 대신할 수 있다 @@@ 의미 확인

일부분을 가림으로써 어떤 부분이 가장 영향력이 있는지를 확률적으로 계산하였다 (abliation study)

특정 부분을 가렸을 때 가장 성능이 안좋다면 그 부분은 가장 영향력이 있는 부분인 것이다 (파란색 부분이 가장 영향력 있는 부분)

a와 c는 AlexNet b와 d는 ZFNet

 

Layer 1

a 그림에서는 dead feature가 꽤 있고 좀 더 흐릿하게 구분된 반면

c 그림에서는 dead feature가 굉장히 많이 줄고 특징이 좀 더 선명하게 구분되었다

filter사이즈와 stride를 줄임으로써 좀 더 특징을 잘 구분할 수 있게 학습이되었다고 할 수 있다

 

Layer 2

c 그림에서 보면 빈 공간이 많고 aliasing(계단현상)이 발견된 반면

d 그림에서는 빈 공간이 적고 특징이 더 선명하게 잘 구분되도록 학습이 되었다

Network In Network

네트워크 안에 네트워크를 넣는 방식
convolution layer사이에 mlp가 있다 (사실상 1x1 convolution을 사용한 것)

Flatten의 문제

import tensorflow as tf 

(X_train, y_train), (X_test, y_test) = tf.keras.datasets.mnist.load_data()

X_train = X_train.reshape(-1,28,28,1)/255

# AlexNet
 
input_ = tf.keras.Input((224,224,3))
x = tf.keras.layers.Conv2D(96,11,4)(input_)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Conv2D(256, 5, padding='same')(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.MaxPool2D(3,2)(x)
x = tf.keras.layers.Conv2D(384,3)(x) 
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.MaxPool2D(3,2)(x)
x = tf.keras.layers.Conv2D(384,3)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Conv2D(256, 3)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.MaxPool2D(3,2)(x)
x = tf.keras.layers.Flatten()(x) # 일렬로 만들어 지기 때문에 위치 정보를 잃고 학습할 weight가 많이 생긴다 (FC만 썼을때 위치정보를 잃는다)
x = tf.keras.layers.Dense(4096)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Dropout(0.5)(x)
x = tf.keras.layers.Dense(4096, kernel_initializer=tf.keras.initializers.Constant(1))(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Dropout(0.5)(x)
x = tf.keras.layers.Dense(1000, activation='softmax')(x)

model = tf.keras.models.Model(input_,x)
model.summary()

# Model: "model_1"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# input_2 (InputLayer)         [(None, 224, 224, 3)]     0         
# _________________________________________________________________
# conv2d_5 (Conv2D)            (None, 54, 54, 96)        34944     
# _________________________________________________________________
# re_lu_6 (ReLU)               (None, 54, 54, 96)        0         
# _________________________________________________________________
# conv2d_6 (Conv2D)            (None, 54, 54, 256)       614656    
# _________________________________________________________________
# re_lu_7 (ReLU)               (None, 54, 54, 256)       0         
# _________________________________________________________________
# max_pooling2d_2 (MaxPooling2 (None, 26, 26, 256)       0         
# _________________________________________________________________
# conv2d_7 (Conv2D)            (None, 24, 24, 384)       885120    
# _________________________________________________________________
# re_lu_8 (ReLU)               (None, 24, 24, 384)       0         
# _________________________________________________________________
# max_pooling2d_3 (MaxPooling2 (None, 11, 11, 384)       0         
# _________________________________________________________________
# conv2d_8 (Conv2D)            (None, 9, 9, 384)         1327488   
# _________________________________________________________________
# re_lu_9 (ReLU)               (None, 9, 9, 384)         0         
# _________________________________________________________________
# conv2d_9 (Conv2D)            (None, 7, 7, 256)         884992    
# _________________________________________________________________
# re_lu_10 (ReLU)              (None, 7, 7, 256)         0         
# _________________________________________________________________
# max_pooling2d_4 (MaxPooling2 (None, 3, 3, 256)         0         
# _________________________________________________________________
# flatten_1 (Flatten)          (None, 2304)              0         
# _________________________________________________________________
# dense_3 (Dense)              (None, 4096)              9441280   
# _________________________________________________________________
# re_lu_11 (ReLU)              (None, 4096)              0         
# _________________________________________________________________
# dropout_2 (Dropout)          (None, 4096)              0         
# _________________________________________________________________
# dense_4 (Dense)              (None, 4096)              16781312  
# _________________________________________________________________
# re_lu_12 (ReLU)              (None, 4096)              0         
# _________________________________________________________________
# dropout_3 (Dropout)          (None, 4096)              0         
# _________________________________________________________________
# dense_5 (Dense)              (None, 1000)              4097000   
# =================================================================
# Total params: 34,066,792
# Trainable params: 34,066,792
# Non-trainable params: 0
# _________________________________________________________________

 

 

# AlexNet Flatten x / Global average pooling 
 
input_ = tf.keras.Input((224,224,3))
x = tf.keras.layers.Conv2D(96,11,4)(input_)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Conv2D(256, 5, padding='same')(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.MaxPool2D(3,2)(x)
x = tf.keras.layers.Conv2D(384,3)(x) 
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.MaxPool2D(3,2)(x)
x = tf.keras.layers.Conv2D(384,3)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Conv2D(256, 3)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.MaxPool2D(3,2)(x)
x = tf.keras.layers.Conv2D(1000, 3)(x) # 1x1 convolution 
x = tf.keras.layers.GlobalAveragePooling2D()(x) # 1차원으로  바뀌었기 때문에 Flatten과 똑같다. 하지만 Flatten보다 Parameter를 훨씬 줄일 수 있다 
x = tf.keras.layers.Dense(1000)(x)

model = tf.keras.models.Model(input_,x)
model.summary()

# Model: "model_6"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# input_8 (InputLayer)         [(None, 224, 224, 3)]     0         
# _________________________________________________________________
# conv2d_35 (Conv2D)           (None, 54, 54, 96)        34944     
# _________________________________________________________________
# re_lu_42 (ReLU)              (None, 54, 54, 96)        0         
# _________________________________________________________________
# conv2d_36 (Conv2D)           (None, 54, 54, 256)       614656    
# _________________________________________________________________
# re_lu_43 (ReLU)              (None, 54, 54, 256)       0         
# _________________________________________________________________
# max_pooling2d_20 (MaxPooling (None, 26, 26, 256)       0         
# _________________________________________________________________
# conv2d_37 (Conv2D)           (None, 24, 24, 384)       885120    
# _________________________________________________________________
# re_lu_44 (ReLU)              (None, 24, 24, 384)       0         
# _________________________________________________________________
# max_pooling2d_21 (MaxPooling (None, 11, 11, 384)       0         
# _________________________________________________________________
# conv2d_38 (Conv2D)           (None, 9, 9, 384)         1327488   
# _________________________________________________________________
# re_lu_45 (ReLU)              (None, 9, 9, 384)         0         
# _________________________________________________________________
# conv2d_39 (Conv2D)           (None, 7, 7, 256)         884992    
# _________________________________________________________________
# re_lu_46 (ReLU)              (None, 7, 7, 256)         0         
# _________________________________________________________________
# max_pooling2d_22 (MaxPooling (None, 3, 3, 256)         0         
# _________________________________________________________________
# conv2d_40 (Conv2D)           (None, 1, 1, 1000)        2305000   
# _________________________________________________________________
# global_average_pooling2d_2 ( (None, 1000)              0         
# _________________________________________________________________
# dense_13 (Dense)             (None, 1000)              1001000   
# =================================================================
# Total params: 7,053,200
# Trainable params: 7,053,200
# Non-trainable params: 0
# _________________________________________________________________

Flatten vs Global Average Pooling

Flatten은 원본 데이터 그대로 1차원으로 변화 시키지만 GAP은 최종결과에서 평균을 내어 하나의 값으로 바꾸고 그 형태가 1차원으로 변화된다

GAP는 전체 값 중에서 noise나 outlier등 학습이 안된 것들을 뭉뚱그리기 때문에 오히려 성능이 향상 되는 경우가 있다

 

GAP는 전체를 반영하기 때문에 Flatten한 것 보다 값을 더 잘 반영 하는 경우가 있지만

weight가 줄어들기 때문에 하나의 관점보다 여러개의 관점으로 파악하는 경우가 성능이 좋은 경우가 있을 수 있다

따라서 경우에 따라서 결정해야 할 문제이다

Hyperparameter처럼 데이터에 따라서 직접 정해줘야 한다

Grouped Convolution

Grouped Convolution은 입력 값의 채널들을 여러 개의 그룹으로 나누어 독립적으로 Convolution 연산을 수행하는 방식이다.

모델이 복잡할때 parameter를 줄이기 위해서 사용하는 경우가 있다

1x1 Convolution

Point-wise Convolution

1. 1x1의 depth에 따라서 차원이 바뀐다

2. Non-linear 특징을 부여한다

3. Fully connected 처럼 사용한다

GoogLeNet

1. Network in Network (1x1 convolution)

2. Stacking

3. Global average pooling

 

GoogLeNet은 3가지 내용을 참고하여 만들어졌다

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형
728x90
반응형

논문 구현

import tensorflow as tf 

input_ = tf.keras.Input(shape=(32,32,1))
x = tf.keras.layers.Conv2D(6, 5, activation='tanh')(input_) # filter 개수, filter 크기 / stride는 생략되었기 때문에 1이라 가정한다 / padding: valid
x = tf.keras.layers.AvgPool2D(2)(x) # 기본적으로 non-overlapping 방식이다 
x = tf.keras.layers.Conv2D(16, 5, activation='tanh')(x)
x = tf.keras.layers.MaxPool2D(6, 5)(x)
x = tf.keras.layers.Flatten()(x)
x = tf.keras.layers.Dense(120, activation='tanh')(x)
x = tf.keras.layers.Dense(84, activation='tanh')(x)
x = tf.keras.layers.Dense(10, activation='softmax')(x)

model = tf.keras.models.Model(input_, x)
# pooling 사용했을 때 
model.summary()
# Model: "model_1"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# input_3 (InputLayer)         [(None, 32, 32, 1)]       0         
# _________________________________________________________________
# conv2d_1 (Conv2D)            (None, 28, 28, 6)         156       
# _________________________________________________________________
# average_pooling2d (AveragePo (None, 14, 14, 6)         0         
# _________________________________________________________________
# conv2d_2 (Conv2D)            (None, 10, 10, 16)        2416      
# _________________________________________________________________
# max_pooling2d (MaxPooling2D) (None, 1, 1, 16)          0         
# _________________________________________________________________
# flatten (Flatten)            (None, 16)                0         
# _________________________________________________________________
# dense (Dense)                (None, 120)               2040      
# _________________________________________________________________
# dense_1 (Dense)              (None, 84)                10164     
# _________________________________________________________________
# dense_2 (Dense)              (None, 10)                850       
# =================================================================
# Total params: 15,626
# Trainable params: 15,626
# Non-trainable params: 0
# _________________________________________________________________
# pooling 사용하지 않았을 때 
model.summary()

# Model: "model_3"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# input_5 (InputLayer)         [(None, 32, 32, 1)]       0         
# _________________________________________________________________
# conv2d_5 (Conv2D)            (None, 28, 28, 6)         156       
# _________________________________________________________________
# conv2d_6 (Conv2D)            (None, 24, 24, 16)        2416      
# _________________________________________________________________
# flatten_2 (Flatten)          (None, 9216)              0         
# _________________________________________________________________
# dense_6 (Dense)              (None, 120)               1106040   
# _________________________________________________________________
# dense_7 (Dense)              (None, 84)                10164     
# _________________________________________________________________
# dense_8 (Dense)              (None, 10)                850       
# =================================================================
# Total params: 1,119,626
# Trainable params: 1,119,626
# Non-trainable params: 0
# _________________________________________________________________

ImageNet Classification with Deep Convolutional Neural Networks

ImageNet LSVRC 대회에서 ImageNet 데이터를 사용한 CNN

Relu

ReLU는 Sigmoid와 tanh가 갖는 Gradient Vanishing 문제를 해결하기 위한 함수이다

ReLU는 sigmoid, tanh 함수보다 학습이 빠르고, 연산 비용이 적고, 구현이 매우 간단하다

Dying Relu

Dying relu는 모든 0이하의 입력에 대해서 미분 값이 0이 되어 가중치에 곱해지면서 해당 노드가 통째로 죽어버리는 현상을 말한다

이러한 단점을 보완한 reaky relu가 있다

Normalization

layer가 깊어질 수록 값의 범위가 매번 바뀌고 최소값으로 수렴이 안되는 underfitting이 발생한다

이런 경우를 방지하기 위해서 값의 범위를 일정하게 맞춰주는 방법이 바로 normalization이다

 

대표적인 정규화 방법 가지

1. Min-Max Normalization (최소-최대 정규화)

- 최소값은 0, 최대값은 1, 그리고 다른 값들은 0 1 사이의 값으로 변환하는 방식

- (data - MIN) / (MAX-MIN) 2. Z-Score Normalization (Z-점수 정규화)

- 평균은 0, 표준편차는 1 정규 분포를 그리도록 데이터의 분포를 바꾸는 방식

- 이상치(outlier) 문제를 피하는 데이터 정규화 전략-

- (data - 평균) / 표준편차

Pooling

1. overlapping pooling

- 겹쳐가며 pooling을 하는 방법

- 성능에 크게 영향을 미치는 방법은 아니다

2. non overlapping pooling

- 겹치지 않고 pooling을 하는 방법

pooling을 하는 이유

1. parameter 줄여주기 때문에 연산량을 줄여준다

2. invariance한 속성을 더해준다

Data augmentation

Overfitting을 줄이기 위한 방법으로써 이미지 데이터를 변형해서 학습 데이터의 수를 늘리는 방법이다

이미지 데이터를 좌우반전, 상하반전, 회전, 자르기 등을 하여 학습하지 않은 데이터를 대처할 수 있는 일반적인 모델을 만들어주는 데에 효과적인 방법이다

예시

 

Dropout

Dropout은 특정 확률로 hidden layer의 node 출력값을 0으로 설정하는 방법이다 이렇게 dropout된 node들은 foward, backward propagation에 관여를 하지 않는다 dropout이 사용된 NN는 입력이 주어질 때마다 달라진 신경망 구조를 거치게 되고 이는 노드간의 의존성을 약화시켜 가장 영향력 있는 노드의 연결성이 강화되는 방식으로 학습을 하게된다 따라서 성능은 비슷하지만 연산 복잡도를 줄이면서 overfitting 문제를 해결하는 방법이 될 수 있다 ※ Fully connected layer 다음에 Dropuout을 사용한다

Result

Ensemble기법을 사용하고 pre-trained 모델인 경우에 에러율이 더 낮았다

※ CNNs는 Boosting기법(Ensemble)을 사용한 방법

AlexNet

논문 구현

하드웨어 메모리가 부족하여 GPU 병렬 연산을 위해 CNN 구조를 절반으로 나누어 설계되었다

# 평균은 0, 표준분포는 0.01인 정규분포 값으로 가중치를 초기화 한다 
bias = tf.keras.initializers.Constant(1) # relu 때문에 초기화 값을 1로 지정한다 (음수가 들어가면 dying relu현상이 발생하기 때문)

input_ = tf.keras.Input((224,224,3))
x = tf.keras.layers.Conv2D(96,5,4)(input_)
x = tf.keras.layers.MaxPool2D(3,2)(x) # overlapping pooling
x = tf.keras.layers.Conv2D(256,3, padding='same', bias_initializer=bias)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.MaxPool2D(3,2)(x)
x = tf.keras.layers.Conv2D(384,3, padding='same', bias_initializer='ones')(x) # ones 단축키는 버전에따라 지원하지 않을 수 있다 -
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Conv2D(384,3, padding='same', bias_initializer=bias)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Conv2D(256,3, padding='same', bias_initializer=bias)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Flatten()(x)
x = tf.keras.layers.Dense(4096, bias_initializer=bias)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Dropout(0.5)(x)
x = tf.keras.layers.Dense(4096, bias_initializer=bias)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Dropout(0.5)(x)
x = tf.keras.layers.Dense(1000, bias_initializer=bias, activation='softmax')(x)
model = tf.keras.models.Model(input_,x) # tensorflow from_logit
model.summary()
# Model: "model_3"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# input_4 (InputLayer)         [(None, 224, 224, 3)]     0         
# _________________________________________________________________
# conv2d_15 (Conv2D)           (None, 55, 55, 96)        7296      
# _________________________________________________________________
# max_pooling2d_6 (MaxPooling2 (None, 27, 27, 96)        0         
# _________________________________________________________________
# conv2d_16 (Conv2D)           (None, 27, 27, 256)       221440    
# _________________________________________________________________
# re_lu_18 (ReLU)              (None, 27, 27, 256)       0         
# _________________________________________________________________
# max_pooling2d_7 (MaxPooling2 (None, 13, 13, 256)       0         
# _________________________________________________________________
# conv2d_17 (Conv2D)           (None, 13, 13, 384)       885120    
# _________________________________________________________________
# re_lu_19 (ReLU)              (None, 13, 13, 384)       0         
# _________________________________________________________________
# conv2d_18 (Conv2D)           (None, 13, 13, 384)       1327488   
# _________________________________________________________________
# re_lu_20 (ReLU)              (None, 13, 13, 384)       0         
# _________________________________________________________________
# conv2d_19 (Conv2D)           (None, 13, 13, 256)       884992    
# _________________________________________________________________
# re_lu_21 (ReLU)              (None, 13, 13, 256)       0         
# _________________________________________________________________
# flatten_3 (Flatten)          (None, 43264)             0         
# _________________________________________________________________
# dense_9 (Dense)              (None, 4096)              177213440 
# _________________________________________________________________
# re_lu_22 (ReLU)              (None, 4096)              0         
# _________________________________________________________________
# dropout_4 (Dropout)          (None, 4096)              0         
# _________________________________________________________________
# dense_10 (Dense)             (None, 4096)              16781312  
# _________________________________________________________________
# re_lu_23 (ReLU)              (None, 4096)              0         
# _________________________________________________________________
# dropout_5 (Dropout)          (None, 4096)              0         
# _________________________________________________________________
# dense_11 (Dense)             (None, 10)                40970     
# =================================================================
# Total params: 197,362,058
# Trainable params: 197,362,058
# Non-trainable params: 0
# _________________________________________________________________

Loss 3가지

loss function 사용하는 3가지 방법

1. 객체지향 => 옵션 사용 가능

2. 함수형 => 옵션 사용 가능하지만 parital을 사용해야 한다 (Higer order function)

3. 함수형 단축 => 옵션 사용 불가

 

label encoding 방식에 따라서 loss function 방식도 달라져야 한다

- one-hot encoding (Multi label 일때)

- sparse label encoding (Multi label 아닐때) => Sparse가 붙은 loss function 사용

model.compile(loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False))

tf.keras.utils.to_categorical # label에서 one-hot으로 바꿔준다
# <function tensorflow.python.keras.utils.np_utils.to_categorical(y, num_classes=None, dtype='float32')>

 

반응형

'Computer_Science > Visual Intelligence' 카테고리의 다른 글

20일차 - 논문 수업 (CNN)  (0) 2021.10.08
19일차 - 논문 수업 (CNN)  (0) 2021.10.08
17일차 - 논문 수업 (CNN)  (0) 2021.10.04
16일차 - 논문 수업 (CNN)  (0) 2021.10.04
15일차 - CNN  (0) 2021.10.04
728x90
반응형

Convolutional Neural Network

위 막대 그래프는 다양한 분류 방법의 테스트 셋에 대한 오류율 이다

[deslant]는 기울어진 데이터 셋을 기반으로 학습된 분류 모델이다

[dist]는 인위적으로 왜곡된 샘플이 추가된 학습 데이터를 사용한 모델이다

다른 알고리즘과 비교했을 때 성능이 가장 좋았고, 자

기 자신의 예전 모델과도 비교해서 가장 성능이 좋았다

(Boosted 된 LeNet-4가 성능이 가장 좋았다)

Bagging

Bagging은 샘플을 무작위로 여러 번 뽑아 각 모델을 학습시켜 결과를 평균내는 방법이다 (Ensemble 기법중 하나)

Bagging 복원 추출을 하고 전체 데이터에서 일부를 뽑아 모델을 학습시킨다

여러 모델중에서 평균을 내는 방법이기 때문에 편차를 줄여주고 Overfitting을 피할 수 있는 방법이다

일반적인 모델을 만드는 것에 강점이 있다

ex) random forest

Boosting

Boosting은 Bagging과 동일하게 전체 데이터에서 일부 데이터만 사용하고 복원 추출을 한다

두 방법의 차이점은 잘 못 분류한 데이터들이 있을 경우 가중치를 두고 모델을 점차 강화한다는 점이다

학습이 끝나면 나온 결과에따라 가중치가 재분배 된다

오답에 대해 높은 가중치를 부여하고, 정답에 대해 낮은 가중치를 부여하기 때문에 오답에 더욱 집중하여 학습을 하게 된다

Bagging보다 좀 더 맞추기 어려운 문제나 성능을 좋은 장점은 있지만 outlier에 취약한 단점을 지니고 있다

ex) XGBoost, AdaBoost, GradientBoost

Convolution 두 가지 관점

1. 미리 자르는 방식

2. 이동하여 자르는 방식 (좌상->우하)

이미지 데이터에 대해서 전통적인 NN보다 CNN이 더 좋은 이유

전통적인 NN에서 이미지 데이터를 2D에서 1D로 변형할 때 두 가지 문제가 발생한다

1. column이 많아지는 문제

2. Locality를 상실한다

그러나 CNN에서는 두 가지 문제를 해결할 수 있다

1. convolution filter를 거치는 것은 데이터의 차원을 줄이지않고 그대로 사용하기 때문에 column이 많이 늘어나지 않는다. 즉, 적은 column을 갖는다

2. convolution filter를 거치면 특징이 있는지 없는지 관한 데이터로 변형 되기 때문에 Locality를 잃지 않는다

NN은 오른쪽 사진이 사람이라는 것과 왼쪽 사진이 사람이 아니라는 것을 잘 구별은 하지만

사람의 얼굴 크기가 많이 달라진다거나 방향이 비틀어졌거나 다른 위치에 있으면 사람이더라도

사람이라고 구별을 잘 못하는 경우가 발생할 수 있다

 

반면 CNN은 오른쪽 사진이 사람이라는 것과 사람의 얼굴 크기가 다르거나, 위치가 다르거나 방향이 뒤틀려도 잘 구별한다

하지만 왼쪽 사진 처럼 사람의 특징이 부분 별로 나뉘어져 있어도 전체를 보고 판단하지 않기 때문에 사람이라고 구별하는 오류를 범할 수 있다

Locally connected neural network

Locally connected neural network는 전통적인 NN에서 특징들의 위치 데이터에 민감하여

다양한 경우의 이미지를 구별하지 못하는 문제점을 보완한 방법이다

(ex) 크기가 다르거나 뒤틀리거나 하는 이미지를 구별하지 못하는 문제)

가까운 노드 끼리만 연결된다

 

연산 복잡도도 줄어들고 상대적인 위치에 대한 정보를 보기 때문에

shared weight를 쓰지 않았기 때문에 같은 값이면 같은 특징이다라는 점을 활용하지 못한다

Convolutional neural network(s

hared-weight local)

CNN은 shared-weight를 사용하면서 locally connected neural network인 모델이다

shared-weight를 사용하기 때문에 같은 값이면 같은 특징이다라는 점을 활용할 수 있고,

locally connected하기 때문에 부분적인 특징을 보고 특징이 있는지 없는지 여부를 판단할 수 있다

(Locality를 잃지 않는다)

CNN의 가정

1. Stationarity of statistics

- 정상성

- 이미지에서의 정상성이란 이미지의 한 부분에 대한 통계가 다른 부분들과 동일하다는 가정을 한다

- 이미지에서 한 특징이 위치에 상관없이 여러 군데 존재할 수 있고 특정 부분에서 학습된 특징 파라미터를 이용해

다른 위치에서도 동일한 특징을 추출할 수 있다는 의미이다

2. Locality of pixel dependencies

- 이미지는 작은 특징들로 구성되어 있기 때문에 각 픽셀들의 종속성은 특징이 있는 작은 지역으로 한정된다.

- 이미지를 구성하는 특징들은 이미지 전체가 아닌 일부 지역에 근접한 픽셀들로만 구성되고

근접한 픽셀들끼리만 종속성을 가진다

위 그림에서 왼쪽의 경우와 오른쪽의 경우는 같은 것이라 판단할 수 있지만

가운데의 것도 같은 것이라고 판단할 수 있을까?

convolutional layer를 한 번만 통과했다면 다른 것이라 판단할 수 있지만

layer를 여러번 통과한다면 세 가지 경우 모두 같은 특성이라고 볼수 있게 된다

=> layer가 많으면 많을 수록 좋은 점

 

Type Markdown and LaTeX: 𝛼^2

import tensorflow as tf 
from sklearn.datasets import load_digits 
import matplotlib.pyplot as plt

tf.keras.layers.Dense 
tf.keras.layers.LocallyConnected2D # weight를 공유하지 않는다 / 애매하기 때문에 이것도 저것도 아닌 상황에서 성능이 좋을 수 있다 
tf.keras.layers.Conv2D
tf.keras.layers.MaxPool2D (tf.keras.layers.MaxPooling2D)
tf.keras.layers.AvgPool2D (tf.keras.layers.AveragePooling2D)

tf.keras.layers.Conv2D is tf.keras.layers.Convolution2D # 단축 표현 
# True

(X_train, y_train), (X_test, y_test) = tf.keras.datasets.mnist.load_data()
data = load_digits()

padding

import numpy as np 
import scipy 
from scipy.ndimage import convolve
from scipy.signal import convolve, convolve2d

a = np.array([-1,0,1])
b = np.arange(5)

convolve(a, b, 'valid') 
# array([-2, -2, -2])

convolve 연산 방법

-1, 0, 1 => 1, 0, -1 (상하,좌우 반전)

0 0 1 2 3 4 x 1 0 -1 곱, 합 => (0x1) + (0x0) + (1x-1) = -1

0 0 1 2 3 4 x 1 0 -1 곱, 합 => (0x1) + (1x0) + (2x-1) = -2

0 0 1 2 3 4 x 1 0 -1 곱, 합=> (1x1) + (2x0) + (3x-1) = -2

 

a = np.array([-1,0,1])
b = np.arange(4)
convolve(a, b, 'same') # zero padding을 사용한다 
# array([-1, -2, -2])

convolve 연산 방법

-1, 0, 1 => 1, 0, -1 (상하,좌우 반전)

0 0 1 2 3 x 1 0 -1 곱, 합 => (0x1) + (0x0) + (1x-1) = -1

0 0 1 2 3 x 1 0 -1 곱, 합 => (0x1) + (1x0) + (2x-1) = -2

0 0 1 2 3 x 1 0 -1 곱, 합 => (1x1) + (2x0) + (3x-1) = -2

 

a = np.array([-1,0,1])
b = np.arange(4)

convolve(a, b, 'full') 
# array([ 0, -1, -2, -2,  2,  3])

convolve 연산 방법

-1, 0, 1 => 1, 0, -1 (상하,좌우 반전)

# 하나라도 걸치면 연산 할 수 있도록 0을 추가한다

0 0 0 1 2 3 0 0 x 1 0 -1 곱, 합 => (0x1) + (0x0) + (0x-1) = 0

0 0 0 1 2 3 0 0 x 1 0 -1 곱, 합 => (0x1) + (0x0) + (1x-1) = -1

0 0 0 1 2 3 0 0 x 1 0 -1 곱, 합 => (0x1) + (1x0) + (2x-1) = -2

0 0 0 1 2 3 0 0 x 1 0 -1 곱, 합 => (1x1) + (2x0) + (3x-1) = -2

0 0 0 1 2 3 0 0 x 1 0 -1 곱, 합 => (2x1) + (3x0) + (0x-1) = 2

0 0 0 1 2 3 0 0 x 1 0 -1 곱, 합 => (3x1) + (0x0) + (0x-1) = 3 

a = np.array([[-1,0],[1,0]])
b = np.arange(9).reshape(3,3)

convolve2d(a,b,'full') # zero padding을 함으로써 값이 공평한 횟수로 연산된다 즉, 공평하게 특성을 검출할 수 있다 

# array([[ 0, -1, -2,  0],
#        [-3, -3, -3,  0],
#        [-3, -3, -3,  0],
#        [ 6,  7,  8,  0]])

convolve 연산 방법

-1, 0 => 0, 1 (상하,좌우 반전)

1, 0 0,-1

0 0 0 0 0

00 1 2 0 0 1 좌상에서 우하로 연산한다

0 3 4 5 0 x 0 -1

0 6 7 8 0

0 0 0 0 0

convolve2d(a,b,'valid')
# array([[-3, -3],
#        [-3, -3]])
convolve2d(a,b,'same')
# array([[-3, -3],
#        [-3, -3]])

Invariance vs Equivariance

Invariance: 불변성

- CNN은 invariance하다 (Translation에 대해서 invariance하다)

- 똑같은 특징이 있으면 위치와 상관없이 똑같은 값을 예측한다

- CNN은 Rotation, size, viewpoint, illumination에 대해서는 invariance하지 않다

(CNN은 회전되거나, 시점이다르거나, 사이즈가 다르거나 밝기가 다른 이미지는 예측할 수 없다)

 

Equivariance: 동일한

- input의 위치가 달라지면 output의 위치가 달라진다

- convolution 연산은 equivariance의 특징을 갖는다

CNN 모델이 범용적으로 쓰이려면 data augmentation이 필요하다

Pooling

pooling은 대표적인 값으로 줄이기 때문에 회전된 이미지도 같은 값으로 인식하는 경우가 발생할 수 있다

크기가 줄면서 정보의 손실이 발생할 수 있지만 invariance한 특성을 보장하기 때문에 오히려 성능이 늘어날 수 있다 (항상 그런건 아님)

Striving for Simplicity: The All Convolutional Net

stride를 크게하면 pooling 쓰지 않으면서 pooling을 한 것 같은 효과를 볼 수 있다

conv + pooling => stride를 크게 하여 conv하나로 만든다

pooling을 하는 것보다 연산복잡도가 줄어들기 때문에 성능은 유지하면서 학습 속도를 빠르게 할 수 있다는 장점이 있다

논문 LeNet-5 구현

input_ = tf.keras.Input(shape=(32,32,1))
x = tf.keras.layers.Conv2D(6, 5)(input_) # filter 개수, filter 크기 / stride는 생략되었기 때문에 1이라 가정한다 / padding: valid
x = tf.keras.layers.Activation('tanh')(x) # 그 당시 LeRU가 없었다 
model = tf.keras.models.Model(input_, x)

model.summary()
# Model: "model_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_2 (InputLayer)         [(None, 32, 32, 1)]       0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 28, 28, 6)         156       
_________________________________________________________________
activation_1 (Activation)    (None, 28, 28, 6)         0         
=================================================================
Total params: 156
Trainable params: 156
Non-trainable params: 0
_________________________________________________________________

 

반응형

'Computer_Science > Visual Intelligence' 카테고리의 다른 글

19일차 - 논문 수업 (CNN)  (0) 2021.10.08
18일차 - 논문 수업 (CNN)  (0) 2021.10.08
16일차 - 논문 수업 (CNN)  (0) 2021.10.04
15일차 - CNN  (0) 2021.10.04
14일차 - 딥러닝 (Tensorflow) (3)  (0) 2021.10.04
728x90
반응형

Convolutional Neural Network

합성곱 신경망

Conv2D

- feature를 뽑아내는 3x3 filter

- filter 개수는 32개

- neural network에서 perceptron이 32개있는 것과 유사하다

- 3x3 filter는 처음에 랜덤하게 숫자가 정해진다

- linear연산이기 때문에 다양한 조합을 만들수가 없다

- Hyperparameter: filter 개수, filter 모양, padding, strides

- 3차원 연산

Activation

- ReLU - 0보다 작은 값은 0으로 0보다 큰 값은 값 그대로 출력한다

- non-linear한 함수를 활용하여 다양한 조합을 만든다

Conv2D

- filter를 다시 한번 더 통과 시킨다

- 원본 데이터에서 filter를 적용하면서 특징을 배워간다

- 가장 특징이 잘 나타내도록 변화 하는 작업을 수행한다

Activation

- filter 하나당 9개 weight를 갖고 총 32개 filter가 있기 때문에 총 288개 weight가 생긴다

MaxPooling2D

- 계산 복잡도를 줄이기 위해서 Maxpooling을 사용하여 크기를 줄인다

- 숫자 데이터에 대한 서로 다른 32가지 관점으로 해석을 한 후 데이터를 만들어 낸다

Dropout

- dropout을 사용하게 되면 좀 더 의미 있는 특징을 추출하게 된다

- 노드들을 무작위로 생략시키면서 학습을 하게되면 parameter들의 co-adaptation되는 것을 막을 수 있다

※ co-adaptation : 학습하는 도중 같은 층에서 두 개 이상의 노드의 입력 및 연결강도가 같아지게 되면,

아무리 학습이 진행되어도 그 노드들은 같은 일을 수행하게 되어 불필요한 중복이 생기는 문제

Flatten

- 특징이 잘 나타나도록 변경된 데이터 셋을 학습시키기 위해 1차원 데이터로 변환한다

최종적으로 0-9까지의 특징을 가장 잘 파악할 수 있는 32가지 filter를 학습하게 된다

CNN의 문제점 중 하나는 사람의 얼굴 특징이 모두 있지만 분리되어 있는 사진인 경우에도 얼굴이라고 인식하는 오류를 범한다

3차원 연산

CNN은 color이미지 일때 R,G,B 체널로 분리시켜 3차원 연산을 한다

CNN에서는 흑백 이미지일때에도 차원을 증가시켜 3차원 연산을 한다 (채널 데이터를 갖고 있어야 한다)

CNN에서 이미지를 변화시키는 이유는 구분시키는 특징을 잘 파악하는 데이터로 변화시키기 위해서 이다

서로 분리된 채널에 의한 이미지들은 element wise 연산을 통해 하나의 데이터에 대한 특징을 파악할 수 있다

Reference

Basic Convnet for MNIST

!pip install mglearn

초기값의 중요성

import mglearn
# dtype이 uint8일 때 최대값은 255, 최소값은 0 
# MinMaxScaler로 정규화 할 경우 0과 1사이로 값이 바뀌기 때문에 정사각형 형태로 데이터가 분포한다   
# 따라서 방향에 대한 크기변화가 없기 때문에 빠른 학습속도와 정확한 학습결과를 기대할 수 있다 
mglearn.plot_scaling.plot_scaling()

왜 convolution 연산에 대해서 합을 할까?

convolution 연산을 할때 element wise 연산을 하게되면(분리된 채널에서 합쳐질 때)특성을 알 수 없을 수도 있다

물론 depth wise convolution은 각각의 특성만 독립적으로 연산하는 경우도 있다

그러나 더하는 것이 성능이 더 좋고, convolution 연산 결과가 원본 이미지의 의미가 변하는 경우는 거의 나오지 않는다

왜 그런 경우가 나오지 않을까?

weight와 bias는 학습을 통해서 찾기 때문에 채널별로 서로 다른 결과가 나올수 있도록 학습이 되기 때문이다

(kernel은 특성을 잘 파악하도록 학습이 된다)

합하는 것이 왜 좋을까?

전통적인 NN에 영향을 받아서 hierarchy한 것을 고려했기 때문에 hierarchy 특징을 학습할 수 있다

중간 결과 및 filter 이미지 확인하기

 

import tensorflow as tf 
import numpy as np

(X_train, y_train), (X_test, y_test) = tf.keras.datasets.mnist.load_data()

from sklearn.datasets import load_digits
import matplotlib.pyplot as plt

data = load_digits()

data.data[0]
array([ 0.,  0.,  5., 13.,  9.,  1.,  0.,  0.,  0.,  0., 13., 15., 10.,
       15.,  5.,  0.,  0.,  3., 15.,  2.,  0., 11.,  8.,  0.,  0.,  4.,
       12.,  0.,  0.,  8.,  8.,  0.,  0.,  5.,  8.,  0.,  0.,  9.,  8.,
        0.,  0.,  4., 11.,  0.,  1., 12.,  7.,  0.,  0.,  2., 14.,  5.,
       10., 12.,  0.,  0.,  0.,  0.,  6., 13., 10.,  0.,  0.,  0.])
       
data.images[0]
array([[ 0.,  0.,  5., 13.,  9.,  1.,  0.,  0.],
       [ 0.,  0., 13., 15., 10., 15.,  5.,  0.],
       [ 0.,  3., 15.,  2.,  0., 11.,  8.,  0.],
       [ 0.,  4., 12.,  0.,  0.,  8.,  8.,  0.],
       [ 0.,  5.,  8.,  0.,  0.,  9.,  8.,  0.],
       [ 0.,  4., 11.,  0.,  1., 12.,  7.,  0.],
       [ 0.,  2., 14.,  5., 10., 12.,  0.,  0.],
       [ 0.,  0.,  6., 13., 10.,  0.,  0.,  0.]])
plt.imshow(data.images[0], cmap='gray')

data.images.shape
# (1797, 8, 8)
image = data.images.reshape(1797,8,8,1) # CNN에서 사용하는 연산하기 위해서 데이터 하나가 3차원이 되도록 데이터를 변화 시켰다

layer1 = tf.keras.layers.Conv2D(2, (3,3)) # filter 개수, filter 모양(단축 표현 가능 (3,3)=>3)
layer1.built # 일시키기 전까지 초기화가 안된다 => lazy Evaluation / 내부적으로 im2col
# False
layer1(image[0]) # 동시에 여러개 연산하기 때문에 안된다 / 데이터를 하나 연산하더라도 4차원 형태로 만들어 줘야 한다 
# ValueError: Input 0 of layer conv2d_1 is incompatible with the layer: : expected min_ndim=4, found ndim=3. Full shape received: (8, 8, 1)
layer1(image[0][tf.newaxis]) 
<tf.Tensor: shape=(1, 6, 6, 2), dtype=float32, numpy=
array([[[[-10.622592  ,   0.6645769 ],
		 ...
         [ -3.2092843 ,  -0.36533844]]]], dtype=float32)>
layer1.weights # weight를 xavier glorot uniform방식으로 초기화 하고 연산을 한다 
# [<tf.Variable 'conv2d_1/kernel:0' shape=(3, 3, 1, 2) dtype=float32, numpy=
#  array([[[[ 0.06324342,  0.15853754]],
#          [[-0.14388585, -0.19692683]],
#          [[-0.40798104,  0.04143384]]],
#         [[[-0.24675035, -0.07410842]],
#          [[-0.3730538 ,  0.22583339]],
#          [[-0.22161803,  0.13686094]]],
#         [[[ 0.11666891,  0.40331647]],
#          [[-0.17990309,  0.3350769 ]],
#          [[-0.34412956, -0.15513435]]]], dtype=float32)>,
#  <tf.Variable 'conv2d_1/bias:0' shape=(2,) dtype=float32, numpy=array([0., 0.], dtype=float32)>]
len(layer1.weights)
# 2

layer1.weights[0] # filter / kernel은 (3,3,1)가 2개 있다로 해석해야 한다 
# <tf.Variable 'conv2d_1/kernel:0' shape=(3, 3, 1, 2) dtype=float32, numpy=
# array([[[[ 0.06324342,  0.15853754]],
#         [[-0.14388585, -0.19692683]],
#         [[-0.40798104,  0.04143384]]],
#        [[[-0.24675035, -0.07410842]],
#         [[-0.3730538 ,  0.22583339]],
#         [[-0.22161803,  0.13686094]]],
#        [[[ 0.11666891,  0.40331647]],
#         [[-0.17990309,  0.3350769 ]],
#         [[-0.34412956, -0.15513435]]]], dtype=float32)>
layer1.weights[0][...,0] # 첫번째 filter 
<tf.Tensor: shape=(3, 3, 1), dtype=float32, numpy=
array([[[ 0.06324342],
        [-0.14388585],
        [-0.40798104]],

       [[-0.24675035],
        [-0.3730538 ],
        [-0.22161803]],

       [[ 0.11666891],
        [-0.17990309],
        [-0.34412956]]], dtype=float32)>
        
layer1.weights[0][...,1] # 두번째 filter 
<tf.Tensor: shape=(3, 3, 1), dtype=float32, numpy=
array([[[ 0.15853754],
        [-0.19692683],
        [ 0.04143384]],

       [[-0.07410842],
        [ 0.22583339],
        [ 0.13686094]],

       [[ 0.40331647],
        [ 0.3350769 ],
        [-0.15513435]]], dtype=float32)>
        
np.squeeze(layer1.weights[0][...,1])
array([[ 0.15853754, -0.19692683,  0.04143384],
       [-0.07410842,  0.22583339,  0.13686094],
       [ 0.40331647,  0.3350769 , -0.15513435]], dtype=float32)
       
tf.reshape((np.squeeze(layer1.weights[0][...,1])),(3,3))
<tf.Tensor: shape=(3, 3), dtype=float32, numpy=
array([[ 0.15853754, -0.19692683,  0.04143384],
       [-0.07410842,  0.22583339,  0.13686094],
       [ 0.40331647,  0.3350769 , -0.15513435]], dtype=float32)>
plt.imshow(np.squeeze(layer1.weights[0][...,1]), cmap='gray')

plt.imshow(np.squeeze(layer1.weights[0][...,0]), cmap='gray')

layer1.weights[1] # bias
# <tf.Variable 'conv2d_1/bias:0' shape=(2,) dtype=float32, numpy=array([0., 0.], dtype=float32)>

layer1_result = layer1(image[0][tf.newaxis])
layer1_result.shape
# TensorShape([1, 6, 6, 2])

layer1_result[0,...,0]
# <tf.Tensor: shape=(6, 6), dtype=float32, numpy=
array([[-10.622592 , -17.233952 , -14.855642 , -15.18894  , -13.4780655,
         -5.6591477],
       [-14.596352 , -16.461687 ,  -8.46327  , -12.294258 , -13.634556 ,
         -5.975335 ],
       [-14.3555565,  -9.104046 ,  -1.3667734,  -9.231415 , -13.976131 ,
         -5.8030467],
       [-13.614567 ,  -7.204097 ,  -0.2758534,  -9.567868 , -13.996439 ,
         -5.7096176],
       [-13.090911 ,  -9.931416 ,  -5.137371 , -12.04954  , -11.825691 ,
         -4.75425  ],
       [-10.976872 , -13.707218 , -12.3282795, -12.9457   , -10.296714 ,
         -3.2092843]], dtype=float32)>
         
plt.imshow(layer1_result[0,...,0], cmap='gray') # 8x8 이미지에서 3x3 filter를 썻기 때문에 8-3+1 = 6 => 6x6 결과가 나온다

Convolution layer를 통과한 데이터

(X_train, y_train), (X_test, y_test) = tf.keras.datasets.mnist.load_data()
X_train = X_train.reshape(-1,28,28,1)
input_ = tf.keras.Input(shape=(28,28,1))
x = tf.keras.layers.Conv2D(10,3)(input_)
model = tf.keras.models.Model(input_,x)

plt.imshow(model(X_train)[0][...,0], cmap='gray')

plt.imshow(model(X_train)[0][...,1], cmap='gray')

plt.imshow(model(X_train)[0][...,2], cmap='gray')

Convolution layer -> ReLU를 통과한 데이터

(X_train, y_train), (X_test, y_test) = tf.keras.datasets.mnist.load_data()
X_train = X_train.reshape(-1,28,28,1)
input_ = tf.keras.Input(shape=(28,28,1))
x = tf.keras.layers.Conv2D(10,3)(input_)
x = tf.keras.layers.ReLU()(x)
model = tf.keras.models.Model(input_,x)

plt.imshow(model(X_train)[0][...,0], cmap='gray')

plt.imshow(model(X_train)[0][...,0], cmap='binary')

plt.imshow(model(X_train)[0][...,1], cmap='gray')

plt.imshow(model(X_train)[0][...,1], cmap='binary')

plt.imshow(model(X_train)[0][...,2], cmap='gray')

plt.imshow(model(X_train)[0][...,2], cmap='binary')

LeNet-5

Gradient-Based Learning Applied to Document Recognition
Yann LeCun, Yoshua Bengio 등..

최초의 Convolutional Neural network가 상업적으로 성공한 논문

Feature extracion module은 trainable classifier module의 성능을 높이기 위한 수단이었다

나중에 Feature extracion module와 trainable classifier module를 결합해서 End-to-End로 만들었다

32x32를 한 이유는 정 중앙에 숫자를 넣기 위해서 조금 더 크게 만들었다

=> 제약 조건을 만들었다

성능을 높이기 위해서 가정을 추가한 것이다

 

이미지 크기가 크면 클수록 연산해야 할것이 많아지고, 많은 데이터가 필요하다

그런데 subsampling을 한다는 것은 줄이는 것이기 때문에 정보의 손실이 발생한다

이 지점에서 trade off가 발생한다

 

데이터가 많을 경우 pooling을 안하는 것이 성능이 더 좋다 하지만, 데이터가 적을 경우는 pooling을 하는 것이 더 좋다

 

subsampling으로 계산 복잡도를 줄였기 때문에 특징을 더 늘려야 한다 (이미지 피라미드)

데이터가 많으면 많을 수록 column이 많이 있는 것이 좋다(풍부한 nuance를 갖기 때문에)

특징이 있는지 없는 데이터 형태로 변환 시킨다

Subsampling

전체에서 일부만 뽑아서 줄이는 것 ex) pooling

 

 

 

 

 

 

 

 

 

반응형

'Computer_Science > Visual Intelligence' 카테고리의 다른 글

18일차 - 논문 수업 (CNN)  (0) 2021.10.08
17일차 - 논문 수업 (CNN)  (0) 2021.10.04
15일차 - CNN  (0) 2021.10.04
14일차 - 딥러닝 (Tensorflow) (3)  (0) 2021.10.04
13일차 - 딥러닝 (Tensorflow) (2)  (0) 2021.09.28
728x90
반응형

Block연산과 Window연산

from skimage.util import view_as_blocks, view_as_windows
import matplotlib.pyplot as plt
import skimage
from skimage.data import camera
import numpy as np

Block

겹치지 않게 동일한 크기의 block형태로 분할연산을 한다

camera = camera()
plt.imshow(camera, cmap='gray')

view_as_blocks(camera, (4,4)).shape # 4x4형태로 가로, 세로 128등분 나눠준다 / 겹치지 않게 자르는 방법 
# (128, 128, 4, 4)

camera.shape
# (512, 512)

block = view_as_blocks(camera, (4,4))
block[0,0].mean() # 4x4 이미지를 하나의 값으로 표현할 수 있다 
# 157.125

block_flatten = block.reshape(block.shape[0],block.shape[1],-1)
block_flatten.shape
# (128, 128, 16)

block_flatten[0,0]
# array([156, 157, 160, 159, 156, 157, 159, 158, 158, 157, 156, 156, 160,
       157, 154, 154], dtype=uint8)

block_flatten.mean(axis=2) # 맨 마지막 차원을 평균으로 구해서 128x128 형태로 결과를 낸다
array([[157.125 , 156.625 , 157.5625, ..., 154.75  , 152.4375, 152.1875],
       [156.875 , 156.125 , 157.625 , ..., 154.875 , 152.6875, 152.875 ],
       [154.375 , 156.6875, 156.8125, ..., 148.9375, 150.125 , 151.4375],
       ...,
       [115.5625, 104.5   , 131.    , ..., 102.3125,  91.5   , 101.3125],
       [120.5   , 109.25  , 121.125 , ..., 113.    , 126.5   , 120.75  ],
       [124.0625, 138.5625, 138.75  , ..., 129.4375, 128.375 , 118.9375]])
       
block_flatten.mean(axis=2).shape
# (128, 128)

plt.imshow(block_flatten.mean(axis=2), cmap='gray')

plt.imshow(block_flatten.max(axis=2), cmap='gray')

plt.imshow(block_flatten.min(axis=2), cmap='gray')

Winow

좌상에서 우하 방향으로 겹치면서 동일한 크기의 block형태로 연산을 한다

디테일을 유지한체 이미지를 변화시키는 기법

view_as_windows(camera, (4,4)).shape
# (509, 509, 4, 4)

512-4+1
# 509

view_as_windows(camera, (4,4),2).shape
# (255, 255, 4, 4)

512/2 - 1
# 255.0

window = view_as_windows(camera, (4,4))
window_flatten = window.reshape(window.shape[0],window.shape[1],-1)

plt.imshow(winow_flatten.mean(axis=2), cmap='gray')

plt.imshow(winow_flatten.min(axis=2), cmap='gray')

plt.imshow(winow_flatten.max(axis=2), cmap='gray')

Correlation, Convolution

1. Correlation

- 데이터를 상하, 좌우 반전하지 않고 필터를 통해 합성곱 연산을 한다

2. Convolution

- 데이터를 상하, 좌우 반전후 correlation연산을 하는 방법

def corr(im, kernel, stride=1): # im: 2d
  h,w = im.shape 
  out_h = (h-kernel.shape[0]//stride) + 1
  out_w = (w-kernel.shape[1]//stride) + 1 
  output = np.zeros((out_h, out_w))
  for i in range(out_h):
    for j in range(out_w):
      output[i,j] = (kernel*im[i:i+kernel.shape[0]*stride, j:j+kernel.shape[1]*stride]).sum()
  return output
def filter_by_conv(im, kernel, stride=1): # im: 2d
  h,w = im.shape 
  kernel = np.flipud(np.fliplr(kernel)) # 커널이 상-하, 좌-우가 반전된다 
  out_h = (h-kernel.shape[0]//stride) + 1
  out_w = (w-kernel.shape[1]//stride) + 1 
  output = np.zeros((out_h, out_w))
  for i in range(out_h):
    for j in range(out_w):
      output[i,j] = (kernel*im[i:i+kernel.shape[0]*stride, j:j+kernel.shape[1]*stride]).sum()
  return output
im1 = np.arange(36).reshape(6,6)
kernel = np.array([[1,2],[2,1]])
conv(im1, kernel)
# array([[ 21.,  27.,  33.,  39.,  45.],
#        [ 57.,  63.,  69.,  75.,  81.],
#        [ 93.,  99., 105., 111., 117.],
#        [129., 135., 141., 147., 153.],
#        [165., 171., 177., 183., 189.]])

kernel = np.array([[1,0,-1],[1,0,-1],[1,0,-1]])
plt.imshow(corr(camera,kernel), cmap='gray')

plt.imshow(filter_by_conv(camera, kernel), cmap='gray')

kernel = np.array([[1,2,1],[2,4,2],[1,2,1]])/16 # 가우시안 형태 

plt.imshow(corr(camera,kernel), cmap='gray') # 가우시안 블러

plt.imshow(filter_by_conv(camera, kernel), cmap='gray')

전처리 관점

from sklearn.datasets import load_breast_cancer, load_wine, load_iris
import seaborn as sns

cancer = load_breast_cancer(as_frame=True)
wine = load_wine(as_frame=True)
iris = load_iris(as_frame=True)

print(data.DESCR)

feature extraction은 데이터의 특성을 가장 잘나타나는 형태로 데이터를 구성하는 방법이다

 

cancer.frame # 특징을 잘 나타내는 값으로 표현했다 (feature extraction) 
	mean radius	mean texture	mean perimeter	mean area	mean smoothness	mean compactness	mean concavity	mean concave points	mean symmetry	mean fractal dimension	radius error	texture error	perimeter error	area error	smoothness error	compactness error	concavity error	concave points error	symmetry error	fractal dimension error	worst radius	worst texture	worst perimeter	worst area	worst smoothness	worst compactness	worst concavity	worst concave points	worst symmetry	worst fractal dimension	target
0	17.99	10.38	122.80	1001.0	0.11840	0.27760	0.30010	0.14710	0.2419	0.07871	1.0950	0.9053	8.589	153.40	0.006399	0.04904	0.05373	0.01587	0.03003	0.006193	25.380	17.33	184.60	2019.0	0.16220	0.66560	0.7119	0.2654	0.4601	0.11890	0
1	20.57	17.77	132.90	1326.0	0.08474	0.07864	0.08690	0.07017	0.1812	0.05667	0.5435	0.7339	3.398	74.08	0.005225	0.01308	0.01860	0.01340	0.01389	0.003532	24.990	23.41	158.80	1956.0	0.12380	0.18660	0.2416	0.1860	0.2750	0.08902	0
2	19.69	21.25	130.00	1203.0	0.10960	0.15990	0.19740	0.12790	0.2069	0.05999	0.7456	0.7869	4.585	94.03	0.006150	0.04006	0.03832	0.02058	0.02250	0.004571	23.570	25.53	152.50	1709.0	0.14440	0.42450	0.4504	0.2430	0.3613	0.08758	0
3	11.42	20.38	77.58	386.1	0.14250	0.28390	0.24140	0.10520	0.2597	0.09744	0.4956	1.1560	3.445	27.23	0.009110	0.07458	0.05661	0.01867	0.05963	0.009208	14.910	26.50	98.87	567.7	0.20980	0.86630	0.6869	0.2575	0.6638	0.17300	0
4	20.29	14.34	135.10	1297.0	0.10030	0.13280	0.19800	0.10430	0.1809	0.05883	0.7572	0.7813	5.438	94.44	0.011490	0.02461	0.05688	0.01885	0.01756	0.005115	22.540	16.67	152.20	1575.0	0.13740	0.20500	0.4000	0.1625	0.2364	0.07678	0
...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...
564	21.56	22.39	142.00	1479.0	0.11100	0.11590	0.24390	0.13890	0.1726	0.05623	1.1760	1.2560	7.673	158.70	0.010300	0.02891	0.05198	0.02454	0.01114	0.004239	25.450	26.40	166.10	2027.0	0.14100	0.21130	0.4107	0.2216	0.2060	0.07115	0
565	20.13	28.25	131.20	1261.0	0.09780	0.10340	0.14400	0.09791	0.1752	0.05533	0.7655	2.4630	5.203	99.04	0.005769	0.02423	0.03950	0.01678	0.01898	0.002498	23.690	38.25	155.00	1731.0	0.11660	0.19220	0.3215	0.1628	0.2572	0.06637	0
566	16.60	28.08	108.30	858.1	0.08455	0.10230	0.09251	0.05302	0.1590	0.05648	0.4564	1.0750	3.425	48.55	0.005903	0.03731	0.04730	0.01557	0.01318	0.003892	18.980	34.12	126.70	1124.0	0.11390	0.30940	0.3403	0.1418	0.2218	0.07820	0
567	20.60	29.33	140.10	1265.0	0.11780	0.27700	0.35140	0.15200	0.2397	0.07016	0.7260	1.5950	5.772	86.22	0.006522	0.06158	0.07117	0.01664	0.02324	0.006185	25.740	39.42	184.60	1821.0	0.16500	0.86810	0.9387	0.2650	0.4087	0.12400	0
568	7.76	24.54	47.92	181.0	0.05263	0.04362	0.00000	0.00000	0.1587	0.05884	0.3857	1.4280	2.548	19.15	0.007189	0.00466	0.00000	0.00000	0.02676	0.002783	9.456	30.37	59.16	268.6	0.08996	0.06444	0.0000	0.0000	0.2871	0.07039	1
569 rows × 31 columns
iris.frame # 데이터를 그대로 사용해도 특성을 띄기 때문에 전처리를 하지 않아도 된다 
	sepal length (cm)	sepal width (cm)	petal length (cm)	petal width (cm)	target
0	5.1	3.5	1.4	0.2	0
1	4.9	3.0	1.4	0.2	0
2	4.7	3.2	1.3	0.2	0
3	4.6	3.1	1.5	0.2	0
4	5.0	3.6	1.4	0.2	0
...	...	...	...	...	...
145	6.7	3.0	5.2	2.3	2
146	6.3	2.5	5.0	1.9	2
147	6.5	3.0	5.2	2.0	2
148	6.2	3.4	5.4	2.3	2
149	5.9	3.0	5.1	1.8	2
150 rows × 5 columns
sns.pairplot(wine.frame, hue='target') # 
# 원본 데이터를 그 특성에 제일 잘 맞게 다른 형태의 데이터로 변화 시킬 필요가 있다 => Featured data 형태로 바꾼다 
# min-max 또는 standard scaling을 사용해서 비정상적으로 영향력이 커지는 경우를 방지하기도 한다 
wine.frame.boxplot(figsize=(20,8))

Image의 문제점

1. 2차원 데이터 => 1차원 데이터 변환하는 과정에 column이 너무 많아진다

2. i.i.d(비정형 데이터의 특성)에서 벗어난다 => 전통적인 머신러닝을 사용하여 성능을 높이려면 가정이 많이 필요하다

3. 이미지 자체가 특성이 뚜렷하지 않은 경우 feature extraction을 통해 featured data로 변환해야 한다

어떤 필터를 적용하면 성능이 높아질까?

filter

- filter를 사용하면 가장 특징이 잘 나타나게 data를 변형 할 수 있다 (특징의 존재 여부로 문제를 변형한다)

- filter를 사용하여 이미지의 특성을 뚜렷하게 만든다

- filter를 사용하면 특징을 유지한체 크기가 줄어들기 때문에 데이터의 차원이 줄어드는 효과를 기대할 수 있다

- filter는 feature cross와 유사하다

Feature cross

feature를 합성해서 본래 갖고 있던 의미를 잃지 않은 채로 차원을 축소시키는 방법

filter를 사용하면 image 데이터의 문제점을 보완해주기 때문에 굉장히 좋은 방법이지만,

어떤 filter를 사용해야 하는지 선택하는 문제는 어려운 문제이다

결국 어떤 필터를 적용할지 학습을 통해서 찾을수 있지 않을까? 하는 의문으로 해결하게 된다

 

from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
wine.frame.iloc[:,:-1] = ss.fit_transform(wine.frame.iloc[:,:-1])
wine.frame.boxplot(figsize=(20,8)) # 데이터가 다른 형태로 바뀌었다

Convolution Neural Network

- 1989 - 1991 LeNet-1 - 1997 LeNet-5 (MNIST)

convolution filter의 특징

1. neural network 연산과 똑같다 ( + )

2. window연산을 하기 때문에 전통적인 fully connected 방식과 달리 구해야할 weight의 수가 급격하게 줄어든다 (parameter가 줄어든다)

=> 차원의 저주를 피할 있다

3. stationarity: 이미지의 특정 구간에서 filter 거친 값이 A라고 했을 다른 구간에서 A라는 값이나오면 구간은 특성이 같다(numerical stability와 유사한 의미)

=> 서로 다른 위치의 값이 유사할 경우 부분은 특성이 유사하다

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형
728x90
반응형

Tensorflow

import tensorflow as tf 
(X_train, y_train), (X_test,y_test) = tf.keras.datasets.fashion_mnist.load_data()
X_train.dtype
# dtype('uint8')
# Normalization (min-max) => 최소값 0 최대값 1로 정규화를 한다 => 학습시 훨씬 더 효율적으로 할 수 있기 때문에 더 정확하고 빠르게 할 수 있다 
X_train = X_train / 255
X_test = X_test / 255


# 전처리는 model안에서

# Sequential 버전 
model = tf.keras.Sequential([
  tf.keras.layers.Flatten(input_shape=(28,28)),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dense(10, activation='softmax')
])

# Model 버전 
inputs_ = tf.keras.layers.Input(shape=(28,28))
x = tf.keras.layers.Flatten()(inputs_)
x = tf.keras.layers.Dense(128)(x)
x = tf.keras.layers.ReLU()(x)
outputs = tf.keras.layers.Dense(10, activation='softmax')(x)

model = tf.keras.models.Model(inputs_, outputs)

model.summary()
Model: "model_4"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_5 (InputLayer)         [(None, 28, 28)]          0         
_________________________________________________________________
flatten_6 (Flatten)          (None, 784)               0         
_________________________________________________________________
dense_12 (Dense)             (None, 128)               100480    
_________________________________________________________________
re_lu_4 (ReLU)               (None, 128)               0         
_________________________________________________________________
dense_13 (Dense)             (None, 10)                1290      
=================================================================
Total params: 101,770
Trainable params: 101,770
Non-trainable params: 0
_________________________________________________________________
model.trainable_weights # 학습 가능한 가중치를 학습시킬 것이다
[<tf.Variable 'dense_2/kernel:0' shape=(784, 128) dtype=float32, numpy=
 array([[ 0.02516936,  0.06438791,  0.018306  , ..., -0.01758076,
          0.06290304,  0.05140124],
        [-0.05912167, -0.01394046,  0.00835894, ...,  0.07631402,
         -0.02987464,  0.03332863],
        [-0.0592133 ,  0.03133401,  0.07544664, ...,  0.0805388 ,
         -0.07592296, -0.03545989],
        ...,
        [ 0.04126004,  0.02557782, -0.07374297, ..., -0.01776882,
          0.05950726,  0.03152514],
        [ 0.04481585, -0.01106533,  0.0462807 , ...,  0.02908169,
          0.02692767, -0.03776729],
        [ 0.00387245, -0.05717902,  0.07691073, ..., -0.03013743,
          0.04765027, -0.012512  ]], dtype=float32)>,
 <tf.Variable 'dense_2/bias:0' shape=(128,) dtype=float32, numpy=
 array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)>,
 <tf.Variable 'dense_3/kernel:0' shape=(128, 10) dtype=float32, numpy=
 array([[-0.15315153,  0.0456792 , -0.01593776, ...,  0.10890259,
          0.05543895,  0.05593623],
        [ 0.13440786,  0.08750169,  0.10087   , ..., -0.15075403,
         -0.13427767,  0.15088643],
        [ 0.00122444,  0.02775083, -0.05616018, ..., -0.01628929,
         -0.00568283, -0.05492131],
        ...,
        [ 0.07487939, -0.07071173,  0.1954471 , ..., -0.01074487,
          0.10662811, -0.13067412],
        [ 0.13852535,  0.161729  ,  0.18972401, ..., -0.1629928 ,
          0.04696299,  0.08850865],
        [-0.13064459, -0.07557841, -0.06935515, ...,  0.19506954,
          0.18600823,  0.00797179]], dtype=float32)>,
 <tf.Variable 'dense_3/bias:0' shape=(10,) dtype=float32, numpy=array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)>]

Loss function

모델은 학습을 할때 실제값 - 예측값을 최소화 하는 방향으로 학습을 하는데

이때 loss function은 예측값이 실제값에 가까워지는지 판단하는 척도가 되는 함수이다

 

tf.keras.losses.binary_crossentropy # parameter 변경 불가능, decorator로 기능을 확장할 수 있다 / 그대로 사용할 때 편리함 
tf.keras.losses.BinaryCrossentropy() # instance 하면서 완전히 다른 값을 가질 수 있다, subclass 상속을 통해서 다른 값을 가질 수 있다 / 인자를 바꾸거나 원하는 형태로 바꿀 때는 클래스 방식을 쓴다
tf.keras.losses.categorical_crossentropy
tf.keras.losses.CategoricalCrossentropy
tf.keras.losses.SparseCategoricalCrossentropy # one-hot-encoding을 내부적으로 해준다 
tf.keras.losses.sparse_categorical_crossentropy # partial을 굳이 사용하지 않고 one-hot-encoding을 할 수 있도록 클래스를 제공한다 

from functools import partial
def x(a,b):
  return a+b
x2 = partial(x, b=1) # 기존의 함수기능을 변경할 수 있다 
x2(3)
# 4
# compile은 내부적으로 computational graph로 바꾸어 lose function를 효율적으로 자동 미분하도록 도와준다  
# tf.keras.losses.categorical_crossentropy의 단축 표현 => categorical_crossentropy 단, 단축표현은 parameter 변경 불가능 
model.compile(loss=tf.keras.losses.categorical_crossentropy)

compile(학습 설계) 필요한 파라미터 3가지

1. loss function

2. optimizer => 자동 미분을 사용하는 방법 설정

3. metrics => 평가 기준 설정

# 내가 원하는 값의 형태로 바꾸지 않는 지점까지를 logit이라고 한다 / from_logits=True는 logits으로 부터 실제값 - 예측값을 구하는 방법을 사용하겠다는 의미이다 
model.compile(loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True), optimizer='adam')

'adam' # parameter 변경 불가능 
tf.keras.optimizers.Adam() # parameter 변경 가능

Softmax

softmax는 numerical stability하지 않는 문제가 발생할 수 있다

def softmax(logits): 
  exp = tf.exp(logits)
  return exp / tf.reduce_sum(exp)
  
softmax([10000.,0.]) # softmax는 지수연산을 하기 때문에 큰 값이 들어오면 쉽게 오버플로우가 발생한다 
# <tf.Tensor: shape=(2,), dtype=float32, numpy=array([nan,  0.], dtype=float32)>

softmax([1.,3.,2.])
# <tf.Tensor: shape=(3,), dtype=float32, numpy=array([0.09003057, 0.66524094, 0.24472848], dtype=float32)>

def softmax2(logits): # 큰 값이 들어갔을 때 오버플로우를 방지하는 방법 그러나 이 또한 문제가 있다
  exp = tf.exp(logits-tf.reduce_max(logits))
  return exp / tf.reduce_sum(exp)
  
softmax2([100000., 0.])
# <tf.Tensor: shape=(2,), dtype=float32, numpy=array([1., 0.], dtype=float32)>

softmax2([100.,3.,0.]) # 가장 큰값만 값을 가지고 나머지는 값을 못갖게 되는 일도 발생한다 
# <tf.Tensor: shape=(3,), dtype=float32, numpy=array([1., 0., 0.], dtype=float32)>

softmax2([100.,300.,200.])
# <tf.Tensor: shape=(3,), dtype=float32, numpy=array([0., 1., 0.], dtype=float32)>

softmax2([0.00011,0.000012,0.000014]) # 너무 작은 값이 들어가도 언더플로우가 발생하여 모두 동일한 비율로 들어가게 된다 
# <tf.Tensor: shape=(3,), dtype=float32, numpy=array([0.3333549 , 0.33332223, 0.3333229 ], dtype=float32)>

학습과정 설정 및 학습(compile & fit)

model.compile(loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False), 
              optimizer='adam', metrics=['acc'])
              
model.fit(X_train,y_train, epochs=2) # 학습 데이터와 epoch을 정해주면 학습이 가능하다 / default로 epoch=1, batch size = 32
Epoch 1/2
1875/1875 [==============================] - 5s 2ms/step - loss: 0.5010 - acc: 0.8243
Epoch 2/2
1875/1875 [==============================] - 4s 2ms/step - loss: 0.3774 - acc: 0.8643
<keras.callbacks.History at 0x7efc4ebf33d0>

X_train.shape # 6만개 데이터 
# (60000, 28, 28)

60000/1875 # batch size
# 32.0

# loss, metrics return 
model.train_on_batch(X_train, y_train) # fit은 batch size만큼 train_on_batch가 실행된다 ex) 데이터 개수 = 60000, batch size=100 600번 train_on_batch실행 
# [0.38287022709846497, 0.8614166378974915]

GridSearch CV

Hyperparameter tuning 방법중 하나이다

from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV

knn = KNeighborsClassifier(n_neighbors=5)

GridSearchCV(KNeighborsClassifier(), {'n_neighbors':[5,6,7,8,9,10]}) # 사용자가 지정한 파라미터를 반복문을 사용하는 것처럼 구해주는 방법

Callback

callback은 특정 상황에 대해서 그 결과를 판단할 수 있도록 결과값을 알려주는 기능

 

class MyCallback(tf.keras.callbacks.Callback):
  def on_epoch_end(self, epoch, logs=None): # signature를 동일하게 맞춰야 한다 
    print('epoch', epoch+1, '시작')
    
dir(tf.keras.callbacks.Callback)

dir(tf.keras.callbacks)
['BaseLogger',
 'CSVLogger',
 'Callback',
 'CallbackList',
 'EarlyStopping',
 'History',
 'LambdaCallback',
 'LearningRateScheduler',
 'ModelCheckpoint',
 'ProgbarLogger',
 'ReduceLROnPlateau',
 'RemoteMonitor',
 'TensorBoard',
 'TerminateOnNaN',
 '__builtins__',
 '__cached__',
 '__doc__',
 '__file__',
 '__loader__',
 '__name__',
 '__package__',
 '__path__',
 '__spec__',
 '_sys',
 'experimental']
h = model.fit(X_train,y_train, steps_per_epoch=100, epochs=2, callbacks=[MyCallback()])
Epoch 1/2
100/100 [==============================] - 0s 4ms/step - loss: 0.2951 - acc: 0.8926
epoch 1 시작
Epoch 2/2
100/100 [==============================] - 0s 4ms/step - loss: 0.2919 - acc: 0.8947
epoch 2 시작

inputs_ = tf.keras.layers.Input(shape=(28,28))
x = tf.keras.layers.Flatten()(inputs_)
x = tf.keras.layers.Dense(2)(x)
x = tf.keras.layers.ReLU()(x)
outputs = tf.keras.layers.Dense(10, activation='softmax')(x)

model = tf.keras.models.Model(inputs_, outputs)

model.compile(loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False), 
              optimizer='adam', metrics=['accuracy'])

model.weights[0] # 학습전  
<tf.Variable 'dense_14/kernel:0' shape=(784, 2) dtype=float32, numpy=
array([[ 0.0621696 ,  0.03114827],
       [ 0.05718201, -0.06315091],
       [ 0.01374986, -0.00775776],
       ...,
       [ 0.00518525,  0.02914727],
       [ 0.04352903, -0.05101464],
       [ 0.03367535,  0.01672252]], dtype=float32)>
       
model.fit(X_train, y_train)
1875/1875 [==============================] - 5s 2ms/step - loss: 1.3585 - accuracy: 0.4977
<keras.callbacks.History at 0x7efc51d21ed0>

model.weights[0] # 학습 후 (epoch 1)
<tf.Variable 'dense_14/kernel:0' shape=(784, 2) dtype=float32, numpy=
array([[ 0.01506082,  0.07337335],
       [ 0.02667496, -0.08142766],
       [-0.03281154, -0.00934248],
       ...,
       [ 0.02592397,  0.03641215],
       [ 0.06711672, -0.02997859],
       [ 0.01211459,  0.00046465]], dtype=float32)>
       
model.fit(X_train, y_train, epochs=3) # 이전에 epoch이 한번 돌아갔으므로 총 epochs은 4번 돌린것과 같다 (mutable이기 때문)       
Epoch 1/3
1875/1875 [==============================] - 5s 2ms/step - loss: 0.9381 - accuracy: 0.6460
Epoch 2/3
1875/1875 [==============================] - 4s 2ms/step - loss: 0.8567 - accuracy: 0.6885
Epoch 3/3
1875/1875 [==============================] - 4s 2ms/step - loss: 0.8133 - accuracy: 0.7038
<keras.callbacks.History at 0x7efc51d5e650>

model.weights[0] # 학습 후 (epoch 4)
<tf.Variable 'dense_14/kernel:0' shape=(784, 2) dtype=float32, numpy=
array([[-0.04761839,  0.18095993],
       [-0.0655762 , -0.07643786],
       [-0.17626587,  0.11628444],
       ...,
       [ 0.15831317,  0.12745775],
       [ 0.0916123 ,  0.08825199],
       [ 0.03401611,  0.01437407]], dtype=float32)>
       
model.fit(X_train, y_train, initial_epoch=3, epochs=5) # initial epoch부터 다시 학습을 시작한다 
Epoch 4/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.7889 - accuracy: 0.7098
Epoch 5/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.7734 - accuracy: 0.7145
<keras.callbacks.History at 0x7efc51d21f90>

model.fit(X_train, y_train, epochs=2, verbose=2)  # 숫자가 커지면 표현되는 정보가 줄어든다 
Epoch 1/2
1875/1875 - 3s - loss: 0.9043
Epoch 2/2
1875/1875 - 3s - loss: 0.8777
<keras.callbacks.History at 0x7efc50cd7210>

model.fit(X_train, y_train, epochs=2, verbose=3) 
Epoch 1/2
Epoch 2/2
<keras.callbacks.History at 0x7efc50ca5610>
h = model.fit(X_train, y_train, initial_epoch=5, epochs=20, validation_split=0.3) # 학습을 하면 항상 history callback 이다 
Epoch 6/20
1313/1313 [==============================] - 6s 4ms/step - loss: 0.7630 - accuracy: 0.7176 - val_loss: 0.7644 - val_accuracy: 0.7236
Epoch 7/20
1313/1313 [==============================] - 6s 4ms/step - loss: 0.7571 - accuracy: 0.7197 - val_loss: 0.7743 - val_accuracy: 0.7108
Epoch 8/20
1313/1313 [==============================] - 6s 4ms/step - loss: 0.7529 - accuracy: 0.7206 - val_loss: 0.7593 - val_accuracy: 0.7146
Epoch 9/20
1313/1313 [==============================] - 5s 4ms/step - loss: 0.7485 - accuracy: 0.7202 - val_loss: 0.7564 - val_accuracy: 0.7232
Epoch 10/20
1313/1313 [==============================] - 5s 4ms/step - loss: 0.7454 - accuracy: 0.7230 - val_loss: 0.7620 - val_accuracy: 0.7138
Epoch 11/20
1313/1313 [==============================] - 5s 4ms/step - loss: 0.7426 - accuracy: 0.7242 - val_loss: 0.7688 - val_accuracy: 0.7273
Epoch 12/20
1313/1313 [==============================] - 5s 4ms/step - loss: 0.7410 - accuracy: 0.7253 - val_loss: 0.7562 - val_accuracy: 0.7230
Epoch 13/20
1313/1313 [==============================] - 5s 4ms/step - loss: 0.7383 - accuracy: 0.7252 - val_loss: 0.7649 - val_accuracy: 0.7212
Epoch 14/20
1313/1313 [==============================] - 5s 4ms/step - loss: 0.7361 - accuracy: 0.7273 - val_loss: 0.7529 - val_accuracy: 0.7227
Epoch 15/20
1313/1313 [==============================] - 5s 4ms/step - loss: 0.7342 - accuracy: 0.7278 - val_loss: 0.7500 - val_accuracy: 0.7280
Epoch 16/20
1313/1313 [==============================] - 5s 4ms/step - loss: 0.7330 - accuracy: 0.7300 - val_loss: 0.7539 - val_accuracy: 0.7308
Epoch 17/20
1313/1313 [==============================] - 5s 4ms/step - loss: 0.7321 - accuracy: 0.7296 - val_loss: 0.7486 - val_accuracy: 0.7286
Epoch 18/20
1313/1313 [==============================] - 6s 4ms/step - loss: 0.7303 - accuracy: 0.7314 - val_loss: 0.7518 - val_accuracy: 0.7164
Epoch 19/20
1313/1313 [==============================] - 6s 4ms/step - loss: 0.7288 - accuracy: 0.7309 - val_loss: 0.7553 - val_accuracy: 0.7300
Epoch 20/20
1313/1313 [==============================] - 5s 4ms/step - loss: 0.7272 - accuracy: 0.7303 - val_loss: 0.7629 - val_accuracy: 0.7312

'history' in dir(h)
# True
h.history
{'accuracy': [0.7176190614700317,
  0.7197142839431763,
  ...
  'loss': [0.7630206346511841,
  0.7571397423744202,
  ...
  'val_accuracy': [0.7235555648803711,
  0.710777759552002,
  ...
  'val_loss': [0.764350175857544,
  0.7743284106254578,
  0.7628713250160217]}
import pandas as pd
pd.DataFrame(h.history)
	loss	accuracy	val_loss	val_accuracy
0	0.763021	0.717619	0.764350	0.723556
1	0.757140	0.719714	0.774328	0.710778
2	0.752870	0.720595	0.759297	0.714556
3	0.748499	0.720167	0.756395	0.723222
4	0.745416	0.723024	0.761951	0.713833
5	0.742576	0.724190	0.768764	0.727278
6	0.740972	0.725310	0.756249	0.723000
7	0.738272	0.725167	0.764873	0.721167
8	0.736076	0.727286	0.752897	0.722722
9	0.734219	0.727786	0.749965	0.728000
10	0.732950	0.730024	0.753874	0.730778
11	0.732133	0.729571	0.748595	0.728611
12	0.730341	0.731429	0.751841	0.716389
13	0.728781	0.730857	0.755321	0.730000
14	0.727199	0.730286	0.762871	0.731222


pd.DataFrame(h.history).plot.line()

 

 

 

 

 

반응형
728x90
반응형

Tensorflow

모델을 만드는 여러가지 표현 방법

1. Sequential

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(2))
model.add(tf.keras.layers.Dense(2))

x = tf.constant([[1,2]])
y = tf.constant([[1,2],[2,3]])

model(x) 
# <tf.Tensor: shape=(1, 2), dtype=float32, numpy=array([[0.3294789, 0.589738 ]], dtype=float32)>

model.built
# True

model.summary()

# Model: "sequential"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# dense (Dense)                (1, 2)                    6         
# _________________________________________________________________
# dense_1 (Dense)              (1, 2)                    6         
# =================================================================
# Total params: 12
# Trainable params: 12
# Non-trainable params: 0
# _________________________________________________________________
model(y)
# <tf.Tensor: shape=(2, 2), dtype=float32, numpy=
# array([[0.3294789 , 0.589738  ],
#        [0.2781678 , 0.97357416]], dtype=float32)>

model.summary()
# Model: "sequential"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# dense (Dense)                (None, 2)                 6         
# _________________________________________________________________
# dense_1 (Dense)              (None, 2)                 6         
# =================================================================
# Total params: 12
# Trainable params: 12
# Non-trainable params: 0
# _________________________________________________________________

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.InputLayer(input_shape=(2,))) # 두 개의 값을 갖는 1차원 데이터를 받겠다 (데이터의 개수는 상관없이 받는다)
model.add(tf.keras.layers.Dense(2))
model.add(tf.keras.layers.Dense(2))

model.summary()
# Model: "sequential_1"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# dense_2 (Dense)              (None, 2)                 6         
# _________________________________________________________________
# dense_3 (Dense)              (None, 2)                 6         
# =================================================================
# Total params: 12
# Trainable params: 12
# Non-trainable params: 0
# _________________________________________________________________
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(2, input_shape=(2,))) # input layer를 추가하지 않고 줄여서 사용할 수 있다 
model.add(tf.keras.layers.Dense(2))

model.summary()
# Model: "sequential_3"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# dense_5 (Dense)              (None, 2)                 6         
# _________________________________________________________________
# dense_6 (Dense)              (None, 2)                 6         
# =================================================================
# Total params: 12
# Trainable params: 12
# Non-trainable params: 0
# _________________________________________________________________
model = tf.keras.models.Sequential([
  tf.keras.layers.Dense(2, input_shape=[2]), # (2,)처럼 튜플 형태말고 리스트 형태로도 표현할 수 있다 
  tf.keras.layers.Dense(2)
])

model.summary()
# Model: "sequential_4"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# dense_7 (Dense)              (None, 2)                 6         
# _________________________________________________________________
# dense_8 (Dense)              (None, 2)                 6         
# =================================================================
# Total params: 12
# Trainable params: 12
# Non-trainable params: 0
# _________________________________________________________________

Model

inputs = tf.keras.Input(shape=(2,)) # tensor 
x = tf.keras.layers.Dense(2)(inputs)s
outputs = tf.keras.layers.Dense(2)(x)

model = tf.keras.models.Model(inputs, outputs) # input과 output을 같이 인자로 넣어줘야 한다 / 그리고 input으로 tensor를 받아야 한다 

model.summary() # input layer가 명시된다 
# Model: "model"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# input_4 (InputLayer)         [(None, 2)]               0         
# _________________________________________________________________
# dense_15 (Dense)             (None, 2)                 6         
# _________________________________________________________________
# dense_16 (Dense)             (None, 2)                 6         
# =================================================================
# Total params: 12
# Trainable params: 12
# Non-trainable params: 0
# _________________________________________________________________
inputs = tf.keras.layers.InputLayer(input_shape=(2,)) # layer
x = tf.keras.layers.Dense(2)(inputs) # tensor를 인자로 받아야 한다 
outputs = tf.keras.layers.Dense(2)(x)
# TypeError: Inputs to a layer should be tensors. Got: <keras.engine.input_layer.InputLayer object at 0x7f09f68a56d0>

# Sequential이 아닌 Model을 사용하는 것은 inputlayer를 표시하여서 조금더 복잡한 모델을 만들수있기 때문

inputs1 = tf.keras.Input(shape=(2,))
inputs2 = tf.keras.Input(shape=(2,))
x1 = tf.keras.layers.Dense(2)(inputs1)
x2 = tf.keras.layers.Dense(2)(inputs2) 
outputs1 = tf.keras.layers.Dense(2)(x1)
outputs2 = tf.keras.layers.Dense(2)(x2)

model = tf.keras.models.Model([inputs1, inputs2], [outputs1,outputs2])

model.summary() # InputLayer나 connected to가 있을 경우 Model로 만들었다는 의미 이다 

# Model: "model_1"
# __________________________________________________________________________________________________
# Layer (type)                    Output Shape         Param #     Connected to                     
# ==================================================================================================
# input_8 (InputLayer)            [(None, 2)]          0                                            
# __________________________________________________________________________________________________
# input_9 (InputLayer)            [(None, 2)]          0                                            
# __________________________________________________________________________________________________
# dense_19 (Dense)                (None, 2)            6           input_8[0][0]                    
# __________________________________________________________________________________________________
# dense_20 (Dense)                (None, 2)            6           input_9[0][0]                    
# __________________________________________________________________________________________________
# dense_21 (Dense)                (None, 2)            6           dense_19[0][0]                   
# __________________________________________________________________________________________________
# dense_22 (Dense)                (None, 2)            6           dense_20[0][0]                   
# ==================================================================================================
# Total params: 24
# Trainable params: 24
# Non-trainable params: 0
# __________________________________________________________________________________________________

Sequential과 달리 input layer와 output layer를 두 개 이상 받을 수 있다

tf.keras.utils.plot_model(model)

tf.keras.utils.plot_model(model, show_shapes=True)

inputs1 = tf.keras.Input(shape=(2,))
inputs2 = tf.keras.Input(shape=(2,))
x1 = tf.keras.layers.Dense(2)(inputs1)
x2 = tf.keras.layers.Dense(2)(inputs2) 
outputs1 = tf.keras.layers.Add()([x1,x2])
outputs2 = tf.keras.layers.Subtract()([x1,x2])

model = tf.keras.models.Model([inputs1, inputs2], [outputs1,outputs2])

tf.keras.utils.plot_model(model, show_shapes=True)

Model과 Sequential을 동시에 활용하는 방법

se = tf.keras.models.Sequential([
  tf.keras.layers.Dense(2),
  tf.keras.layers.Dense(2)                                 
])

inputs_ = tf.keras.Input(shape=(3,))
outputs = se(inputs_)
model = tf.keras.models.Model(inputs_, outputs)

model
# <keras.engine.functional.Functional at 0x7f73508eef10>
model.summary() # 모델 안에 모델을 넣지는 않지만 단순화 하기 위해서 모델 안에 sequential을 넣는 방법을 사용하는 경우는 많다  
# Model: "model_2"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# input_6 (InputLayer)         [(None, 3)]               0         
# _________________________________________________________________
# sequential (Sequential)      (None, 2)                 14        
# =================================================================
# Total params: 14
# Trainable params: 14
# Non-trainable params: 0
# _________________________________________________________________

데이터 시각화로 Balanced data인지 구별하기

(X_train, y_train), (X_test, y_test) = tf.keras.datasets.mnist.load_data()

X_train.shape
# (60000, 28, 28)

X_train
# array([[[0, 0, 0, ..., 0, 0, 0],
#         [0, 0, 0, ..., 0, 0, 0],
#         [0, 0, 0, ..., 0, 0, 0],
#         ...
#         [0, 0, 0, ..., 0, 0, 0],
#         [0, 0, 0, ..., 0, 0, 0],
#         [0, 0, 0, ..., 0, 0, 0]]], dtype=uint8)
np.unique(y_train, return_counts=True)
# (array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=uint8),
# array([5923, 6742, 5958, 6131, 5842, 5421, 5918, 6265, 5851, 5949]))

plt.hist(y_train) # blanced data
# (array([5923., 6742., 5958., 6131., 5842., 5421., 5918., 6265., 5851.,
#         5949.]),
#  array([0. , 0.9, 1.8, 2.7, 3.6, 4.5, 5.4, 6.3, 7.2, 8.1, 9. ]),
#  <a list of 10 Patch objects>)

 

MLP

# numerical stability => input이 있으면 output이 있어야 한다 

# Normalization 
X_train = X_train / 255 # coersion
X_test = X_test / 255

preprocessing을 모델 안에서 하는지 모델 밖에서 하는지 결정해야 한다

 

Inside model

- portability, 편리하다

- GPU 연산이 가능하다

 

Outside model

- 데이터의 형태에 제약이 없어 범용성이 있다

- 기본적으로 CPU방식이지만 CPU + GPU방식을 쓸 수 있다

 

tensorflow에서는 3차원,즉 흑백 이미지는 (Batch(size), H, W)로 받아들인다

4차원(color 이미지) 일때는 (B, H, W, C) 또는 (B, C, H, W)(theano 기본)으로 받아들인다

 

Flatten

tf.keras.layers.Flatten()(X_train) # 함수 밖에서 사용하면 cpu로 연산한다  
# <tf.Tensor: shape=(60000, 784), dtype=float32, numpy=
# array([[0., 0., 0., ..., 0., 0., 0.],
#        [0., 0., 0., ..., 0., 0., 0.],
#        [0., 0., 0., ..., 0., 0., 0.],
#        ...,
#        [0., 0., 0., ..., 0., 0., 0.],
#        [0., 0., 0., ..., 0., 0., 0.],
#        [0., 0., 0., ..., 0., 0., 0.]], dtype=float32)>
       
X_train_bw = X_train.reshape(60000, 28, 28, 1)
tf.keras.layers.Flatten()(X_train_bw) 
# <tf.Tensor: shape=(60000, 784), dtype=float32, numpy=
# array([[0., 0., 0., ..., 0., 0., 0.],
#        [0., 0., 0., ..., 0., 0., 0.],
#        [0., 0., 0., ..., 0., 0., 0.],
#        ...,
#        [0., 0., 0., ..., 0., 0., 0.],
#        [0., 0., 0., ..., 0., 0., 0.],
#        [0., 0., 0., ..., 0., 0., 0.]], dtype=float32)>
X_train_bw.flatten().shape
# (47040000,)
# 그냥 하면 depth 까지 다 flat해짐

numpy에서 flatten은 모든 것을 1차원으로 만들어 준다

'__call__' in dir(tf.keras.layers.Flatten()) # instance => Function 
# True

MLP를 만드는 다양한 방법

input_ = tf.keras.Input(shape=(28,28)) 
x = tf.keras.layers.Flatten()(input_) # 1차가 되었기 때문에 fully conntected 모델을 사용할 수 있다 
x = tf.keras.layers.Dense(128, activation='relu')(x) # Dense에는 하나의 데이터가 1차원인 경우에만 집어 넣을 수 있다 

x
# <KerasTensor: shape=(None, 128) dtype=float32 (created by layer 'dense_6')>

input_ = tf.keras.Input(shape=(28,28))
x = tf.keras.layers.Dense(128, activation='relu')(input_) # 2차원 값을 Dense에 넣으면 원하는 output을 만들어 낼 수 없다

x
# <KerasTensor: shape=(None, 28, 128) dtype=float32 (created by layer 'dense_7')>

Option1

input_ = tf.keras.Input(shape=(28,28)) 
x = tf.keras.layers.Flatten()(input_) 
x = tf.keras.layers.Dense(2)(x)
x = tf.keras.layers.Activation('relu')(x) # 또는 x = tf.keras.layers.ReLU()(x)
# Activation layer를 따로 두는 이유는 Batch Normalization을 하기 위해서 이다

Option2

input_ = tf.keras.Input(shape=(28,28)) 
x = tf.keras.layers.Flatten()(input_) 
x= tf.keras.layers.Dense(128, activation='relu')(x)

input_ = tf.keras.Input(shape=(28,28)) 
x = tf.keras.layers.Flatten()(input_) 
x = tf.keras.layers.Dense(128)(x)
x = tf.keras.layers.ReLU()(x)
x = tf.keras.layers.Dropout(0.2)(x)
output = tf.keras.layers.Dense(10, activation='softmax')(x) 
# Batch Normalization과 상관 없기 때문에 관례상 마지막은 단축 표현을 쓴다 

model = tf.keras.models.Model(input_, output)

model.summary() # param이 0인 경우 학습하지 않아도 되는 단순한 연산이다 

# Model: "model_3"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# input_9 (InputLayer)         [(None, 28, 28)]          0         
# _________________________________________________________________
# flatten_1 (Flatten)          (None, 784)               0         
# _________________________________________________________________
# dense_8 (Dense)              (None, 128)               100480    
# _________________________________________________________________
# re_lu (ReLU)                 (None, 128)               0         
# _________________________________________________________________
# dropout (Dropout)            (None, 128)               0         
# _________________________________________________________________
# dense_9 (Dense)              (None, 10)                1290      
# =================================================================
# Total params: 101,770
# Trainable params: 101,770
# Non-trainable params: 0
# _________________________________________________________________

neural network parameter 구하는 법

입력값 (28x28) X dense layer nodes(128) + dense layer bias(128) = 100480

model.weights[0] 
# tensorflow에서는 weight를 kernel라고 부른다 그리고 weight는 kernel + bias를 지칭한다  
# kernel은 glorot방식으로 초기화 된다(학습이 빠르고 잘 수렴되는 초기화 방식)

# <tf.Variable 'dense_7/kernel:0' shape=(784, 128) dtype=float32, numpy=
# array([[-0.00481777, -0.05054575, -0.066313  , ...,  0.01311962,
#          0.04805059,  0.00298249],
#        [ 0.07520033, -0.01051669,  0.00903524, ..., -0.07472851,
#          0.01202653, -0.00115251],
#        [-0.01647546, -0.03879095, -0.03718614, ..., -0.05494369,
#         -0.05540787,  0.05530912],
#        ...,
#        [-0.00182921,  0.07649232, -0.07937535, ...,  0.05838447,
#          0.05726648, -0.03632762],
#        [-0.00923116,  0.01400795, -0.05262435, ..., -0.07948828,
#          0.01813819, -0.02076239],
#        [-0.01461188,  0.07456786,  0.0081539 , ...,  0.01914987,
#          0.07928162, -0.03385995]], dtype=float32)>
model.weights[1]
# <tf.Variable 'dense_7/bias:0' shape=(128,) dtype=float32, numpy=
# array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
#        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
#        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
#        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
#        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
#        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
#        0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
#        0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)>
model.weights[2]
# <tf.Variable 'dense_8/kernel:0' shape=(128, 10) dtype=float32, numpy=
# array([[-0.01635328,  0.00763369,  0.13723023, ..., -0.18139066,
#          0.09355612,  0.14300655],
#        [-0.06704196, -0.12000238,  0.20172156, ...,  0.0606968 ,
#         -0.02551591, -0.10963563],
#        [ 0.00977565, -0.11188473,  0.15327264, ...,  0.12097086,
#          0.00371699,  0.11089064],
#        ...,
#        [ 0.15975083, -0.12796631, -0.12143513, ...,  0.00048973,
#          0.08025642,  0.09352569],
#        [-0.10482513, -0.00614406,  0.16832988, ...,  0.1809843 ,
#          0.16601638, -0.18317826],
#        [ 0.10724227,  0.1758986 ,  0.03089926, ...,  0.09623767,
#          0.0754603 , -0.14214656]], dtype=float32)>
model.weights[3]
# <tf.Variable 'dense_8/bias:0' shape=(10,) dtype=float32, numpy=array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)>

model.trainable_weights == model.trainable_variables
# True

model.trainable_weights is model.trainable_variables
# False

model.trainable_weights
# [<tf.Variable 'dense_8/kernel:0' shape=(784, 128) dtype=float32, numpy=
#  array([[-0.05531485, -0.07744511, -0.0746323 , ..., -0.06485563,
#          -0.05913215, -0.03761471],
#         [ 0.00124295,  0.07567873,  0.00529402, ...,  0.03713652,
#          -0.03533567,  0.02690652],
#         [ 0.06762456, -0.02606952, -0.03866001, ...,  0.0321365 ,
#          -0.05224103, -0.03288466],
#         ...,
#         [ 0.05756753,  0.03487769, -0.04956114, ...,  0.07006838,
#          -0.04104863, -0.08020123],
#         [ 0.03739367,  0.05591244,  0.0753384 , ...,  0.0743489 ,
#           0.00566504, -0.05400074],
#         [-0.00660357, -0.06026491, -0.07941656, ..., -0.05506966,
#          -0.06525376, -0.05522396]], dtype=float32)>,
#  <tf.Variable 'dense_8/bias:0' shape=(128,) dtype=float32, numpy=
#  array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
#         0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
#         0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
#         0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
#         0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
#         0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
#         0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
#         0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)>,
#  <tf.Variable 'dense_9/kernel:0' shape=(128, 10) dtype=float32, numpy=
#  array([[ 0.09544928,  0.08058016, -0.19936405, ...,  0.06292586,
#           0.05765642, -0.18936837],
#         [-0.03744939, -0.09664733,  0.01312402, ...,  0.10993271,
#           0.14227311,  0.10375817],
#         [-0.11351802,  0.05995773,  0.19267906, ...,  0.02832732,
#           0.1751137 ,  0.08727919],
#         ...,
#         [ 0.18473722,  0.0153936 ,  0.17687447, ..., -0.07043667,
#           0.07194577, -0.2060329 ],
#         [ 0.04917909, -0.19079669,  0.03048648, ..., -0.04494686,
#           0.19417565, -0.18756153],
#         [ 0.04652865,  0.02577874, -0.12224188, ..., -0.19071367,
#           0.04850109,  0.04275919]], dtype=float32)>,
#  <tf.Variable 'dense_9/bias:0' shape=(10,) dtype=float32, numpy=array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)>]

Learning

학습시키는 가지 방법

1. compile 방식 => computational graph 형태로 변환 시켜준다 / 내가 만든 모델이 tensorflow에서 지원해준다

2. 직접 구현하는 방식

 

 

 

반응형
728x90
반응형

데이터 학습 단위 및 용어

1. 전체 데이터 => 가지고 있는 전체 데이터

2. Epoch => 전체 데이터 셋을 한번 학습 했을 때의 단위. 1 Epoch은 전체 데이터를 학습 / Epoch = 전체 데이터 /Batch size

3. Iteration => 학습 횟수. 1 Iteration은 1 학습

4. Batch size => 1 Iteration에 사용되는 데이터 크기

5. Stochastic => 학습 데이터를 하나씩 사용하면서 가중치를 업데이트 하는 방법

 

전체 데이터를 한꺼번에 학습하면 메모리 문제가 발생하고 정교하지 않게 가중치가 업데이트 되는 문제가 있을 있다

그래서 전체 데이터를 한꺼번에 사용하지 않고 데이터를 조각 내서 사용하면 한꺼번에 학습 하는 것보다 속도가 느려지긴 하지만 정교하게 가중치가 업데이트 되기 때문에 목표하는 모델을 만들수 있는 가능성이 높아진다

One Data 1D Vector

Neural network의 연산은 array기반의 vectorization연산을 하고 fully connected하기 때문에 하나의 데이터는 1차원의 vector를 입력값으로 받아야 한다

Neural network에서 이미지 데이터를 활용한다면

이미지 데이터 특성상 1차원으로 변환하면 계산복잡도가 증가한다는 문제가 발생한다

Neural Network for image data

Image data

이미지 데이터의 특성

1. 이미지 데이터는 2차원 이상이다

2. 전통적인 머신러닝을 사용하려면 하나의 데이터가 일차원 형태로 변환해야 한다

3. 2차원 데이터에서 1차원 데이터로 변환할 경우 Locality를 잃어버린다(주변 값과의 관계가 사라진다)

4. I.I.D가 아니다

5. Neural Network에서 Fully connected한 특징때문에 1차원으로 변형시 feature가 기하 급수적으로 늘어난다(연산 복잡도가 폭발적으로 증가한다)

두 가지 해결 방법 (Column이 많은 이미지 데이터)

1. 다른 문제로 환원

- 원본 이미지를 다른 형태로 바꾼다

- Feature가 있는지 없는지 여부의 문제로 환원한다

- Feature문제로 환원했을 중요한 것은 어떤 Feature를 뽑아 내야 하는지가 관건이다

2. 전처리

- 사이즈 조절

- 차원 조절

- 의미를 잃어버리기 때문에 추가적인 가정이 필요하다

Tensorflow

Tensorflow는 numpy를 기반으로 autograd(자동 미분)을 지원하고 neural network에서 자주 사용하는 기능들을 지원해주는 라이브러리이다

뿐만 아니라 numpy는 연산이 복잡해지면 속도가 느려지는데 gpu연산이 가능하도록 지원하도록 만들어졌기 때문에 훨씬 효율적인 NN 프로그래밍을 도와준다 (GPU사용시 50배 이상 속도가 빨라진다)

 

import tensorflow as tf 
tf.__version__ # 2.3버전 이후에 많이 바뀌었기 때문에 본 수업은 2.3버전 이상에서 진행된다 
# '2.6.0'

tf.version.VERSION
# '2.6.0'

tf.executing_eagerly() 
# True

Neural Network를 구성하는 6가지 방법

1. tf.keras.models.Sequential # 쉽지만 쓸모없는 방식

2. tf.keras.models.Model # 전문가적인 방식

3. subclass (tf.keras.models.Model) # 전문가적인 방식

4. tf.estimator.

5. tf.nn.

6. tf.Module # Meta class 방식

2,3 방식을 집중적으로 알아볼 것이다

a = tf.constant([1,2,3]) # Tensor라고 나오면 상수 / immutable 
b = tf.Variable([1,2,3]) # Varaible은 이름이 있다 / mutable => 가중치를 갱신할때 사용한다 

a
# <tf.Tensor: shape=(3,), dtype=int32, numpy=array([1, 2, 3], dtype=int32)>

b
# <tf.Variable 'Variable:0' shape=(3,) dtype=int32, numpy=array([1, 2, 3], dtype=int32)>

b.assign([3,4,5]) 
# <tf.Variable 'UnreadVariable' shape=(3,) dtype=int32, numpy=array([3, 4, 5], dtype=int32)>

b
# <tf.Variable 'Variable:0' shape=(3,) dtype=int32, numpy=array([3, 4, 5], dtype=int32)>

tf.debugging.set_log_device_placement(True) # gpu연산을 하는지 확인할 수 있다 / colab에서 사용시 Runtime type을 GPU로 바꾼후 확인해 보세요
a = tf.constant([1,2,3])
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0

a + a
# Executing op AddV2 in device /job:localhost/replica:0/task:0/device:GPU:0
# <tf.Tensor: shape=(3,), dtype=int32, numpy=array([2, 4, 6], dtype=int32)>

b = tf.Variable([1,2,3]) 
# Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
# Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:CPU:0
# Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:CPU:0

b+b
# Executing op ReadVariableOp in device /job:localhost/replica:0/task:0/device:CPU:0
# Executing op ReadVariableOp in device /job:localhost/replica:0/task:0/device:CPU:0
# Executing op AddV2 in device /job:localhost/replica:0/task:0/device:GPU:0
# <tf.Tensor: shape=(3,), dtype=int32, numpy=array([2, 4, 6], dtype=int32)>

d = tf.constant([3,4,5])
# Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0

'__array_priority__' in dir(d) # numpy와 호환된다 
# True

d.numpy()
# array([3, 4, 5], dtype=int32)
import numpy as np

a = tf.constant([1,2,3]) 
b = tf.Variable([1,2,3])
c = np.array([1,2,3])
# Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
# Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
# Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:CPU:0
# Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:CPU:0
# Executing op DestroyResourceOp in device /job:localhost/replica:0/task:0/device:CPU:0

%timeit np.add(a,a) # numpy method에 tensor를 넣어도 된다 / tensor => numpy 변환 후 numpy operation을 한다 / 이때는 resource가 적게 들어간다 
# The slowest run took 24.50 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 5: 9.62 µs per loop

np.add(b,b)
# Executing op ReadVariableOp in device /job:localhost/replica:0/task:0/device:CPU:0
# Executing op Identity in device /job:localhost/replica:0/task:0/device:GPU:0
# Executing op ReadVariableOp in device /job:localhost/replica:0/task:0/device:CPU:0
# Executing op Identity in device /job:localhost/replica:0/task:0/device:GPU:0
# array([2, 4, 6], dtype=int32)
%timeit tf.add(c,c) # tensor연산에 numpy를 넣으면 gpu를 사용하여 연산한다 / numpy에서 tensor로 타입을 바꾼 후 tensor operation을 한다 / 이때는 resource가 많이 들어간다 
# Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
# Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
...
# Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
# Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
# Executing op AddV2 in device /job:localhost/replica:0/task:0/device:GPU:0
# 100 loops, best of 5: 7.22 ms per loop
%timeit tf.add(a,a) # 데이터 양이 많다면 텐서데이터로 텐서 연산할 때가 가장 빠르다 
# Executing op AddV2 in device /job:localhost/replica:0/task:0/device:GPU:0
# Executing op AddV2 in device /job:localhost/replica:0/task:0/device:GPU:0
...
# Executing op AddV2 in device /job:localhost/replica:0/task:0/device:GPU:0
# Executing op AddV2 in device /job:localhost/replica:0/task:0/device:GPU:0
# 100 loops, best of 5: 2.42 ms per loop

numpy데이터를 tensor연산했을때가 tensor데이터를 numpy연산 했을 때 보다 훨씬 속도가 느리다

따라서 numpy데이터 타입일 경우 tensor로 변환 후 연산하는 것이 빠르다

Big data일 때

연산 속도가 빠른 순위

1. Tensor로 Tensor연산

2. Tensor로 numpy연산

3. Numpy로 Tensor연산

dir(tf.keras) # Input, Model, Sequential => alias(단축 표현) / s가 붙어 있으면 하위 기능을 제공한다 ex) activations 
['Input',
 'Model',
 'Sequential',
 '__builtins__',
 '__cached__',
 '__doc__',
 '__file__',
 '__internal__',
 '__loader__',
 '__name__',
 '__package__',
 '__path__',
 '__spec__',
 '__version__',
 '_sys',
 'activations',
 'applications',
 'backend',
 'callbacks',
 'constraints',
 'datasets',
 'estimator',
 'experimental',
 'initializers',
 'layers',
 'losses',
 'metrics',
 'mixed_precision',
 'models',
 'optimizers',
 'preprocessing',
 'regularizers',
 'utils',
 'wrappers']
tf.keras.Input is tf.keras.layers.Input # 단축 표현 (alias)
# True

dir(tf.keras.Model)
['_TF_MODULE_IGNORED_PROPERTIES',
 '__call__',
 '__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getstate__',
 ...
 
 'variables',
 'weights',
 'with_name_scope']

Deep learning framework의 역사

theano => 최초의 deep learning framework

wrapper backend: theano interface: keras keras는 theano의 단점을 보완했다

- theory를 구현할 수 있게 문법을 만들었다 (이론과 실제의 간극을 줄였다)

 

theano다음으로 tensorflow가 출현했다

keras는 theano/tensorflow/cntk(microsoft)로 쉽게 전환 할 수 있도록 보완했다

tensorflow다음으로 torch(facebook)가 출현했다

keras만든 사람을 google로 스카웃 tensorflow 1.6부터 keras를 포함 시켰다

tensorflow 2.0부터는 tensorflow 1version 없애버렸다

tensorflow 2.6부터는 keras/tensorflow를 분리시켰다

backend개념은 keras에서 사용되는 개념이다.

즉, keras는 theano/tensorflow/cntk로 구동할 수 있고 껍데기 interface는 keras를 사용할 수 있다

model = tf.keras.models.Sequential() # 함성함수 껍데기 
model2 = tf.keras.models.Model()  

# Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
issubclass(model.__class__, model2.__class__) # model이 model2의 subclass이다 
# Ture

model.__class__.__bases__ # 부모는 Functional 
# (keras.engine.functional.Functional,)

model.__class__.mro()
# [keras.engine.sequential.Sequential,
 keras.engine.functional.Functional,
 keras.engine.training.Model,
 keras.engine.base_layer.Layer,
 tensorflow.python.module.module.Module,
 tensorflow.python.training.tracking.tracking.AutoTrackable,
 tensorflow.python.training.tracking.base.Trackable,
 keras.utils.version_utils.LayerVersionSelector,
 keras.utils.version_utils.ModelVersionSelector,
 object]
 
model2.__class__.__bases__
# (keras.engine.base_layer.Layer, keras.utils.version_utils.ModelVersionSelector)

sample = np.array([[1,2]])
# layer 추가 방법1 (한개씩) 

model.add(tf.keras.layers.Dense(2))
# layer 추가 방법2 (한꺼번에)

model2 = tf.keras.models.Sequential([
  tf.keras.layers.Dense(2)
])
#
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op DestroyResourceOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op DestroyResourceOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op DestroyResourceOp in device /job:localhost/replica:0/task:0/device:GPU:0
model(sample) # Feed foward(predict) / 결과가 tensor / tensor연산 / 합성함수 방식 / 이론과 현실의 간극을 줄이기 위한 방법 
# Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
# Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
...
# Executing op ReadVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
# Executing op BiasAdd in device /job:localhost/replica:0/task:0/device:GPU:0
# <tf.Tensor: shape=(1, 2), dtype=float32, numpy=array([[ 0.44565853, -0.7990122 ]], dtype=float32)>
model.predict(sample) # numpy연산 / method 방식 
# Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op RangeDataset in device /job:localhost/replica:0/task:0/device:CPU:0
Executing op RepeatDataset in device /job:localhost/replica:0/task:0/device:CPU:0
Executing op MapDataset in device /job:localhost/replica:0/task:0/device:CPU:0
Executing op PrefetchDataset in device /job:localhost/replica:0/task:0/device:CPU:0
Executing op FlatMapDataset in device /job:localhost/replica:0/task:0/device:CPU:0
Executing op TensorDataset in device /job:localhost/replica:0/task:0/device:CPU:0
Executing op RepeatDataset in device /job:localhost/replica:0/task:0/device:CPU:0
Executing op ZipDataset in device /job:localhost/replica:0/task:0/device:CPU:0
Executing op ParallelMapDatasetV2 in device /job:localhost/replica:0/task:0/device:CPU:0
Executing op OptionsDataset in device /job:localhost/replica:0/task:0/device:CPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AnonymousIteratorV2 in device /job:localhost/replica:0/task:0/device:CPU:0
Executing op MakeIterator in device /job:localhost/replica:0/task:0/device:CPU:0
Executing op __inference_predict_function_2745 in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Identity in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op DeleteIterator in device /job:localhost/replica:0/task:0/device:CPU:0
array([[ 0.44565853, -0.7990122 ]], dtype=float32)
model1.add(tf.keras.layers.Dense(2)) # 자동적으로 array형태로 맞춰준다 / input shape을 지정하지 않아도 된다 

model1.summary() # input shape을 지정하지 않았기 때문에 어떤 모델인지 아직 불명확하다 
# raise ValueError('This model has not yet been built. '
# ValueError: This model has not yet been built. Build the model first by calling `build()` or calling `fit()` with some data, or specify an `input_shape` argument in the first layer(s) for automatic build.
model1.built # 아직 만들어지지 않았다 
# False

model1(sample) # sample 데이터구조를 받았기 때문에 자동적으로 만들어진다 
# Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
# Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
...
# Executing op BiasAdd in device /job:localhost/replica:0/task:0/device:GPU:0
# <tf.Tensor: shape=(1, 2), dtype=float32, numpy=array([[1.4473007, 1.210985 ]], dtype=float32)>

model1.summary() 
# Model: "sequential_2"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# dense_3 (Dense)              (1, 2)                    6         
# _________________________________________________________________
# dense_4 (Dense)              (1, 2)                    6         
# =================================================================
# Total params: 12
# Trainable params: 12
# Non-trainable params: 0
# _________________________________________________________________
sample_test = np.array([[1,2]])
model_test1 = tf.keras.models.Sequential() 
model_test1.add(tf.keras.layers.Dense(2, input_shape=(2,))) # 데이터가 몇개가 들어올지 지정되지 않는다 / input shape은 data sample 1개의 모양이다 
# Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
...
# Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0

model_test1.built
# True

model_test1.summary() # None은 데이터의 갯수 상관없이 받을 수 있다는 의미이다 / input shape을 지정하면 데이터의 갯수 상관없이 받을 수 있는 형태로 만들어진다 
# Model: "sequential_7"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# dense_11 (Dense)             (None, 2)                 6         
# =================================================================
# Total params: 6
# Trainable params: 6
# Non-trainable params: 0
# _________________________________________________________________
sample_test2 = np.array([[1,2]])
inputs = tf.keras.Input(shape=(2,))
x = tf.keras.layers.Dense(4, activation=tf.nn.relu)(inputs)
outputs = tf.keras.layers.Dense(2, activation=tf.nn.relu)(x)
model_test2 = tf.keras.models.Model(inputs=inputs, outputs=outputs)  
# Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
# Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
...
# Executing op DestroyResourceOp in device /job:localhost/replica:0/task:0/device:GPU:0
# Executing op DestroyResourceOp in device /job:localhost/replica:0/task:0/device:GPU:0

model_test2.built
# True 

model_test2.summary()
# Model: "model_5"
# _________________________________________________________________
# Layer (type)                 Output Shape              Param #   
# =================================================================
# input_3 (InputLayer)         [(None, 2)]               0         
# _________________________________________________________________
# dense_13 (Dense)             (None, 4)                 12        
# _________________________________________________________________
# dense_14 (Dense)             (None, 2)                 10        
# =================================================================
# Total params: 22
# Trainable params: 22
# Non-trainable params: 0
# _________________________________________________________________

 

반응형
728x90
반응형

OpenCV ML

import cv2
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

data = load_iris()

X_train, X_test, y_train, y_test = train_test_split(data.data ,data.target)

# 편미분을 위한 데이터 타입 변환 
X_train = X_train.astype('float32')
y_train = y_train.astype('float32')
X_test = X_test.astype('float32')
y_test = y_test.astype('float32')

X_train.shape
# (112, 4)

knn = cv2.ml.KNearest_create()
knn.train(X_train,cv2.ml.ROW_SAMPLE, y_train) # transpose되어 있는 데이터를 transpose하면 연산에 비효율적이기 때문에 내부적으로 최적화 계산을 해준다 
# True

cv2.ml.ROW_SAMPLE
# 0

y_test.shape
# (38,)

knn.predict(X_test)[1].reshape(38) == y_test
# array([ True,  True,  True,  True,  True,  True,  True,  True,  True,
#        True,  True,  True, False,  True,  True,  True,  True,  True,
#        True, False,  True,  True,  True,  True,  True,  True,  True,
#        True,  True,  True,  True,  True,  True,  True,  True,  True,
#        True,  True])

Assumption

가정이 많아지면 많아질 수록 가정을 만족하는 데이터에 대해서는 성능이 좋아지지만, 일반성은 떨어진다

즉, 잘 정제된 데이터를 학습해서 좋은 데이터에서는 성능이 좋지만, 정제되지 않은 현실 데이터에 적용하기에는 좋지 않은 모델이 만들어질 수 있다

 

import tensorflow as tf 
import matplotlib.pyplot as plt

(X_train,y_train), (X_test, y_test) = tf.keras.datasets.mnist.load_data()

plt.imshow(X_train[0], cmap='gray') # 패턴이 뚜렷하게, 크기를 일치하는 가정을 둔 사례

대체적으로 성능 좋은 알고리즘 (대세)

1980 - 1990 ANN

1990 - 2000 SVM

2000 - 2010 Ensemble (Random Forest)

               - Structured data => Boosting

               - XGBoosting, LightGBM

               - ETC (Deep Learning)

데이터가 작을 때에는 SVM부터 사용하는 것이 좋다

왜냐하면 Ensemble, Boosting, Deep Learning은 데이터가 많을 때라는 가정이 있어야 성능이 좋기 때문이다

Neural Network

Neural network는 뉴런에서 영감을 얻어 데이터를 통해 스스로 학습이 가능하도록 설계된 알고리즘, 네트워크 또는 모델이라고 한다

모델의 구조를 먼저 정하고

그 구조에 있는 파라미터를 찾는 모델 방식을 가진다

 

구조도 학습을 통해서 알아낼 수 있다 (NAS/Neural Architecture Search)

Hypothesis

가설은 어떤 현상을 해결하기 위한 함수이고 사실과 비슷하다고 믿는 함수이다

Model

머신러닝에서는 가설 = 모델이다

정의 자체에서 모델은 항상 틀릴 수 있다

모델은 시스템 관점에서 머신러닝 알고리즘을 사용해서 데이터로 학습시킨 것을 머신러닝 모델이라고 한다

※ scikit-learn에서 학습 안된 알고리즘을 estimator라고 한다

모델의 4가지 관점

1. 수학적으로 표현할 수 있어야 한다

2. 그림 또는 그래프로 표현할 수 있어야 한다

3. 통계치를 통해서 표현할 수 있어햐 한다

4. 코드를 통해서 표현할 수 있어야 한다

모델 분류 기준들

1. Linear vs Nonlinear

- Linear는 aX+b에서 a와 b를 찾는데 집중한다

- Nonlinear는 회귀식이 비선형 함수로 나타내는 경우를 말한다

2. Generative vs Discriminative

- Generative는 입력값과 결과값이 주어질때, 일정한 분포 규칙속에 존재한다는 가정을 하는 모델

- Discriminative는 입력 데이터가 있을 때 label data를 구별해내는 모델

3. Black box vs Descriptive

- Black box는 설명 불가능

- Descriptive는 설명 가능

4. First-principle vs Data-driven

- First-principle은 원리, 규칙에 기반한 모델인가

- Data-driven은 데이터에 기반한 모델인가

5. Stochastic vs Deterministic

- Stochastic는 확률론적인 방법

- Deterministic 결정론적인 방법

6. Flat vs Hierarchical

7. Parametric vs Non-parametric

- Parametric는 고정된 개수의 파라미터들을 학습하여 튜닝하는 것

- Non-parametric는 학습해서 튜닝할 파라미터가 명시적으로 존재하지 않거나 정확히 셀 수 없는 경우

Data modeling vs Algorithmic Modeling

Data modeling

- 데이터를 바탕으로 파라미터를 찾는 것에 집중하는 모델

- 데이터를 해당 모델에 얼마나 잘 적합시키는 가에 초점이 있다

- 모델 자체를 가정하기 때문에 모델이 잘 못될 경우 잘 못된 결과를 도출 할 수 있다

 

Algorithmic modeling

- 알고리즘을 모르는 상태에서 데이터를 통해 모델을 새로 만드는 방법

Perceptron

뉴런을 모방한 알고리즘 또는 모델

Perceptron과 linear model의 차이점은 선형 함수의 기울기와 bias를 찾는 방법이 다르다

perceptron은 delta rule에 의해서 학습을 한다

delta rule은 기대값과 실제값의 차이를 줄여 나가는 방식으로 싱글 레이어 퍼셉트론에서 인공 뉴런들의 연결 강도를 갱신하는데 쓰인다

 

from sklearn.linear_model import Perceptron
per = Perceptron() # linear model 
per.fit(X_train, y_train)
# Perceptron(alpha=0.0001, class_weight=None, early_stopping=False, eta0=1.0,
#           fit_intercept=True, max_iter=1000, n_iter_no_change=5, n_jobs=None,
#           penalty=None, random_state=0, shuffle=True, tol=0.001,
#           validation_fraction=0.1, verbose=0, warm_start=False)

per.score(X_test, y_test)
# 0.8947368421052632

MLP(Multi Layer Perceptron)

MLP는 perceptron를 쌓기 위해서 Layer 개념을 도입하고 여러 layer를 연결한 형태를 말한다

neural network는 기본적으로 fully connected여야 한다

Memorization Capacity

Layer가 많으면 많을 수록 성능이 좋아진다

그러나 ML에서 feature처럼 layer가 많으면 많을 수록 데이터가 많이 필요하다

 

전통적인 머신러닝 알고리즘에서는 데이터가 아무리 많아도 더 이상 성능이 올라가지 않는 plateau라는 현상이 생긴다

Universal Approximation Theorem

이론적으로 activation 함수가 비선형 일때 레이어가 많으면 어떠한 형태의 함수도 만들어 낼 수 있다

따라서 어떠한 데이터 셋도 분류 할 수 있다

 

단, activation function을 sigmoid나 tanh같은 함수를 사용하면 gradient vanishing현상이 생긴다

layer를 함수라고 본다면 neural network는 composition function이다

Feature cross

두 개 이상의 feature를 연산해서 새로운 feature형태로 만들어 주는 기법

Gradient vanishing

Gradient vanishing은 Back-propagation(편미분 연산)을 할 때마다 gradient가 전달이 되야하는데

sigmoid나 tanh와 같은 activation을 사용하는 네트워크에서 깊이가 깊어지면 값이 0이 되어 학습이 안되는 현상을 말한다

 

Dying Relu

Dying relu는 모든 0이하의 입력에 대해서 미분 값이 0이 되어 가중치에 곱해지면서 해당 노드가 통째로 죽어버리는 현상을 말한다

Optimization

실제값 - 예측값을 함수로 일반화 시키고 가능한 (실제값 - 예측값)을 가장 작게 만드는 과정을 최적화한다

최소값 찾는 문제는 미분하는 방법과 미분을 쓰지 않는 방법 두 가지로 나뉘어 해결 할 수 있다

Fully connected된 layer는 array연산으로 바꿀 수 있다

따라서 Neural Network는 vectorization이 최적화된 연산을 지원한다

Back propagation

수치 미분을 통해 최적화 하는 과정

foward propagation이 결과를 prediction하는 과정이라면

back propagation은 반대로 prediction된 결과와 실제 값의 오차를 계산하여 가중치를 업데이트하는 것을 말한다

Epoch

Back-propagation을 하는 과정에서 가중치가 업데이트 되었기 때문에 앞서 학습에 사용되었던 데이터는 가중치 업데이트에 영향을 거의 미치지 않게 되어 의미를 잃어버린다

따라서 전에 학습했던 데이터를 재활용 함으로써 전체 데이터가 가중치를 업데이트하는데에 기여를 할 수 있도록 여러번 학습 시킨다

단, Epoch을 많이 하면 할 수록 overfitting이 발생할 수 있다

ex) 2 Epoch => 전체 데이터를 두 번 학습 시킨다

Regularization

모델에 제약(penalty)을 줌으로써 overfitting을 방지하고 일반화 시키는 방법

from sklearn.linear_model import Ridge, Lasso, ElasticNet, Perceptron

Lasso => L1을 추가한다

Ridge => L2를 추가한다

ElasticNeet => L1, L2를 추가한다

Learning Rate

Gradient decent를 할 때 어느 정도의 보폭으로 최소값에 도달할 것인가를 지정하는 파라미터 => 학습률

학습률이 클때는 속도가 빠른 대신 local minimum에 영원히 도달하지 못할 가능성이 있는 반면

학습률이 작을때는 local minimum에는 도달할 수 있겠지만 속도가 매우느린 단점을 갖는다

따라서 적당한 학습률을 선택하는 것이 중요하다

 

 

 

 

반응형

+ Recent posts