안녕하세요.

이번 장에서는 지난시간에 배운 내용들을 토대로 코드를 작성해보도록 하겠습니다.

첫 번째에는 아예 새로운 CNN 모델을 구축(by Functional API)하여 학습시키는 방식을 구현하고, 두 번째에는 pre-trained model을 다운받아 transfer learning과 fine-tuning을 적용시킨 방식을 구현해보도록 하겠습니다. 

 

 

 

1. New model 구축 버전

import os
from tensorflow import keras
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras import layers
from tensorflow import keras
import matplotlib.pyplot as plt
import math

base_dir 경

 

base_dir = './datasets/COVID_19/'
train_dir = os.path.join(base_dir, 'train')
validation_dir = os.path.join(base_dir, 'validation')


train_datagen = ImageDataGenerator(
    featurewise_center=True,
    featurewise_std_normalization=True,
    rescale=1./255,
    rotation_range=20,
    width_shift_range=0.2,
    height_shift_range=0.2,
    horizontal_flip=True,
    validation_split=0.2)
 
 validation_datagen = ImageDataGenerator(rescale=1./255)
 
 
 train_generator = train_datagen.flow_from_directory(
        # 타깃 디렉터리
        train_dir,
        # 모든 이미지를 150 × 150 크기로 바꿉니다
        target_size=(150, 150),
        batch_size=32,
        # categorical_crossentropy 손실을 사용
        class_mode='categorical') #COVID_19는 3개의 클래스로 구성됨
        
 validation_generator = validation_datagen.flow_from_directory(
        validation_dir,
        target_size=(150, 150),
        batch_size=32,
        class_mode='categorical')
 
input_shape = (150,150,3)
img_input = layers.Input(shape=input_shape)
output1 = layers.Conv2D(kernel_size=(3,3), filters=32, activation='relu')(img_input)
output2 = layers.MaxPooling2D((2,2))(output1)
output3 = layers.Conv2D(kernel_size=(3,3), filters=64, activation='relu')(output2)
output4 = layers.MaxPooling2D((2,2))(output3)
output5 = layers.Conv2D(kernel_size=(3,3), filters=128, activation='relu')(output4)
output6 = layers.MaxPooling2D((2,2))(output5)
output7 = layers.Conv2D(kernel_size=(3,3), filters=128, activation='relu')(output4)
output8 = layers.MaxPooling2D((2,2))(output7)
output9 = layers.Flatten()(output8)
output10 = layers.Dropout(0.5)(output9)
output11 = layers.Dense(512, activation='relu')(output10)
predictions = layers.Dense(2, activation='softmax')(output11)

model = keras.Model(inputs=img_input, outputs=predictions)

model.summary()
opt = SGD(lr=INIT_LR, momentum=0.9)
loss = CategoricalCrossentropy(label_smoothing=0.1)
model.compile(loss=loss, optimizer=opt, metrics=["accuracy"])
train_step = math.ceil(train_generator.n/32)
valid_step = math.ceil(valid_generator.n/32)

history = model.fit_generator(
      train_generator,
      steps_per_epoch=train_step,
      epochs=30,
      validation_data=validation_generator,
      validation_steps=valid_step)
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(len(acc))

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()

plt.figure()

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()

plt.show()
model.save('CNN_epoch_20.h5')

test_dir = os.path.join(base_dir, 'test')
test_datagen = ImageDataGenerator(rescale=1./255)
test_generator = test_datagen.flow_from_directory(
        test_dir,
        target_size=(150, 150),
        batch_size=32,
        class_mode='binary')

test_step = math.ceil(test_generator.n/32)

test_loss, test_acc = model.evaluate_generator(test_generator, steps=test_step, workers=4)
print(f'test loss : {test_loss:.4f} / test acc : {test_acc*100:.2f} %')

 

 

 

 

 

2. Pre-trained model with transfer learning an fine tuning 구축 버전

import os
from tensorflow import keras
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras import layers
from tensorflow import keras
from tensorflow.keras.applications import VGG16
import matplotlib.pyplot as plt
import math

base_dir 경

 

base_dir = './datasets/COVID_19/'
train_dir = os.path.join(base_dir, 'train')
validation_dir = os.path.join(base_dir, 'validation')


train_datagen = ImageDataGenerator(
    featurewise_center=True,
    featurewise_std_normalization=True,
    rescale=1./255,
    rotation_range=20,
    width_shift_range=0.2,
    height_shift_range=0.2,
    horizontal_flip=True,
    validation_split=0.2)
 
 validation_datagen = ImageDataGenerator(rescale=1./255)
 
 
 train_generator = train_datagen.flow_from_directory(
        # 타깃 디렉터리
        train_dir,
        # 모든 이미지를 150 × 150 크기로 바꿉니다
        target_size=(150, 150),
        batch_size=32,
        # categorical_crossentropy 손실을 사용
        class_mode='categorical') #COVID_19는 3개의 클래스로 구성됨
        
 validation_generator = validation_datagen.flow_from_directory(
        validation_dir,
        target_size=(150, 150),
        batch_size=32,
        class_mode='categorical')
 
vgg_base = VGG16(weights='imagenet',
                  include_top=False,
                  input_shape=(150, 150, 3))
vgg_base.summary()

model = models.Sequential()
model.add(vgg_base)
model.add(layers.Flatten())
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dense(3, activation='softmax'))
for layer in vgg_base.layers:
	layer.trainable = False
    
for layer in vgg_base.layers[15:]:
	layer.trainable = True
opt = SGD(lr=INIT_LR, momentum=0.9)
loss = CategoricalCrossentropy(label_smoothing=0.1)
model.compile(loss=loss, optimizer=opt, metrics=["accuracy"])
train_step = math.ceil(train_generator.n/32)
valid_step = math.ceil(valid_generator.n/32)

history = model.fit_generator(
      train_generator,
      steps_per_epoch=train_step,
      epochs=30,
      validation_data=validation_generator,
      validation_steps=valid_step)
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(len(acc))

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()

plt.figure()

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()

plt.show()
model.save('CNN_epoch_20.h5')

test_dir = os.path.join(base_dir, 'test')
test_datagen = ImageDataGenerator(rescale=1./255)
test_generator = test_datagen.flow_from_directory(
        test_dir,
        target_size=(150, 150),
        batch_size=32,
        class_mode='binary')

test_step = math.ceil(test_generator.n/32)

test_loss, test_acc = model.evaluate_generator(test_generator, steps=test_step, workers=4)
print(f'test loss : {test_loss:.4f} / test acc : {test_acc*100:.2f} %')

 

안녕하세요. 

이번 글에서는 transfer learning과 fine-tuning을 하는 tensorflow code를 살펴보도록 하겠습니다.

 

 

 

1. Transfer Learning

아래 코드를 실행시키고 자세히 보면 prediction part(→Flatten, Dense layer 부분이 빠져있는걸 확인할 수 있습니다)

from tensorflow.keras.applications import VGG16

vgg_base = VGG16(weights='imagenet',
                  include_top=False,
                  input_shape=(150, 150, 3))
vgg_base.summary()

 

Prediction layers 분은 굳이 Functional API로 구현할 필요는 없기 때문에 sqeuntial로 prediction layer 부분을 추가해 줍니다.

from tensorflow.keras import models
from tensorflow.keras import layers

model = models.Sequential()
model.add(vgg_base)
model.add(layers.Flatten())
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.summary()

 

위와 같이 model을 구성했다면 이전에 배운대로 아래 코드를 수행시켜 학습을 실행시킵니다.

model.compile(optimizer=optimizers.RMSprop(lr=2e-5),
              loss='binary_crossentropy',
              metrics=['acc'])

history = model.fit(train_features, train_labels,
                    epochs=30,
                    batch_size=20,
                    validation_data=(validation_features, validation_labels))

 

 

 

2. Fine tuning

위와 같이 transfer learning을 적용시킨 후 특정 layer들만 학습시키려면 우선 아래와 같이 Convolution base 부분을 아래 코드와 같이 freezing 시킵니다.

for layer in vgg_base.layers:
	layer.trainable = False

 

 

보통 fine tuning을 할 때, 끝단에 위치한 bottom conv layer (=deeper layer) 부분만 미세하게 학습시켜주는 것이 일반적입니다. 왜냐하면, 어떠한 이미지분류 문제이든 해당 객체의 edge(←top layer의 conv filter가 뽑는 feature)는 거의 비슷할 테니까요. 중간 layer에 있는 conv filter가 보통 texture feature를 뽑아내는데, 만약 ImageNet에서 학습한 이미지의 texture와 내가 분류하려는 새로운 이미지들의 texture가 많이 다르다는 판단을 하게 된다면 이 부분도 미세하게 학습시켜주어야 합니다. 이러한 방법은 아래와 같은 코드로 진행이 됩니다.

for layer in vgg_base.layers[15:]:
	layer.trainable = True

 

 

[정리]

지금까지 배운 pre-trained model을 다운받아 transfer learning 및 fine-tuning을 적용시키는 코드를 작성해보도록 하겠습니다.

from tensorflow.keras import models
from tensorflow.keras import layers
from tensorflow.keras.applications import VGG16
vgg_base = VGG16(weights='imagenet',
                  include_top=False,
                  input_shape=(150, 150, 3))
vgg_base.summary()
for layer in vgg_base.layers:
	layer.trainable = False
for layer in vgg_base.layers[15:]:
	layer.trainable = True
model = models.Sequential()
model.add(vgg_base)
model.add(layers.Flatten())
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dense(2, activation='softmax'))
model.compile(optimizer=optimizers.RMSprop(lr=2e-5),
              loss='categorical_crossentropy',
              metrics=['acc'])

history = model.fit(train_features, train_labels,
                    epochs=30,
                    batch_size=20,
                    validation_data=(validation_features, validation_labels))

 

 

3. Model 저장 및 불러오기

앞선 작업을 통해 학습시킨 CNN 모델을 따로 저장할 수 도 있고, 나중에 데이터셋이 더 마련되면 해당 CNN 모델을 불러와 다시 re-training 시킬 수 있습니다.

 

tensorflow에서 CNN 모델을 저장시키거나 불러올 때 사용되는 CNN 모델 파일 format은 TensorFlow SavedModel 형식 or Keras H5 형식 or checkpoint 형식으로 크게 세 가지가 있습니다.

 

 

3-1. h5 파일 형태로 저장 또는 불러오기

tensorflow에서는 학습시킨 모델을 h5 형태의 파일로 저장시킬 수 있습니다. 본래 h5 형태의 파일은 keras에서 지원하던 파일형식인데 keras가 tensorflow backend를 사용할 때 tf.keras 로 h5 형태의 파일을 저장 및 불러오는 것을 가능하게 했습니다.

# Calling `save('my_model.h5')` creates a h5 file `my_model.h5`.
model.save("my_h5_model.h5")

# It can be used to reconstruct the model identically.
reconstructed_model = keras.models.load_model("my_h5_model.h5")

 

