Deeplearning - chap 9-2

심준보·2023년 6월 12일
0
post-thumbnail

최신 컨브넷 아키텍처 패턴

  • 1
from tensorflow import keras
from tensorflow.keras import layers

inputs = keras.Input(shape=(32, 32, 3))
x = layers.Conv2D(32, 3, activation="relu")(inputs)
residual = x    
x = layers.Conv2D(64, 3, activation="relu", padding="same")(x)
residual = layers.Conv2D(64, 1)(residual)    
x = layers.add([x, residual]) 
  • inputs = keras.Input(shape=(32, 32, 3))

-> shape=(32, 32, 3)는 32x32 크기의 RGB 이미지를 의미합니다. 입력은 keras.Input 함수를 사용하여 정의되며, 모델의 첫 번째 레이어로 사용

  • x = layers.Conv2D(32, 3, activation="relu")(inputs)

-> 3x3 크기의 필터를 사용하여 32개의 출력 채널을 가지는 컨볼루션 레이어를 정의합니다. 입력은 inputs이며, 활성화 함수로 ReLU를 사용 , 특징추출

  • residual = x

-> 이는 나중에 스킵 연결(skip connection)을 수행하기 위해 사용

  • residual = layers.Conv2D(64, 1)(residual)

-> residual을 입력으로 받아 1x1 크기의 필터를 사용하여 64개의 출력 채널을 가지는 컨볼루션 레이어를 정의

  • x = layers.add([x, residual])ㅇ

-> 이전 레이어의 출력이 현재 레이어의 출력에 직접적으로 추가

inputs = keras.Input(shape=(32, 32, 3))
x = layers.Rescaling(1./255)(inputs)

def residual_block(x, filters, pooling=False):
    residual = x
    x = layers.Conv2D(filters, 3, activation="relu", padding="same")(x)
    x = layers.Conv2D(filters, 3, activation="relu", padding="same")(x)
    if pooling:
        x = layers.MaxPooling2D(2, padding="same")(x)
        residual = layers.Conv2D(filters, 1, strides=2)(residual)
    elif filters != residual.shape[-1]:
        residual = layers.Conv2D(filters, 1)(residual)
    x = layers.add([x, residual])
    return x

x = residual_block(x, filters=32, pooling=True)
x = residual_block(x, filters=64, pooling=True)
x = residual_block(x, filters=128, pooling=False)

x = layers.GlobalAveragePooling2D()(x)
outputs = layers.Dense(1, activation="sigmoid")(x)
model = keras.Model(inputs=inputs, outputs=outputs)
model.summary()
  • if pooling:
    x = layers.MaxPooling2D(2, padding="same")(x)
    residual = layers.Conv2D(filters, 1, strides=2)(residual)

-> pooling=True 인 경우, 2x2 크기의 최대 풀링(Max Pooling)을 적용하고 스킵 연결을 위해 이전 레이어의 출력 residual에 1x1 크기의 필터를 사용하여 다운샘플링을 수행

  • elif filters != residual.shape[-1]:
    residual = layers.Conv2D(filters, 1)(residual)

-> pooling=False 이면서 filters와 residual.shape[-1]이 다른 경우, 1x1 크기의 필터를 사용하여 스킵 연결을 수행

깊이별 분리 합성곱

from google.colab import files
files.upload()
import os, shutil, pathlib
from tensorflow.keras.utils import image_dataset_from_directory

original_dir = pathlib.Path("train")
new_base_dir = pathlib.Path("cats_vs_dogs_small")

def make_subset(subset_name, start_index, end_index):
    for category in ("cat", "dog"):
        dir = new_base_dir / subset_name / category
        os.makedirs(dir)
        fnames = [f"{category}.{i}.jpg" for i in range(start_index, end_index)]
        for fname in fnames:
            shutil.copyfile(src=original_dir / fname,
                            dst=dir / fname)

make_subset("train", start_index=0, end_index=1000)
make_subset("validation", start_index=1000, end_index=1500)
make_subset("test", start_index=1500, end_index=2500)

train_dataset = image_dataset_from_directory(
    new_base_dir / "train",
    image_size=(180, 180),
    batch_size=32)
validation_dataset = image_dataset_from_directory(
    new_base_dir / "validation",
    image_size=(180, 180),
    batch_size=32)
test_dataset = image_dataset_from_directory(
    new_base_dir / "test",
    image_size=(180, 180),
    batch_size=32)

files 모듈의 upload() 함수를 사용하여 파일을 업로드합니다. 이 함수는 사용자에게 파일 선택 대화 상자를 표시하고, 선택한 파일을 현재 작업 공간으로 업로드합니다.

  • image_dataset_from_directory 함수를 사용하여 이미지 데이터셋을 생성하는 작업을 수행
    -디렉토리에서 이미지를 자동으로 로드하여 데이터셋을 생성합니다.
    -이미지 파일의 경로를 사용하여 클래스 레이블을 자동으로 할당합니다.
    -이미지를 로드하고 전처리하기 위해 TensorFlow의 데이터셋 파이프라인을 활용합니다.
    -데이터셋을 배치로 나누어 모델 학습에 사용할 수 있도록 합니다.

  • make_subset 함수는 지정된 범위에 해당하는 이미지 파일을 원하는 하위 데이터셋 디렉토리로 복사하는 역할을 합니다. "train", "validation", "test" 세 가지 하위 데이터셋을 생성합니다.

  • 증강
