In [1]:
import pegasos
import numpy as np
import pickle
from collections import defaultdict
import pdb
import random
from tqdm import tqdm
from time import time
import matplotlib.pyplot as plt
from scipy import misc
import matplotlib.gridspec as gridspec
import os

# Keras imports
import keras
from keras.models import load_model, Sequential, Model
from keras.layers import Dropout, Dense, Conv2D, Flatten, MaxPooling2D, Activation, Input, LeakyReLU, BatchNormalization
from keras.callbacks import ModelCheckpoint



class SVM_Triplet:
    def __init__(self, X1, X2, Y, base_classes, pos_class, new_class):
        self.X1 = X1
        self.X2 = X2
        self.Y = Y
        self.base_classes = base_classes
        self.pos_class = pos_class
        self.new_class = new_class

def prepare_features(pos_class, neg_classes, feature_vectors, is_train=True, 
                     equal_features=False, train_split=0.9):
    '''
    Returns 4096-dim features for each image which would be used for SVM training
    inputs : 
        is_train -> will return 90% of features for each class if is_train=True, else returns 10% features
        equal_features -> if set to True, then len(neg_features) = len(pos_features)
    
    Returns:
        pos_features -> features of images in the positive class
        neg_features -> features of images in the negative classes
    '''
    
    if is_train:
        num_pos_samples = int(train_split*feature_vectors[pos_class].shape[0])
        pos_features = feature_vectors[pos_class][:num_pos_samples]    # n x 4096
        
        neg_features = []

        for neg_class in neg_classes:
            num_neg_samples = int(train_split*feature_vectors[neg_class].shape[0])
            neg_features.extend(feature_vectors[neg_class][:num_neg_samples])
            
    else:
        num_pos_samples = int(train_split*feature_vectors[pos_class].shape[0])
        pos_features = feature_vectors[pos_class][num_pos_samples:]    # n x 4096
        
        neg_features = []

        for neg_class in neg_classes:
            num_neg_samples = int(train_split*feature_vectors[neg_class].shape[0])
            neg_features.extend(feature_vectors[neg_class][num_neg_samples:])
             
    if equal_features:
        neg_features = np.random.permutation(neg_features)[:pos_features.shape[0]]
    
    return pos_features, neg_features
    
def compute_accuracy(weight_vector, pos_features, neg_features):
    classifier = pegasos.PegasosSVMClassifier()
    classifier.fit(np.zeros((2, 1024)), np.asarray([1, 0]))
    classifier.weight_vector.weights = weight_vector

    # Concat data and pass to SVM
    result = classifier.predict(np.vstack((pos_features, neg_features)))
    ground_truth = np.concatenate((np.ones(len(pos_features)), np.zeros(len(neg_features))))
    return np.average(np.equal(ground_truth, result))

def get_svm_weights(x_train, y_train):
    svm = pegasos.PegasosSVMClassifier()
    svm.fit(x_train, y_train)
    weight_vector = svm.weight_vector.weights
    return weight_vector


def get_x_y(pos_features, neg_features):
    x = np.vstack((pos_features, neg_features))
    y = np.hstack((np.ones( len(pos_features)),
                   np.zeros(len(neg_features))))
    return x, y

'''
SVM for novel class. 
pos_class = pos_class
neg_classes = base_classes - pos_class
'''
def compute_X1(pos_class, base_classes, feature_vectors, is_train=True):
    neg_classes = np.delete(base_classes, np.argwhere(base_classes==pos_class))
    pos_features, neg_features = prepare_features(pos_class, neg_classes, feature_vectors, is_train=is_train)
    x_train, y_train = get_x_y(pos_features, neg_features)
    weight_vector = get_svm_weights(x_train, y_train)
    return weight_vector

'''
SVM for novel class. 
pos_class = novel_class
neg_classes = base_classes
'''
def compute_X2(novel_class, base_classes, feature_vectors, is_train=True):
    pos_features, neg_features = prepare_features(novel_class, base_classes, feature_vectors, is_train=is_train)
    x_train, y_train = get_x_y(pos_features, neg_features)
    weight_vector = get_svm_weights(x_train, y_train)
    return weight_vector
    
'''
SVM for pos class under the influence of the neg class. 
pos_class = pos_class
neg_classes = base_classes - pos_class + novel_class
'''
def compute_Y(pos_class, novel_class, base_classes, feature_vectors, is_train=True):
    neg_classes = np.delete(base_classes, np.argwhere(base_classes==pos_class))
    neg_classes = np.append(neg_classes, novel_class)
    pos_features, neg_features = prepare_features(pos_class, neg_classes, feature_vectors, is_train=is_train)
    x_train, y_train = get_x_y(pos_features, neg_features)
    weight_vector = get_svm_weights(x_train, y_train)
    return weight_vector


Using TensorFlow backend.

In [2]:
FEATURE_FILE = '/media/red/capstone/data/mit_67/vgg16_features.pickle'
TRIPLETS_FILE = '/media/red/capstone/data/triplets.pkl'

In [3]:
# Load features
# split the classes
# Split the images within each class
features, file_names = pickle.load(open(FEATURE_FILE, "rb"))

seed = 1234
np.random.seed(seed)

# Splitting classes into train/val/test
labels = np.array(list(features.keys()))
perm = np.random.permutation(len(labels))
labels = labels[perm]

splits = {}
splits['base']=labels[:30]
splits['novel'] = labels[30:50]
splits['test']=labels[50:]

print(splits)


{'base': array(['meeting_room', 'inside_bus', 'poolinside', 'inside_subway',
       'casino', 'mall', 'subway', 'dining_room', 'toystore', 'classroom',
       'livingroom', 'laundromat', 'greenhouse', 'airport_inside',
       'computerroom', 'fastfood_restaurant', 'bar', 'bathroom', 'museum',
       'children_room', 'concert_hall', 'lobby', 'grocerystore',
       'shoeshop', 'bedroom', 'gameroom', 'auditorium', 'bakery',
       'restaurant_kitchen', 'movietheater'],
      dtype='<U19'), 'novel': array(['trainstation', 'tv_studio', 'gym', 'garage', 'church_inside',
       'bowling', 'corridor', 'operating_room', 'warehouse', 'stairscase',
       'buffet', 'winecellar', 'kindergarden', 'deli', 'dentaloffice',
       'artstudio', 'hairsalon', 'elevator', 'hospitalroom', 'waitingroom'],
      dtype='<U19'), 'test': array(['clothingstore', 'restaurant', 'prisoncell', 'library', 'nursery',
       'jewelleryshop', 'pantry', 'cloister', 'closet', 'videostore',
       'florist', 'studiomusic', 'bookstore', 'kitchen', 'locker_room',
       'laboratorywet', 'office'],
      dtype='<U19')}