H5 파일은 Hierarchical Data Format (HDF) 5의 축약표현입니다. 보통 과학 데이터의 다차원 배열이 포함되기 때문에 다양한 과학분야(ex: 물리학, 공학, 딥러닝, ... 등)에서 주로 사용되는 파일형태입니다.

 

 

3-2. SavedModel 형태로 저장 또는 불러오기

# Calling `save('my_model')` creates a SavedModel folder `my_model`.
model.save("my_model")

# It can be used to reconstruct the model identically.
reconstructed_model = keras.models.load_model("my_model")

 

아래링크에서 SavedModel과 h5파일을 사용할 때 어떠한 차이가 있는지 기술해놓았으니 참고하시면 좋을 것 같습니다.

https://www.tensorflow.org/guide/keras/save_and_serialize?hl=ko 

 

Keras 모델 저장 및 로드  |  TensorFlow Core

소개 Keras 모델은 다중 구성 요소로 이루어집니다. 모델에 포함된 레이어 및 레이어의 연결 방법을 지정하는 아키텍처 또는 구성 가중치 값의 집합("모델의 상태") 옵티마이저(모델을 컴파일하여

www.tensorflow.org

 

 

 

3-3. Checkpoint

기존 tensorflow에서는 모델을 저장시키거나 불러올 때, SavedModel 방식 또는 Checkpoint 방식을 사용했습니다. Checkpoint에 대한 설명은 추후에 더 자세히 다루도록 하겠습니다. 아래링크에서 checkpoint에 관한 내용을 다루고 있으니 참고하시면 좋을 것 같습니다.

 

https://www.tensorflow.org/guide/checkpoint?hl=ko 

 

체크포인트 훈련하기  |  TensorFlow Core

Note: 이 문서는 텐서플로 커뮤니티에서 번역했습니다. 커뮤니티 번역 활동의 특성상 정확한 번역과 최신 내용을 반영하기 위해 노력함에도 불구하고 공식 영문 문서의 내용과 일치하지 않을 수

www.tensorflow.org

 

 

 

안녕하세요.

이번 글에서는 CNN 모델이 학습한 후 어떻게 성능을 평가하는지 알아보도록 하겠습니다.

 

우선 지금까지 배운 코드를 정리하면 아래와 같습니다.

 

 

##관련 모듈 import##

import os
from tensorflow import keras
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras import layers
from tensorflow import keras

 

 

##Data Load Code##

base_dir = './datasets/cats_and_dogs/'
train_dir = os.path.join(base_dir, 'train')
validation_dir = os.path.join(base_dir, 'validation')


train_datagen = ImageDataGenerator(
    featurewise_center=True,
    featurewise_std_normalization=True,
    rescale=1./255,
    rotation_range=20,
    width_shift_range=0.2,
    height_shift_range=0.2,
    horizontal_flip=True,
    validation_split=0.2)
 
 validation_datagen = ImageDataGenerator(rescale=1./255)
 
 
 train_generator = train_datagen.flow_from_directory(
        # 타깃 디렉터리
        train_dir,
        # 모든 이미지를 150 × 150 크기로 바꿉니다
        target_size=(150, 150),
        batch_size=32,
        # binary_crossentropy 손실을 사용하기 때문에 이진 레이블이 필요합니다
        class_mode='binary') #cats_and_dogs는 2개의 클래스만 있음
        
 validation_generator = validation_datagen.flow_from_directory(
        validation_dir,
        target_size=(150, 150),
        batch_size=32,
        class_mode='binary')
 

 

 

##CNN implementation by functional API##

input_shape = (150,150,3)
img_input = layers.Input(shape=input_shape)
output1 = layers.Conv2D(kernel_size=(3,3), filters=32, activation='relu')(img_input)
output2 = layers.MaxPooling2D((2,2))(output1)
output3 = layers.Conv2D(kernel_size=(3,3), filters=64, activation='relu')(output2)
output4 = layers.MaxPooling2D((2,2))(output3)
output5 = layers.Conv2D(kernel_size=(3,3), filters=128, activation='relu')(output4)
output6 = layers.MaxPooling2D((2,2))(output5)
output7 = layers.Conv2D(kernel_size=(3,3), filters=128, activation='relu')(output4)
output8 = layers.MaxPooling2D((2,2))(output7)
output9 = layers.Flatten()(output8)
output10 = layers.Dropout(0.5)(output9)
output11 = layers.Dense(512, activation='relu')(output10)
predictions = layers.Dense(2, activation='softmax')(output11)

model = keras.Model(inputs=img_input, outputs=predictions)

model.summary()

 

 

##Loss function, optimizer, learning rate schedule 설정

opt = SGD(lr=INIT_LR, momentum=0.9)
loss = CategoricalCrossentropy(label_smoothing=0.1)
model.compile(loss=loss, optimizer=opt, metrics=["accuracy"])

 

##Training 실행 코드##

train_step = train_generator.n // 32
valid_step = valid_generator.n // 32

history = model.fit_generator(
      train_generator,
      steps_per_epoch=train_step,
      epochs=30,
      validation_data=validation_generator,
      validation_steps=valid_step)

  • step_per_epoch: 한 epoch에 사용한 스텝 수를 지정합니다. 총 20000개의 training sample이 있고 batch size가 32이므로, 20000를 32로 나눈 몫(=20000/32=625)이 됩니다. (만약, 20001개의 training sample이 있다면 step_per_epoch은 "(20001//32)+1"이 되어야 합니다) 이러한 이유로 위의 train_step, valid_step을 아래와 같이 변경시켜주는 것이 좋습니다.
    • ex)총 45개의 훈련 샘플이 있고 배치사이즈가 3이라면 15 스텝(=step_per_epoch)으로 지정합니다.

 

  • validation_step: 한 epoch 종료 시 마다 검증할 때 사용되는 검증 스텝 수를 지정합니다.
    • ex) 총 15개의 validation 샘플이 있고 배치사이즈가 3이라면, validation_step을 5 스텝으로 지정합니다.

 

 

검은색: training sample/ 빨간색: validation sample

 

 

 

1. Metrics

딥러닝의 성능을 평가하기 위해 여러 성과지표(metrics)가 사용됩니다.

위에서 설명한 metrics은 accurcy로써 가장 대표적인 성과지표라 할 수 있습니다.

accuracy를 이용해 성과지표를 visualization하면 아래와 같이 표현할 수 있습니다.

 

import matplotlib.pyplot as plt

acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(len(acc))

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()

plt.figure()

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()

plt.show()

 

 

 

Test dataset을 evaluation하려면 아래와 같이 코드를 작성해주면 됩니다. 

model.save('CNN_epoch_20.h5')

test_dir = os.path.join(base_dir, 'test')
test_datagen = ImageDataGenerator(rescale=1./255)
test_generator = test_datagen.flow_from_directory(
        test_dir,
        target_size=(150, 150),
        batch_size=32,
        class_mode='binary')

test_step = test_generator.n // 32

test_loss, test_acc = model.evaluate_generator(test_generator, steps=test_step, workers=4)
print(f'test loss : {test_loss:.4f} / test acc : {test_acc*100:.2f} %')

이미지 출처: https://junstar92.tistory.com/119

 

 

※loss function에 따라 metrics도 바뀔 수 있는 듯 합니다. (예전에 사용할 때 loss function을 categorical_crossentropy를 사용했을 때, 그냥 metrics를 accuracy로 해도 문제가 없었던것 같은데 나중에 바꿔서 써봐야겠네요)

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['sparse_categorical_accuracy'])

 

 

 

 

2. Keras and Tensorflow backend metrics

모델 컴파일(model.compile) 할 때, Backend 엔진이 tensorflow(=tf)인 경우 몇 가지 기본 성과지표(ex: recall, precision 등을 제공해줍니다)

 

https://www.tensorflow.org/api_docs/python/tf/keras/metrics

 

Module: tf.keras.metrics  |  TensorFlow Core v2.5.0

Built-in metrics.

www.tensorflow.org

 

 

Keras tensorflow backend기반의 다양한 metrics 코드 구현 관련 내용은 아래 링크를 참고해주세요!

 

https://www.tensorflow.org/tutorials/structured_data/imbalanced_data?hl=ko 

 

불균형 데이터 분류  |  TensorFlow Core

이 튜토리얼에서는 한 클래스의 예시의 수가 다른 클래스보다 훨씬 많은 불균형 데이터세트를 분류하는 방법을 소개합니다. Kaggle에서 호스팅 되는 신용 카드 부정 행위 탐지 데이터세트를 사용

www.tensorflow.org

 

 

3. Keras and other backend metrics

 

하지만, Keras 2버전 부터는 tensorflow backend가 아니라면 아래 링크에서 제공되는 metrics를 제외하고서는 전부 사용자 정의 함수로 구현해주어야 합니다.

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

 

Metrics - Keras Documentation

