https://www.youtube.com/watch?v=6TGyI4XjlCk&t=1153s 

대부분 해당 영상에서 가져왔습니다.

 

 

컨볼루션 신경망이란 (Convolution Neural Network,  CNN) 

 

- 완전 연결 네트워크의 문제로 부터 시작

  ~ 매개변수의 폭발적인 증가

  ~ 공간 추론의 부족 (픽셀 사이 근접성 개념이 소실되는 문제)

 

- 합성곱 계층은 입력이미지가 커져도 매개변수 개수에 영향을 주지않음

 

- 어떤 이미지에도 차원 수와 상관없이 적용 가능

 

[이미지 출처]  https://medium.com/@pechyonkin/key-deep-learning-architectures-lenet-5-6fc3c59e6f4

 

 

2. 컨볼루션 연산

 

- 필터연산 

  ~ 입력데이터에 필터를 통해 연산을 진행

  ~ 필터에 대응하는 원소끼리 곱하고, 합을 구함

  ~ 연산이 완료된 결과를 feature 맵이라고 함

 

- 필터(filter)
  ~ 커널(kernel)이라고도 칭함

  ~ 필터의 사이즈는 "거의 항상 홀수"
       * 짝수이면 패딩이 비대칭이 되어버림

       * 왼쪽, 오른쪽을 다르게 주어야함

       * 중심위치가 존재, 즉 구별된 하나의 픽셀(중심 픽셀)이 존재

 ~ 필터의 학습 파라미터 개수는 입력 데이터의 크기와 상관없이 일정
 ~ 따라서, 과적합을 방지할 수 있음

 

[출처] https://towardsdatascience.com/intuitively-understanding-convolutions-for-deep-learning-1f6f42faee1

  ~ 일반적으로 합성곱 연산을 한 후 사이즈는

        (n - f + 1) * (n - f + 1)

         * n은 입력데이터의 크기, f는 필터의 크기  (정사각 일 떄)

         * 위의 경우 (5-3+1) = 3

 

- 패딩

  ~ 입력 데이터의 주변을 특정값으로 채우는 기법(주로 0으로 채움)

  ~ 전 이미지와 크기를 같이 하기위함

 

[출처] https://towardsdatascience.com/intuitively-understanding-convolutions-for-deep-learning-1f6f42faee1

  ~ TF에서 padding='valid'  시 패딩x padding='same' 시 입력값과 출력값의 크기를 같게

     (padding_size = (filter_size-1)/2, stride=1)

 

 

- 스트라이드

  ~ 필터를 적용하는 간격을 의미

  ~ 커지면 출력 데이터가 작아짐(과적합x)

     

- TF

conv = Conv2D(filters=N, kernel_size=(k,k), strides=5,
              padding='valid', activation='relu')

k*k size의 필터를 N개 적용하는 층, padding은 없고 strides 는 5

 

 

- 풀링 (Pooling)

  ~맥스풀링 (Max Pooling)

    * 가장 많이 사용

    * 일반적으로 strides=2, kernel_size=2 를 통해 특징맵을 절반으로 줄임

    * 물체의 주요한 특징을 학습할 수 있더록

  ~ 평균풀링(Avg Pooling)

     * 필터 내의 평균을 구하는과정

     * 일반적으로 strides=2, kernel_size=2 를 통해 특징맵을 절반으로 줄임

     * 과거에 많이 사용 요즘에는 거의 사용 x

 

 

- LeNet

최초의 cnn모델 위에서 배운 풀링을 활용하여 구현

 

원 모델은 activation 으로 sigmoid를 사용했으나 예제에서는 relu활용

from tensorflow.keras import Model
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense
from tensorflow.keras.datasets import mnist

import numpy as np


class LeNet5(Model):
  def __init__(self, num_classes):
    super(LeNet5, self).__init__()
    self.conv1 = Conv2D(6, kernel_size=(5,5), padding='same', activation='relu')
    self.conv2 = Conv2D(16, kernel_size=(5,5), activation='relu')
    self.max_pool = MaxPooling2D(pool_size=(2,2))
    self.flatten = Flatten()
    self.dense1 = Dense(120, activation='relu')
    self.dense2 = Dense(84, activation='relu')
    self.dense3 = Dense(10, activation='softmax')
  
  def call(self, input_data):
    x = self.max_pool(self.conv1(input_data))
    x = self.max_pool(self.conv2(x))
    x = self.flatten(x)
    x = self.dense3(self.dense2(self.dense1(x)))

    return x
    