Create triplets for training


In [ ]:
random.seed(1234)
NUM_SIMULATIONS = 100000
triplets = []

for i in tqdm(range(int(NUM_SIMULATIONS/200))):
    base_class_ind = np.random.permutation(len(splits['base']))[:10]
    base_classes = splits['base'][base_class_ind]
    
    X1s = {}
    for pos_class in base_classes:
        X1s[pos_class] = compute_X1(pos_class, base_classes, features)
    
    X2s = {}
    for new_class in splits['novel']:
        X2s[new_class] = compute_X2(new_class, base_classes, features)

    
    # The following code generates 200 triplets - 10 pos classes x 20 novel classes for each pos class
    for pos_class in base_classes:
        X1 = X1s[pos_class]
        for new_class in splits['novel']:
            
            X2 = X2s[new_class]
            Y = compute_Y(pos_class, new_class, base_classes, features)
#             pdb.set_trace()
            
    
    
            # Sanity check
            t1 = time()
#             neg_classes = np.delete(base_classes, np.argwhere(base_classes==pos_class))
#             neg_classes_extra = np.append(neg_classes, new_class)
#             pos_features_test, neg_features_test = prepare_features(pos_class, 
#                                                                     neg_classes_extra, 
#                                                                     features, 
#                                                                     is_train=False, 
#                                                                     equal_features=False)
#             acc1 = compute_accuracy(X1, pos_features_test, neg_features_test)
#             acc2 = compute_accuracy(Y, pos_features_test, neg_features_test)
            print (time() - t1)
            
            print(acc1, acc2)
            
            triplets.append(SVM_Triplet(X1, X2, Y, base_classes, pos_class, new_class))
    
#     # Snapshot after every 200 triplets
#     with open(TRIPLETS_FILE, 'wb') as f:
#         print('Dumping start...')
#         pickle.dump(triplets, f)

Training the regressor network


In [ ]:
# Prepare data for training
triplets = pickle.load(open(TRIPLETS_FILE, "rb"))

In [ ]:
'''
Prepare data for training
'''
normalize = False
X_train, Y_train = [], []
for triplet in triplets:
    
    ### NORMALIZE X1, X2 and Y here!!!
    if normalize:
        X1 = triplet.X1 / np.linalg.norm(triplet.X1, axis=0, keepdims=True)
        X2 = triplet.X2 / np.linalg.norm(triplet.X2, axis=0, keepdims=True)
        Y  = triplet.Y  / np.linalg.norm(triplet.Y,  axis=0, keepdims=True)
        X_train.append(np.hstack((X1, X2)))
        Y_train.append(Y-X1)
    
    else:   
        X_train.append(np.hstack((triplet.X1, triplet.X2)))
        Y_train.append(triplet.Y-triplet.X1)

In [ ]:
'''
Define the architecture
'''
FEATURE_SHAPE = 4096
inp = Input(shape=(FEATURE_SHAPE * 2,))
x = Dense(FEATURE_SHAPE * 2, name='dense_1', activation='relu')(inp)
# x = Dropout(0.1)(x)
# x = BatchNormalization()(x)
x = Dense(FEATURE_SHAPE * 2, name='dense_2', activation='relu')(x)
# x = Dropout(0.1)(x)
# x = BatchNormalization()(x)
x = Dense(FEATURE_SHAPE, name='dense_3', activation='relu')(x)
# x = BatchNormalization()(x)
x = Dense(FEATURE_SHAPE, name='dense_4')(x)

model = Model(inputs=inp, outputs=x)

optimizer = keras.optimizers.Adam(lr=0.0001)

model.compile(loss='cosine_proximity', optimizer=optimizer, metrics=['accuracy'])

    
SAVE_FILE =  'mit_adam_cosine_100k__lr4_nobn_nonorm_{epoch:02d}-{val_acc:.2f}.h5'   
    
checkpoint = ModelCheckpoint(SAVE_FILE, monitor='val_acc', verbose=1, save_best_only=True, mode='max')
callbacks_list = [checkpoint]

model.fit(np.array(X_train), 
          np.array(Y_train), 
          epochs=5, 
          batch_size=32, 
          shuffle=True, 
          verbose=1,
          callbacks=callbacks_list,
          validation_split=0.05)

# model.save('mit_e100_rms_cosine_100k_nobn.h5')

In [ ]:
# Compare our model with the baseline

model = load_model('mit_adam_cosine_100k__lr4_nobn_nonorm_02-0.11.h5')
acc1_all, acc2_all = [], []
per_class_acc = defaultdict(list)

base_class_ind = np.random.permutation(len(splits['base']))[:20]
base_classes = splits['base'][base_class_ind]
  

for pos_class in base_classes:
    acc1, acc2 = [], []
    X1 = compute_X1(pos_class, base_classes, features, is_train=True)
    neg_classes = np.delete(base_classes, np.argwhere(base_classes==pos_class))
    
    for new_class in splits['test']:
        neg_classes_extra = np.append(neg_classes, new_class)    # 9 + 1 classes
        pos_features_test, neg_features_test = prepare_features(pos_class, 
                                                                neg_classes_extra, 
                                                                features, 
                                                                is_train=False, 
                                                                equal_features=False)
        acc1.append(compute_accuracy(X1, pos_features_test, neg_features_test))

        # Test out our incremental hypothesis
        X2 = compute_X2(new_class, base_classes, features, is_train=True)
        X = np.hstack((X1, X2))
        X = np.reshape(X, (1, 8192))
        Y_hat = model.predict(X)
        Y = X1 + Y_hat.reshape((4096))
        acc2.append(compute_accuracy(Y, pos_features_test, neg_features_test))
        print('%.5f %.5f %.5f %s|%s' % (acc1[-1],acc2[-1], acc2[-1] - acc1[-1], pos_class, new_class))
        per_class_acc[pos_class].append(acc2[-1] - acc1[-1])

    acc1_all.append(acc1)
    acc2_all.append(acc2)
    
    