측정항목의 사용법 측정항목은 모델의 성능을 평가하는데 사용되는 함수입니다. 측정항목 함수는 모델이 컴파일 될 때 metrics 매개변수를 통해 공급됩니다. model.compile(loss='mean_squared_error', optimize

keras.io

 

 

실제로 Keras 2에서 precision, recall, fmeasure 등과 같은 metrics는 따로 구현해야 한다고 언급하고 있네요. 

 

"Several legacy metric functions have been removed, namely matthews_correlation, precision, recall, fbeta_score, fmeasure."

 

https://github.com/keras-team/keras/wiki/Keras-2.0-release-notes

 

keras-team/keras

Deep Learning for humans. Contribute to keras-team/keras development by creating an account on GitHub.

github.com

 

 

Keras기반의 사용자 정의 함수(metrics) 코드 구현 관련 내용은 아래 링크를 참고해주세요!

https://neptune.ai/blog/keras-metrics

 

Keras Metrics: Everything You Need To Know - neptune.ai

Keras metrics are functions that are used to evaluate the performance of your deep learning model. Choosing a good metric for your problem is usually a difficult task. you need to understand which metrics are already available in Keras and tf.keras and h

neptune.ai

 

 

 

 

[Reference Site]

 

https://nbviewer.jupyter.org/github/rickiepark/deep-learning-with-python-notebooks/blob/tf2/5.2-using-convnets-with-small-datasets.ipynb

 

Jupyter Notebook Viewer

이제 2,000개의 훈련 이미지, 1,000개의 검증 이미지, 1,000개의 테스트 이미지가 준비되었습니다. 분할된 각 데이터는 클래마다 동일한 개수의 샘플을 포함합니다. 균형잡힌 이진 분류 문제이므로

nbviewer.jupyter.org

 

 

https://junstar92.tistory.com/119

 

[Tensorflow][Kaggle] Cats vs. Dogs Classification(수정 : 2020-12-07)

www.kaggle.com/c/dogs-vs-cats-redux-kernels-edition Dogs vs. Cats Redux: Kernels Edition Distinguish images of dogs from cats www.kaggle.com 딥러닝 연습으로 Kaggle의 Dogs vs. Cats Classification을..

junstar92.tistory.com

 

https://m.blog.naver.com/wideeyed/221226716255

 

[Keras] 2.0에서 precision,recall 사용하기

tf.keras.metrics를 통해 precision, recall을 지원하므로 사용한다. 다른 Backend엔진을 사용하거나 더 ...

blog.naver.com

 

안녕하세요.

앞서 CNN 구조를 구성했다면 최종적으로 model.compile 함수를 이용하여 해당 모델에 적용할 loss function, optimizer, metrics등을 설정해주어야 합니다.

from tensorflow.keras import layers
from tensorflow import keras
from tensorflow.keras import optimizers

###CNN 모델 구축###
input_shape = (150,150,3)
img_input = layers.Input(shape=input_shape)
output1 = layers.Conv2D(kernel_size=(3,3), filters=32, activation='relu')(img_input)
output2 = layers.MaxPooling2D((2,2))(output1)
output3 = layers.Conv2D(kernel_size=(3,3), filters=64, activation='relu')(output2)
output4 = layers.MaxPooling2D((2,2))(output3)
output5 = layers.Conv2D(kernel_size=(3,3), filters=128, activation='relu')(output4)
output6 = layers.MaxPooling2D((2,2))(output5)
output7 = layers.Conv2D(kernel_size=(3,3), filters=128, activation='relu')(output4)
output8 = layers.MaxPooling2D((2,2))(output7)
output9 = layers.Flatten()(output8)
output10 = layers.Dropout(0.5)(output9)
output11 = layers.Dense(512, activation='relu')(output10)
predictions = layers.Dense(2, activation='softmax')(output11)

model = keras.Model(inputs=img_input, outputs=predictions)

###Loss, optimizer, metrics 설정###
model.compile(loss='binary_crossentropy',
              optimizer=optimizers.RMSprop(lr=1e-4),
              metrics=['accuracy'])

 

이번 글에서는 model.compile에 적용되는 loss, optimizer, metrics 들에 대해 좀 더 자세히 알아보도록 하겠습니다.

 

 

 

 

 

1. Loss

1-1. 기본 Loss function

Tensorflow2는 아래링크에서 볼 수 있듯이 기본적인  loss function을 제공해줍니다.

https://www.tensorflow.org/api_docs/python/tf/keras/losses

 

Module: tf.keras.losses  |  TensorFlow Core v2.5.0

Built-in loss functions.

www.tensorflow.org

 

Loss function을 적용하는 방식은 크게 두 가지 입니다.

 

첫 번째 방식. compile 함수에 있는 loss 속성에 특정 loss를 기재

model.compile(loss='binary_crossentropy',
              optimizer=optimizers.RMSprop(lr=1e-4),
              metrics=['accuracy'])

 

두 번째 방식. loss instance 생성 후, compile 함수에 있는 loss 속성에 앞서 생성한 loss instance를 기재 

loss = CategoricalCrossentropy()
model.compile(loss=loss, optimizer='adam', metrics=["accuracy"])

 

Q. tf.keras.losses 부분 보면 bianry_crossentropy는 function이고, BinaryCrossentropy는 class로 되어 있는데, 이 두 가지가 어떤 차이가 있는지 모르겠네요. 어느 사이트 보면 function으로 선언한 경우 accuracy가 더 떨어져서 나온다는 말도 있는데, 정확히 어떤 차이가 있는건지...

 

 

 

1-2. 세 가지 기본 Loss function 소개

앞서 tensorflow에서 제공한 기본 loss 함수 중에, 딥러닝 분류 목적으로 사용하는 대표적인 loss function은 3가지 입니다.

 

1) Binary Crossentropy

Tensorflow에서 제공하는 BinaryCrossentropy는 2가지의 클래스를 구분하는 task에 적용할 수 있는 함수입니다.   

이미지 출처: https://gombru.github.io/2018/05/23/cross_entropy_loss/

 

 

 

2) Categorical Crossentropy

3개 이상의 클래스를 classification 할 경우 우리는 이를 multiclassification이라고 합니다.

이 경우에는 tensorflow에서 제공하는 CategoricalCrossentropy를 적용해주어야 합니다.

이미지 출처: https://gombru.github.io/2018/05/23/cross_entropy_loss/

 

 

3) SparseCategorical Crossentropy

10개의 클래스를 분류한다고 한다는 가정하에 아래 그림에 있는 기호를 간단히 표현하면 다음과 같습니다.

  • t → label=answer → [0, 0, 0, 0, 0, 1, 0, 0, 0, 0]
  • y → probability = predict → [0.1, 0.05, 0.05, 0.1, 0.1, 0.3, 0.1, 0.05, 0.05, 0.1]

아래의 CategoricalCrossentropy 수식을 보면 사실 6번째 해당하는 class를 제외하면 모든 t는 0이기 때문에 loss function에 아무런 영향도 미치지 않습니다. 사실상 6번째에 해당하는 t, y 값만 고려해주고 나머지는 무시해줘도 되는 것이죠. 

 

예를 들어, if 문을 이용하여 정답에 해당하는 label에 대해서만 "loss=-t×log(y)" 를 적용해주면 속도도 더 빨라지게 되는데, 이러한 방식의 loss function을 SparseCategoricalCrossentropy 라고 합니다. (실제로 DNN을 hardcoding 했을 때, CategoricalCrossentropy와 SparseCategoricalCrossentropy 학습 결과에는 변함이 없었습니다. 또한, 실제로 돌려보면 SparseCategoricalCrossentropy 방식으로 hardcoding 했을 때 좀 더 학습 속도가 빨랐습니다)

 

 

 

 

1-3. Label smoothing

Tensorflow 기본 loss API에서는 label smoothing을 쉽게 적용할 있게 구현해 놨습니다. 

 

loss = CategoricalCrossentropy(label_smoothing=0.1)
model.compile(loss=loss, optimizer='adam', metrics=["accuracy"])

 

For example, if 0.1, use (0.1 / num_classes) for non-target labels and (0.9 + (0.1 / num_classes)) for target labels. (참고로 non-target labels의 확률값은 uniform distribution을 따릅니다)

이미지 출처: https://towardsdatascience.com/label-smoothing-make-your-model-less-over-confident-b12ea6f81a9a

 

 

참고로 앞서 설명한 SparseCategoricalCrossentropy의 기본전제는 hard label이기 때문에, label smoothing 속성이 왜 없는지 쉽게 파악할 수 있습니다.

  • hard label: 실제 정답외에 모든 label 값은 0으로 설정하는 방식

 

 

1-4. Extra loss functions by Tensorflow addons

Tensorflow 기본 loss API외에 SIG라는 곳에서 추가적인 loss function 들을 구현해 tensorflow에 contribution하고 있습니다. 예를 들어, 최근에 contrastive loss 도 주목을 받고 있는데, 이러한 loss를 Tensorflow Addons (by SIG) 에서 제공하는 API를 이용해 사용할 수 있습니다.

 

https://www.tensorflow.org/addons/api_docs/python/tfa/losses

 

Module: tfa.losses  |  TensorFlow Addons

Additional losses that conform to Keras API.

www.tensorflow.org

 

 

 

 

 

1-5. Custom Loss function

우리가 사용할 loss function이 앞서 소개된 기본 loss function에 없다면 우리가 스스로 만들어야 합니다.

 

대부분 정해진 task에 의해 기본적인 loss function을 쓰는 것이 보편적이지만, 종종 자신만의 loss function을 만들어 사용하는 경우도 있습니다. 예를 들어, Semi-supervised loss function, focal loss function과 같은 경우는 tensorflow에서 기본적으로 제공되는 loss function이 아니기 때문에 사용자가 직접 함수를 만들어 사용해야 합니다.

 

예를 들어, hubber loss라는 것을 만들어 사용하려면 아래와 같이 작성해주면 됩니다.

def my_huber_loss(y_true, y_pred):
	threshold = 1
	error = y_true - y_pred
	is_small_error = tf.abs(error) <= threshold
	small_error_loss = tf.square(error) / 2
	big_error_loss = threshold * (tf.abs(error) - (0.5 * threshold))
	return tf.where(is_small_error, small_error_loss, big_error_loss)
    
    
model.compile(optimizer='sgd', loss='my_huber_loss')


(↓↓huber loss 수식 설명↓↓)

https://mypark.tistory.com/14?category=1007621 

 

[Tensorflow 2][Keras] Week 2 - Custom loss functions

