2021/05/23 프로그래머스에서 Dev-Matching 머신러닝 개발자 챌린지에 도전했습니다. 지금까지 나름 많이 공부했다고 생각했는데 아직 많이 부족하다는 생각을 했습니다.
문제는 단순히 이런 그림 데이터를 갖고 개, 코끼리, 기린, 기타, 말, 집, 사람으로 분류하는거였습니다.
제가 사용한 방법은 ResNet으로 사전학습된 모델로 특징 추출만하고 추출된 데이터로 DNN을 구현하는거였습니다.
물론 점수는 78.571점이라는 낮은 점수가 나왔고, 100점이신분들도 많아서 좋은 코드도 많습니다. 하지만, 이 방식이 매우 독특하고 컴퓨터 사양이 안좋은 환경에서는 적합하다고 생각되어 코드를 공유합니다.
데이터를 ImageDataGenerator에 넣습니다.
(사실 데이터 양이 얼마 안돼서 그냥 glob로 이미지 데이터를 불러와도 됩니다. 다시보니까 정말 비효율적인 코드네요...)
- 각각의 이미지를 라벨링한 list를 만들었고, 그것을 csv파일로 만들어서 따로 보관해놨습니다.
- csv파일에서 ImageDataGenerator를 통해 이미지 경로와 onehotencoding된 y값을 받아옵니다.
import pandas as pd import numpy as np import glob from keras_preprocessing.image import ImageDataGenerator dogs = glob.glob("../train/dog/*.jpg") elephant = glob.glob("../train/elephant/*.jpg") giraffe = glob.glob("../train/giraffe/*.jpg") guitar = glob.glob("../train/guitar/*.jpg") horse = glob.glob("../train/horse/*.jpg") house = glob.glob("../train/house/*.jpg") person = glob.glob("../train/person/*.jpg") train_df = pd.read_csv("../train_answer_aug.csv") train_answer_val = [] for img in dogs: DIR = img[9:] DIR = DIR.replace('\\','/') train_answer_val.append([DIR,1,0,0,0,0,0,0]) for img in elephant: DIR = img[9:] DIR = DIR.replace('\\','/') train_answer_val.append([DIR,0,1,0,0,0,0,0]) for img in giraffe: DIR = img[9:] DIR = DIR.replace('\\','/') train_answer_val.append([DIR,0,0,1,0,0,0,0]) for img in guitar: DIR = img[9:] DIR = DIR.replace('\\','/') train_answer_val.append([DIR,0,0,0,1,0,0,0]) for img in horse: DIR = img[9:] DIR = DIR.replace('\\','/') train_answer_val.append([DIR,0,0,0,0,1,0,0]) for img in house: DIR = img[9:] DIR = DIR.replace('\\','/') train_answer_val.append([DIR,0,0,0,0,0,1,0]) for img in person: DIR = img[9:] DIR = DIR.replace('\\','/') train_answer_val.append([DIR,0,0,0,0,0,0,1]) train_answer = pd.DataFrame(train_answer_val, columns = ["DIR", "dogs", 'elephant', 'giraffe', 'guitar', 'horse' , 'house', 'person']) train_answer.to_csv('../train_answer.csv', index=False) data = pd.read_csv("../train_answer.csv") columns = data.columns datagen=ImageDataGenerator(rescale = 1/255) data_generator=datagen.flow_from_dataframe( dataframe=data, directory='../train/', x_col="DIR", y_col=columns[1:], batch_size=1, shuffle=False, class_mode="raw", target_size=(224,224))
이미지 데이터를 ResNet의 사전학습된 가중치로 predict(precomputed)합니다.
(이렇게 하면 완벽하진 않지만 어느정도 특징이 추출된 1000사이즈의 데이터로 만들어집니다.)
import tensorflow as tf
from sklearn.model_selection import train_test_split
my_rnet = tf.keras.applications.ResNet152V2(
include_top=True, weights='imagenet',input_shape=(224,224,3), pooling="avg")
my_rnet.trainable = True
precomputed_data = my_rnet.predict(train_generator, verbose=1)
X_train, X_valid, y_train, y_valid = train_test_split(precomputed_data, data.iloc[:,1:], test_size=0.2, random_state=1234)
사전처리된 DNN모델에 학습시킵니다.
(학습속도가 매우 빠르기 때문에 저사양에서도 순식간에 많은 epoch를 학습시킬 수 있습니다.)
from tensorflow.keras.models import Model, Sequential, load_model from tensorflow.keras.layers import Dense, Dropout, BatchNormalization, Input from tensorflow.keras.optimizers import Adam topModel = Sequential() topModel.add(Input((1000,))) topModel.add(BatchNormalization()) topModel.add(Dense(512, activation='relu')) topModel.add(BatchNormalization()) topModel.add(Dense(256, activation='relu')) topModel.add(BatchNormalization()) topModel.add(Dense(128, activation='relu')) topModel.add(BatchNormalization()) topModel.add(Dense(7, activation='softmax')) topModel.summary() mc = ModelCheckpoint('best_model.h5', monitor='val_loss', mode='min', verbose=1, save_best_only=True) topModel.compile(loss='categorical_crossentropy', optimizer=Adam(0.001), metrics=['mae']) topModel.fit(X_train, y_train, epochs=100, batch_size=32, validation_data=(X_valid, y_valid),callbacks=[mc])
학습 중 저장된 best_model.h5 모델과 resnet을 합친 모델을 만들어서 predict합니다.
from tensorflow.keras.models import load_model loaded_model = load_model('best_model.h5') final_model = Sequential([my_rnet, topModel]) final_model.summary() test_df = pd.DataFrame() test = glob.glob("../test/0/*.jpg") test_dir = [] for img in test: test_dir.append(img[10:]) test_df["DIR"] = test_dir test_datagen=ImageDataGenerator(rescale = 1/255) test_generator = test_datagen.flow_from_dataframe( dataframe=test_df[:], directory='../test/0', x_col="DIR", y_col=columns[0], batch_size=1, shuffle=False, class_mode="raw", target_size=(224,224)) pred = model.predict(test_generator, verbose=1) answer = np.array([y.argmax() for y in pred]) test_df = pd.read_csv("../test_answer_sample_.csv") test_df.iloc[:,1] = answer test_df.to_csv('answer_resNet_aug2.csv', index=False)
아직 부족한게 많지만, 이런 아이디어도 있다는 것에 관심 가져주셨으면 합니다.
사실 비전학습은 pytorch가 짱이죠 그냥 torch쓰세요.
'ML | DL' 카테고리의 다른 글
AutoML_Alex 라이브러리 설명 (0) | 2021.07.15 |
---|---|
RandomForest, XGBoost, LGBM, CatBoost뭐가 다를까? (1) | 2021.06.09 |
ALS 추천시스템(Implicit 라이브러리) (0) | 2021.06.01 |
신용카드 사용자 연체 예측 AI 경진대회 (0) | 2021.05.27 |
댓글