acc1_all = np.array(acc1_all)
acc2_all = np.array(acc2_all)
acc1_mean = np.mean(acc1_all, axis=0)
acc2_mean = np.mean(acc2_all, axis=0)

In [ ]:
# Plotting

fig = plt.figure(figsize=(20,10))
ax = fig.add_subplot(111)
N = len(splits['test'])         # Number of classes
ind = np.arange(N)                # the x locations for the groups
width = 0.35                      # the width of the bars

## the bars
rects1 = ax.bar(ind, acc1_mean, width,color='orange')
rects2 = ax.bar(ind+width, acc2_mean, width, color='green')

# axes and labels
ax.set_xlim(-width,len(ind)+width)
ax.set_ylim(0,1)
ax.set_ylabel('Accuracy')
ax.set_title('Comparision when adding a new class (10 + 1)')
xTickMarks = ['Class ' + str(i) for i in range(0,21)]
ax.set_xticks(ind+width)
xtickNames = ax.set_xticklabels(xTickMarks)
plt.setp(xtickNames, rotation=45, fontsize=12)

## add a legend
ax.legend( (rects1[0], rects2[0]), ('No update', 'SVM weights updated') )

plt.show()

Test across randomized pos classes


In [4]:
model = load_model('mit_adam_cosine_100k__lr4_nobn_nonorm_02-0.11.h5')
acc1, acc2 = [], []
per_class_acc = defaultdict(list)

for i in range(200):
    base_class_ind = np.random.permutation(len(splits['base']))[:10]
    base_classes = splits['base'][base_class_ind]
    pos_class = np.random.choice(base_classes)
    
    
    X1 = compute_X1(pos_class, base_classes, features, is_train=True)
    neg_classes = np.delete(base_classes, np.argwhere(base_classes==pos_class))


    new_class = np.random.choice(splits['test'])
    neg_classes_extra = np.append(neg_classes, new_class)    # 9 + 1 classes
    pos_features_test, neg_features_test = prepare_features(pos_class, 
                                                            neg_classes_extra, 
                                                            features, 
                                                            is_train=False, 
                                                            equal_features=False)
    

    # Test out our incremental hypothesis
    X2 = compute_X2(new_class, base_classes, features, is_train=True)

    X = np.hstack((X1, X2))
    X = np.reshape(X, (1, 8192))
    Y_hat = model.predict(X)
    Y = X1 + Y_hat.reshape((4096))
    acc1.append(compute_accuracy(X1, pos_features_test, neg_features_test))
    acc2.append(compute_accuracy(Y, pos_features_test, neg_features_test))
    per_class_acc[pos_class].append(acc2[-1] - acc1[-1])
    print('%.5f %.5f %0.3f %s|%s' % (acc1[-1],acc2[-1], acc2[-1]-acc1[-1], pos_class, new_class))