본 포스팅은 다음 과정을 정리 한 글입니다. Custom Models, Layers, and Loss Functions with TensorFlow www.coursera.org/specializations/tensorflow-advanced-techniques 지난 시간 리뷰 2021.03.13 - [Artif..

mypark.tistory.com

 

 

 

 

 

2. Optimizer

2-1. 기본 optimizer

Tensorflow2는 아래링크에서 볼 수 있듯이 기본적인 Optimizer를 제공해줍니다.

https://www.tensorflow.org/api_docs/python/tf/keras/optimizers

 

Module: tf.keras.optimizers  |  TensorFlow Core v2.5.0

Built-in optimizer classes.

www.tensorflow.org

 

위링크에서 자신이 적용시키고 싶은 optimizer를 클릭하면 해당 optimizer에 어떤 속성들(ex: learning rate, etc...)이 있는지 알 수 있습니다.

 

 

 

 

optimizer도 아래와 같이 두 가지 패턴으로 선언이 가능합니다.

 

첫 번째 방식

model.compile(loss='binary_crossentropy',
              optimizer=optimizers.RMSprop(lr=1e-4),
              metrics=['accuracy'])

 

두 번째 방식

opt = SGD(lr=INIT_LR, momentum=0.9)
loss = CategoricalCrossentropy(label_smoothing=0.1)
model.compile(loss=loss, optimizer=opt, metrics=["accuracy"])

 

 

2-2. Extra optimizers by Tensorflow addons

앞서 loss functionn에서 언급한 것 처럼, 기본 tensorflow API에서 제공되는 optimizer 외에 SIG에서 제공하는 다양한 optimizer들이 있습니다.

(↓↓supported by SIG↓)

https://www.tensorflow.org/addons/api_docs/python/tfa/optimizers

 

Module: tfa.optimizers  |  TensorFlow Addons

Additional optimizers that conform to Keras API.

www.tensorflow.org

 

 

 

 

2-3. 최신 optimizer

앞서 제공한 기본적인 optimizer 외에도 현재 개발중인 다양한 optimizer들이 등장하고 있습니다. 예를 들어, 작년에 NeurIPS에서 Adabelief라는 optimizer를 발표한바 있습니다.

https://arxiv.org/abs/2010.07468

 

AdaBelief Optimizer: Adapting Stepsizes by the Belief in Observed Gradients

Most popular optimizers for deep learning can be broadly categorized as adaptive methods (e.g. Adam) and accelerated schemes (e.g. stochastic gradient descent (SGD) with momentum). For many models such as convolutional neural networks (CNNs), adaptive meth

arxiv.org

 

 

보통 이런 최신 optimizer는 논문이 나오면 github에 등록하여 일반 사용자들이 쉽게 사용할 수 있도록 기록해놓습니다. 

https://github.com/juntang-zhuang/Adabelief-Optimizer

 

juntang-zhuang/Adabelief-Optimizer

Repository for NeurIPS 2020 Spotlight "AdaBelief Optimizer: Adapting stepsizes by the belief in observed gradients" - juntang-zhuang/Adabelief-Optimizer

github.com

 

 

위의 사이트에 접속하면 아래와 같이 tensorflow에서 어떻게 사용하면 되는지 설명되어 있습니다.

이미지 출처: https://github.com/juntang-zhuang/Adabelief-Optimizer

 

 

아래 글을 보면 tensorflow 기반의 keras 에서는 호환이 안된다고 했는데, 

https://github.com/juntang-zhuang/Adabelief-Optimizer/issues/2

 

Tensorflow implementation doesn't work · Issue #2 · juntang-zhuang/Adabelief-Optimizer

TF 2.3 from tensorflow.keras.layers import Dense from tensorflow.keras.models import Sequential import numpy as np from adabelief_tf import AdaBeliefOptimizer x = np.random.random_sample((5,)) y = ...

github.com

 

 

"Make it compatiable with tensorflow and keras"라는 부분을 검색해보면 해당 부분이 수정된 것으로 보입니다 (아직 적용해보지 않아 실제로 잘 동작하는지 아닌지는 확인해봐야합니다 (Pytorch 버전은 잘 돌아가네요).

 

 

 

 

2-4. Learning rate schedule

학습이 진행 될 수록 점점 global minimum에 접근한다고 가정했을 때, learning rate도 천천히 줄여주는 것이 학습에 효과적이라고 알려져있습니다. 즉, schedule대로 learning rate를 변경해가며 사용하는 것이죠.

 

예를 들어, 위의 이미지에서는 exponential learning rate decay 방식을 표현하고 있는데, 이를 tensorflow 2 코드로 적용시키면 아래와 같습니다.

initial_learning_rate = 0.1
lr_schedule = keras.optimizers.schedules.ExponentialDecay(
    initial_learning_rate,
    decay_steps=100000,
    decay_rate=0.96,
    staircase=True)

optimizer = keras.optimizers.RMSprop(learning_rate=lr_schedule)

 

Tensorflow 2에서는 "opimizer.schedules"을 통해 여러 learning rate decay 기법을 제공해줍니다.

https://www.tensorflow.org/api_docs/python/tf/keras/optimizers/schedules

 

Module: tf.keras.optimizers.schedules  |  TensorFlow Core v2.5.0

Public API for tf.keras.optimizers.schedules namespace.

www.tensorflow.org

 

예를 들어, CosineAnnealing 방식을 적용하고 싶다면 아래와 같이 코드를 작성해주면 됩니다.

tf.keras.optimizers.schedules.CosineDecayRestarts(
    initial_learning_rate, first_decay_steps, t_mul=2.0, m_mul=1.0, alpha=0.0,
    name=None
)
  • initial_learning_rate : 최초의 학습률
  • first_decay_steps : (첫 주기의 감쇄가 진행되는 총 스텝 수) 최초의 주기 길이
  • t_mul : 주기 T를 늘려갈 비율 (첫 주기가 100step이면 그 다음은 200step, 그 다음은 400step...)
  • m_mul : 최초 학습률로 설정한 값에 매 주기마다 곱해줄 값 (0.9라면 매 주기 시작마다 initial_learning_rate에 (i는 주기 인덱스)만큼 곱한 값을 주기 시작 학습률로써 사용한다.)
  • alpha : 학습률의 하한을 설정하기위한 파라미터로 학습률의 감소 하한은 initial_learning_rate * alpha가 된다.
  • 레퍼런스 사이트

이미지 출처: https://www.programmersought.com/article/96553631082/

 

 

 

 

(↓↓↓위에서 언급한 learning rate decay 구현 및 시각화한 사이트↓↓↓)

https://www.programmersought.com/article/96553631082/

 

The tricks of learning rate decay in Tensorflow - Programmer Sought

The method of parameter update in deep learning must be very clear to everyone-sgd, adam, etc., and the discussion about which is better is also extensive. but,learning rate decay strategyHas anyone paid special attention? When training neural networks, th

www.programmersought.com

 

 

2-4. Learning rate warm-up

※Learning rate warm-up도 굉장히 자주쓰이는 트릭인데, tensorflow에서 기본적으로 제공해주는 방식은 없는 듯합니다. Github에서 다운받거나 아래 사이트를 참고하여 직접구현해주면서 사용해야 할 듯 합니다 (Pytorch는 굉장히 쉽게 사용할 수 있게 되어 있는데, tensorflow로 쓰려니 참...)

(↓↓↓아래 사이트에서 learning rate warm up 코드 부분을 참고해주세요!↓↓↓)

https://www.dlology.com/blog/bag-of-tricks-for-image-classification-with-convolutional-neural-networks-in-keras/

 

Bag of Tricks for Image Classification with Convolutional Neural Networks in Keras | DLology

Posted by: Chengwei 2 years, 6 months ago (Comments) This tutorial shows you how to implement some tricks for image classification task in Keras API as illustrated in paper https://arxiv.org/abs/1812.01187v2. Those tricks work on various CNN models like

www.dlology.com

 

 

지금까지 model.compile의 속성들 중인 loss function, optimizer, learning rate schedule 에 대해서 살펴보았습니다.

 

다음 글에서는 마지막 남은 속성인 metrics에 대해 소개하도록 하겠습니다.

안녕하세요. 

이번에는 tensorflow 2 기반으로 CNN 모델을 구현하는 내용을 다루도록 하겠습니다.

Tensorflow 2에서 DNN or CNN 모델을 구축하는 방식은 크게 2가지로 나눌 수 있습니다.

  1. Sequential API
  2. Functional API

먼저, sequential API에 대해 설명한 후, functional API를 설명하도록 하겠습니다.

 

 

1. Sequential API

  • Sequential API는 tensorflow 2에서 뉴럴 네트워크를 가장 쉽게 구성할 수 있는 방식입니다.
  • Sequential이라는 이름에 맞게 add 함수를 이용하면 layer가 순차대로 연결이 됩니다.
  • A sequential model is appropriate for a plain stack of layers where each layer has exactly one input tensor and one output tensor.
    • 즉, add 함수를 통해 각 layer들은 정확히 하나의 input값만을 받을 수 있으며, output또한 하나의 tensor 형태로만 출력이 가능합니다.
    • 이러한 특징이 갖고 있는 단점 중 하나는 복잡한 CNN 모델을 구성하기 힘들다는 점입니다.
    • 예를 들어, ResNet 같은 경우는 Residual block 을 구성하기 위해서는 두개의 input 값 (ex: F(x), x)을 받아야 하는데, Sequential API로 구성하는 경우 x값을 받을 수 없으니 ResNet 모델을 구현할 수 없게 됩니다. 
    • 위와 같은 이유로 DenseNet 또한 구현이 불가능 합니다.

from tensorflow.keras import layers
from tensorflow.keras import models

#Conv2D(채널 수, (Conv filter 크기), activation function, 입력 데이터 크기)

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu',
                        input_shape=(150, 150, 3))) 
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Flatten())
model.add(layers.Dropout(0.5))
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))

 

 

 

2. Functional API

  • Functional API을 이용하면 다양한 input 값을 받을 수 있습니다.
  • 즉, layer에 input 값을 따로 기재해줄 수 있다는 뜻이죠.
from tensorflow.keras import layers
from tensorflow import keras

input_shape = (150,150,3)
img_input = layers.Input(shape=input_shape)
output1 = layers.Conv2D(kernel_size=(3,3), filters=32, activation='relu')(img_input)
output2 = layers.MaxPooling2D((2,2))(output1)
output3 = layers.Conv2D(kernel_size=(3,3), filters=64, activation='relu')(output2)
output4 = layers.MaxPooling2D((2,2))(output3)
output5 = layers.Conv2D(kernel_size=(3,3), filters=128, activation='relu')(output4)
output6 = layers.MaxPooling2D((2,2))(output5)
output7 = layers.Conv2D(kernel_size=(3,3), filters=128, activation='relu')(output4)
output8 = layers.MaxPooling2D((2,2))(output7)
output9 = layers.Flatten()(output8)
output10 = layers.Dropout(0.5)(output9)
output11 = layers.Dense(512, activation='relu')(output10)
predictions = layers.Dense(2, activation='softmax')(output11)

model = keras.Model(inputs=img_input, outputs=predictions)

 

 

3. Functional API를 이용해 Residual block 구성하기

  • BatchNormalization layer 추가
  • skip connection 적용

input = X
#첫 번째 conv layer에 있는 residual block
block_1_output1 = layers.Conv2D(kernel_size=(3,3), filters=channel_num, padding='same', name=name + '0_conv')(input)
block_1_output2 = BatchNormalization(name=name + '0_bn')(block_1_output1)
block_1_output3 = Activation('relu', name=name + '0_relu')(block_1_output2)
block_1_output4 = Conv2D(kernel_size=(3, ), filters=channel_num, padding='same', name=name + '1_conv')(block_1_output3)
# Zero gamma - Last BN for each ResNet block, easier to train at the initial stage.
#block_1_output4 = F(X)
block_1_output4 = BatchNormalization(gamma_initializer='zeros', name=name + '1_bn')(block_1_output4)
#merge_data = X+F(X)
merge_data = add([block_1_output4, input], name=name + '1_add') 
out = Activation('relu', name=name + '2_conv')(merge_data)

 

위의 코드는 아래 이미지의 original 버전이라고 생각하시면 됩니다. 위의 코드를 기반으로 나머지 구조들((b), (c), (d), (e))도 구현하실 수 있겠죠?

 

 

 

 

3. Model summary

앞서 CNN 모델을 작성했다면, 해당 모델에 대한 간단한 구조를 summary 함수를 통해 알아볼 수 있습니다.

model.summary()

 

위의 출력결과에서는 "Non-trainable params:0"으로 표현되어 있는데, 나중에 transfer learning or fine-tuning을 적용시킬 때는 특정 layer까지 freezing 시키는 경우도 빈번하므로 Non-trainable params가 0이 아닐 때도 생깁니다. 이 부분은 trasnfer learning을 다룰 때 설명하도록 하겠습니다.

 

CNN모델을 학습시킬 때, 가장먼저 해야할 것은 train, validation, test dataset을 load하는 것입니다.

이번 장에서는 내가 구축한 (custom) dataset을 load하는 방식에 대해서 알아보도록 하겠습니다.

 

 

1. Custom dataset directory 설정

1) 학습데이터는 이미지 파일이므로 파일데이터와 관련된 module를 import합니다.

  • OS 모듈은 환경 변수나 디렉터리, 파일 등의 OS 자원을 제어할 수 있게 해주는 모듈
import os

 

 

2)학습할 데이터셋을 세팅합니다.