model.compile(optimizer='sgd',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
  
callbacks = [tf.keras.callbacks.EarlyStopping(patience=3, monitor='val_loss'),
             tf.keras.callbacks.TensorBoard(log_dir='./logs', histogram_freq=1)]
             
             
model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          validation_data=(x_test,y_test),
          callbacks=callbacks)
          
%load_ext tensorboard         
%tensorboard --logdir logs

mnist에서의 결과

'TF' 카테고리의 다른 글

[TF] 딥러닝 학습기술  (0) 2022.04.12
[TF] 모델의 저장, callbacks  (0) 2022.04.11
[TF] 모델 컴파일 및 학습 mnist  (0) 2022.04.11
[TF] Layer, Model, 모델구성  (0) 2022.04.11

과대적합과 과소적합을 해결하는 딥러닝학습기술

 

 

 

1. 모델의 크기조절

- 가장 단순한 방법

- 모델의 크기를 줄인다는 것은 학습 파라미터의 수를 줄이는 것

- 당연히 학습속도도 같이 커지거나 작아짐

- 파라미터의 수가 클 수록 과적합에 더욱민감하잼

val_loss

 

model 의 경우 총 160,305개의 파라미터

model(small)의 경우 70,007개의 파라미터

model(big)의 경우 총 1,296,769개의 파라미터

 

2. 옵티마이저

 

- 확률적 경사하강법(SGD)

  전체를 한번에 계산하지않고 확률적으로 일부 샘플을 뽑아 조금씩 나누어 학습

  데이터의 수가 적어지기대문에 한 번 처리하는 속도는 빠름

  손실함수의 최솟값에 이르기 까지 다소 위아래로 요동

  단순하지만 문제에 따라 시간이 매우 오래걸림

 

- Momentum

  운동량을 의미, 관성을 의미

  이전의 속도를 유지하려는 성향

  SGD보다 방향이 적게 변함

from tensorflow.keras.optimizers import SGD

optimizer = SGD(learning_rate=0.001, momentum=0.9)
# 모멘텀안주면 일반적인거 씀

 

 

- Nesterov

  모멘텀의 방향으로 조금 앞선곳에서 그래디언트르르 구함

  시간이 지날수록 좀 더 빠르게 최솟값도달

optimizer = SGD(lr=0.001, momentum=0.9, nesterov=True)

 

 

- AdaGrad

  가장 가파른 경사를 따라 하강하는 방법

  학습률을 자동으로 변화시킴

  학습률이 너무 감소되어 전역최솟값에 도달하기 전에 학습이 빨리 종료되기도 하기댸문에 딥러닝에서 자제

from tensorflow.keras.optimizers import Adagrad
optimizer = Adagrad(learning_rate=0.01, epsilon=None, decay=0.0)

 

- RMSProp

  adagrad를 보완하기위해 등장

  합 대신 지수의 평균값을 활용

  학습이 잘안되면 학습률을 키우고 너무 크면 다시줄임

 

from tensorflow.keras.optimizers import RMSprop

optimizer = RMSprop(lr=0.001, rho=0.9, epsilon=None, decay=0.0)

 

- Adam

  모멘텀의 최적화와 RMSProp의 아이디어를 더한것

  지난 그래디언트의 지수 감소 평균을 따르고(Momentum), 지난 그레디언트 제곱의 지수 감소된 평균(RMSProp)을 따    름

  가장많이 사용되는 방법

 

from tensorflow.keras.optimizers import Adam

optimizer = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)

 

 

- 최적화 optimizer 비교

3. 가중치 초기화

 

- 가중치 소실

  활성화함수가 선형일 때, 은닉층의 갯수가 늘어 날수록 가중치가 역전파되며 가중치 소실문제 발생

  * 0~1사이로 출력되면서 0또는 1에 가중치값이 편중됨 이는 미분값이 0에 가까워짐을 의미

  * relu 등장

- 가중치 초기화문제

  가중치의 값이 치우쳐지면 표현 가능한 신경망의 수가 적어짐

  따라서 활성화 값이 골고루 분포되는것이 중요

 

- Xavier (Glorot)

  은닉층의 노드 수가 n이면 표준편차가 1/sqrt(n) 인분포

  활성화함수가 선형인 경우 매우적합

 

- He

  표준편차가 sqrt(2/n) 인분포

  활성화함수가 비선형일떄 매우적합

 

Dense(1, kernel_initializer='he_normal')

Dense(1, kernel_initializer='glorot_normal')

 

 

4. 배치 정규화

 