0.90385 0.94231 0.038 shoeshop|prisoncell
0.98291 0.96866 -0.014 restaurant_kitchen|bookstore
0.41853 0.82748 0.409 subway|office
0.79706 0.79706 0.000 livingroom|kitchen
1.00000 0.96405 -0.036 greenhouse|prisoncell
0.82637 0.82637 0.000 subway|jewelleryshop
0.81013 0.70042 -0.110 livingroom|clothingstore
0.96356 0.95142 -0.012 children_room|cloister
0.96241 0.95489 -0.008 children_room|laboratorywet
0.80112 0.80112 0.000 livingroom|prisoncell
0.84615 0.82621 -0.020 bar|locker_room
1.00000 0.96715 -0.033 greenhouse|locker_room
0.92593 0.92593 0.000 auditorium|office
0.92657 0.92308 -0.003 grocerystore|locker_room
0.95167 0.95167 0.000 gameroom|cloister
0.97455 0.96000 -0.015 inside_bus|kitchen
0.95987 0.95987 0.000 children_room|kitchen
0.93919 0.89640 -0.043 inside_subway|library
0.95238 0.95918 0.007 children_room|studiomusic
0.70085 0.94872 0.248 auditorium|kitchen
0.65818 0.96000 0.302 concert_hall|jewelleryshop
0.84840 0.86589 0.017 inside_subway|library
0.92444 0.87556 -0.049 dining_room|jewelleryshop
0.94180 0.94180 0.000 lobby|cloister
0.90909 0.90374 -0.005 auditorium|laboratorywet
0.86170 0.80851 -0.053 subway|laboratorywet
0.95197 0.95197 0.000 restaurant_kitchen|office
0.73958 0.93750 0.198 auditorium|studiomusic
0.94783 0.94783 0.000 shoeshop|library
0.94800 0.94800 0.000 gameroom|cloister
0.95956 0.93750 -0.022 museum|office
0.89151 0.89623 0.005 grocerystore|library
0.99485 0.99485 0.000 greenhouse|bookstore
0.77640 0.86646 0.090 inside_subway|prisoncell
0.92405 0.92405 0.000 mall|closet
0.94141 0.92969 -0.012 auditorium|kitchen
0.68201 0.94561 0.264 gameroom|videostore
0.94170 0.95067 0.009 concert_hall|prisoncell
0.92332 0.92332 0.000 meeting_room|nursery
0.94224 0.90253 -0.040 dining_room|locker_room
0.91192 0.94301 0.031 concert_hall|office
0.92070 0.91630 -0.004 movietheater|studiomusic
0.59643 0.91429 0.318 meeting_room|closet
0.95510 0.85714 -0.098 toystore|clothingstore
0.92105 0.91729 -0.004 grocerystore|restaurant
0.94461 0.92128 -0.023 meeting_room|clothingstore
0.94764 0.96859 0.021 children_room|pantry
0.96154 0.96154 0.000 laundromat|cloister
0.95885 0.81070 -0.148 inside_subway|jewelleryshop
0.94488 0.95276 0.008 children_room|videostore
0.95331 0.95331 0.000 fastfood_restaurant|prisoncell
0.96659 0.95704 -0.010 poolinside|kitchen
0.95638 0.93960 -0.017 poolinside|library
0.95593 0.95593 0.000 gameroom|restaurant
0.57784 0.90765 0.330 toystore|nursery
0.73832 0.80997 0.072 bar|studiomusic
0.77950 0.77950 0.000 livingroom|nursery
0.97239 0.96319 -0.009 shoeshop|bookstore
0.93031 0.93728 0.007 auditorium|prisoncell
0.50896 0.83513 0.326 inside_subway|nursery
0.22796 0.87538 0.647 bakery|nursery
0.96178 0.96178 0.000 classroom|nursery
0.87733 0.82133 -0.056 bedroom|clothingstore
0.82759 0.85345 0.026 casino|library
0.93491 0.86391 -0.071 inside_subway|studiomusic
0.93035 0.91045 -0.020 auditorium|laboratorywet
0.98095 0.95873 -0.022 gameroom|kitchen
0.73729 0.84181 0.105 livingroom|restaurant
0.97872 0.96353 -0.015 classroom|restaurant
0.60221 0.83149 0.229 bar|jewelleryshop
0.76862 0.83777 0.069 airport_inside|closet
0.93500 0.94000 0.005 shoeshop|videostore
0.90566 0.83558 -0.070 airport_inside|restaurant
0.96936 0.96936 0.000 concert_hall|kitchen
0.93929 0.87500 -0.064 toystore|restaurant
0.86667 0.75185 -0.115 bedroom|locker_room
0.76087 0.77899 0.018 airport_inside|locker_room
0.41948 0.77154 0.352 bar|studiomusic
0.79298 0.76491 -0.028 bedroom|nursery
0.95942 0.96812 0.009 lobby|cloister
0.88327 0.89105 0.008 dining_room|restaurant
0.96296 0.96296 0.000 restaurant_kitchen|closet
0.95425 0.96078 0.007 children_room|library
0.96842 0.85614 -0.112 bakery|office
0.96479 0.95423 -0.011 gameroom|nursery
0.79635 0.92705 0.131 meeting_room|clothingstore
0.96127 0.96127 0.000 inside_bus|jewelleryshop
0.93182 0.90909 -0.023 laundromat|cloister
0.95817 0.93156 -0.027 lobby|videostore
0.90877 0.93684 0.028 movietheater|studiomusic
0.97120 0.96859 -0.003 classroom|florist
0.91740 0.74336 -0.174 laundromat|studiomusic
0.96262 0.95950 -0.003 gameroom|pantry
0.96013 0.96013 0.000 classroom|kitchen
0.94822 0.96117 0.013 computerroom|office
0.96842 0.96140 -0.007 greenhouse|laboratorywet
0.88816 0.82895 -0.059 casino|prisoncell
0.70462 0.81231 0.108 airport_inside|office
0.93333 0.93333 0.000 bathroom|jewelleryshop
0.87415 0.82313 -0.051 casino|restaurant
0.84561 0.78596 -0.060 bar|closet
0.94801 0.94495 -0.003 poolinside|locker_room
0.94613 0.77441 -0.172 bedroom|laboratorywet
0.95261 0.94313 -0.009 computerroom|videostore
0.95973 0.95973 0.000 shoeshop|kitchen
0.96479 0.92958 -0.035 bathroom|office
0.95635 0.94841 -0.008 bathroom|closet
0.95763 0.94915 -0.008 computerroom|studiomusic
0.95068 0.95068 0.000 movietheater|library
0.95794 0.92056 -0.037 museum|restaurant
0.97484 0.96226 -0.013 classroom|florist
0.96508 0.96508 0.000 inside_bus|closet
0.95122 0.93728 -0.014 movietheater|restaurant
0.99233 0.96931 -0.023 shoeshop|bookstore
0.91346 0.94231 0.029 auditorium|jewelleryshop
0.95312 0.87187 -0.081 bakery|kitchen
0.94828 0.95862 0.010 laundromat|pantry
0.93750 0.93750 0.000 museum|videostore
0.64365 0.80387 0.160 livingroom|studiomusic
0.95699 0.95699 0.000 classroom|cloister
0.96324 0.96691 0.004 shoeshop|office
0.97173 0.95760 -0.014 children_room|prisoncell
0.80117 0.84503 0.044 subway|studiomusic
0.72549 0.80065 0.075 airport_inside|cloister
0.95528 0.95528 0.000 lobby|library
0.95317 0.96970 0.017 lobby|laboratorywet
0.78592 0.93239 0.146 meeting_room|bookstore
0.84706 0.83922 -0.008 bakery|florist
0.96358 0.96358 0.000 inside_bus|library
0.46933 0.85890 0.390 inside_subway|bookstore
0.97119 0.92593 -0.045 grocerystore|closet
0.95167 0.93309 -0.019 poolinside|library
0.94671 0.94671 0.000 museum|nursery
0.96809 0.95745 -0.011 classroom|office
0.93510 0.94690 0.012 mall|bookstore
0.92739 0.88449 -0.043 toystore|library
0.96820 0.95760 -0.011 classroom|prisoncell
0.97340 0.97074 -0.003 restaurant_kitchen|restaurant
0.96078 0.96078 0.000 children_room|nursery
0.92971 0.92971 0.000 grocerystore|prisoncell
0.95517 0.95517 0.000 gameroom|videostore
0.92308 0.92788 0.005 grocerystore|office
0.80833 0.83056 0.022 bar|pantry
0.92342 0.92342 0.000 museum|office
0.96785 0.96141 -0.006 lobby|prisoncell
0.97098 0.97098 0.000 restaurant_kitchen|bookstore
0.95820 0.96141 0.003 computerroom|kitchen
0.95294 0.95294 0.000 fastfood_restaurant|pantry
0.77011 0.93103 0.161 auditorium|laboratorywet
0.82779 0.82779 0.000 airport_inside|office
0.95570 0.96203 0.006 fastfood_restaurant|library
0.91515 0.91515 0.000 dining_room|pantry
0.92038 0.96178 0.041 fastfood_restaurant|bookstore
0.80224 0.75000 -0.052 livingroom|jewelleryshop
0.87915 0.93958 0.060 bathroom|office
0.97039 0.97494 0.005 inside_bus|prisoncell
0.82295 0.82295 0.000 subway|locker_room
0.94224 0.96751 0.025 gameroom|nursery
0.96944 0.96944 0.000 restaurant_kitchen|jewelleryshop
0.94340 0.94340 0.000 classroom|florist
0.82331 0.78947 -0.034 subway|locker_room
0.80913 0.77593 -0.033 subway|restaurant
0.81293 0.79252 -0.020 bar|studiomusic
0.93485 0.93485 0.000 bathroom|prisoncell
0.93089 0.92683 -0.004 mall|clothingstore
0.90448 0.91642 0.012 dining_room|locker_room
0.95308 0.95015 -0.003 museum|jewelleryshop
0.52234 0.93814 0.416 mall|locker_room
0.95802 0.92366 -0.034 bathroom|florist
0.96071 0.76786 -0.193 inside_bus|locker_room
0.94833 0.94833 0.000 museum|bookstore
0.90981 0.94164 0.032 grocerystore|restaurant
0.79228 0.78932 -0.003 livingroom|pantry
0.96333 0.96333 0.000 restaurant_kitchen|florist
0.96562 0.96562 0.000 inside_bus|jewelleryshop
0.96393 0.91148 -0.052 laundromat|closet
0.58333 0.81944 0.236 casino|office
0.86728 0.85494 -0.012 subway|clothingstore
0.82892 0.82892 0.000 livingroom|kitchen
0.88304 0.82164 -0.061 bar|pantry
0.95044 0.94752 -0.003 mall|library
0.97527 0.94505 -0.030 bathroom|clothingstore
0.93515 0.93857 0.003 mall|closet
0.39458 0.84337 0.449 casino|florist
0.85223 0.84192 -0.010 inside_subway|florist
0.72852 0.90378 0.175 dining_room|nursery
0.93403 0.81250 -0.122 subway|cloister
0.97358 0.95094 -0.023 gameroom|locker_room
0.92347 0.85714 -0.066 laundromat|jewelleryshop
0.58983 0.94237 0.353 museum|studiomusic
0.96078 0.96078 0.000 classroom|nursery
0.97436 0.93407 -0.040 movietheater|laboratorywet
0.81853 0.93050 0.112 mall|jewelleryshop
0.94167 0.92500 -0.017 movietheater|bookstore
0.88618 0.88618 0.000 dining_room|studiomusic
0.91364 0.88182 -0.032 casino|kitchen
0.96178 0.96178 0.000 classroom|prisoncell
0.98418 0.96519 -0.019 concert_hall|laboratorywet
0.90541 0.72432 -0.181 bedroom|kitchen
0.86909 0.77818 -0.091 bar|closet