우선 학습할 데이터를 다운받고 아래와 같이 세팅이 되어 있는지 확인해 줍니다.

기본적으로 학습을 위한 데이터(cat_and_dogs)는 아래와 같이 train, validation, test 데이터 셋으로 구성이 되어있습니다. 

base_dir 경로

 

train, validation, test 데이터셋(폴더)에는 각각 클래스와 관련된 폴더가 있고, 해당 폴더에 실제 이미지 데이터가 위치합니다. cats_and_dogs 분류문제는 개와 고양이 두 클래스를 구분하는 binary classification 문제이므로, 각 폴더에 2개의 클래스(개, 고양이)가 포함되어 있습니다.

train_dir 경로

 

!! 주석부분에 폴더 정보들을 기록해놨으니 꼭 확인해 주세요 !!

#base_dir → 다운받은 원본 데이터셋 경로 = 모든 training, validation, test 데이터셋이 포함되어 있음
#cats_and_dogs에 있는 총 이미지 데이터 개수 = 25,000 ← training:20,000 + validation:4,000 + test:500
base_dir = './datasets/cats_and_dogs/'

#train_dir → 원본 데이터셋의 학습 데이터 경로 = 모든 class(개, 고양이)들의 이미지들이 포함되어 있음
#train_dir에 있는 총 이미지 데이터 개수 = 20,000 ← 강아지=10,000 + 고양이=10,000
train_dir = os.path.join(base_dir, 'train')  #train_dir = './datasets/cats_and_dogs/train'

#validation_dir → 원본 데이터셋의 학습 데이터 경로 = 모든 class(개, 고양이)들의 이미지들이 포함되어 있음
#validation_dir에 있는 총 이미지 데이터 개수 = 4,000 ← 강아지=2,000 + 고양이=2,000
validation_dir = os.path.join(base_dir, 'validation')  #validation_dir = './datasets/cats_and_dogs/validation'

#test_dir → 원본 데이터셋의 학습 데이터 경로 = 모든 class(개, 고양이)들의 이미지들이 포함되어 있음
#test_dir에 있는 총 이미지 데이터 개수 = 1,000 ← 강아지=500 + 고양이=500
test_dir = os.path.join(base_dir, 'test')  #test_dir = './datasets/cats_and_dogs/test'

 

 

 

2. Preprocessing (Normalization)

아래 링크에 걸어둔 글에서 볼 수 있듯이, 보통 효율적인 학습을 위해 딥러닝의 학습데이터들은 전처리의 일환으로 normalization이 적용됩니다

https://89douner.tistory.com/42?category=868069 

 

8. 데이터 전처리 (Data Preprocessing and Normalization)

Q. DNN을 학습시키기 전에 왜 데이터를 전처리해주어야 하나요? 안녕하세요~ 이번시간에는 DNN 모델이 학습을 효율적으로 하기위해 필요한 정규(Noramlization; 정규화) 대해서 알아보도록 할거에요~

89douner.tistory.com

 

 

간단하게 말하자면, normalization이 적용된 학습데이터의 problem space가 더 안정적으로 형성될 수 있으므르로 학습이 더 수월하게 된다는 이점이 있습니다.

 

 

위와 같은 normalization을 적용해주기 위해서는 아래와 같이 zero center를 맞춰준후, data를 normalization 해주어야 합니다.

 

위와 같이 "zero-center→normalization"을 적용시켜주려면 아래와 같은 순서를 따르면 됩니다.

  1. Zero center: 모든 데이터들의 평균을 구한다 → 모든 데이터들 각각에 해당 평균 값을 빼준다.
  2. Normalization: 모들 데이터들의 표준편차를 구한다 → 모든 데이터들 각각에 해당 표준편차 값을 나눠준다.

이미지 출처: https://www.kdnuggets.com/2020/04/data-transformation-standardization-normalization.html

 

위와 같은 데이터 전처리를 이미지에 적용할 때, 가능한 2가지 경우의 수가 있습니다.

 

2-1) 하나의 이미지 데이터를 기반으로 normalization 적용하기

예를 들어, 224×224×3 이미지가 있다고 가정해보겠습니다. 하나의 pixel에는 0~255값들이 들어 있는데, 앞에서 언급한 이미지 크기를 기준으로 한다면 150528(=224×224×3) pixel들이 존재하게 됩니다. 

 

이미지 출처: http://openframeworks.kr/ofBook/chapters/image_processing_computer_vision.html

 

즉, 하나의 이미지에 해당하는 고유의 평균 및 표준편차 값을 구할 수 있기 때문에, 하나의 데이터에만 normalization을 적용할 수 있게 됩니다. 예를 들어, 150528(=224×224×3) 개의 pixel값들을 기반으로 평균 및 표준편차 값을 구하고, 모든 pixel에 평균값을 빼준후 표준편차값을 나눠주게 됩니다.

 

Keras API에서 의 설명을 보면 알 수 있듯이, 하나의 이미지당 normalization을 적용시키려면 samplewise 속성을 이용하면 됩니다.

  • samplewise_center: Boolean. Set each sample mean to 0.
  • samplewise_std_normalization: Boolean. Divide each input by its std.
tf.keras.preprocessing.image.ImageDataGenerator(
    samplewise_center=True,
    samplewise_std_normalization=True
)

 

 

(↓↓↓Keras Image data Preprocessing API: ex) ImageDataGenerator↓↓↓)

https://keras.io/api/preprocessing/image/

 

Keras documentation: Image data preprocessing

Image data preprocessing image_dataset_from_directory function tf.keras.preprocessing.image_dataset_from_directory( directory, labels="inferred", label_mode="int", class_names=None, color_mode="rgb", batch_size=32, image_size=(256, 256), shuffle=True, seed

keras.io

 

 

 

2-2) 모든 이미지 데이터를 기반으로 normalization 적용하기

이번에는 하나의 이미지가 아닌 batch 단위로 묶인 이미지들을 기반으로 하여 해당 평균 및 표준편차 값을 구한 뒤, normalization을 적용 시키는 방식입니다. (사실, 전체 학습 이미지에 대한 평균 및 표준편차 값을 구하는건지 아닌지 모르겠으나 해당 API에서 "The data will be looped over (in batches)."라고 기술된 부분을 보고 'batch 단위로 평균 및 표준편차 값이 구해지겠구나'라고 추정했습니다. 혹시 아니면 알려주시면 감사하겠습니다)

 

예를 들어 batch가 4라고 하면, 224×224×3×4 개의 pixel값들을 기반으로 평균 및 표준편차 값을 구하고, 모든 pixel에 평균값을 빼준후 표준편차값을 나눠주게 됩니다.

 

Keras API에서 의 설명을 보면 알 수 있듯이, batch 이미지당 normalization을 적용시키려면 featurewise 속성을 이용하면 됩니다.

tf.keras.preprocessing.image.ImageDataGenerator(
    featurewise_center=True,
    featurewise_std_normalization=True
)
  • featurewise_center: Boolean. Set input mean to 0 over the dataset, feature-wise.
  • featurewise_center: Boolean. Set input mean to 0 over the dataset, feature-wise.

 

아래 API를 보면 featurewise와 samplewise 관련 속성은 모두 False로 적용되어 있는걸 확인할 수 있다.

(↓↓↓Tensorflow 2 API 에서 ImageDataGenerator ↓↓↓)

https://www.tensorflow.org/api_docs/python/tf/keras/preprocessing/image/ImageDataGenerator

 

tf.keras.preprocessing.image.ImageDataGenerator

Generate batches of tensor image data with real-time data augmentation.

www.tensorflow.org

 

 

Q. DNN에서 봤을 때는 이러한 것이 많은 도움이 되는걸 이론적으로 확인할 수 있습니다. 그런데, 개인적으로 pytorch 기반으로 작성하여 CNN에 적용시켰을 때는 적용을 하나 안하나 큰 차이가 없었던 것 같습니다. 다른 분야에서는 어떻게 적용하고 있는지 궁금하네요. 

 

 

3. Data augmentation

CNN은 굉장히 다양한 data augmentation 기법을 지원합니다.

따라서 분류하려는 대상에 따라 적절한 data augmentation 기법을 적용시키면 됩니다.

예를 들어, Chest X-ray 같은 경우는 90도 rotation 해서 evaluation 하는 경우는 없으니, 90도 rotation은 적용시키지 않아도 되겠죠?

 

아래 코드에서 rescale은 overfitting을 방지하고자 모든 pixel 값들을 0~1 범위로 normalization 해주는 것인데, 앞서 "2. Preprocessing (Normalization)"에서 언급한 것과 같은 목적으로 적용된 것이라 생각하시면 될 것 같습니다.

tf.keras.preprocessing.image.ImageDataGenerator(
    featurewise_center=True,
    featurewise_std_normalization=True,
    zca_whitening=False,
    zca_epsilon=1e-06,
    rotation_range=0,
    width_shift_range=0.0,
    height_shift_range=0.0,
    brightness_range=None,
    shear_range=0.0,
    zoom_range=0.0,
    channel_shift_range=0.0,
    fill_mode="nearest",
    cval=0.0,
    horizontal_flip=False,
    vertical_flip=False,
    rescale=1./255
)

 

(↓↓↓위에서 언급한 data augmentation 중 몇 가지 예시↓↓↓)

https://theailearner.com/2019/07/06/data-augmentation-with-keras-imagedatagenerator/

 

Data Augmentation with Keras ImageDataGenerator

One of the methods to prevent overfitting is to have more data. By this, our model will be exposed to more aspects of data and thus will generalize better. To get more data, either you manually col…

theailearner.com

 

Q. rescaling=./255를 먼저 해주고, feature_wise or sample_wise같은 normalization을 적용을 해주는건지, 아니면 그 반대순서로 적용을 해주는건지 모르겠네요....

 

 

4. 총정리: Data Load

지금까지 배운 내용을 토대로 data load 코드를 작성하면 아래와 같습니다.

import os
from tensorflow import keras
from tensorflow.keras.preprocessing.image import ImageDataGenerator

base_dir = './datasets/cats_and_dogs/'
train_dir = os.path.join(base_dir, 'train')
validation_dir = os.path.join(base_dir, 'validation')


train_datagen = ImageDataGenerator(
    featurewise_center=True,
    featurewise_std_normalization=True,
    rescale=1./255,
    rotation_range=20,
    width_shift_range=0.2,
    height_shift_range=0.2,
    horizontal_flip=True,
    validation_split=0.2)
 
 validation_datagen = ImageDataGenerator(rescale=1./255)
 
 
 train_generator = train_datagen.flow_from_directory(
        # 타깃 디렉터리
        train_dir,
        # 모든 이미지를 150 × 150 크기로 바꿉니다
        target_size=(150, 150),
        batch_size=32,
        # binary_crossentropy 손실을 사용하기 때문에 이진 레이블이 필요합니다
        class_mode='binary') #cats_and_dogs는 2개의 클래스만 있음
        
 validation_generator = validation_datagen.flow_from_directory(
        validation_dir,
        target_size=(150, 150),
        batch_size=32,
        class_mode='binary')
 

 

