728x90
반응형
Kaggle surface crack detection data는 콘크리트 표면 결함을 발견하고 예측하기 위한 Kaggle의 공개 데이터로서, 평균적으로 227 x 227 크기를 가지는 color 이미지이며, crack 없는 Negative 데이터 2만개와 crack 발생한 Positive 데이터 2만개, 총 4만개의 이미지 데이터이다.
모델 아키텍처 및 데이터 전처리
Conv -> MaxPooling -> Conv -> MaxPooling -> Conv -> MaxPooling -> Flatten -> Dense -> Dense
데이터 다운로드
import tensorflow as tf
from tensorflow.keras.layers import Dropout, Dense, Conv2D, GlobalAveragePooling2D, MaxPool2D
from tensorflow.keras.models import Sequential
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from google.colab import drive
drive.mount('/content/gdrive/')
import shutil
import os
try:
dataset_path = 'content/gdrive/My Drive/Colab Notebooks/dataset'
shutil.copy(os.path.join(dataset_path, 'surface_crack.zip'), '/content')
except Exception as err:
print(str(err))
# ROOT_DIR, DATA_ROOT_DIR 등의 변수를 설정해두면, Colab이외 시스템에서는 디렉토리 설정 부분만 변경하면
# 프로그램 호한성을 높일 수 있음
ROOT_DIR = '/content'
DATA_ROOT_DIR = os.path.join(ROOT_DIR, 'surface_crack')
TRAIN_DATA_ROOT_DIR = os.path.join(DATA_ROOT_DIR, 'train')
TEST_DATA_ROOT_DIR = os.path.join(DATA_ROOT_DIR, 'test')
import zipfile
with zipfile.ZipFile(os.path.join(ROOT_DIR, 'surface_crack.zip'), 'r') as target_file:
target_file.extractall(DATA_ROOT_DIR)
# Negative, Positive 디렉토리는 이미지 정답(label)을 나타내며, 해당 디렉토리에 정답에 해당하는 이미지가 들어가있음
# 즉, 총 2개의 정답을 가지는 이미지가 학습데이터임
label_name_list = os.listdir(DATA_ROOT_DIR)
print(label_name_list)
for label_name in label_name_list:
label_dir = os.path.join(DATA_ROOT_DIR, label_name)
print('train label : ' + label_name + ' => ', len(os.listdir(os.path.join(DATA_ROOT_DIR, label_name))))
데이터 전처리 (train dir / test dir 생성)
import shutil
try:
shutil.copytree(DATA_ROOT_DIR, TRAIN_DATA_ROOT_DIR)
except EXxception as err:
print(str(err))
if not os.path.exists(TEST_DATA_ROOT_DIR):
os.mkdir(TEST_DATA_ROOT_DIR)
if not os.path.exists(os.path.join(TEST_DATA_ROOT_DIR, 'Positive')):
os.mkdir(os.path.jjoin(TEST_DATA_ROOT_DIR, 'Positive'))
if not os.path.exists(os.path.join(TEST_DATA_ROOT_DIR, 'Negative')):
os.mkdir(os.path.join(TEST_DATA_ROOT_DIR, 'Negative'))
데이터 전처리 (train data : test data = 8 : 2)
import os
import shutil
import random
MOVE_RATIO = 0.2 # train data로 부터 생성될 test data비율, 즉 8:2 비율로 train data와 test data를 만들 예정
label_name_list = os.listdir(TRAIN_DATA_ROOT_DIR)
for label_name in label_name_list:
src_dir_path = os.path.join(TRAIN_DATA_ROOT_DIR, label_name)
dst_dir_path = os.path.join(TEST_DATA_ROOT_DIR, label_name)
# shuffle train data
# 다양한 데이터를 확보하기 위해 train data list를 random하게 shuffle한 후에, numpy slice를 이용하여 test data list 생성
train_data_file_list = os.listdir(src_dir_path)
random.shuffle(train_data_file_list)
split_num = int(MOVE_RATIO*len(train_data_file_list))
test_data_file_list = train_data_file_list[0:split_num]
# shutil.move 이용해서 train 디렉토리에서 20% 비율로 test 디렉토리로 data move
for test_data_file in test_data_file_list:
try:
shutil.moe(os.path.join(src_dir_path, test_data_file),
os.path.join(dst_dir_path, test_data_file))
except Exception as err:
print(str(err))
데이터 전처리
train_datagen = ImageDataGenerator(rescale=1./255, validation_split=0.20) # 20% 비율로 validation 생성
validation_datagen = ImageDataGenerator(rescale=1./255, validation_split=0.20)
test_datagen = ImageDataGenerator(rescale=1./255)
IMG_WIDTH = 128
IMG_HEIGHT = 128 # 데이터 전체 개수가 많기 때문에 이미지 사이즈 224 x 224 등으로 크게하면 Memory Fail 발생
train_generator = train_datagen.flow_from_directory(TRAIN_DATA_ROOT_DIR, batch_size=32, color_mode='rgb', class_mode='sparse', target_size=(IMG_WIDTH, IMG_HEIGHT), subset='training')
validation_generator = validation_datagen.flow_from_directory(TRAIN_DATA_ROOT_DIR, batch_size=32, color_mode='rgb', class_mode='sparse', target_size=(IMG_WIDTH, IMG_HEIGHT), subset='validation')
test_generator = test_datagen.flow_from_directory(TEST_DATA_ROOT_DIR, batch_size=32, color_mode='rgb', class_mode='sparse', target_size=(IMG_WIDTH, IMG_HEIGHT))
print(train_generator.class_indices, train_generator.num_classes)
모델 아키텍처
3개의 컨볼루션 레이어와 맥스풀링 레이어를 교차로 가지고 있는 구조로 설정
Conv -> MaxPooling -> Conv -> MaxPooling -> Conv -> MaxPooling -> Flatten -> Dense -> Dense
class_nums = train_generator.num_classes # class_nums = 2
model =Sequential()
model.add(Conv2D(kernel_size=(3,3), filters=32, activation='relu', padding='same', input_shape(IMG_WIDTH, IMG_HEIGHT, 3)))
model.add(MaxPool2D(pool_size=(2,3)))
model.add(Dropout(0.25))
model.add(Conv2D(kernel_size=(3,3), filters=64, activation='relu', padding='same'))
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Dropout(0.25))
model.add(Conv2D(kernel_size=(3,3), filters=128, activation='relu' padding='same'))
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Dropout(0.25))
model.add(GlobalAveragePooling2D())
# 정확도를 높이고 오버피팅을 줄이기 위해 2개의 Desne 레이어와 1개의 Dropout 레이어 구성
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(class_nums, activation='softmax'))
model.complie(loss='sparse_categorical_crossentropy', optimizer=tf.keras.optimizers.Adam(1e-4), metrics=['acc'])
데이터 학습
from tensorflow.keras.callbacks import EarlyStopping
earlystopping = EarlyStopping(monitor='val_loss', patience=5, verbose=1)
hist = model.fit(train_generator, epochs=30, validation_data=validation_generator, callbacks=[earlystopping])
model.evaluate(test_generator)
반응형
'IT > 머신러닝공부' 카테고리의 다른 글
PyTorch 간단 소개 Colab 사용 (0) | 2023.01.04 |
---|---|
AI Snake Game - Reinforcement Learning with PyTorch[1] by Patrick Loeber (2) | 2023.01.02 |
GTSRB(German Traffic Sign Recognition Benchmark) Project 간단 정리 및 Example script (0) | 2022.12.31 |
Callback 함수 간단 정리 (0) | 2022.12.31 |
Transfer Learning 전이학습을 활용한 나만의 이미지 분류 시스템 구현 예제 script (0) | 2022.12.31 |