In [6]:
print(np.mean(acc1))
print(np.mean(acc2))
# # print(np.mean(acc1_mean))
# # print(np.mean(acc2_mean))

x = []
y = []
for k, v in per_class_acc.items():
    x.append(k)
    y.append(np.mean(v)*100)
    
    print('%s ----- %f'%(x[-1],y[-1]))


    
fig, ax = plt.subplots(figsize=(15, 15))    
width = 0.75 # the width of the bars 
ind = np.arange(len(y))  # the x locations for the groups
ax.barh(ind, y, width, color="blue")
ax.set_yticks(ind+width/2)
ax.set_yticklabels(x, minor=False)
plt.title('Per class results of Catastrophic Forgetting')
plt.xlabel('Accuracy improvement')
plt.ylabel('Classes')    
plt.show()


0.885797847556
0.905690885974
shoeshop ----- 0.213109
restaurant_kitchen ----- -0.241494
subway ----- 2.207898
livingroom ----- 1.109222
greenhouse ----- -1.895299
children_room ----- 0.092847
bar ----- 4.698912
auditorium ----- 6.728305
grocerystore ----- -0.159550
gameroom ----- 2.303267
inside_bus ----- -2.897811
inside_subway ----- 6.887926
concert_hall ----- 6.457751
dining_room ----- 1.519715
lobby ----- -0.130371
museum ----- 3.627098
mall ----- 7.657265
meeting_room ----- 11.434230
movietheater ----- -0.787202
toystore ----- 3.116653
laundromat ----- -5.086822
fastfood_restaurant ----- 1.193260
poolinside ----- -1.199263
bakery ----- 11.151064
classroom ----- -0.469391
bedroom ----- -11.033665
casino ----- 9.478654
airport_inside ----- 3.333995
computerroom ----- -0.044821
bathroom ----- -0.675653

In [9]:
DATA_PATH = '/media/red/capstone/data/mit_67/Images/'
def preview_category(category):
    # Load data from disk
    features, file_names = pickle.load(open(FEATURE_FILE, "rb"))
    train_split = 0.9
    num_samples = int(train_split*len(file_names[category]))
    training_imgs = file_names[category][:num_samples]
    test_imgs = file_names[category][num_samples:]
    
    # Plot training images 
    num_rows = 7
    num_cols = 7
    fig = plt.figure(figsize=(12,12))
    gs = gridspec.GridSpec(num_rows, num_cols, wspace=0.0, hspace=0.0)
    ax = [plt.subplot(gs[i]) for i in range(num_rows*num_cols)]
    for i in range(num_rows):
        for j in range(num_cols):
            img_path = os.path.join(DATA_PATH, category, training_imgs[5*i+j])
            img = misc.imread(img_path)
            ax[i*num_rows+j].imshow(img)
            ax[i*num_rows+j].axis('off')
            ax[i*num_rows+j].set_aspect('auto')
    fig.suptitle('Training images for %s'%(category), size=20)
    plt.show()
    
    # Plot test images
    num_rows = 3
    num_cols = 3
    fig = plt.figure(figsize=(10,10))
    gs = gridspec.GridSpec(num_rows, num_cols, wspace=0.0, hspace=0.0)
    ax = [plt.subplot(gs[i]) for i in range(num_rows*num_cols)]
    for i in range(num_rows):
        for j in range(num_cols):
            img_path = os.path.join(DATA_PATH, category, test_imgs[5*i+j])
            img = misc.imread(img_path)
            ax[i*num_rows+j].imshow(img)
            ax[i*num_rows+j].axis('off')
            ax[i*num_rows+j].set_aspect('auto')
    fig.suptitle('Test images for %s'%(category), size=20)
    plt.show()
    