위와 같이 코드를 세팅해주면 학습을 시켜주기 위한 data loader 과정이 마무리 됩니다.

이후 아래 코드를 실행시켜주면 학습이 진행됩니다.

아래 코드는 다음 글에서 설명하도록 하겠습니다.

from tensorflow.keras import layers
from tensorflow.keras import models
from tensorflow.keras import optimizers

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu',
                        input_shape=(150, 150, 3)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Flatten())
model.add(layers.Dropout(0.5))
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer=optimizers.RMSprop(lr=1e-4),
              metrics=['accuracy'])

 

 

※보통 cifar10, mnist, fashion mnist와 같은 적은 양의 데이터셋은 아래 링크에 기재된 tensorflow.keras.datasets 에서 제공을 해줍니다. 하지만, ImageNet 같은 경우는 데이터양이 워낙 방대하여 직접다운로드 받고 학습을 위한 구조를 세팅해주고 학습시켜야 한다는점 알아두시면 좋을것 같습니다!

 

https://www.tensorflow.org/api_docs/python/tf/keras/datasets

 

Module: tf.keras.datasets  |  TensorFlow Core v2.5.0

Small NumPy datasets for debugging/testing.

www.tensorflow.org

 

 

 

Tensorflow 기반 CNN 구현 코드는 아래 사이트들을 참고했습니다.

 

 

(5장→CNN)

https://github.com/rickiepark/deep-learning-with-python-notebooks/tree/tf2

 

rickiepark/deep-learning-with-python-notebooks

<케라스 창시자에게 배우는 딥러닝> 도서의 주피터 노트북. Contribute to rickiepark/deep-learning-with-python-notebooks development by creating an account on GitHub.

github.com

 

안녕하세요.

이번 글에서는 Class Activation Map (CAM)을 알아보기 전에 Activation Map을 통해 알 수 있는 것들이 무엇인지 알아보도록 하겠습니다.

 

 

 

1.  CNN의 기본적인 연산 과정

 

Activation Map에 대해 설명하기 전에 CNN의 기본구조를 다시 한 번 간단히 살펴보도록 하겠습니다.

 

아래 그림을 보면 특정 입력에 대해서 convolution filter가 어떻게 연산이 되는지 보여주고 있습니다.

  • 아래 그림에서는 input에 해당하는 데이터가 3×3×3의 형태입니다. 다시 말해, input 데이터는 3개의 독립적인(=서로 별개인) channel이 각각 3×3 size로 구성되어 있다고 할 수 있습니다. 
  • 여기서 Conv filter size는 2×2로 구성되어 있습니다.
  • Conv filter channel은 input 데이터의 channel 개수와 동일합니다.
  • 때문에 아래 예시에서는 하나의 conv filter가 "3×3×3"의 format(형태)를 갖고 있다고 할 수 있습니다.
  • 그리고, 아래 예시에서는 하나의 conv filter가 적용되는 과정은 아래와 같습니다. 
  • (실제로는 activation function이 적용 된 후의 값도 고려해야겠죠)

 

이미지 출처: https://wikidocs.net/62306

 

그렇다면 위에서 배운 개념을 입력 이미지에 국한해서 일반화시켜 봅시다.

먼저, 앞서 언급한 하나의 convolution filter(=kernel)는 input image의 depth와 동일합니다.

 

하나의 conv filter가 순차적으로 input 데이터를 거치게 되면 하나의 map형태의 결과값이 나오게 되는데 이를 feature map or activation map이라고 합니다.

 

 

만약 Conv filter가 N개라면 아래와 같이 output에 해당하는 feature map 개수도 N개가 될 것입니다. 

이미지출처: https://indoml.com/2018/03/07/student-notes-convolutional-neural-networks-cnn-introduction/

 

 

위에서 얻은 output은 다음 conv layer(consisting of conv filters)에 적용될 때, input 데이터가 됩니다.

예를 들어, N×N×3의 input 데이터는 6개의 convolution filter와, subsampling(=pooling) 작업을 통해 M×M라는 output feature map을 6개를 생성해냅니다. 그리고, 이 output feature map은 pooling 과정을 거쳐 또 다른 M×M×6 형태의 input 데이터가 됩니다. 아래 그림에서는 M×M×6 형태의 input 데이터에 12개의 conv filter를 적용하여 12개의 feature map을 얻게 됩니다. 

 

이미지 출처: http://daddynkidsmakers.blogspot.com/2019/06/blog-post_5.html

 

 

하나의 feature map이 직관적으로 의미하는 바는 무엇일까요?

지금부터 이것에 대해 천천히 알아보도록 하겠습니다.

 

 

 

2.  Conv filter와 Activation Map의 직관적인 관계

 

Conv filter는 특정 feature들을 걸러줍니다.

각각의 conv layer에서 뽑는 feature map의 특성은 아래와 같습니다. 예를 들어, 아래 그림에서 첫 번째 Conv 1을 거친 feature map은 입력 이미지의 edge같은 feature들을 잘 보여주는 특징을 지닙니다. 

이미지 출처: 밑바닥부터 시작하는 딥러닝

(↓↓↓자세한 설명은 아래 글을 참고해주세요↓↓↓)

https://89douner.tistory.com/57?category=873854

 

3. CNN(Convolution Neural Network)는 어떤 구조인가요?

안녕하세요~ 이번글에서는 Convolution Neural Network(CNN)의 기본구조에 대해서 알아보도록 할거에요. CNN은 기본적으로 Convolution layer-Pooling layer-FC layer 순서로 진행이 되기 때문에 이에 대해서 차..

89douner.tistory.com

 

 

2-1. Edge feature

입력 이미지가 들어왔을 때 아래와 같이 conv filter 값들을 설정해주면, 세로 edge의 특징들이 뽑힌다는 걸 알 수 있습니다.

 

Vertical filter를 보면, 흰색에서 검은색(밝은 곳에서 어두운 곳) 으로 경계가 바뀌는 vertical 부분이 가장 강하게 activation(=feature map에서 흰색) 될 거라고 예측할 수 있습니다. (※ conv filter나 입력이미지 모두 plt.imshow라는 함수로 visualization 해주는데, visualization을 해줄 시 모든 pixel 값들을 normalization 해줍니다).

 

"즉 feature map을 통해서 어떤 feature들이 뽑힐지 conv filter (vertical filter)만 보고도 추측할 수 있는 것이죠." 

 

앞서 설명한 것과 같은 맥락으로 검은색에서 흰색(어두운 곳에서 밝은 곳으로)으로 경계가 바뀌는 vertical 부분의 feature들을 뽑아낼 거라고 추론할 수 있습니다.

 

아래 conv filter는 horizontal edge feature를 뽑아냅니다. Horizontal filter 1은 흰색에서 검은색(밝은 곳에서 어두운 곳으로)으로 경계가 바뀌는 horizontal 부분의 feature들을 뽑아냅니다. Horizontal filter 2는 검은색에서 흰색(어두운 곳에서 흰색인 곳으로)으로 경계가 바뀌는 horizontal 부분의 feature들을 뽑아냅니다.

 

대각선 관련한 conv filter들은 아래와 같이 구성됩니다.

CNN에서 초기 Conv filter 들은 초기에 random하게 초기화됩니다. Training 과정을 통해 아래와 같은 feature들을 뽑을 수 있게 CNN filter들이 학습(=형성) 됩니다.

 

 

 

 

[Note. 주의하세요!]

1) Conv filter 내부에 구성된 양수, 음수의 비율을 고려하세요!

Conv filter가 아래와 같이 구성되어 있다고 해서 대각선의 특징을 뽑는 것이 아닙니다.

 

위에서 적용된 conv filter에서는 -1의 비율이 많기 때문에 대부분 실제 이미지의 밝기 정도를 반전하는 결과를 도출하게 됩니다. 예를 들어, conv filter가 적용되는 입력 위치가 가장 밝은 부분이라면 conv filter가 적용된 후 가장 어두운 부분이 되게 됩니다.

 

또한, -8값의 필터를 통과한 결과 feature map이 좀 더 contrast(대비)큽니다(=흰색부분이 좀 더 진한거 같음). 그 이유를 추측해보면 곱해주는 배수가 커질 수록 conv filter를 통해 생겨난 출력값들간의 편차가 더 심해지기 대문이라는걸 알 수 있습니다.

 

 

2-2. object feature

앞서 아래와 같은 이야기를 한 적이 있습니다.

 

"즉 feature map을 통해서 어떤 feature들이 뽑힐지 conv filter (vertical filter)만 보고도 추측할 수 있는 것이죠." 

 

하지만, 중간 conv layer에 갈 수록 filter만 보고 어떤 특징을 추출할 것인지 파악하는건 쉽지 않습니다.

 

예를 들어, 중간 conv layer에서 아래와 같은 conv filter가 형성(학습)되었다고 가정해보겠습니다.

conv layer1의 입력 이미지에 해당하는 700x500 크기에서는 아래의 conv filter를 통해 알 수 있는 것이 별로 없습니다. Conv filter만 보면 동그라미와 같은 edge를 뽑을 수 있을 것 같은데, edge가 동그라미일 경우가 그리 많지는 않겠죠 (대부분 edge는 선, 곡선 같은 모양이니까요).

 

반면에, pooling을 통해 작아진 350x250 입력 데이터는 중간에 위치한 conv layer의 입력 값이라고 볼 수 있습니다. 이 때 activation map을 통해 살펴보면 filter는 좀 더 추상적인 object (=눈, 눈썹, 코, 입술) 와 같은 특징을 잘 뽑아낸다는 것을 알 수 있습니다.

 

Conv filter의 생김새와 상관없이 중간 layer의 activation map이 좀 더 추상적인 정보를 뽑아내는 걸 보여줍니다.

 

 

 

위의 결과를 통해 알 수 있는 사실은 아래와 같습니다.

 

"feature(activation) map을 통해서 중간 conv layer에서 위치한 conv filter들의 역할을 대략적으로 추론 할 수 있습니다."

 

 

 

 

3.  Medical Imaging에서의 activation map

이전까지 Activation map에 대해 살펴 봤습니다.

그렇다면 이러한 activation map을 통해 medical imaging에서는 어떤 도움을 얻을 수 있을까요?

 

가장 도움을 많이 받을 수 있는 부분은 medical imaging에 나타난 병변들을 구분 할 때, CNN이 어떤 근거들을 기반으로 하는지 설명해 줄 수 있다는 점입니다.

 

예를 들어, 아래 이미지들을 살펴봅시다. 