- 모델에 들어가는 샘플들을 균일하게 만드는 방법

 

- 가중치의 활성화값이 적당히 퍼지게끔함

 

- 학습을 빠르게 진행시킴

 

- 일반화성능ㅇ을 늘림

 

- 과대적합방지

 

- 주로  Dense또는 Conv2D 이후, 활성화함수 이전에 놓임

 

from tensorflow.keras.layers import BatchNormalization, Dense, Activation
from tensorflow.keras.utils import plot_model

model = Sequential()

model.add(Dense(32, input_shape=(28*28,), kernel_initializer='he_normal'))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.summary()

plot_model(model)

5. 규제 regularzation 

 

- 과대적합(Overfitting, 오버피팅)을 방지하는 방법 중 하나


- 과대적합은 가중치의 매개변수 값이 커서 발생하는 경우가 많음


- 이를 방지하기 위해 큰 가중치 값에 큰 규제를 가하는 것


- 규제란 가중치의 절댓값을 가능한 작게 만드는 것으로, 가중치의 모든 원소를 0에 가깝게 하여 모든 특성이 출력에 주    는 영향을 최소한으로 만드는 것(기울기를 작게 만드는 것)을 의미


- 복잡한 네트워크 일수록 네트워크의 복잡도에 제한을 두어 가중치가 작은 값을 가지도록 함


- 적절한 규제값을 찾는 것이 중요

 

- L2 규제: 가중치의 제곱에 비례하는 비용이 추가(흔히 가중치 감쇠라고도 불림)
  가중치의 제곱합 

  손실함수값에 일정값을 더함으로써 과적합을 방지 

  lambda값이 크면 규제가 커지고 반대는 작아진다

  더 로버스트한 모델을 생성하므로 l1보다 더 많이 사용

 

from tensorflow.keras.regularizers import l1, l2, l1_l2

l2_model = Sequential([Dense(16, kernel_regularizer=l2(0.001), activation='relu', input_shape=(10000,)),
                       Dense(16, kernel_regularizer=l2(0.001), activation='relu'),
                       Dense(1, activation='sigmoid')])


- L1 규제: 가중치의 절댓값에 비례하는 비용이 추가
  가중치의 절대값합

  l2규제와 달리 어떤 가중치는 0이되는데 이는 모델이 가벼워짐을 의미

l1_model = Sequential([Dense(16, kernel_regularizer=l1(0.00001), activation='relu', input_shape=(10000,)),
                       Dense(16, kernel_regularizer=l1(0.00001), activation='relu'),
                       Dense(1, activation='sigmoid')])

 

- l1 l2 동시사용

Dense(16, kernel_regularizer=l1_l2(l1=0.00001, l2=0.001), activation='relu', input_shape=(10000,))

 

 

6. Dropout 

 

- 신경망을 위해 사용되는 규제 기법 중 가장 효과적이고 널리 사용되는 방법

 

- 학습할 때 사용하는 노드의 수를 전체 노드 중에서 일부만을 사용

- 신경망의 레이어에 드롭아웃을 적용하면 훈련하는 동안 무작위로 층의 일부 특성(노드)를 제외

 

- 테스트 단계에서는 그 어떤 노드도 드롭아웃 되지 않고, 대신 해당 레이어의 출력 노드를 드롭아웃 비율에 맞게 줄여줌

 

dropout_model = Sequential([Dense(16, activation='relu', input_shape=(10000,)),
                       Dropout(0.5),
                       Dense(16, activation='relu'),
                       Dropout(0.5),
                       Dense(1, activation='sigmoid')])

'TF' 카테고리의 다른 글

[TF] CNN 컨볼루션 신경망  (0) 2022.04.13
[TF] 모델의 저장, callbacks  (0) 2022.04.11
[TF] 모델 컴파일 및 학습 mnist  (0) 2022.04.11
[TF] Layer, Model, 모델구성  (0) 2022.04.11

 

https://www.youtube.com/watch?v=28QbrkRkHlo&t=5526s 

 

대부분 위의 영상을 참고했다.

 

 

 

모델의 저장과 복원

- save() 메소드를 이용하여 저장

 

- load_model() 을 이용해 복원

 

- Sequencial API, 함수형 API에서는 모델의 저장 및 로드가 가능하지만 서브클래싱 방식으로는 할 수 없음

 

- 서브클래싱 방식은 save_weights()와 load_weights()를 이용해 모델의 파라미터만 저장 및 로드

 

- JSON 형식
model.to_json() (저장)
tf.keras.models.model_from_json(file_path) (복원)

 

