Skip to content

Instantly share code, notes, and snippets.

@yunsu3042
Created January 15, 2019 09:43
Show Gist options
  • Save yunsu3042/240b15b14a551ebbd49a52acfddbace3 to your computer and use it in GitHub Desktop.
Save yunsu3042/240b15b14a551ebbd49a52acfddbace3 to your computer and use it in GitHub Desktop.
# -*- coding: utf_8 -*-
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import os
import cv2
import argparse
import pickle
import nsml
import numpy as np
from nsml import DATASET_PATH
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten, Activation
from keras.layers import Conv2D, MaxPooling2D
from keras.callbacks import ReduceLROnPlateau
from keras import backend as K
from keras.applications.resnet50 import ResNet50
from keras.applications.resnet50 import preprocess_input
from sklearn.neighbors import NearestNeighbors
from sklearn.externals import joblib
from data_loader import train_data_loader
def bind_model(model):
def save(dir_name):
os.makedirs(dir_name, exist_ok=True)
model.save_weights(os.path.join(dir_name, 'model'))
print('model saved!')
def load(file_path):
model.load_weights(file_path)
print('model loaded!')
def build_knn(reference_img, n_neighbor):
""" KNN """
X = preprocess_input(reference_img.astype(np.float))
X_conv = model.predict(X)
knn = NearestNeighbors(n_neighbors=n_neighbor, n_jobs=8, algorithm='ball_tree')
knn.fit(X_conv)
return knn
def make_resnet_conv(input_shape):
model = ResNet50(input_shape=input_shape, weights = 'imagenet', include_top=False,
pooling='avg' )
for layer in model.layers:
layer.trainable = False
return model
def infer(queries, db):
# Query 개수: 195
# Reference(DB) 개수: 1,127
# Total (query + reference): 1,322
queries, query_img, references, reference_img = preprocess(queries, db)
print('test data load queries {} query_img {} references {} reference_img {}'.
format(len(queries), len(query_img), len(references), len(reference_img)))
queries = np.asarray(queries)
query_img = np.asarray(query_img)
references = np.asarray(references)
reference_img = np.asarray(reference_img)
""" Model """
print("making resnet model")
input_shape = (224, 224, 3) # input image shape
model = make_resnet_conv(input_shape=input_shape)
bind_model(model)
# caching db knn
print("building knn")
db_output = './db_knn.pkl'
if os.path.exists(db_output):
knn = joblib.load(f)
else:
knn = build_knn(reference_img, len(references))
joblib.dump(knn, db_output)
print('inference start')
query_features = model.predict(query_img)
query_tagging = []
for (i, query_feature) in enumerate(query_features):
neighbors = knn.kneighbors(query_feature, return_distance=True)
nearests = get_nearest(neighbors)
refer_tag = list(map(lambda n : "refer_" + n, nearests))
query_tag = queries[i].split('/')[-1].split('.')[0]
tagging = (i, (query_tag, refer_tag))
query_tagging.append(tagging)
print('done')
return query_tagging
# DONOTCHANGE: They are reserved for nsml
nsml.bind(save=save, load=load, infer=infer)
def get_nearest(neighbors):
distance = neighbors[0][0]
indexs = neighbors[1][0]
return indexs
def l2_normalize(v):
norm = np.linalg.norm(v)
if norm == 0:
return v
return v / norm
# data preprocess
def preprocess(queries, db):
query_img = []
reference_img = []
img_size = (224, 224)
for img_path in queries:
img = cv2.imread(img_path, 1)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, img_size)
query_img.append(img)
for img_path in db:
img = cv2.imread(img_path, 1)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, img_size)
reference_img.append(img)
return queries, query_img, db, reference_img
if __name__ == '__main__':
args = argparse.ArgumentParser()
# hyperparameters
args.add_argument('--epochs', type=int, default=5)
args.add_argument('--batch_size', type=int, default=128)
# DONOTCHANGE: They are reserved for nsml
args.add_argument('--mode', type=str, default='train', help='submit일때 해당값이 test로 설정됩니다.')
args.add_argument('--iteration', type=str, default='0', help='fork 명령어를 입력할때의 체크포인트로 설정됩니다. 체크포인트 옵션을 안주면 마지막 wall time 의 model 을 가져옵니다.')
args.add_argument('--pause', type=int, default=0, help='model 을 load 할때 1로 설정됩니다.')
config = args.parse_args()
# training parameters
nb_epoch = config.epochs
batch_size = config.batch_size
num_classes = 1000
input_shape = (224, 224, 3) # input image shape
""" Model """
model = Sequential()
model.add(Conv2D(32, (3, 3), padding='same', input_shape=input_shape))
model.add(Activation('relu'))
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes))
model.add(Activation('softmax'))
model.summary()
bind_model(model)
if config.pause:
nsml.paused(scope=locals())
bTrainmode = False
if config.mode == 'train':
bTrainmode = True
""" Initiate RMSprop optimizer """
opt = keras.optimizers.rmsprop(lr=0.00045, decay=1e-6)
model.compile(loss='categorical_crossentropy',
optimizer=opt,
metrics=['accuracy'])
""" Load data """
print('dataset path', DATASET_PATH)
output_path = ['./img_list.pkl', './label_list.pkl']
train_dataset_path = DATASET_PATH + '/train/train_data'
if nsml.IS_ON_NSML:
# Caching file
nsml.cache(train_data_loader, data_path=train_dataset_path, img_size=input_shape[:2],
output_path=output_path)
else:
# local에서 실험할경우 dataset의 local-path 를 입력해주세요.
train_data_loader(train_dataset_path, input_shape[:2], output_path=output_path)
with open(output_path[0], 'rb') as img_f:
img_list = pickle.load(img_f)
with open(output_path[1], 'rb') as label_f:
label_list = pickle.load(label_f)
x_train = np.asarray(img_list)
labels = np.asarray(label_list)
y_train = keras.utils.to_categorical(labels, num_classes=num_classes)
x_train = x_train.astype('float32')
x_train /= 255
print(len(labels), 'train samples')
""" Callback """
monitor = 'acc'
reduce_lr = ReduceLROnPlateau(monitor=monitor, patience=3)
""" Training loop """
for epoch in range(nb_epoch):
res = model.fit(x_train, y_train,
batch_size=batch_size,
initial_epoch=epoch,
epochs=epoch + 1,
callbacks=[reduce_lr],
verbose=1,
shuffle=True)
print(res.history)
train_loss, train_acc = res.history['loss'][0], res.history['acc'][0]
nsml.report(summary=True, epoch=epoch, epoch_total=nb_epoch, loss=train_loss, acc=train_acc)
nsml.save(epoch)
# """ Save dataset """
# output_path = ['./img_list.pkl', './label_list.pkl']
# train_dataset_path = DATASET_PATH + '/train/train_data'
# if nsml.IS_ON_NSML:
# # Caching file
# nsml.cache(train_data_loader, data_path=train_dataset_path, img_size=input_shape[:2],
# output_path=output_path)
# """ Load dataset """
# with open(output_path[0], 'rb') as img_f:
# img_list = pickle.load(img_f)
# np_img_list = np.asarray(img_list)
# with open(output_path[1], 'rb') as label_f:
# label_list = pickle.load(label_f)
# np_label_list = np.asarray(label_list)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment