Tensorflow를 활용한 classification 진행하기

chi yeong Yu·2022년 3월 18일
0

tensorflow

목록 보기
1/5

이번에 진행할 데이터는 기차레일의 손상 분류하는 문제 !!!!

from tensorflow.keras.preprocessing.image import ImageDataGenerator
# image 전처리 및 위치, class 분류 
# 아주 훌륭한 함수
from tensorflow.keras import models, layers
from tensorflow.keras.applications import ResNet50V2, VGG16, DenseNet121
# 비교를 위해 3개의 trained model을 가져옴
import os
import matplotlib.pyplot as plt
import matplotlib.image as img
from glob import glob

train = 'Train/'
val = 'Validation/'
test = 'Test/'

#데이터 가져오기
train_defective = os.listdir(train+'Defective')
train_non_defective = os.listdir(train+'Non defective')

rows = 2
cols = 2

fig = plt.gcf() # 그릴려고 하는 figure 객체를 구하는 방법
fig.set_size_inches(cols * 5, rows * 5)

# 현재 가지고 있는 사진들에 path를 적용
next_defect = [os.path.join(train+'Defective', name) for name in train_defective[1:5]]
next_non_defect = [os.path.join(train+'Non defective', name) for name in train_non_defective[1:5]]

for i, img_path in enumerate(next_defect + next_non_defect):
    sub = plt.subplot(rows+2, cols+2, i+1)
    sub.axis('off')
    # img -> import matplotlib.image as img 
    image = img.imread(img_path)
    plt.imshow(image)
plt.show()
# 윗 줄은 아무 이상 없는 Rail
#아랫 줄은 고리가 끊어지거나 정비가 필요해 보이는 Rail

image = img.imread(next_defect[0])
plt.imshow(image)
plt.show()
# 이런 데이터 구나 확인하기 위함....
#image.shape -> (721, 960, 3)

train_generator = ImageDataGenerator(rescale = 1./255, # scale 적용
                                     rotation_range = 40, # 회전 각도 범위
                                     width_shift_range=0.2, # 전체 가로 넓이 비율
                                     height_shift_range=0.2, # 전체 세로 넓이 비율
                                     shear_range=0.2, # 반시계 방향 층 밀어내기
                                     zoom_range=0.2, # 무작위 확대하기
                                     horizontal_flip=True, # 무작위로 가로로 뒤집기 
                                     vertical_flip=True) # 무작위로 세로로 뒤집기
                                     # 이렇게 다양하게 효과를 주는 이유는 
                                     # 사진 1장에 다양한 효과 (노이즈)를 줘서 하나의 이미지에서 다양한 결과를 추출하기 위함

train_gen = train_generator.flow_from_directory(train,
                                                target_size = (300, 300),
                                                batch_size = 16,
                                                color_mode = 'rgb',
                                                shuffle=True, # train에만 shuffle 적용  == test, val 적용하면 결과값이 계속 바뀌는 불상사 발생 
                                                seed=42,
                                                class_mode='categorical')
                                                # class_mode = binary 도 있는데 2가지의 클래스를 구분하기 위해 categorical로 적용
                                                # 정답과 정답이 아닌 것을 적용을 하려면 binary
  
val_generator = ImageDataGenerator(rescale=1./255)
val_gen = val_generator.flow_from_directory(val,
                                            target_size=(300, 300),
                                            batch_size=16,
                                            color_mode='rgb',
                                            shuffle=False,
                                            class_mode='categorical')
  
test_generator = ImageDataGenerator(rescale=1./255)
test_gen = test_generator.flow_from_directory(test,
                                              target_size=(300, 300),
                                              batch_size=16,
                                              color_mode='rgb',
                                              shuffle=False,
                                              class_mode='categorical')

폴더별로 class를 나눠줌 -> 데이터도 다 찾아줌

resnet = ResNet50V2(input_shape = (300, 300, 3), weights='imagenet', include_top=False)
resnet.trainable = False # 가져온 모델이 가중치 업데이트를 하지 못하게 함

#resnet, vgg, densenet 비교하기위함
x=resnet.output
x=layers.GlobalAveragePooling2D()(x)
x=layers.Dense(128,activation='relu')(x)  
preds=layers.Dense(2,activation='softmax')(x) 

resnet_model=models.Model(inputs=resnet.input,outputs=preds)
resnet_model.summary()
#---------------------------------------------------------------
  vgg_model
#vgg = VGG16(input_shape = (300, 300, 3), #weights='imagenet', include_top=False)
#vgg.trainable = False # 가져온 모델이 가중치 업데이트를 하지 못하게 함