먼저, 아래와 같은 가정을 해보겠습니다.

 

  • COVID-19, Pneumonia(폐렴), Normal(정상인) 을 분류하기 위해 CNN 모델을 학습시켰다.
  • i 이미지들은 Conv layer 1에 해당하는 conv filter (=주로 edge 특징을 뽑아냄) 들을 통해 출력한 feature map들이다.
    • ii 이미지에서 왼쪽 부분은 original image(input image)를 의미하고, 오른쪽 부분은 i 이미지들(=feature maps by conv layer 1's filters) 중에 가장 activation이 활성화된 feature map을 의미한다.
  • iii 이미지들은 좀 더 뒷 쪽(=N번째 layer)에 위치한 Conv layer에 해당하는 conv filter(=주로 좀 더 추상화된 object or texture 등의 특징을 뽑아냄) 들을 통해 출력한 feature map들이다.
    • iv 이미지는 iii 이미지들(=feature maps by conv layer N's filters) 중에 가장 activation이 활성화된 feature map을 의미한다.

논문: Can AI help in screening Viral and COVID-19 pneumonia?

 

 

논문에 의하면 초기 COVID-19 병변 같은 경우는 사람(=숙련된 radiologist)들이 발견하기 어렵다고 합니다. 예를 들어, 아래 빨간색으로 표시된 부분들은 사람들이 볼 수 없는 특징이라고 합니다. 하지만, deep layer는 normal, pneumonia와 구분되는 COVID-19만의 특징(=abnormality)을 뽑을 수 있는데 이러한 것을 시각화하여 보여줄 수 있습니다.

 

예를 들어, 아래와 같이 DenseNet201 모델의 14번째 convolution layer의 23번째 conv filter를 이용하면 normal, COVID-19, Penumonia를 구분할 수 있는 feature들을 감지할 수 있다는걸 알 수 있습니다. 

 

논문: Can AI help in screening Viral and COVID-19 pneumonia?

 

 

 

 

지금까지 Activation Map에 대해 간단히 알아보았습니다.

Activation Map과 관련한 pytorch 코드는 아래 링크를 참조하시면 될 것 같습니다.

 

https://androidkt.com/how-to-visualize-feature-maps-in-convolutional-neural-networks-using-pytorch/

 

How to Visualize Feature Maps in Convolutional Neural Networks using PyTorch - knowledge Transfer

The idea of visualizing a feature map for a specific input image would be to understand what features of the input are detected or preserved in the feature maps.

androidkt.com

 

 

 

 

다음 글에서는 Class Activation Map이 무엇인지 본격적으로 알아보도록 하겠습니다.

읽어주셔서 감사합니다~

안녕하세요.

이번 글에서는 기능의학이 무엇인지 설명해보고,

기능의학이 어떻게 디지털 헬스케어와 연결될 수 있는지에 대해

저만의 생각을 이야기 해보도록 하겠습니다.

 

 

1. 개인적인 경험

2년전 즘에 열심히 공부를 하다 몸 일부가 바늘로 찌르는 듯한 통증을 느껴졌습니다.

처음에는 참을만 하더니 나중에는 온 몸이 벌레가 물어뜯는 느낌이 들었죠.

그런데 이상하게 피부에는 아무런 변화가 없이 통증만 있었습니다.

 

처음에는 근처 병원을 갔더니 스트레스를 너무 많이 받아서 그런것 같다고

어떤 약을 처방해주시고 경과를 지켜보자고 하시더라구요.

사실 정확한 병명도 말씀해주시진 않았어요.

 

 

하지만, 증상이 나아지지는 않았습니다.

그래서, 인터넷으로 검색해보니 콜린성 두드러기라는 병에 걸린 환자들이

저와 비슷한 증상을 보이길래 해당 병의 진료과에 속한 우리나라 top3 대학병원 중 한 곳을

예약하고 진료를 받았죠.  

 

사실 좀 놀랐던건 굉장히 진료가 디테일할 줄 알았는데,

30초만에 진료가 끝났어요. 

증상을 말하니 '항히스타민제' 처방만 받고 끝나더라구요.

 

항히스타민제를 먹으면 2시간 정도는 괜찮지만 그 이후로는 증상이 더 심해지는 듯한

느낌을 받았습니다.

 

(사실 콜린성 두드러기가 아니였는지도 모르죠.... 자가면역질환인 경우 환자나 병원이 그 증상을 정확히 파악하는게 힘들다고 합니다.)

 

그리고 나서 생각했죠.

 

"병원에서 내리는 처방약만 믿고 살다간 평생 고통받고 살겠다"

 

그래서 이 때부터 자가면연질환에 대한 공부를 하면서 

스스로 어떻게 해야 괜찮아질지 기록하고 여러 방식들을 시도한 끝에

몸이 괜찮아지는 방법을 찾게 되었고,

일상생활이 가능할 정도로 몸이 회복됐습니다.

 

(↓↓↓콜린성 두드러기를 극복하고자 실행했던 행동들↓↓↓)

https://89douner.tistory.com/116?category=882998 

 

이 글을 쓰게된 이유

안녕하세요~ 최근 현대인들이 앉아 있는 시간이 많아지면서 활동성이 굉장히 저하되어 있다고 합니다. 앉아 있으면서 자세도 굉장히 불균형하기 때문에 목 또는 허리디스크가 걸리는 경우가 빈

89douner.tistory.com

 

 

 

2. 현대의학의 문제점 (Feat. 증상치료)

개인적으로 힘든 경험을 하면서 의학에 대해 여러 생각을하게 됐습니다.

 

분명 우리나라 의학은 최고 수준이라고 하는데, 

왜 이런 병들에 대한 해결책은 제시가 안되는 것일까?

 

그래서, 현대의학(주류의학)이라고 하는 것이 어떤 특징을 갖고 있는 알아보았습니다.

 

여러 내용들을 살펴보면서 공통적으로 접했던 용어는 '증상치료' 였습니다.

일반적으로 우리나라 병원들은 환자를 진료할 때 어떤 증상(symptom)을 토대로 질병을 판별합니다.

예를 들어, 어떤 증상을 이야기하면 해당 증상을 감기라고 진단하고, 해열제 또는 콧물억제제 같은 것을 처방합니다.

 

 

암같은 경우도 암 같은 증상이 나타나면 진단을 받고, 

수술을 통해 제거하거나 항암치료를 통해 암을 치료하기도 하죠.

 

하지만, 여기서 중요한 점이 있습니다.

위에서 말한 감기와 암 같은 경우, 일시적으로 그 병이 고쳐지긴 하겠지만,

재발하지 않는다고 장담할 수 있을까요?

 

이런 질문을 하는 이유는 

'증상치료'라는 것이 질병의 증상을 완하시키거나 일시적으로 해결해줄 수 있는 방법이긴 하나,

해당 질병의 근본적인 원인을 고치는 방법은 아니라는 점입니다.

 

재발을 한다는 것은 우리도 모르게 병을 일으키는 근본적인 원인을

계속 반복한다는 것이니까요.

 

그래서 보통 병을 고치는 관점은 크게 두 가지로 나눌 수 있습니다.

  1. 병의 증상을 없애려는 것
  2. 병의 근본적인 원인을 없애려는 것

 

 

 

3. 기능의학 (Functional medicine)

앞서 설명한 치료 관점 중 "병의 근본적인 원인을 없애려는" 시도를 하는 의학을 기능의학이라고 합니다.

 

앞서 콜린성 두드러기를 경험하고 나서 생각했던건 근본원인을 파악하려는 시도를 했다고 말씀드렸죠? 이러한 노력을 하는 것을 기능의학이라고 해요. (아.. 제가 기능의학을 했다는 말은 아닙니다ㅎ;;)

 

기능의학의 정확한 용어정의는 아래와 같습니다.

 

"Functional Medicine is a systems biology–based approach that focuses on identifying and addressing the root cause of disease."

 

쉽게 말해, 근본적인 원인을 파악함으로써 질병으로 인해 손상된 기능을 회복하는 치료방식입니다.

이러한 방식은 환자의 개별적인 특성을 고려해 치료할 수 도 있습니다.

 

이미지 출처: https://drkguidingwellness.com/what-is-metabolic-syndrome-causes-symptoms-and-treatment/

 

질병을 일으키는 원인으로는 굉장히 다양한 요소들이 있죠.

ex) 식습관, 생활패턴, 환경(ex: 미세먼지 농도), 수면부족 등..

 

 

 

4. Digital Functional Medicine

사실 "Digital Functional Medicine"이라는 용어는 존재하지 않습니다. 

그냥 제가 "Digital healthcare" + "Functional Medicine"의 합성어로 만들어낸 용어이죠.

 

이러한 용어를 만들어낸 이유는

digital healthcare에서 사용되는 모든 기술들이 functional medicine 분야를 개척하는데 필수적이라고 판단했기 때문이에요.

 

이미지 출처: https://www.freepik.com/free-vector/digital-health-technologies-flat-composition_7272631.htm

 

 

사실 주류의학 외에 대체의학이라고 하는 것들 중에는 침술, 민간요법 등이 있습니다.

이러한 대체의학이 '돌팔이'라고 간주되는 이유는 치료에 대한 과학적 근거가 없기 때문입니다.

 

예전에는 기능의학도 대체의학으로 보는 관점이 있었지만,

최근에는 다양한 데이터를 기반으로 과학적 근거들을 모집하려는 노력을 하고 있습니다.

 

예를 들어, 질병의 근본원인을 찾기 위해서는 아래와 같은 질문에 답할 수 있는 데이터들이 필요합니다.

  • What: 질병이 무엇 때문에 생겼는가? 
  • When: 질병이 언제 발생했는가? 
  • Where: 질병이 어디서 발생했는가?
  • How: 질병이 어떻게 발생했는가?
  • Why: 질병이 왜 발생했는가?

 

기존에 대학병원에서 기능의학을 하기 어려웠던 이유는 

환자마다 생활패턴, 식습관, 수면패턴 같은 것을 볼 시간적 여유가 없었기 때문입니다.

 

하지만 IT, AI의 발달로 위와 같은 데이터를 수집하는 것은 물론이고,

뛰어난 분석기술로 유의미한 처방을 해주는 노력들을 하고 있죠.

 

(↓↓↓ 디지털 치료제↓↓↓)

https://www.youtube.com/watch?v=t8MwTMo15fY 

 

 

디지털 헬스케어 분야도 기능의학에 대한 지식을 융합하면

수많은 연구가 진행될 수 있을 거라 생각합니다.

 

단순히 어떤 기계로 생체 데이터를 분석해서 내 삶에 적용했더니 

삶의 질이 높아졌다고 주장하는 것 보단

 

디지털 헬스케어 기술로 축적한 연구 결과를 기능의학과 관련된 논문으로 제출하면

의학적인 연구로 인정받을테니 기업이나 대학 입장에서도 과학적인 권위를 인정받는 연구를 진행할 수 있을거에요.

 

(↓↓↓기능의학 설명 영상 (Feat. 미국 top1 병원인 Mayo Clinic이 2위와 격차를 벌리는 이유)↓↓↓)

https://www.youtube.com/watch?v=0qQmL1FEuL8

 

 

(↓↓↓ 제가 작성한 디지털 헬스케어 관련글 ↓↓↓)

https://89douner.tistory.com/195?category=986138 

 

1. 미국의 Healthcare환경 및 의료시스템

안녕하세요. 이번 글에서는 미국의 healthcare환경 및 의료 시스템에 대해서 알아보도록 하겠습니다. 사실, 각 나라마다 의료환경이 다릅니다. 예를 들어, 유럽의 의료환경, 한국의 의료환경, 미국

89douner.tistory.com

 

 

 

지금까지 기능의학에 대한 기본적인 개념과,

디지털 헬스케어 기술이 기능의학과 융합되면 어떨지

저만의 견해를 말씀드렸습니다.

 

앞서 여러 이야기들을 했지만,

사실 넘어야 하거나 더 기술이 정교하게 다듬어져야 할 것 들이 많습니다.

예를 들어, 단순히 상관관계를 보고 결론을 내리는 것이 아니라,

인과관계와 같은 casual inference를 기반으로 의사결정을 내려야 하며,

의학과 IT, AI가 잘 융합할 수 있도록 정책또한 뒷받침이 되어야 하지 않나 싶습니다.

 

개인적으로 "이러한 분야에 뛰어들면 어떨까?"하는 고민도 하게되네요.

 

 

그럼 읽어주셔서 감사합니다!

 

 

 

 

 

안녕하세요.

이번 글에서는 MRI, PET, 초음파, 내시경 영상 이미지에 대해 알아보도록 하겠습니다.

 

사실 MRI, PET, 초음파, 내시경 영상 등을 딥러닝에 적용해 본적이 없기 때문에, 

해당 이미지들에 대한 자세한 정보들은 관련 프로젝트를 할 때,

더 추가하도록 하겠습니다.

 

 

1. MRI

(↓↓↓MRI 원리↓↓↓)

https://www.youtube.com/watch?v=P_ZD9epgwfU 

 

앞선 글에서 언급한 X-ray, CT 의 가장 큰 장점은 짧은 촬영시간과 적은 비용을 들 수 있습니다.

X-ray 같은 경우는  단 1분이내면 촬영이 끝나고, CT 촬영 또한 4분이면 마무리가 됩니다. 

 

하지만, X-ray, CT 같은 경우는 방사선 노출을 피할 수 없으며, 근육조직이나 혈관 같은 부분을 정밀하게 촬영하지 못하는 단점이 있습니다. 그래서 뇌의 구조적 변화를 살피는 것이 어려운 경우가 많습니다.

 

반면에, MRI의 경우에는 자기장을 이용하기 때문에 방사선에 노출될 위험이 없고, 뇌의 구조적 변화를 살필 수 있을 정도로 정밀한 해상도를 출력하기 때문에 'Alzheimer's Disease (치매)' 같은 질병을 영상학적으로 판단할 때 MRI를 주로 사용합니다. 

 

이미지 출처: https://www.nature.com/articles/s41598-018-29295-9

 

하지만 MRI 경우에도 단점은 있습니다.

  • 25분 정도 되는 긴 촬영시간 → 폐쇠공포 유발 가능
  • 큰 기계 소음
  • 자기장을 이용하기 때문에 몸 내부에 철로 만든 의료기기가 내장 되어 있으면 촬영이 불가능할 수 있음

 

 

 

2. PET (양전자 단층 촬영)

CT, MRI 같은 경우는 해부학적 변화를 보기 때문에 초기 질병을 발견하기 힘든 경우가 많습니다.

예를 들어, 암세포가 어느 정도있어야 CT로 확인이 가능한데, 암세포가 어느 정도 있다는 것은 어느 정도 암이 진전된 상태를 이야기 합니다.

 

다시말해, 암을 해부학적으로 확인하기 위해선 어느정도 암이 진전된 상태여야 CT 상으로 확인이 가능합니다. 

 

이러한 단점을 극복하고자, 핵 의학자들이 초기 질병을 발견할 수 있도록 만든 기술이 PET 입니다.

PET은 해부학적 변화가 일어나기 전에 생화학적 기능변화를 영상화하여 보는 기술입니다.

PET을 이용하면 인체의 생화학적 대사 이상을 보기 때문에 초기에 질병을 발견할 확률이 높죠.

 

이미지 출처: https://m.blog.naver.com/PostView.nhn?isHttpsRedirect=true&blogId=lhc930102&logNo=221164468799&categoryNo=6&proxyReferer=

 

PET이 어떤 원리로 동작하는지 알아보도록 하겠습니다.

 

암은 기본적으로 에너지(혈액, 영양)을 흡수하는 성향이 있습니다. 그래서, 보통 암이 생기면 암세포에게 내 영양분을 다 뺏기게 되고, 필요한 기관에 충분한 에너지가 전달이 안되게 됩니다.

 

핵 의학자들은 이러한 암세포의 성향을 이용해 암의 위치를 발견하고자 했습니다. 

예를 들어, 암세포가 포도당을 흡수하는데, 흡수되는 포도당에 방사선 물질이 결합되어 있는 경우, 해당 방사선이 암세포에 붙게되고, 암세포에 붙은 방사선이 방출되면서 암세포 위치가 촬영이 되는 원리이죠.

 

쉽게 순서대로 정리해보면 아래와 같습니다.

  1. 포도당과 방사능 물질을 결합한 약물(=조영제)을 몸에 투과한다.
  2. 해당 약물을 몸 전체를 돌아다니면서 암세포 같은 곳에 들러붙는다.
  3. 암세포에 붙은 약물에는 양전자가 있는데, 이 양전자가 주위 음전자와 부딪혀 방사선을 방출한다.
  4. 이때 PET 촬영 기기가 방출하는 방사선을 capture해서 해당 위치들을 영상화 한다. 

 

(↓↓↓위의 순서를 보여주는 영상↓↓↓)

https://www.youtube.com/watch?v=oySvkmezdo0 

 

앞서 언급한 것 처럼 해부학적으로 발견하기 힘든 초기 암을 진단하기 위해 사용되기도 하지만,

PET-CT는 암 판정(by CT)을 받고 암의 형상, 전이여부를 알기 위해 찍기도 합니다.

 

하지만, PET 역시 단점을 갖고 있습니다.

아무래도 방사능 물질이 체내에 주입되다보니 걱정이 되긴 하겠죠.

 

 

 

3. 초음파

(↓↓↓ 초음파 원리 ↓↓↓)

https://www.youtube.com/watch?v=PwzbsVZIJ8k 

 

초음파의 가장 큰 장점은 아래와 같이 정리할 수 있습니다.

  1. 방사선에 노출되지 않음 → 그래서 보통 뱃속 태아 상태를 확인하기 위해 사용됨
  2. 관절염 같은 질병은 해당 관절에 물이 있는지 여부를 보고 판단하는데, 초음파는 물방울 만큼의 소량의 물만 있어도 확인이가능 → 관절염 또는 연부조직 같은 곳의 상태를 확인할 때 탁월
  3. 약물 투여 치료시, 정확한 위치에 투여해야 하는 경우 초음파로 미리 해당 부위를 찾아내고 주입 
  4. 한 부위 만을 실시간 촬영 가능  → 즉, 한 부위에서 시간별 이미지를 얻을 수 있음(시계열 데이터로도 분석가능)

 

개인적으로 위에서 언급한 '3, 4'번의 장점은 딥러닝의 장점과 잘 융합될 수 있을거라 생각합니다.

 

예를 들어, 3번 같은 경우는 어떤 약물을 사람의 체내에 주입해야 할 때, 실시간 초음파 이미지를 통해 해당 부위를 찾고, 찾은 위치에 약물을 주입하게 하면 많은 도움이 될 것이라 생각됩니다. (로봇이 주입하면 항상 정량대로 주입할 수 도 있겠죠?)

 

4번 같은 경우는 실시간 이미지들을 분석해, anomaly detection 기법을 적용해 볼 수 있겠네요. 예를들어, 근육의 움직임이 이상하다던가, 혈관과 관련된 움직임 패턴이 이상하던가 말이죠.

 

 

 

4. 내시경

(↓↓↓ 내시경 ↓↓↓)

https://www.youtube.com/watch?v=-QzM4wjMx28 

 

앞서 설명한 이미지들은 보통 무언가를 투과시켜 반사되는 양을 측정해 이미지화 한 것들입니다. 

그렇기 때문에, 실제 장기들의 상태를 확인하는 것이 힘들죠.

그래서, 내시경 같은 장비를 이용하면 직접 장기를 촬영하기 때문에 "식도, 위, 십이지장, 대장, 방광 등"에 대한 컬러 이미지를 얻을 수 있게 됩니다. 

 

Kaggle이나 MICCAI 같은 곳에 가면 아래와 같은 내시경 이미지를 이용해 classification, detection, segmentation 등의 challenge를 진행합니다.

이미지 출처: https://www.kaggle.com/balraj98/polyp-segmentation-in-colonoscopy-frames-deeplab

 

 

 

5. 조직검사 이미지 (Feat. digital pathology)

앞서 알아본 X-ray, CT, MRI 등과 같은 이미지들에서 암을 찾을 수 있다고 설명했습니다.

하지만, 암을 찾은 것이 아니라 "암을 추정"하는 것이라고 말하는 것이 더 정확한 표현이라고 할 수 있습니다.

 

보통 암을 확진하는 순서는 아래와 같습니다.

  1. CT, MRI, X-ray 등과 같은 영상 이미지를 통해 병변을 의심하게 된다.
  2. 특정 병(ex: 암)이라고 의심되면 조직검사를 하게 된다.
  3. 조직검사는 아래와 같은 순서로 진행된다.
    1. 의심되는 부위에서 일부 조직을 떼낸다.
    2. 해당 조직을 "병리과"에서 현미경으로 관찰한다. 이때, 현미경으로 관찰되는 이미지를 digital pathology image라고 한다.
    3. 해당 조직을 검사해 특정 병(ex:암)이라는 소견이 나오면, 최종적으로 확인을 판정한다.

확진 판정 후에 수술로 제거할 수 있으면 제거하고, 너무 단계가 많이 진행 됐으면 화학적 치료 (ex:항암치료) 까지 진행하게 됩니다.

 

요약하자면, 조직검사를 통해 얻은 digital pathology image를 기반으로 암인지 아닌지 classifciation 해야 확진판정을 할 수 있게 되는 것입니다.

 

이미지 출처: https://www.kaggle.com/c/histopathologic-cancer-detection

 

 

(↓↓↓조직검사 과정↓↓↓)

https://www.youtube.com/watch?v=Cg4nOLeOW5U 

 

(↓↓↓루닛에서 계획하는 의료 딥러닝 process↓↓↓)

https://www.youtube.com/watch?v=ohwucxAoODE 

 

 

지금까지 설명한 영상이미지외에 안과에서 사용하는 retina 이미지도 있으며, 

정말 다양한 영상 이미지들이 존재하기 때문에 딥러닝이 이러한 병변들을 발견하는데 큰 기여를 할 수 있을거라 생각합니다.

+ Recent posts