- YAML로 직렬화
model.to_yaml() (저장)
tf.keras.models.model_from_yaml(file_path) (복원)

 

model.save('mnist_model.h5')
loaded_model = models.load_model('mnist_model.h5')
loaded_model.summary()

 

 

콜백 (callbacks)

- 학습시에 callbacks 변수를 통해 훈련의 시작이나 끝에 호출할 객체 지정

- 여러개 같이 사용가능

 

from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping, LearningRateScheduler, TensorBoard

 

1. ModelCheckpoint

 

-정기적으로 모델의 체크포인트를 저장하고 문제가 발생시 복구하는데에 사용

check_point_cb = ModelCheckpoint('keras_mnist_model.h5', save_best_only=True)
history = model.fit(x_train, y_train, epochs=10,
                    validation_data=(x_val, y_val),
                    callbacks=[check_point_cb])

save_best_only=True 시 최상의 모델만을 저장 (validation 의 성능을 보고 판단)

 

 

2. EarlyStopping

 

- val_set이 한동안 개선되지 않을 경우 학습을 중단할 때 사용

- 일정 patience 동안 val_set의 점수가 오르지 않으면 학습을 중단함

- 모델이 좋아지지않으면 학습이 자동으로 중단되므로 epochs를 크게 가져가도 무방하다 (과적합에 주의)

- 학습이 끝난 후 최상의 가중치를 복원한다.

check_point_cb = ModelCheckpoint('keras_mnist_model.h5', save_best_only=True)
earlystopping_cb = EarlyStopping(patience=3, monitor='val_loss',
                                 restore_best_weights=True)
history = model.fit(x_train, y_train, epochs=10,
                    validation_data=(x_val, y_val),
                    callbacks=[check_point_cb, earlystopping_cb])

 

3. LearnigRateScheduler

- 학습중에 학습률을 변경시키기 위해 사용

def scheduler(epoch, leaning_rate):
  if epoch < 10:
    return leaning_rate
  else:
    return leaning_rate * tf.math.exp(-0.1)
    
    
print(round(model.optimizer.lr.numpy(),5))
lr_scheduler_cb = LearningRateScheduler(scheduler)

history = model.fit(x_train, y_train, epochs=15,
                    callbacks=[lr_scheduler_cb], verbose=0)

print(round(model.optimizer.lr.numpy(),5))

 

0.01
0.00607

함수를 정의하여 lr을 어떻게 변화시킬지 정의해야함

 

4. Tensorboard

 

- 학습과정 모니터링하기 위함

-

log_dir = './logs'
tensor_board_cb = [TensorBoard(log_dir=log_dir, histogram_freq=1, write_graph=True, write_images=True,)]
model.fit(x_train, y_train, batch_size=32, validation_data=(x_val, y_val),
          epochs=30, callbacks=tensor_board_cb)
%load_ext tensorboard
#%tensorboard --logdir {log_dir} port 8000
%tensorboard --logdir {log_dir}

이런식으로 동적으로 확인할 수 있는  창이 뜸

'TF' 카테고리의 다른 글

[TF] CNN 컨볼루션 신경망  (0) 2022.04.13
[TF] 딥러닝 학습기술  (0) 2022.04.12
[TF] 모델 컴파일 및 학습 mnist  (0) 2022.04.11
[TF] Layer, Model, 모델구성  (0) 2022.04.11

https://www.youtube.com/watch?v=28QbrkRkHlo&t=5526s 

대부분 위의 영상을 참고했다.

모델 컴파일 (compile)

 

- 학습시에 사용할 loss function

- 학습 진행방식을 결정하는 optimizer

- 모델을 모니터링할 지표를 설정하는 단계이다. 

 

model.compile(loss='sparse_categorical_crossentropy',
              optimizer='sgd',
              metrics=['accuracy'])

모델을 정의하고 loss, optimizer를 설정한다.

 

 

1. 손실함수 (loss function)

 

- 학습이 진행되면서 얼마나 잘되고 있는지 확인할 지표

 

- 모델이 훈련되면서 최소화될 값

 

- 손실함수에 따라서 학습파라미터fmf whwjd

 

-  미분가능한 함수를 사용

 

- https://keras.io/ko/losses/

 

- loss 설정 detail https://keras.io/api/losses/probabilistic_losses/#kldivergence-function 

 

- 주요 손실함수

 

* 분류

 categorical_crossentropy (원핫 인코딩되어있는 라벨데이터에 사용)

 sparse_categorical_crossentropy (다중분류)

 binary_crossentropy (이진분류)