data_augmentation = keras.Sequential(
    [
        layers.RandomFlip("horizontal"),
        layers.RandomRotation(0.1),
        layers.RandomZoom(0.2),
    ]
)
  • layers.RandomFlip("horizontal")
    -> 수평 방향으로 랜덤하게 이미지를 뒤집는 레이어입니다. 이를 통해 이미지의 좌우 반전을 수행하여 데이터 다양성을 높일 수 있습니다.

  • layers.RandomRotation(0.1)
    -> 랜덤하게 이미지를 회전시키는 레이어입니다. 이를 통해 이미지를 약간 회전시켜 데이터의 다양성을 추가합니다. 여기서 인자로 주어진 0.1은 회전 각도의 범위를 지정

  • layers.RandomZoom(0.2)

-> 랜덤하게 이미지를 확대 또는 축소하는 레이어입니다

inputs = keras.Input(shape=(180, 180, 3))
x = data_augmentation(inputs)

x = layers.Rescaling(1./255)(x)
x = layers.Conv2D(filters=32, kernel_size=5, use_bias=False)(x) 

for size in [32, 64, 128, 256, 512]:
    residual = x

    x = layers.BatchNormalization()(x)
    x = layers.Activation("relu")(x)
    x = layers.SeparableConv2D(size, 3, padding="same", use_bias=False)(x)

    x = layers.BatchNormalization()(x)
    x = layers.Activation("relu")(x)
    x = layers.SeparableConv2D(size, 3, padding="same", use_bias=False)(x)

    x = layers.MaxPooling2D(3, strides=2, padding="same")(x)

    residual = layers.Conv2D(
        size, 1, strides=2, padding="same", use_bias=False)(residual)
    x = layers.add([x, residual])

x = layers.GlobalAveragePooling2D()(x)
x = layers.Dropout(0.5)(x)
outputs = layers.Dense(1, activation="sigmoid")(x)
model = keras.Model(inputs=inputs, outputs=outputs)
  • x = layers.Rescaling(1./255)(x)
    -> 데이터 값을 0-1 범위로 정규화하기 위해 Rescaling 레이어를 사용

  • x = layers.Conv2D(filters=32, kernel_size=5, use_bias=False)(x)
    -> use_bias가 false로 설정되어 있으므로 편향은 사용되지 않는다.

  • x = layers.BatchNormalization()(x)
    -> 배치정규화를 수행한다. 모델의 안정성과 학습 속도를 향상시키는데 도움이 된다.

  • x = layers.SeparableConv2D(size, 3, padding="same", use_bias=False)(x)
    -> 깊이별 분리 컨볼루션을 적용한다.

  • x = layers.Activation("relu")(x)
    -> relu활성화 함수를 적용한다.

  • x = layers.MaxPooling2D(3, strides=2, padding="same")(x)
    -> 최대 풀링 레이어를 추가하여 공간 차원을 줄입니다.

  • residual = layers.Conv2D(size, 1, strides=2, padding="same", use_bias=False)(residual)
    -> 1x1 컨볼루션 레이어를 사용하여 입력 residual의 차원을 줄입니다. 이렇게 함으로써 잔차 연결을 위한 차원을 맞춰줍니다.
  • x = layers.GlobalAveragePooling2D()(x)
    -> 전역 평균 풀링 레이어를 사용하여 공간 차원을 축소
    ->이는 입력 이미지의 공간적인 위치에 상관없이 각 채널에 대한 평균값을 계산하여 1차원 벡터로 변환

  • x = layers.Dropout(0.5)(x)
    ->드롭아웃 레이어를 사용하여 과적합을 방지하기 위해 일부 뉴런을 무작위로 비활성화합니다. 여기서는 0.5의 드롭아웃 비율을 사용

  • outputs = layers.Dense(1, activation="sigmoid")(x)
    -> 마지막으로, 전결합층(Dense)을 사용하여 이진 분류를 수행합니다. 이진 분류를 위해 출력 뉴런은 1개이며, 시그모이드 활성화 함수를 사용 , dense사용

model.compile(loss="binary_crossentropy",
              optimizer="rmsprop",
              metrics=["accuracy"])
history = model.fit(
    train_dataset,
    epochs=100,
    validation_data=validation_dataset)
  • model.compile(loss="binary_crossentropy", optimizer="rmsprop", metrics=["accuracy"])
    -> 모델을 컴파일합니다. 이때 손실 함수로 이진 분류를 위한 이진 크로스 엔트로피(binary_crossentropy)를 사용하고, 옵티마이저로 RMSprop을 선택합니다. 평가 지표로는 정확도(accuracy)를 사용

  • history = model.fit(train_dataset, epochs=100, validation_data=validation_dataset)
    -> train_dataset은 학습 데이터셋이며, epochs는 에포크 수를 나타냅니다. validation_data는 검증 데이터셋으로, 학습 중에 모델의 성능을 평가하는 데 사용
    여기서 , fit할때 train, label따로 넣어주지 않는 것이 특징

profile
밑거름이라고생각합니다

0개의 댓글