In [10]:
import os, random, glob, pickle, collections, math, json
import numpy as np
import pandas as pd
from __future__ import division
from __future__ import print_function
# import ujson as json
from PIL import Image
from sklearn.model_selection import train_test_split
from sklearn.metrics import log_loss
from sklearn.preprocessing import LabelEncoder
import matplotlib.pyplot as plt
%matplotlib inline
import tensorflow as tf
sess = tf.Session()
from keras.models import Sequential, Model, load_model, model_from_json
from keras.layers import GlobalAveragePooling2D, Flatten, Dropout, Dense, LeakyReLU
from keras.optimizers import Adam, RMSprop
from keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau, TensorBoard
from keras.preprocessing.image import ImageDataGenerator
from keras.utils import np_utils
from keras.preprocessing import image
from keras import backend as K
K.set_image_dim_ordering('tf')
K.set_session(sess)
In [4]:
from keras.losses import categorical_crossentropy
from keras.metrics import categorical_accuracy
In [1]:
TRAIN_DIR = '../data/train/'
TEST_DIR = '../RFCN/JPEGImages/'
TRAIN_CROP_DIR = '../data/train_crop/'
TEST_CROP_DIR = '../data/test_stg1_crop/'
RFCN_MODEL = 'resnet101_rfcn_ohem_iter_30000'
CROP_MODEL = 'resnet50_FT38_Hybrid_woNoF'
if not os.path.exists('./' + CROP_MODEL):
os.mkdir('./' + CROP_MODEL)
CHECKPOINT_DIR = './' + CROP_MODEL + '/checkpoint/'
if not os.path.exists(CHECKPOINT_DIR):
os.mkdir(CHECKPOINT_DIR)
LOG_DIR = './' + CROP_MODEL + '/log/'
if not os.path.exists(LOG_DIR):
os.mkdir(LOG_DIR)
OUTPUT_DIR = './' + CROP_MODEL + '/output/'
if not os.path.exists(OUTPUT_DIR):
os.mkdir(OUTPUT_DIR)
FISH_CLASSES = ['NoF', 'ALB', 'BET', 'DOL', 'LAG', 'OTHER', 'SHARK', 'YFT']
CROP_CLASSES=FISH_CLASSES[:]
CROP_CLASSES.remove('NoF')
CONF_THRESH = 0.8
ROWS = 224
COLS = 224
BATCHSIZE = 64
LEARNINGRATE = 1e-4
NUM_GPUS = 1
def featurewise_center(x):
mean = np.mean(x, axis=0, keepdims=True)
mean = np.mean(mean, axis=(1,2), keepdims=True)
x_centered = x - mean
return x_centered
def mean(x):
mean = np.mean(x, axis=0)
mean = np.mean(mean, axis=(0,1))
return mean
def load_img(path, bbox, target_size=None):
img = Image.open(path)
# img = img.convert('RGB')
cropped = img.crop((bbox[0],bbox[1],bbox[2],bbox[3]))
width_cropped, height_cropped = cropped.size
if height_cropped > width_cropped: cropped = cropped.transpose(method=2)
if target_size:
cropped = cropped.resize((target_size[1], target_size[0]), Image.BILINEAR)
return cropped
def preprocess_input(x, mean):
#resnet50 image preprocessing
# 'RGB'->'BGR'
# x = x[:, :, ::-1]
# x /= 255.
x[:, :, 0] -= mean[0]
x[:, :, 1] -= mean[1]
x[:, :, 2] -= mean[2]
return x
def get_best_model(checkpoint_dir = CHECKPOINT_DIR):
files = glob.glob(checkpoint_dir+'*')
val_losses = [float(f.split('-')[-1][:-5]) for f in files]
index = val_losses.index(min(val_losses))
print('Loading model from checkpoint file ' + files[index])
model = load_model(files[index])
model_name = files[index].split('/')[-1]
print('Loading model Done!')
return (model, model_name)
In [3]:
# GTbbox_df = ['image_file','crop_index','crop_class','xmin',''ymin','xmax','ymax']
file_name = 'GTbbox_df.pickle'
if os.path.exists(OUTPUT_DIR+file_name):
print ('Loading from file '+file_name)
GTbbox_df = pd.read_pickle(OUTPUT_DIR+file_name)
else:
print ('Generating file '+file_name)
GTbbox_df = pd.DataFrame(columns=['image_file','crop_index','crop_class','xmin','ymin','xmax','ymax'])
for c in CROP_CLASSES:
print(c)
j = json.load(open('../data/BBannotations/{}.json'.format(c), 'r'))
for l in j:
filename = l["filename"]
head, image_file = os.path.split(filename)
basename, file_extension = os.path.splitext(image_file)
image = Image.open(TEST_DIR+image_file)
width_image, height_image = image.size
for i in range(len(l["annotations"])):
a = l["annotations"][i]
xmin = (a["x"])
ymin = (a["y"])
width = (a["width"])
height = (a["height"])
xmax = xmin + width
ymax = ymin + height
assert max(xmin,0)<min(xmax,width_image)
assert max(ymin,0)<min(ymax,height_image)
GTbbox_df.loc[len(GTbbox_df)]=[image_file,i,a["class"],max(xmin,0),max(ymin,0),min(xmax,width_image),min(ymax,height_image)]
if a["class"] != c: print(GTbbox_df.tail(1))
test_size = GTbbox_df.shape[0]-int(math.ceil(GTbbox_df.shape[0]*0.8/BATCHSIZE)*BATCHSIZE)
train_ind, valid_ind = train_test_split(range(GTbbox_df.shape[0]), test_size=test_size, random_state=1986, stratify=GTbbox_df['crop_class'])
GTbbox_df['split'] = ['train' if i in train_ind else 'valid' for i in range(GTbbox_df.shape[0])]
GTbbox_df.to_pickle(OUTPUT_DIR+file_name)
In [4]:
#Load data
def data_from_df(df):
X = np.ndarray((df.shape[0], ROWS, COLS, 3), dtype=np.uint8)
y = np.zeros((df.shape[0], len(CROP_CLASSES)), dtype=K.floatx())
i = 0
for index,row in df.iterrows():
image_file = row['image_file']
fish = row['crop_class']
bbox = [row['xmin'],row['ymin'],row['xmax'],row['ymax']]
cropped = load_img(TEST_DIR+image_file,bbox,target_size=(ROWS,COLS))
X[i] = np.asarray(cropped)
y[i,CROP_CLASSES.index(fish)] = 1
i += 1
return (X, y)
def data_load(name):
file_name = 'data_'+name+'_{}_{}.pickle'.format(ROWS, COLS)
if os.path.exists(OUTPUT_DIR+file_name):
print ('Loading from file '+file_name)
with open(OUTPUT_DIR+file_name, 'rb') as f:
data = pickle.load(f)
X = data['X']
y = data['y']
else:
print ('Generating file '+file_name)
if name=='train' or name=='valid':
df = GTbbox_df[GTbbox_df['split']==name]
elif name=='all':
df = GTbbox_df
else:
print('Invalid name '+name)
X, y = data_from_df(df)
data = {'X': X,'y': y}
with open(OUTPUT_DIR+file_name, 'wb') as f:
pickle.dump(data, f)
return (X, y)
X_train, y_train = data_load('train')
X_valid, y_valid = data_load('valid')
print('Loading data done.')
print('train sample ', X_train.shape[0])
print('valid sample ', X_valid.shape[0])
X_train = X_train.astype(np.float32)
X_valid = X_valid.astype(np.float32)
print('Convert to float32 done.')
X_train /= 255.
X_valid /= 255.
print('Rescale by 255 done.')
X_train_centerd = featurewise_center(X_train)
print('mean of X_train is ', mean(X_train))
X_valid_centerd = featurewise_center(X_valid)
print('mean of X_valid is ', mean(X_valid))
print('Featurewise centered done.')
In [5]:
# #class weight = n_samples / (n_classes * np.bincount(y))
# class_weight_fish = dict(GTbbox_df.groupby('crop_class').size())
# class_weight = {}
# n_samples = GTbbox_df.shape[0]
# for key,value in class_weight_fish.items():
# class_weight[CROP_CLASSES.index(key)] = n_samples / (len(CROP_CLASSES)*value)
# class_weight
class_weight_fish = dict(GTbbox_df.groupby('crop_class').size())
class_weight = {}
ref = max(class_weight_fish.values())
for key,value in class_weight_fish.items():
class_weight[CROP_CLASSES.index(key)] = ref/value
class_weight
Out[5]:
In [10]:
#data preprocessing
train_datagen = ImageDataGenerator(
rotation_range=180,
shear_range=0.2,
zoom_range=0.1,
width_shift_range=0.1,
height_shift_range=0.1,
horizontal_flip=True,
vertical_flip=True)
train_generator = train_datagen.flow(X_train, y_train, batch_size=BATCHSIZE, shuffle=True, seed=None)
assert X_train.shape[0]%BATCHSIZE==0
steps_per_epoch = int(X_train.shape[0]/BATCHSIZE)
In [7]:
#callbacks
early_stopping = EarlyStopping(monitor='val_loss', min_delta=0, patience=10, verbose=1, mode='auto')
model_checkpoint = ModelCheckpoint(filepath=CHECKPOINT_DIR+'weights.{epoch:03d}-{val_loss:.4f}.hdf5', monitor='val_loss', verbose=1, save_best_only=True, save_weights_only=False, mode='auto')
learningrate_schedule = ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=5, verbose=1, mode='auto', epsilon=0.001, cooldown=0, min_lr=0)
tensorboard = TensorBoard(log_dir=LOG_DIR, histogram_freq=0, write_graph=False, write_images=True)
In [16]:
def create_model_VGG16():
model = Sequential()
model.add(Conv2D(64, (3, 3), padding='same', name='block1_conv1'))
model.add(BatchNormalization())
model.add(LeakyReLU(alpha=0.33))
model.add(Conv2D(64, (3, 3), strides=(2, 2), padding='same', name='block1_conv2'))
model.add(BatchNormalization())
model.add(LeakyReLU(alpha=0.33))
model.add(Conv2D(128, (3, 3), padding='same', name='block2_conv1'))
model.add(BatchNormalization())
model.add(LeakyReLU(alpha=0.33))
model.add(Conv2D(128, (3, 3), strides=(2, 2), padding='same', name='block2_conv2'))
model.add(BatchNormalization())
model.add(LeakyReLU(alpha=0.33))
model.add(Conv2D(256, (3, 3), padding='same', name='block3_conv1'))
model.add(BatchNormalization())
model.add(LeakyReLU(alpha=0.33))
model.add(Conv2D(256, (3, 3), padding='same', name='block3_conv2'))
model.add(BatchNormalization())
model.add(LeakyReLU(alpha=0.33))
model.add(Conv2D(256, (3, 3), strides=(2, 2), padding='same', name='block3_conv3'))
model.add(BatchNormalization())
model.add(LeakyReLU(alpha=0.33))
model.add(Conv2D(512, (3, 3), padding='same', name='block4_conv1'))
model.add(BatchNormalization())
model.add(LeakyReLU(alpha=0.33))
model.add(Conv2D(512, (3, 3), padding='same', name='block4_conv2'))
model.add(BatchNormalization())
model.add(LeakyReLU(alpha=0.33))
model.add(Conv2D(512, (3, 3), strides=(2, 2), padding='same', name='block4_conv3'))
model.add(BatchNormalization())
model.add(LeakyReLU(alpha=0.33))
model.add(Conv2D(512, (3, 3), padding='same', name='block5_conv1'))
model.add(BatchNormalization())
model.add(LeakyReLU(alpha=0.33))
model.add(Conv2D(512, (3, 3), padding='same', name='block5_conv2'))
model.add(BatchNormalization())
model.add(LeakyReLU(alpha=0.33))
model.add(Conv2D(512, (3, 3), strides=(2, 2), padding='same', name='block5_conv3'))
model.add(BatchNormalization())
model.add(LeakyReLU(alpha=0.33))
model.add(GlobalAveragePooling2D(dim_ordering='tf'))
# model.add(Dropout(0.8))
model.add(Dense(len(CROP_CLASSES), activation='softmax'))
return model
In [2]:
def average_gradients(tower_grads):
"""Calculate the average gradient for each shared variable across all towers.
Note that this function provides a synchronization point across all towers.
Args:
tower_grads: List of lists of (gradient, variable) tuples. The outer list
is over individual gradients. The inner list is over the gradient
calculation for each tower.
Returns:
List of pairs of (gradient, variable) where the gradient has been averaged
across all towers.
"""
average_grads = []
for grad_and_vars in zip(*tower_grads):
# Note that each grad_and_vars looks like the following:
# ((grad0_gpu0, var0_gpu0), ... , (grad0_gpuN, var0_gpuN))
grads = []
for g, _ in grad_and_vars:
# Add 0 dimension to the gradients to represent the tower.
expanded_g = tf.expand_dims(g, 0)
# Append on a 'tower' dimension which we will average over below.
grads.append(expanded_g)
# Average over the 'tower' dimension.
grad = tf.concat(0, grads)
grad = tf.reduce_mean(grad, 0)
# Keep in mind that the Variables are redundant because they are shared
# across towers. So .. we will just return the first tower's pointer to
# the Variable.
v = grad_and_vars[0][1]
grad_and_var = (grad, v)
average_grads.append(grad_and_var)
return average_grads
In [ ]:
with tf.device('/cpu:0'):
x_0 = tf.placeholder(tf.float32, shape=(None,ROWS,COLS,3))
y_0 = tf.placeholder(tf.float32, shape=(None, 10))
x_1 = tf.placeholder(tf.float32, shape=(None,ROWS,COLS,3))
y_1 = tf.placeholder(tf.float32, shape=(None, 10))
# shared model living on CPU:0
# it won't actually be run during training; it acts as an op template
# and as a repository for shared variables
model = create_model_VGG16()
opt = tf.train.GradientDescentOptimizer(lr)
# tower_grads = []
# for i in xrange(NUM_GPUS):
# with tf.device('/gpu:%d' % i):
# with tf.name_scope('%s_%d' % (tower, i)) as scope:
# # Calculate the loss for one tower of the CIFAR model. This function
# # constructs the entire CIFAR model but shares the variables across
# # all towers.
# preds = model(x_0) # all ops in the replica will live on GPU:0
# loss = tf.reduce_mean(categorical_crossentropy(y_0, preds_0))
# # Calculate the gradients for the batch of data on this CIFAR tower.
# grads = opt.compute_gradients(loss)
# # Keep track of the gradients across all towers.
# tower_grads.append(grads)
# replica 0
with tf.device('/gpu:0'):
preds_0 = model(x_0) # all ops in the replica will live on GPU:0
loss_0 = tf.reduce_mean(categorical_crossentropy(y_0, preds_0))
grads_0 = opt.compute_gradients(loss)
# # replica 1
# with tf.device('/gpu:1'):
# preds_1 = model(x_1) # all ops in the replica will live on GPU:1
# merge outputs on CPU
with tf.device('/cpu:0'):
loss = loss_0
grads = average_gradients([grads_0])
apply_gradient_op = opt.apply_gradients(grads)
update_ops = []
for old_value, new_value in model.updates:
update_ops.append(tf.assign(old_value, new_value))
train_op = tf.group(apply_gradient_op, *update_ops)
# we only run the `preds` tensor, so that only the two
# replicas on GPU get run (plus the merge op on CPU)
with sess.as_default():
for step in xrange(FLAGS.max_steps):
start_time = time.time()
batch = mnist_data.train.next_batch(50)
_, loss_value = sess.run([train_op, loss], feed_dict={x_0: batch[0], y_0: batch[1], K.learning_phase(): 1})
duration = time.time() - start_time
In [ ]:
#VGG16
#train from scratch
from keras.applications.vgg16 import VGG16
base_model = VGG16(include_top=False, weights=None, input_shape=(224,224,3), pooling='avg')
x = base_model.output
# x = GlobalAveragePooling2D()(x)
# x = Flatten()(x)
# x = Dense(256, init='glorot_normal', activation='relu')(x)
# x = Dropout(0.5)(x)
# x = Dense(256, init='glorot_normal', activation='relu')(x)
# x = Dropout(0.5)(x)
predictions = Dense(len(CROP_CLASSES), activation="softmax")(x)
# this is the model we will train
model = Model(inputs=base_model.input, outputs=predictions)
# compile the model (should be done *after* setting layers to non-trainable)
optimizer = Adam(lr=1e-5)
model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])
# train the model on the new data for a few epochs
model.fit_generator(train_generator, steps_per_epoch=steps_per_epoch, epochs=30, verbose=1,
callbacks=[early_stopping, model_checkpoint, learningrate_schedule, tensorboard],
validation_data=(X_valid,y_valid), class_weight=class_weight, workers=3, pickle_safe=True)
In [ ]:
with tf.device('/cpu:0'):
x = tf.placeholder(tf.float32, shape=(None, 784))
# shared model living on CPU:0
# it won't actually be run during training; it acts as an op template
# and as a repository for shared variables
model = Sequential()
model.add(Dense(32, activation='relu', input_dim=784))
model.add(Dense(10, activation='softmax'))
# replica 0
with tf.device('/gpu:0'):
output_0 = model(x) # all ops in the replica will live on GPU:0
# replica 1
with tf.device('/gpu:1'):
output_1 = model(x) # all ops in the replica will live on GPU:1
# merge outputs on CPU
with tf.device('/cpu:0'):
preds = 0.5 * (output_0 + output_1)
# we only run the `preds` tensor, so that only the two
# replicas on GPU get run (plus the merge op on CPU)
output_value = sess.run([preds], feed_dict={x: data})
In [18]:
#VGG16
#top layer training
from keras.applications.vgg16 import VGG16
base_model = VGG16(weights='imagenet', include_top=False)
x = base_model.output
x = GlobalAveragePooling2D()(x)
# x = Flatten()(x)
# x = Dense(256, init='glorot_normal', activation='relu')(x)
# x = Dropout(0.5)(x)
# x = Dense(256, init='glorot_normal', activation='relu')(x)
# x = Dropout(0.5)(x)
predictions = Dense(len(CROP_CLASSES), activation="softmax", kernel_initializer="glorot_normal")(x)
# this is the model we will train
model = Model(inputs=base_model.input, outputs=predictions)
# first: train only the top layers (which were randomly initialized)
for layer in base_model.layers:
layer.trainable = False
# compile the model (should be done *after* setting layers to non-trainable)
optimizer = Adam(lr=1e-3)
model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])
# train the model on the new data for a few epochs
model.fit_generator(train_generator, steps_per_epoch=steps_per_epoch, epochs=30, verbose=1,
callbacks=[early_stopping, model_checkpoint, learningrate_schedule, tensorboard],
validation_data=(X_valid,y_valid), class_weight=class_weight, workers=3, pickle_safe=True)
Out[18]:
In [ ]:
# VGG16
# fine tuning
start_layer = 1
model, model_name = get_best_model()
# print('Loading model from weights.004-0.0565.hdf5')
# model = load_model('./checkpoints/checkpoint3/weights.004-0.0565.hdf5')
for layer in model.layers[:start_layer]:
layer.trainable = False
for layer in model.layers[start_layer:]:
layer.trainable = True
# we need to recompile the model for these modifications to take effect
optimizer = Adam(lr=1e-3)
model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])
model.fit_generator(train_generator, steps_per_epoch=steps_per_epoch, epochs=300, verbose=1,
callbacks=[early_stopping, model_checkpoint, learningrate_schedule, tensorboard],
validation_data=(X_valid,y_valid), class_weight=class_weight, workers=3, pickle_safe=True)
In [ ]:
#resume training
model, model_name = get_best_model()
# print('Loading model from weights.004-0.0565.hdf5')
# model = load_model('./checkpoints/checkpoint3/weights.004-0.0565.hdf5')
model.fit_generator(train_generator, samples_per_epoch=len(X_train), nb_epoch=100, verbose=1,
callbacks=[early_stopping, model_checkpoint, learningrate_schedule, tensorboard],
validation_data=valid_generator, nb_val_samples=len(X_valid), class_weight=class_weight, nb_worker=3, pickle_safe=True)
In [4]:
#test prepare
test_model, test_model_name = get_best_model(checkpoint_dir='./resnet50_FT38_CW_STGTrain/checkpoint/')
# print('Loading model from weights.004-0.0565.hdf5')
# test_model = load_model('./checkpoints/checkpoint2/weights.004-0.0565.hdf5')
def test_generator(df, mean, datagen = None, batch_size = BATCHSIZE):
n = df.shape[0]
batch_index = 0
while 1:
current_index = batch_index * batch_size
if n >= current_index + batch_size:
current_batch_size = batch_size
batch_index += 1
else:
current_batch_size = n - current_index
batch_index = 0
batch_df = df[current_index:current_index+current_batch_size]
batch_x = np.zeros((batch_df.shape[0], ROWS, COLS, 3), dtype=K.floatx())
i = 0
for index,row in batch_df.iterrows():
image_file = row['image_file']
bbox = [row['xmin'],row['ymin'],row['xmax'],row['ymax']]
cropped = load_img(TEST_DIR+image_file,bbox,target_size=(ROWS,COLS))
x = np.asarray(cropped, dtype=K.floatx())
x /= 255.
if datagen is not None: x = datagen.random_transform(x)
x = preprocess_input(x, mean)
batch_x[i] = x
i += 1
if batch_index%50 == 0: print('batch_index', batch_index)
yield(batch_x)
test_aug_datagen = ImageDataGenerator(
rotation_range=180,
shear_range=0.2,
zoom_range=0.1,
width_shift_range=0.1,
height_shift_range=0.1,
horizontal_flip=True,
vertical_flip=True)
In [5]:
train_mean = [0.37698776, 0.41491762, 0.38681713]
In [ ]:
train_mean = train_datagen.mean
valid_mean = valid_datagen.mean
X_train_centered = featurewise_center(X_train)
X_valid_centered = featurewise_center(X_valid)
In [ ]:
#validation data fish logloss
valid_pred = test_model.predict(X_valid_centered, batch_size=BATCHSIZE, verbose=1)
# valid_pred = test_model.predict_generator(test_generator(df=valid_df, mean=valid_mean),
# val_samples=valid_df.shape[0], nb_worker=1, pickle_safe=False)
valid_logloss_df = pd.DataFrame(columns=['logloss','class'])
for i in range(y_valid.shape[0]):
index = np.argmax(y_valid[i,:])
fish = FISH_CLASSES[index]
logloss = -math.log(valid_pred[i,index])
valid_logloss_df.loc[len(valid_logloss_df)]=[logloss,fish]
print(valid_logloss_df.groupby(['class'])['logloss'].mean())
print(valid_logloss_df['logloss'].mean())
train_pred = test_model.predict(X_train_centered, batch_size=BATCHSIZE, verbose=1)
# train_pred = test_model.predict_generator(test_generator(df=train_df, ),
# val_samples=train_df.shape[0], nb_worker=1, pickle_safe=False)
train_logloss_df = pd.DataFrame(columns=['logloss','class'])
for i in range(y_train.shape[0]):
index = np.argmax(y_train[i,:])
fish = FISH_CLASSES[index]
logloss = -math.log(train_pred[i,index])
train_logloss_df.loc[len(train_logloss_df)]=[logloss,fish]
print(train_logloss_df.groupby(['class'])['logloss'].mean())
print(train_logloss_df['logloss'].mean())
In [8]:
#GTbbox_CROPpred_df = ['image_file','crop_index','crop_class','xmin','ymin','xmax','ymax',
# 'NoF', 'ALB', 'BET', 'DOL', 'LAG', 'OTHER', 'SHARK', 'YFT', 'logloss']
file_name = 'GTbbox_CROPpred_df_'+test_model_name+'_.pickle'
if os.path.exists(OUTPUT_DIR+file_name):
print ('Loading from file '+file_name)
GTbbox_CROPpred_df = pd.read_pickle(OUTPUT_DIR+file_name)
else:
print ('Generating file '+file_name)
nb_augmentation = 1
if nb_augmentation ==1:
test_preds = test_model.predict_generator(test_generator(df=GTbbox_df, mean=train_mean),
val_samples=GTbbox_df.shape[0], nb_worker=1, pickle_safe=False)
else:
test_preds = np.zeros((GTbbox_df.shape[0], len(FISH_CLASSES)), dtype=K.floatx())
for idx in range(nb_augmentation):
print('{}th augmentation for testing ...'.format(idx+1))
test_preds += test_model.predict_generator(test_generator(df=GTbbox_df, mean=train_mean, datagen=test_aug_datagen),
val_samples=GTbbox_df.shape[0], nb_worker=1, pickle_safe=False)
test_preds /= nb_augmentation
CROPpred_df = pd.DataFrame(test_preds, columns=['ALB', 'BET', 'DOL', 'LAG', 'NoF', 'OTHER', 'SHARK', 'YFT'])
GTbbox_CROPpred_df = pd.concat([GTbbox_df,CROPpred_df], axis=1)
GTbbox_CROPpred_df['logloss'] = GTbbox_CROPpred_df.apply(lambda row: -math.log(row[row['crop_class']]), axis=1)
GTbbox_CROPpred_df.to_pickle(OUTPUT_DIR+file_name)
#logloss of every fish class
print(GTbbox_CROPpred_df.groupby(['crop_class'])['logloss'].mean())
print(GTbbox_CROPpred_df['logloss'].mean())
In [9]:
# RFCNbbox_RFCNpred_df = ['image_class','image_file','crop_index','xmin','ymin','xmax','ymax',
# 'NoF_RFCN', 'ALB_RFCN', 'BET_RFCN', 'DOL_RFCN',
# 'LAG_RFCN', 'OTHER_RFCN', 'SHARK_RFCN', 'YFT_RFCN']
# select fish_conf >= CONF_THRESH
file_name = 'RFCNbbox_RFCNpred_df_conf{:.2f}.pickle'.format(CONF_THRESH)
if os.path.exists(OUTPUT_DIR+file_name):
print ('Loading from file '+file_name)
RFCNbbox_RFCNpred_df = pd.read_pickle(OUTPUT_DIR+file_name)
else:
print ('Generating file '+file_name)
RFCNbbox_RFCNpred_df = pd.DataFrame(columns=['image_class','image_file','crop_index','xmin','ymin','xmax','ymax',
'NoF_RFCN', 'ALB_RFCN', 'BET_RFCN', 'DOL_RFCN',
'LAG_RFCN', 'OTHER_RFCN', 'SHARK_RFCN', 'YFT_RFCN'])
with open('../data/RFCN_detections/detections_full_AGNOSTICnms_'+RFCN_MODEL+'.pkl','rb') as f:
detections_full_AGNOSTICnms = pickle.load(f, encoding='latin1')
with open("../RFCN/ImageSets/Main/test.txt","r") as f:
test_files = f.readlines()
with open("../RFCN/ImageSets/Main/train_test.txt","r") as f:
train_file_labels = f.readlines()
assert len(detections_full_AGNOSTICnms) == len(test_files)
count = np.zeros(len(detections_full_AGNOSTICnms))
for im in range(len(detections_full_AGNOSTICnms)):
if im%1000 == 0: print(im)
basename = test_files[im][:9]
if im<1000:
image_class = '--'
else:
for i in range(len(train_file_labels)):
if train_file_labels[i][:9] == basename:
image_class = train_file_labels[i][10:-1]
break
image = Image.open(TEST_DIR+'/'+basename+'.jpg')
width_image, height_image = image.size
bboxes = []
detects_im = detections_full_AGNOSTICnms[im]
for i in range(len(detects_im)):
# if np.sum(detects_im[i,5:]) >= CONF_THRESH:
if np.max(detects_im[i,5:]) >= CONF_THRESH:
bboxes.append(detects_im[i,:])
count[im] = len(bboxes)
if len(bboxes) == 0:
ind = np.argmax(np.sum(detects_im[:,5:], axis=1))
bboxes.append(detects_im[ind,:])
bboxes = np.asarray(bboxes)
for j in range(len(bboxes)):
bbox = bboxes[j]
xmin = bbox[0]
ymin = bbox[1]
xmax = bbox[2]
ymax = bbox[3]
assert max(xmin,0)<min(xmax,width_image)
assert max(ymin,0)<min(ymax,height_image)
RFCNbbox_RFCNpred_df.loc[len(RFCNbbox_RFCNpred_df)]=[image_class,basename+'.jpg',j,max(xmin,0),max(ymin,0),
min(xmax,width_image),min(ymax,height_image),
bbox[4],bbox[5],bbox[6],bbox[7],bbox[8],bbox[9],bbox[10],bbox[11]]
RFCNbbox_RFCNpred_df.to_pickle(OUTPUT_DIR+file_name)
In [31]:
GTbbox_CROPpred_df.loc[GTbbox_CROPpred_df['crop_class']!='NoF']
Out[31]:
In [32]:
file_name = 'data_trainfish_Crop_{}_{}.pickle'.format(ROWS, COLS)
if os.path.exists(OUTPUT_DIR+file_name):
print ('Loading from file '+file_name)
with open(OUTPUT_DIR+file_name, 'rb') as f:
data_trainfish = pickle.load(f)
X_trainfish_crop = data_train['X_trainfish_crop']
else:
print ('Generating file '+file_name)
GTbbox_CROPpred_fish_df = GTbbox_CROPpred_df.loc[GTbbox_CROPpred_df['crop_class']!='NoF']
X_trainfish_crop = np.ndarray((GTbbox_CROPpred_fish_df.shape[0], ROWS, COLS, 3), dtype=np.uint8)
i = 0
for index,row in GTbbox_CROPpred_fish_df.iterrows():
image_file = row['image_file']
bbox = [row['xmin'],row['ymin'],row['xmax'],row['ymax']]
cropped = load_img(TEST_DIR+image_file,bbox,target_size=(ROWS,COLS))
X_trainfish_crop[i] = np.asarray(cropped)
i += 1
#save data to file
data_trainfish = {'X_trainfish_crop': X_trainfish_crop}
with open(OUTPUT_DIR+file_name, 'wb') as f:
pickle.dump(data_trainfish, f)
print('Loading data done.')
X_trainfish_crop = X_trainfish_crop.astype(np.float32)
print('Convert to float32 done.')
X_trainfish_crop /= 255.
print('Rescale by 255 done.')
In [33]:
mean(X_trainfish_crop)
Out[33]:
In [28]:
mean(X_test_crop[1251:])
Out[28]:
In [35]:
# test_mean = [0.41019869, 0.43978861, 0.39873621]
test_mean = [0.37698776, 0.41491762, 0.38681713]
In [55]:
# RFCNbbox_RFCNpred_CROPpred_HYBRIDpred_df = ['image_class', 'image_file','crop_index','xmin','ymin','xmax','ymax',
# 'NoF_RFCN', 'ALB_RFCN', 'BET_RFCN', 'DOL_RFCN',
# 'LAG_RFCN', 'OTHER_RFCN', 'SHARK_RFCN', 'YFT_RFCN',
# 'NoF_CROP', 'ALB_CROP', 'BET_CROP', 'DOL_CROP',
# 'LAG_CROP', 'OTHER_CROP', 'SHARK_CROP', 'YFT_CROP',
# 'NoF', 'ALB', 'BET', 'DOL', 'LAG', 'OTHER', 'SHARK', 'YFT']
file_name = 'RFCNbbox_RFCNpred_CROPpred_HYBRIDpred_df_'+test_model_name+'_.pickle'
if os.path.exists(OUTPUT_DIR+file_name):
print ('Loading from file '+file_name)
RFCNbbox_RFCNpred_CROPpred_HYBRIDpred_df = pd.read_pickle(OUTPUT_DIR+file_name)
else:
print ('Generating file '+file_name)
nb_augmentation = 1
if nb_augmentation ==1:
test_preds = test_model.predict_generator(test_generator(df=RFCNbbox_RFCNpred_df, mean=test_mean),
val_samples=RFCNbbox_RFCNpred_df.shape[0], nb_worker=1, pickle_safe=False)
else:
test_preds = np.zeros((RFCNbbox_RFCNpred_df.shape[0], len(FISH_CLASSES)), dtype=K.floatx())
for idx in range(nb_augmentation):
print('{}th augmentation for testing ...'.format(idx+1))
test_preds += test_model.predict_generator(test_generator(df=RFCNbbox_RFCNpred_df, mean=test_mean, datagen=test_aug_datagen),
val_samples=RFCNbbox_RFCNpred_df.shape[0], nb_worker=1, pickle_safe=False)
test_preds /= nb_augmentation
CROPpred_df = pd.DataFrame(test_preds, columns=['ALB_CROP', 'BET_CROP', 'DOL_CROP', 'LAG_CROP', 'NoF_CROP', 'OTHER_CROP', 'SHARK_CROP', 'YFT_CROP'])
RFCNbbox_RFCNpred_CROPpred_HYBRIDpred_df = pd.concat([RFCNbbox_RFCNpred_df,CROPpred_df], axis=1)
RFCNbbox_RFCNpred_CROPpred_HYBRIDpred_df['NoF'] = RFCNbbox_RFCNpred_CROPpred_HYBRIDpred_df['NoF_RFCN']
for fish in ['ALB', 'BET', 'DOL', 'LAG', 'OTHER', 'SHARK', 'YFT']:
RFCNbbox_RFCNpred_CROPpred_HYBRIDpred_df[fish] = RFCNbbox_RFCNpred_CROPpred_HYBRIDpred_df.apply(lambda row: (1-row['NoF_RFCN'])*row[[fish+'_CROP']]/(1-row['NoF_CROP']) if row['NoF_CROP']!=1 else 0, axis=1)
# for fish in FISH_CLASSES:
# RFCNbbox_RFCNpred_CROPpred_HYBRIDpred_df[fish] = RFCNbbox_RFCNpred_CROPpred_HYBRIDpred_df[fish+'_CROP']
RFCNbbox_RFCNpred_CROPpred_HYBRIDpred_df.to_pickle(OUTPUT_DIR+file_name)
In [56]:
# clsMaxAve and hybrid RFCNpred&CROPpred such that RFCNpred for NoF and CROPpred for fish
# test_pred_df = ['logloss','image_class','image_file','NoF', 'ALB', 'BET', 'DOL', 'LAG', 'OTHER', 'SHARK', 'YFT']
# RFCNbbox_RFCNpred_CROPpred_HYBRIDpred_df = ['image_class', 'image_file','crop_index','xmin','ymin','xmax','ymax',
# 'NoF_RFCN', 'ALB_RFCN', 'BET_RFCN', 'DOL_RFCN',
# 'LAG_RFCN', 'OTHER_RFCN', 'SHARK_RFCN', 'YFT_RFCN',
# 'ALB_CROP', 'BET_CROP', 'DOL_CROP',
# 'LAG_CROP', 'OTHER_CROP', 'SHARK_CROP', 'YFT_CROP',
# 'NoF', 'ALB', 'BET', 'DOL', 'LAG', 'OTHER', 'SHARK', 'YFT']
file_name = 'test_pred_df_Hybrid_'+test_model_name+'_.pickle'
if os.path.exists(OUTPUT_DIR+file_name):
print ('Loading from file '+file_name)
test_pred_df = pd.read_pickle(OUTPUT_DIR+file_name)
else:
print ('Generating file '+file_name)
with open("../RFCN/ImageSets/Main/test.txt","r") as f:
test_files = f.readlines()
test_pred_df = pd.DataFrame(columns=['logloss','image_class','image_file','NoF', 'ALB', 'BET', 'DOL', 'LAG', 'OTHER', 'SHARK', 'YFT'])
for j in range(len(test_files)):
image_file = test_files[j][:-1]+'.jpg'
test_pred_im_df = RFCNbbox_RFCNpred_CROPpred_HYBRIDpred_df.loc[RFCNbbox_RFCNpred_CROPpred_HYBRIDpred_df['image_file'] == image_file,
['image_class', 'NoF', 'ALB', 'BET', 'DOL', 'LAG', 'OTHER', 'SHARK', 'YFT']]
image_class = test_pred_im_df.iloc[0]['image_class']
test_pred_im_df.drop('image_class', axis=1, inplace=True)
max_score = test_pred_im_df.max(axis=1)
max_cls = test_pred_im_df.idxmax(axis=1)
test_pred_im_df['max_score'] = max_score
test_pred_im_df['max_cls'] = max_cls
test_pred_im_df['Count'] = test_pred_im_df.groupby(['max_cls'])['max_cls'].transform('count')
idx = test_pred_im_df.groupby(['max_cls'])['max_score'].transform(max) == test_pred_im_df['max_score']
test_pred_im_clsMax_df = test_pred_im_df.loc[idx,['NoF', 'ALB', 'BET', 'DOL', 'LAG', 'OTHER', 'SHARK', 'YFT', 'Count']]
test_pred_im_clsMax_array = test_pred_im_clsMax_df.values
pred = np.average(test_pred_im_clsMax_array[:,:-1], axis=0, weights=test_pred_im_clsMax_array[:,-1], returned=False).tolist()
if image_class!='--':
ind = FISH_CLASSES.index(image_class)
logloss = -math.log(pred[ind])
else:
logloss = np.nan
test_pred_im_clsMaxAve = [logloss,image_class,image_file]
test_pred_im_clsMaxAve.extend(pred)
test_pred_df.loc[len(test_pred_df)]=test_pred_im_clsMaxAve
test_pred_df.to_pickle(OUTPUT_DIR+file_name)
In [ ]:
#### visualization
# RFCNbbox_RFCNpred_CROPpred_df = ['image_class', 'image_file','crop_index','x_min','y_min','x_max','ymax',
# 'NoF_RFCN', 'ALB_RFCN', 'BET_RFCN', 'DOL_RFCN',
# 'LAG_RFCN', 'OTHER_RFCN', 'SHARK_RFCN', 'YFT_RFCN'
# 'NoF_CROP', 'ALB_CROP', 'BET_CROP', 'DOL_CROP',
# 'LAG_CROP', 'OTHER_CROP', 'SHARK_CROP', 'YFT_CROP']
#GTbbox_CROPpred_df = ['image_file','crop_index','crop_class','xmin','ymin','xmax','ymax',
# 'NoF', 'ALB', 'BET', 'DOL', 'LAG', 'OTHER', 'SHARK', 'YFT', 'logloss']
# test_pred_df = ['logloss','image_class','image_file','NoF', 'ALB', 'BET', 'DOL', 'LAG', 'OTHER', 'SHARK', 'YFT']
for j in range(test_pred_df.shape[0]):
image_logloss = test_pred_df.iat[j,0]
image_class = test_pred_df.iat[j,1]
image_file = test_pred_df.iat[j,2]
if j<1000 and j%30== 0:
pass
else:
continue
im = Image.open('../RFCN/JPEGImages/'+image_file)
im = np.asarray(im)
fig, ax = plt.subplots(figsize=(10, 8))
ax.imshow(im, aspect='equal')
RFCN_dets = RFCNbbox_RFCNpred_CROPpred_HYBRIDpred_df.loc[RFCNbbox_RFCNpred_CROPpred_HYBRIDpred_df['image_file']==image_file]
for index,row in RFCN_dets.iterrows():
bbox = [row['xmin'],row['ymin'],row['xmax'],row['ymax']]
RFCN = [row['NoF_RFCN'],row['ALB_RFCN'],row['BET_RFCN'],row['DOL_RFCN'],row['LAG_RFCN'],row['OTHER_RFCN'],row['SHARK_RFCN'],row['YFT_RFCN']]
CROP = [row['NoF'],row['ALB'],row['BET'],row['DOL'],row['LAG'],row['OTHER'],row['SHARK'],row['YFT']]
score_RFCN = max(RFCN)
score_CROP = max(CROP)
index_RFCN = RFCN.index(score_RFCN)
index_CROP = CROP.index(score_CROP)
class_RFCN = FISH_CLASSES[index_RFCN]
class_CROP = FISH_CLASSES[index_CROP]
ax.add_patch(plt.Rectangle((bbox[0], bbox[1]), bbox[2] - bbox[0], bbox[3] - bbox[1], fill=False, edgecolor='red', linewidth=2))
ax.text(bbox[0], bbox[1] - 2, 'RFCN_{:s} {:.3f} \nHYBRID_{:s} {:.3f}'.format(class_RFCN, score_RFCN, class_CROP, score_CROP), bbox=dict(facecolor='red', alpha=0.5), fontsize=8, color='white')
GT_dets = GTbbox_CROPpred_df.loc[GTbbox_CROPpred_df['image_file']==image_file]
for index,row in GT_dets.iterrows():
bbox = [row['xmin'],row['ymin'],row['xmax'],row['ymax']]
CROP = [row['NoF'],row['ALB'],row['BET'],row['DOL'],row['LAG'],row['OTHER'],row['SHARK'],row['YFT']]
score_CROP = max(CROP)
index_CROP = CROP.index(score_CROP)
class_CROP = FISH_CLASSES[index_CROP]
ax.add_patch(plt.Rectangle((bbox[0], bbox[1]), bbox[2] - bbox[0], bbox[3] - bbox[1], fill=False, edgecolor='green', linewidth=2))
ax.text(bbox[0], bbox[3] + 40, 'GT_{:s} \nCROP_{:s} {:.3f}'.format(row['crop_class'], class_CROP, score_CROP), bbox=dict(facecolor='green', alpha=0.5), fontsize=8, color='white')
ax.set_title(('Image {:s} FISH {:s} logloss {}').format(image_file, image_class, image_logloss), fontsize=10)
plt.axis('off')
plt.tight_layout()
plt.draw()
In [58]:
#temperature
T = 1
test_pred_array = test_pred_df[FISH_CLASSES].values
test_pred_T_array = np.exp(np.log(test_pred_array)/T)
test_pred_T_array = test_pred_T_array/np.sum(test_pred_T_array, axis=1, keepdims=True)
test_pred_T_df = pd.DataFrame(test_pred_T_array, columns=FISH_CLASSES)
test_pred_T_df = pd.concat([test_pred_df[['image_class','image_file']],test_pred_T_df], axis=1)
#add logloss
test_pred_T_df['logloss'] = test_pred_T_df.apply(lambda row: -math.log(row[row['image_class']]) if row['image_class']!='--' else np.nan, axis=1)
#calculate train logloss
print(test_pred_T_df.groupby(['image_class'])['logloss'].mean())
train_logloss = test_pred_T_df['logloss'].mean()
print('logloss of train is', train_logloss )
In [62]:
#test submission
submission = test_pred_T_df.loc[:999,['image_file','NoF', 'ALB', 'BET', 'DOL', 'LAG', 'OTHER', 'SHARK', 'YFT']]
submission.rename(columns={'image_file':'image'}, inplace=True)
sub_file = 'RFCN_AGONOSTICnms_'+RFCN_MODEL+'_'+CROP_MODEL+'_clsMaxAve_conf{:.2f}_T{}_'.format(CONF_THRESH, T)+'{:.4f}'.format(train_logloss)+'.csv'
submission.to_csv(sub_file, index=False)
print('Done!'+sub_file)