* 회귀

 mean_squared_error

 mean_absolute_error ( mse에 비해서 좀 더 이상치에 강건함)

 

2. 옵티마이저 (optimizer)

 

- 손실함수를 기반으로 모델이 파라미터가 어떻게 업데이터 되어야하는지 결정한다,

 

- https://keras.io/ko/optimizers/

 

- 옵티마이저의 튜닝을 위해 따로 객체를 생성하여 컴파일 하기도한다.

*

from keras import optimizers

model = Sequential()
model.add(Dense(64, kernel_initializer='uniform', input_shape=(10,)))
model.add(Activation('softmax'))

sgd = optimizers.SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='mean_squared_error', optimizer=sgd)

위의 예와 같은방법으로

 

- 주요 옵티마이저

 keras.optimizer.SGD(): 기본적인 확률적 경사 하강법

 keras.optimizer.Adam(): 자주 사용되는 옵티마이저

 

3. metrics 

 

- 모니터링하는 지표

 

- loss function 이랑 비슷하지만 metric은 모델을 학습하는데 사용되지 않는다는 점에서 다름.

 

- 커스텀 metric

*

import keras.backend as K

def mean_pred(y_true, y_pred):
    return K.mean(y_pred)

model.compile(optimizer='rmsprop',
              loss='binary_crossentropy',
              metrics=['accuracy', mean_pred])

직접 정의한 메트릭도 가능

 

- https://keras.io/ko/metrics/ https://keras.io/api/metrics/

 

- 주요 메트릭

 mae

 mse

 accuracy (acc)

 

 

모델의 학습, 평가 및 예측 mnist

학습 fit()

- x : 학습데이터

- y : 학습데이터 정답

- epochs : 학습회수

- batch_size : 단일 배치에 있는 학습데이터 크기

- validaton_data : 검증을 위한 데이터

 

평가 evaluate()

- 테스트데이터를 이용한 평가

 

예측 predict()

- 임의의 데이터를 사용해 예측

 

데이터를 로드하고 간단하게 확인후 전처리 

import tensorflow as tf
from tensorflow.keras.datasets.mnist import load_data
from tensorflow.keras.models import Sequential
from tensorflow.keras import models
from tensorflow.keras.layers import Dense, Flatten, Input
from tensorflow.keras.utils import to_categorical, plot_model

from sklearn.model_selection import train_test_split
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('seaborn-white')
tf.random.set_seed(111)

(x_train_full, y_train_full), (x_test, y_test) = load_data(path='mnist.npz')

x_train, x_val, y_train, y_val = train_test_split(x_train_full, y_train_full,
                                                  test_size=0.3,
                                                  random_state=111)
                                                  
num_x_train = x_train.shape[0]
num_x_val = x_val.shape[0]
num_x_test = x_test.shape[0]

print(f'train_num :{num_x_train}\t val_num : {num_x_val}\t test_num : {num_x_test}')
train_num :42000	 val_num : 18000	 test_num : 10000
num_sample = 5
randim_idx = np.random.randint(60000, size=num_sample)

plt.figure(figsize=(15, 3))

for i, idx in enumerate(randim_idx):
  img = x_train_full[idx, :]
  label = y_train_full[idx]

  plt.subplot(1, len(randim_idx), i+1)
  plt.imshow(img)
  plt.title(f'index : {idx}, label : {label}')

 

x_train = x_train/255.
x_val = x_val/255.
x_test = x_test/255.

y_train = to_categorical(y_train)
y_val = to_categorical(y_val)
y_test = to_categorical(y_test)

 

모델구성 

 

model = Sequential([Input(shape=(28,28), name='input'),
                    Flatten(input_shape=[28,28], name='flatten'),
                    Dense(100, activation='relu', name='dense1'),
                    Dense(64, activation='relu', name='dense2'),
                    Dense(32, activation='relu', name='dense3'),
                    Dense(10, activation='softmax', name='output')])

model.summary()

plot_model(model, show_shapes=True)

 

 

 

 

모델 컴파일 및 학습

 

model.compile(loss='categorical_crossentropy',
              optimizer='sgd',
              metrics=['accuracy'])
history = model.fit(x_train, y_train,
                    epochs=50,
                    batch_size=128,
                    validation_data=(x_val, y_val))

history_dict = history.history
loss = history_dict['loss']
val_loss = history_dict['val_loss']

epochs = range(1, len(loss)+1)
fig = plt.figure(figsize=(12,5))