preview_category('bedroom')


Compositional updates


In [4]:
model = load_model('mit_adam_cosine_100k__lr4_nobn_nonorm_02-0.11.h5')
acc0, acc2 = [], []
per_class_acc = defaultdict(list)

for i in range(200):
    base_class_ind = np.random.permutation(len(splits['base']))[:10]
    base_classes = splits['base'][base_class_ind]
    pos_class = np.random.choice(base_classes)
    
    
    X1 = compute_X1(pos_class, base_classes, features, is_train=True)
    neg_classes = np.delete(base_classes, np.argwhere(base_classes==pos_class))


    new_class1 = np.random.choice(splits['test'])
    neg_classes_extra = np.append(neg_classes, new_class1)    # 9 + 1 classes
    

    # n + 1 update
    X2 = compute_X2(new_class1, base_classes, features, is_train=True)
    X = np.hstack((X1, X2))
    X = np.reshape(X, (1, 8192))
    Y_hat = model.predict(X)
    Y = X1 + Y_hat.reshape((4096))
    
    
    
    # n + 2 update
    new_class2 = np.random.choice(np.delete(splits['test'], np.argwhere(splits['test']==new_class1)))
    neg_classes_extra = np.append(neg_classes, new_class1)
    pos_features_test, neg_features_test = prepare_features(pos_class, 
                                                            neg_classes_extra, 
                                                            features, 
                                                            is_train=False, 
                                                            equal_features=False)
    
    X2 = compute_X2(new_class2, base_classes, features, is_train=True)
    X = np.hstack((Y, X2))
    X = np.reshape(X, (1, 8192))
    Y_hat = model.predict(X)
    Y_2 = Y + Y_hat.reshape((4096))
    
    # Save accuracies
    acc0.append(compute_accuracy(X1, pos_features_test, neg_features_test))
    acc2.append(compute_accuracy(Y_2, pos_features_test, neg_features_test))
    per_class_acc[pos_class].append(acc2[-1] - acc0[-1])
    

    print('%.5f %.5f %0.3f %s|%s + %s' % (acc0[-1],acc2[-1], 100*(acc2[-1]-acc0[-1]), pos_class, new_class1, new_class2))