#x=vgg.output
#x=layers.GlobalAveragePooling2D()(x)
#x=layers.Dense(128,activation='relu')(x)  
#preds=layers.Dense(2,activation='softmax')(x) 

#vgg_model=models.Model(inputs=vgg.input,outputs=preds)
#vgg_model.summary()
#-----------------------------------------------------------------
  dense_model
#dense = DenseNet121(input_shape = (300, 300, 3), #weights='imagenet', include_top=False)
#dense.trainable = False # 가져온 모델이 가중치 업데이트를 하지 못하게 함

#x=dense.output
#x=layers.GlobalAveragePooling2D()(x)
#x=layers.Dense(128,activation='relu')(x)  
#preds=layers.Dense(2,activation='softmax')(x) 

#dense_model=models.Model(inputs=dense.input,outputs=preds)
#dense_model.summary()

resenet_model

vgg_model

dense_model

step_size_train = train_gen.n//train_gen.batch_size # train_gen.n -> .n (이미지 개수) // 16 (batch_size)
step_size_val = val_gen.n // val_gen.batch_size# val_gen.n -> .n (이미지 개수) // 16 (batch_size)
step_size_test = test_gen.n // test_gen.batch_size# test_gen.n -> .n (이미지 개수) // 16 (batch_size)
epochs=20
---------------------------------#밑으로는 모델 변경  
resnet_model.compile(loss='categorical_crossentropy', optimizer='Adam', metrics=['accuracy'])
# vgg_model, dense_model
history = resnet_model.fit(train_gen,
                    steps_per_epoch=step_size_train, # 1번의 epoch 를 18번 반복
                    epochs=epochs,
                    validation_data=val_gen,
                    validation_steps=step_size_val) # 1번의 epoch를 3번 반복
  
print(history.history.keys())
# model이 돌아갈때 history 변수에 담아줘서 가능함

def show_train_history(hisData,train,val): 
    plt.plot(hisData.history[train])
    plt.plot(hisData.history[val])
    plt.title('Training History')
    plt.ylabel(train)
    plt.xlabel('Epoch')
    plt.legend(['train', 'val'], loc='upper left')
    plt.show()

show_train_history(history, 'loss', 'val_loss')

show_train_history(history, 'accuracy', 'val_accuracy')

Resnet_model

vgg_model.compile(loss='categorical_crossentropy', optimizer='Adam', metrics=['accuracy'])

history_vgg = vgg_model.fit(train_gen,
                    steps_per_epoch=step_size_train,
                    epochs=epochs,
                    validation_data=val_gen,
                    validation_steps=step_size_val)
  
def show_train_history(hisData,train,val): 
    plt.plot(hisData.history[train])
    plt.plot(hisData.history[val])
    plt.title('vgg_Training History')
    plt.ylabel(train)
    plt.xlabel('Epoch')
    plt.legend(['train', 'val'], loc='upper left')
    plt.show()

show_train_history(history_vgg, 'loss', 'val_loss')

show_train_history(history_vgg, 'accuracy', 'val_accuracy')

dense_model.compile(loss='categorical_crossentropy', optimizer='Adam', metrics=['accuracy'])

history_dense = dense_model.fit(train_gen,
                    steps_per_epoch=step_size_train,
                    epochs=epochs,
                    validation_data=val_gen,
                    validation_steps=step_size_val)

def show_train_history(hisData,train,val): 
    plt.plot(hisData.history[train])
    plt.plot(hisData.history[val])
    plt.title('Dense_Training History')
    plt.ylabel(train)
    plt.xlabel('Epoch')
    plt.legend(['train', 'val'], loc='upper left')
    plt.show()

show_train_history(history_dense, 'loss', 'val_loss')

show_train_history(history_dense, 'accuracy', 'val_accuracy')

resnet_model_score = resnet_model.evaluate(test_gen, steps=step_size_test)
vgg_model_score = vgg_model.evaluate(test_gen, steps=step_size_test)
dense_model_score = dense_model.evaluate(test_gen, steps=step_size_test)
  
# score[0] -> loss,  score[1] -> accuracy
print(f'Resnet_score : {resnet_model_score}, Vgg_score : {vgg_model_score}, Dense_score : {dense_model_score}')
# 전반적으로 resnet50v2 성능이 좋다라고 보여진다.

Data : https://www.kaggle.com/salmaneunus/railway-track-fault-detection

profile
호기심천국

0개의 댓글