ax1 = fig.add_subplot(1, 2, 1)
ax1.plot(epochs, loss, color='blue', label='train_loss')
ax1.plot(epochs, val_loss, color='red', label='val_loss')
ax1.set_title('Train and Validation Loss')
ax1.set_xlabel('Epochs')
ax1.set_ylabel('Loss')
ax1.grid()
ax1.legend()

accuracy = history_dict['accuracy']
val_accuracy = history_dict['val_accuracy']

ax2 = fig.add_subplot(1, 2, 2)
ax2.plot(epochs, accuracy, color='blue', label='accuracy')
ax2.plot(epochs, val_accuracy, color='red', label='val_accuracy')
ax2.set_title('Train and Validation Accuracy')
ax2.set_xlabel('Epochs')
ax2.set_ylabel('Accuracy')
ax2.grid()
ax2.legend()

plt.show()

 

모델 평가 및 예측

 

model.evaluate(x_test, y_test)

pred_ys = model.predict(x_test)
print(pred_ys.shape)

np.set_printoptions(precision=7)
print(pred_ys[0])

arg_pred_y = np.argmax(pred_ys, axis=1)
plt.imshow(x_test[0])
plt.title(f'pred_label : {arg_pred_y[0]}')
plt.show()

 

혼동행렬

from sklearn.metrics import classification_report, confusion_matrix
import seaborn as sns
sns.set(style='white')

plt.figure(figsize=(8,8))
cm = confusion_matrix(np.argmax(y_test, axis=1), np.argmax(pred_ys, axis=1))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')
plt.xlabel('Predicted Label')
plt.ylabel('True Label')
plt.show()

 

print(classification_report(np.argmax(y_test, axis=1), np.argmax(pred_ys, axis=1)))

'TF' 카테고리의 다른 글

[TF] CNN 컨볼루션 신경망  (0) 2022.04.13
[TF] 딥러닝 학습기술  (0) 2022.04.12
[TF] 모델의 저장, callbacks  (0) 2022.04.11
[TF] Layer, Model, 모델구성  (0) 2022.04.11

https://www.youtube.com/watch?v=28QbrkRkHlo&t=5526s 

게시글의 내용의 대부분은 위 영상을 참고하며 작성했다.

질 좋은 강의를 무료로 공개하셔서 공부하는데 크게 도움이 될 것이다.

 

 

딥러닝을 학습함에 있어서 필요한 요소로는 크게 네가지로 분류할 수 있다.

 

- 모델을 구성하는 layer

- 입력데이터와 출력값

- 학습시에 사용할 loss function

- 학습 진행방식을 결정하는 optimizer

 

딥러닝의 기본구조에 대한 개념이 있다고 가정하고 keras와 tensorflow를 사용하여 모델을  쌓는 방법에 대해 알아보려한다.

이미지 출처 :&nbsp;http://cloudinsight.net/ai/%EB%94%A5%EB%9F%AC%EB%8B%9D%EC%9D%98-%EA%B0%9C%EB%85%90%EA%B3%BC-%EC%82%AC%EB%A1%80/

Layer

인풋레이어와 아웃풋 레이어를 제외하고 사이의 층, 위 그림의 노란색 노드들을 layer이라고 할 수 있으며 신경망의 핵심데이터 구조이다.

하나이상의 텐서를 입력받아 하나이상의 텐서를 출력한다.

역전파 방법과 체인룰을 이용하여 가중치를 업데이트하며 계산하는 층이라고 할 수 있다.

 

텐서플로와 케라스에서 주로 사용하는 레이어는 크게

- Dense

- Activation

- Flatten

- Input

으로 나뉜다 물론 cnn의 conv도 레이어라고 할 수 있지만 추후에 다루도록하자

 

from tensorflow.keras.layers import Dense, Activation, Flatten, Input

 

1. Dense 

 

- 완전연결계층 (fully-connected layer) 으로 딥러닝 학습의 핵심 구조라고 할 수 있다.

 

- 노드의 수와 activation을 지정해야한다. 

 

- name을 통하여 레이어간의 구분이 가능하다.

 

- 가중치 초기화

 * 신경망의 성능에 큰 영향을 주는 요소

 * 동일한 데이터로 학습시키더라도 가중치의 초기값에 따라서 성능차이가 날 수 있음.

 * 보통 가중치의 초기값으로 0에 가까운 무작위 값을 사용

 * keras에서는 기본적으로 glorot uniform, zero bias로 초기화함.

 * kenel_initializer인자를 통해 다른 방법을 선택가능하다. (https://keras.io/api/layers/initializers/)

 

# 기본적인 사용 Dense(노드수, activation='활성화함수')
Dense(10, activation='softmax')

# Dense(노드수, activation='활성화함수', name='구분을위한(추후 summary 등이름설정'))
Dense(10, activation='relu', name='Dense Layer')

# Dense(노드수, activation='활성화함수', name='이름', kernel_initializer='가중치초기화 선택'))
Dense(10, kernel_initializer='he_normal', name='Dense Layer')

 

2. Activation

- Dense에서 정의할 수 있다

 

- 필요에 따라 별도 레이어를 만들 수 있지만 생략한다. 

 

- https://keras.io/ko/activations/

 

dense = Dense(10, activation='relu', name='Dense Layer')
Activation(dense)

 

이미지 출처 :&nbsp;https://medium.com/hyunjulie/activation-functions-a-short-summary-8450c1b1d426

 

3. Flatten

- 배치크기 또는 데이터크기를 제와하고 데이터를 1차원으로 쭉펼치는 작업이다.

 

- ex) (128, 3, 2, 2) -> (128,12)

 

Flatten(input_shape=(128,3,2,2))

 

4. Input

- 모델의 입력을 정의한다.

 

- shape, dtype등을 지정한다.

 

- summary 메소드에는 보이지 않는다.

 

Input(shape=(28,28), dtype=tf.float32)
Input(shape=(28,), dtype=tf.int32)

 

Model

위에서 언급한 layer들을 쌓아 하나의 모델을 구성한다. 

tf에서 제공하는 모델을 쌓는 방법은 세가지가있다.

 

- Sequential()

- 함수형 API

- 서브클래싱

 

 

모델구성

각 방법으로 모델을 쌓는 방법을 알아보자

 

1. Sequential()

 

- 모델이 순차적인 구조만을 가질 때에 사용한다.

 

- 가장 간단한 방법이라고 할 수 있으며 객체 생성이후 추가하는 방법, 한번에 리스트에 쌓는 방법이 있다

 

- 다중 입출력이 존재하는 등의 복잡한 모델을 구성할 수 없다.

 

* 객체에 쌓기

from tensorflow.keras.layers import Dense, Flatten, Activation, Input
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.utils import plot_model
model = Sequential()
model.add(Input(shape=(28, 28)))
model.add(Flatten(input_shape=[28,28]))
model.add(Dense(300, activation='relu'))
model.add(Dense(100, activation='relu'))
model.add(Dense(10, activation='softmax'))
model.summary()

 

1) 먼저 28,28짜리의 데이터를 입력받으면 

2) 28*28 = 784, 로 쭉펼친뒤에

3) 노드수가 300개인 층을 통과시킨다 우측 params를 보게 되면 235500을 볼 수 있는데

 784(전 노드의 수)*300 (각 가중치) + 300(각 편향)을 의미한다.

4) 노드수가 100개인 층을 통과시킨다 

 300(전 노드의 수)*100 (각 가중치) + 100(각 편향)

5) 최종적으로 10개의 값을 출력한다. 

total params 는 우측 params를 모두 더한 값이 나온다. 모델에서 찾아야하는 값이 266610이라는 뜻이다.

 

plot_model(model)

먼저 모델을 쌓을 틀을 만들고 그 위에 하나 하나 층을 쌓는 방법이다.

plot_model 을 이용하면 모델의 구조를 이미지로 확인가능하다.

 

* 리스트에 쌓기

 

model = Sequential([Input(shape=(28, 28), name='input'),
                    Flatten(input_shape=[28,28], name='Flatten'),
                    Dense(300, activation='relu', name='Dense1'),
                    Dense(100, activation='relu', name='Dense2'),
                    Dense(10, activation='softmax', name='Output')])

model.summary()

위와 같은 모델을 리스트를 이용한 방법으로 구성한 것이다.

 

 

2. 함수형 API

 

- 가장 권장되는 방법

 

- 모델을 복잡하고 유연하게 구성가능하다. 

 

- 다중입출력을 다룰 수 있다.

 

inputs = Input(shape=(28,28,1))
x = Flatten(input_shape=(28,28,1))(inputs)
x = Dense(300, activation='relu')(x)
x = Dense(100, activation='relu')(x)
x = Dense(10, activation='softmax')(x)

model = Model(inputs=inputs, outputs=x)
model.summary()

위의 모델을 함수형 api를 이용하여 구현하는 코드이다.

 

이번에는 다중입출력인 경우를 보자

from tensorflow.keras.layers import Concatenate

input_layer = Input(shape=(28,28))
hidden = Dense(300, activation='relu')(input_layer)
hidden1 = Dense(30, activation='relu')(hidden)
concat = Concatenate()([input_layer, hidden1])
output = Dense(1)(concat)

model = Model(inputs=[input_layer], outputs=[output])
model.summary()

plot_model(model)

함수형을 활용하면 이렇게 여러가지의 경우를 구현 가능하다. 층이 깊어지면 이전의 가중치가 소실되는 경우가 있는데 이를 보완하기 위해 위같은 방법을 이용한다고 한다.

 

input_1 = Input(shape=(10,10), name='input_1')
input_2 = Input(shape=(10,28), name='input_2')

hidden_1 = Dense(100, activation='relu', name='hidden1')(input_2)
hidden_2 = Dense(10, activation='relu', name='hidden2')(hidden_1)

concat = Concatenate()([input_1,hidden_2])
output = Dense(1, activation='sigmoid', name='output')(concat)
sub_out = Dense(1, name='sum_output')(hidden_2)

model = Model(inputs=[input_1, input_2], outputs=[output, sub_out])
model.summary()
plot_model(model)

이렇게 복잡한 수준의 모델도 구현 가능하다.

 

3. 서브클래싱

 

- 커스터마이징에 최적화된 방법이다.

 

- model 클래스를 상속받아 포함된 기능을 사용할 수 있다.

 * fit, evaluate, predict

 * load, save

 

- 주로 call 메소드 안에서 원하는 계산이 가능하다

 

- 권장되는 방법은 아니지만 어떤 모델의 구현 코드를 보고 해석이 가능해야한다.

class mymodel(Model):
  def __init__(self, unit=30, activation='relu', **kwargs):
    super(mymodel, self).__init__(**kwargs)
    self.dense_layer1 = Dense(300, activation=activation)
    self.dense_layer2 = Dense(100, activation=activation)
    self.dense_layer3 = Dense(units, activation=activation)
    self.output_layer = Dense(10, activation='softmax')

  def call(self, inputs):
    x = self.dense_layer1(inputs)
    x = self.dense_layer2(x)
    x = self.dense_layer3(x)
    x = self.output_layer(x)
    return x

 

모델 가중치확인

inputs = Input(shape=(28,28,1))
x = Flatten(input_shape=(28,28,1))(inputs)
x = Dense(300, activation='relu')(x)
x = Dense(100, activation='relu')(x)
x = Dense(10, activation='softmax')(x)

model = Model(inputs=inputs, outputs=x)
model.summary()
model.layers
[<keras.engine.input_layer.InputLayer at 0x7f911aa41090>,
 <keras.layers.core.flatten.Flatten at 0x7f911aa41d90>,
 <keras.layers.core.dense.Dense at 0x7f911a6af950>,
 <keras.layers.core.dense.Dense at 0x7f911a6af590>,
 <keras.layers.core.dense.Dense at 0x7f911aa53590>]

layer메소드를 이용하면 각 층에 접근할 수 있는데.

 

hidden_2 = model.layers[2]
hidden_2.name
'dense_27'

리스트안에 인덱싱으로 각 레이어에 접근가능하다.

 

weights, biases = hidden_2.get_weights()
print(weights.shape)
print(biases.shape)

print(weights[:5])
print(biases[:5])
(784, 300)
(300,)
[[ 0.0649123  0.0568922  0.0244069 ...  0.0261239 -0.0731153 -0.0429611]
 [-0.0251026 -0.0474078 -0.0255548 ...  0.0275116 -0.0723424  0.0565901]
 [-0.0404508  0.004266   0.0089313 ... -0.0602168  0.0643739  0.0600661]
 [-0.0161134  0.0169627 -0.0641473 ... -0.0534405  0.0665736  0.0594366]
 [ 0.0240779  0.0698114  0.0545021 ...  0.014021   0.0201097 -0.0600637]]
[0. 0. 0. 0. 0.]

각 레이어에 get_weights 메소드로 가중치를 확인 가능하다.

현재는 학습이 진행되지않았기때문에 각 initializer의 초기값상태이다.

 

다음에는 모델의 학습과 컴파일 부분을 게시하겠다.

'TF' 카테고리의 다른 글

[TF] CNN 컨볼루션 신경망  (0) 2022.04.13
[TF] 딥러닝 학습기술  (0) 2022.04.12
[TF] 모델의 저장, callbacks  (0) 2022.04.11
[TF] 모델 컴파일 및 학습 mnist  (0) 2022.04.11

+ Recent posts