0.94231 0.94231 0.000 shoeshop|prisoncell + florist
0.96364 0.95909 -0.455 poolinside|videostore + office
0.91473 0.93023 1.550 movietheater|clothingstore + laboratorywet
0.88679 0.93208 4.528 auditorium|cloister + bookstore
0.95720 0.95720 0.000 restaurant_kitchen|laboratorywet + kitchen
0.97571 0.92713 -4.858 movietheater|closet + florist
0.81269 0.78550 -2.719 livingroom|clothingstore + restaurant
0.92664 0.93050 0.386 mall|office + clothingstore
0.89542 0.84641 -4.902 dining_room|laboratorywet + bookstore
0.95322 0.94737 -0.585 auditorium|pantry + florist
0.68382 0.91176 22.794 meeting_room|kitchen + office
0.86219 0.85512 -0.707 bakery|studiomusic + office
0.94340 0.89434 -4.906 laundromat|laboratorywet + clothingstore
0.83526 0.82370 -1.156 bar|videostore + kitchen
0.81571 0.81571 0.000 airport_inside|bookstore + nursery
0.89443 0.96774 7.331 concert_hall|cloister + restaurant
0.83544 0.82025 -1.519 livingroom|jewelleryshop + pantry
1.00000 0.98263 -1.737 greenhouse|videostore + cloister
0.77994 0.92233 14.239 meeting_room|office + jewelleryshop
0.99679 0.96154 -3.526 computerroom|cloister + studiomusic
0.83380 0.83102 -0.277 airport_inside|florist + locker_room
0.98354 0.96296 -2.058 computerroom|library + studiomusic
0.96057 0.96057 0.000 inside_bus|closet + jewelleryshop
0.99298 0.96140 -3.158 greenhouse|studiomusic + jewelleryshop
0.86014 0.81818 -4.196 casino|videostore + laboratorywet
0.97328 0.95802 -1.527 inside_bus|kitchen + bookstore
0.99688 0.96573 -3.115 greenhouse|nursery + prisoncell
0.97304 0.97304 0.000 restaurant_kitchen|nursery + laboratorywet
0.88444 0.84444 -4.000 toystore|videostore + cloister
0.95956 0.95956 0.000 lobby|locker_room + videostore
0.92105 0.92105 0.000 movietheater|studiomusic + florist
0.99595 0.92713 -6.883 movietheater|office + videostore
0.60125 0.96573 36.449 restaurant_kitchen|studiomusic + florist
0.95439 0.95789 0.351 children_room|locker_room + office
0.95095 0.95368 0.272 museum|kitchen + cloister
0.92405 0.92405 0.000 auditorium|videostore + library
0.95652 0.95652 0.000 concert_hall|prisoncell + restaurant
0.88492 0.78571 -9.921 subway|florist + cloister
0.96667 0.96667 0.000 lobby|library + studiomusic
0.91696 0.87889 -3.806 toystore|videostore + pantry
0.94286 0.94286 0.000 mall|cloister + locker_room
0.96565 0.99618 3.053 greenhouse|locker_room + florist
1.00000 0.96508 -3.492 greenhouse|clothingstore + closet
0.92683 0.92683 0.000 mall|kitchen + videostore
0.95946 0.95946 0.000 fastfood_restaurant|laboratorywet + bookstore
0.93269 0.91346 -1.923 movietheater|nursery + kitchen
0.92742 0.91935 -0.806 toystore|closet + clothingstore
0.78641 0.83172 4.531 casino|kitchen + laboratorywet
0.92537 0.95522 2.985 fastfood_restaurant|closet + bookstore
0.94737 0.91667 -3.070 dining_room|florist + library
0.94170 0.95067 0.897 lobby|office + studiomusic
0.96273 0.96273 0.000 classroom|library + locker_room
0.86402 0.82720 -3.683 bar|studiomusic + jewelleryshop
0.92553 0.86170 -6.383 casino|locker_room + office
0.74534 0.81056 6.522 bar|closet + florist
0.78878 0.79868 0.990 bar|cloister + clothingstore
0.83784 0.91892 8.108 meeting_room|restaurant + kitchen
0.95045 0.81532 -13.514 bakery|locker_room + nursery
0.90947 0.72428 -18.519 bedroom|office + restaurant
0.95522 0.95522 0.000 fastfood_restaurant|office + clothingstore
0.96804 0.94521 -2.283 computerroom|prisoncell + office
0.98929 0.95714 -3.214 computerroom|jewelleryshop + nursery
0.94529 0.94529 0.000 movietheater|videostore + closet
0.93061 0.93061 0.000 museum|florist + pantry
0.96183 0.93130 -3.053 poolinside|videostore + florist
0.89333 0.76333 -13.000 livingroom|videostore + kitchen
0.96936 0.88579 -8.357 bakery|jewelleryshop + cloister
0.96541 0.96541 0.000 concert_hall|bookstore + nursery
0.96685 0.41989 -54.696 shoeshop|bookstore + prisoncell
0.95146 0.94660 -0.485 concert_hall|videostore + studiomusic
0.93525 0.93525 0.000 mall|restaurant + videostore
0.95614 0.91228 -4.386 bathroom|locker_room + restaurant
0.92271 0.94686 2.415 restaurant_kitchen|locker_room + nursery
0.97976 0.95142 -2.834 classroom|florist + videostore
0.95833 0.95833 0.000 classroom|locker_room + closet
0.85560 0.93502 7.942 poolinside|jewelleryshop + library
0.82699 0.75433 -7.266 livingroom|prisoncell + locker_room
0.93433 0.90746 -2.687 bakery|videostore + studiomusic
0.42790 0.85579 42.790 bar|jewelleryshop + office
0.83178 0.83178 0.000 subway|closet + prisoncell
0.96226 0.93396 -2.830 laundromat|kitchen + florist
0.93072 0.92771 -0.301 meeting_room|studiomusic + jewelleryshop
0.97802 0.95604 -2.198 computerroom|videostore + locker_room
0.93156 0.82510 -10.646 inside_subway|closet + library
0.88000 0.96000 8.000 computerroom|laboratorywet + cloister
0.91375 0.95148 3.774 mall|cloister + locker_room
0.96581 0.96581 0.000 children_room|clothingstore + office
0.94218 0.94218 0.000 museum|prisoncell + clothingstore
0.95876 0.95876 0.000 classroom|bookstore + videostore
0.94970 0.94970 0.000 museum|videostore + pantry
0.96271 0.96271 0.000 restaurant_kitchen|closet + pantry
0.65132 0.96053 30.921 fastfood_restaurant|prisoncell + bookstore
0.59862 0.84083 24.221 inside_subway|jewelleryshop + nursery
0.91844 0.93617 1.773 poolinside|prisoncell + restaurant
0.90341 0.87784 -2.557 inside_subway|clothingstore + closet
0.74113 0.67730 -6.383 livingroom|restaurant + prisoncell
0.94720 0.79193 -15.528 bedroom|pantry + restaurant
0.97551 0.95510 -2.041 concert_hall|closet + kitchen
0.83129 0.81288 -1.840 airport_inside|jewelleryshop + laboratorywet
0.91781 0.91781 0.000 mall|laboratorywet + locker_room
0.95735 0.94313 -1.422 computerroom|videostore + studiomusic
0.95930 0.88081 -7.849 bakery|kitchen + videostore
0.79276 0.79934 0.658 bar|office + pantry
0.96410 0.93846 -2.564 computerroom|library + locker_room
0.98790 0.94758 -4.032 gameroom|cloister + closet
0.84477 0.96029 11.552 concert_hall|laboratorywet + locker_room
0.95331 0.95331 0.000 fastfood_restaurant|prisoncell + studiomusic
0.94613 0.95960 1.347 children_room|studiomusic + florist
0.31408 0.95668 64.260 fastfood_restaurant|restaurant + videostore
0.94425 0.87805 -6.620 toystore|prisoncell + cloister
0.81915 0.74823 -7.092 livingroom|jewelleryshop + videostore
0.92105 0.92105 0.000 meeting_room|prisoncell + library
0.96677 0.96677 0.000 lobby|restaurant + clothingstore
0.84409 0.83333 -1.075 bar|kitchen + cloister
0.94583 0.92500 -2.083 auditorium|jewelleryshop + closet
0.92361 0.76736 -15.625 bedroom|prisoncell + studiomusic
0.96532 0.80636 -15.896 bedroom|prisoncell + pantry
0.96226 0.96226 0.000 shoeshop|videostore + laboratorywet
0.88889 0.88889 0.000 toystore|florist + library
0.87535 0.86969 -0.567 inside_subway|cloister + bookstore
0.92857 0.80476 -12.381 bakery|clothingstore + pantry
0.57558 0.79360 21.802 livingroom|restaurant + laboratorywet
0.84804 0.80637 -4.167 casino|locker_room + jewelleryshop
0.95787 0.94944 -0.843 auditorium|pantry + videostore
0.62232 0.95279 33.047 inside_bus|library + florist
0.77256 0.95668 18.412 computerroom|bookstore + florist
0.51128 0.77068 25.940 bar|jewelleryshop + cloister
0.96571 0.96571 0.000 fastfood_restaurant|cloister + pantry
0.96057 0.96057 0.000 inside_bus|locker_room + kitchen
0.96382 0.96382 0.000 lobby|office + kitchen
0.90438 0.92829 2.390 mall|bookstore + prisoncell
0.87793 0.83568 -4.225 toystore|library + closet
0.76718 0.76718 0.000 airport_inside|clothingstore + pantry
0.96131 0.96429 0.298 fastfood_restaurant|videostore + laboratorywet
0.92378 0.96646 4.268 restaurant_kitchen|nursery + locker_room
0.90265 0.89381 -0.885 meeting_room|clothingstore + closet
0.85393 0.95131 9.738 gameroom|videostore + cloister
0.94156 0.94156 0.000 poolinside|cloister + nursery
0.81333 0.79667 -1.667 airport_inside|library + closet
0.98000 0.91200 -6.800 grocerystore|pantry + prisoncell
0.95021 0.95436 0.415 lobby|closet + restaurant
0.70752 0.82730 11.978 airport_inside|jewelleryshop + closet
0.89180 0.82951 -6.230 casino|locker_room + cloister
0.87558 0.87097 -0.461 dining_room|office + jewelleryshop
0.96154 0.96474 0.321 inside_bus|bookstore + pantry
0.96782 0.95402 -1.379 bathroom|office + laboratorywet
0.82500 0.87500 5.000 subway|nursery + florist
0.91111 0.79556 -11.556 inside_subway|office + laboratorywet
0.89181 0.86550 -2.632 inside_subway|office + videostore
0.94020 0.94020 0.000 auditorium|studiomusic + clothingstore
0.92059 0.87941 -4.118 bakery|nursery + closet
0.99623 0.95849 -3.774 restaurant_kitchen|locker_room + florist
0.96817 0.94695 -2.122 bathroom|library + restaurant
0.91967 0.92244 0.277 dining_room|restaurant + kitchen
0.90556 0.81389 -9.167 bedroom|restaurant + clothingstore
0.93750 0.93750 0.000 auditorium|bookstore + jewelleryshop
0.94191 0.94606 0.415 shoeshop|library + nursery
0.75329 0.77961 2.632 bedroom|cloister + locker_room
0.96099 0.96099 0.000 lobby|jewelleryshop + office
0.91045 0.91045 0.000 meeting_room|florist + cloister
0.93789 0.95963 2.174 gameroom|restaurant + library
0.96857 0.96857 0.000 concert_hall|locker_room + jewelleryshop
0.77491 0.77491 0.000 bar|videostore + library
0.97009 0.94872 -2.137 shoeshop|videostore + bookstore
0.47059 0.83088 36.029 inside_subway|prisoncell + clothingstore
0.83380 0.96901 13.521 bathroom|kitchen + restaurant
0.97531 0.93827 -3.704 bathroom|nursery + bookstore
0.95026 0.95288 0.262 auditorium|office + pantry
0.95667 0.96333 0.667 restaurant_kitchen|florist + jewelleryshop
0.96774 0.96774 0.000 inside_bus|jewelleryshop + laboratorywet
0.96721 0.94426 -2.295 laundromat|closet + bookstore
0.84774 0.78601 -6.173 casino|office + bookstore
0.70442 0.85083 14.641 subway|clothingstore + locker_room
0.91943 0.93365 1.422 dining_room|kitchen + nursery
0.75000 0.77899 2.899 airport_inside|pantry + library
0.95095 0.95095 0.000 mall|library + studiomusic
0.78992 0.82913 3.922 bar|office + prisoncell
0.91304 0.62207 -29.097 dining_room|closet + clothingstore
0.88472 0.86059 -2.413 casino|florist + jewelleryshop
0.91197 0.83803 -7.394 inside_subway|florist + bookstore
0.94087 0.92802 -1.285 dining_room|nursery + jewelleryshop
0.95302 0.93960 -1.342 mall|restaurant + laboratorywet
0.86290 0.75403 -10.887 bar|closet + clothingstore
0.93194 0.81675 -11.518 toystore|prisoncell + nursery
0.73248 0.96178 22.930 children_room|studiomusic + cloister
0.27895 0.93684 65.789 classroom|nursery + library
0.97151 0.96866 -0.285 concert_hall|laboratorywet + office
0.93050 0.93050 0.000 mall|jewelleryshop + library
0.68627 0.92157 23.529 bathroom|bookstore + jewelleryshop
0.88618 0.89431 0.813 dining_room|studiomusic + restaurant
0.97857 0.97381 -0.476 lobby|kitchen + office
0.91720 0.96178 4.459 classroom|prisoncell + videostore
0.96071 0.92500 -3.571 lobby|laboratorywet + nursery
0.95135 0.96486 1.351 gameroom|kitchen + cloister
0.76410 0.90769 14.359 mall|studiomusic + cloister
0.96508 0.95556 -0.952 grocerystore|nursery + kitchen
0.64017 0.78243 14.226 casino|prisoncell + cloister
0.72680 0.93814 21.134 meeting_room|kitchen + closet
0.76374 0.80495 4.121 livingroom|pantry + cloister
0.96479 0.96127 -0.352 lobby|pantry + laboratorywet

In [5]:
print(np.mean(acc0))
print(np.mean(acc2))


x = []
y = []
for k, v in per_class_acc.items():
    x.append(k)
    y.append(np.mean(v)*100)
    
    print('%s ----- %f'%(x[-1],y[-1]))


    
fig, ax = plt.subplots(figsize=(15, 15))    
width = 0.75 # the width of the bars 
ind = np.arange(len(y))  # the x locations for the groups
ax.barh(ind, y, width, color="blue")
ax.set_yticks(ind+width/2)
ax.set_yticklabels(x, minor=False)
plt.title('Per class results of Catastrophic Forgetting')
plt.xlabel('Accuracy improvement')
plt.ylabel('Classes')    
plt.show()


0.888949089685
0.899685270639
shoeshop ----- -11.283589
poolinside ----- 1.241461
movietheater ----- -2.018930
auditorium ----- 0.159907
restaurant_kitchen ----- 5.003179
livingroom ----- -1.507054
mall ----- 1.778801
dining_room ----- -4.537936
meeting_room ----- 8.136196
bakery ----- -7.087254
laundromat ----- -3.343644
bar ----- 5.819963
airport_inside ----- 1.584586
concert_hall ----- 2.009071
greenhouse ----- -1.689752
computerroom ----- 1.016356
inside_bus ----- 5.306834
casino ----- -1.350498
toystore ----- -4.425224
lobby ----- -0.308793
children_room ----- 6.156904
museum ----- 0.068120
subway ----- 2.430062
fastfood_restaurant ----- 12.307959
classroom ----- 11.235677
bedroom ----- -12.017085
bathroom ----- 4.243257
inside_subway ----- 3.112448
gameroom ----- 2.307709
grocerystore ----- -3.876190

In [ ]: