def split_preprocess_Data(degree1, degree2, strength1, strength2, percentage =1): # 1. load the data x_original_train, train_target, x_original_test, val_target = assign2_utils.load_dataset() #train_pairs, val_pairs = transform_dataset(x_original_train, x_original_test, 30, 0.15) # 2. split the datset. x_original_train = x_original_train.astype('float32') x_original_test = x_original_test.astype('float32') normaliseValue = 255 x_original_train /= normaliseValue # normalized the entries between 0 and 1 x_original_test /= normaliseValue x_original_train1, x_original_train2, train_target1, train_target2 = split_Data(x_original_train,train_target, percentage) #x_original_test1, x_original_test2 , val_target1, val_target2 = split_Data(x_original_test,val_target, percentage) # 3. transform the dataset. warped_pairs1 = np.array([assign2_utils.random_deform(x, degree1, strength1) for x in x_original_train1]) warped_pairs2 = np.array([assign2_utils.random_deform(x, degree2, strength2) for x in x_original_train2]) # train_pairs2 = np.array([assign2_utils.random_deform(x, degree2, strength2) for x in x_original_train2] digit_indicesTrain1 = [np.where(train_target[train_target1] == i)[0] for i in range(NumberOfClass)] train_pairs1, train_y1 = create_pairs(warped_pairs1, digit_indicesTrain1, percentage) digit_indicesTrain2 = [np.where(train_target[train_target2] == i)[0] for i in range(NumberOfClass)] train_pairs2, train_y2 = create_pairs(warped_pairs2, digit_indicesTrain2, percentage) # 4. reshape the pairs for 2D convolutional layer train_twin1_input1, train_twin2_input1 = reshape_input(image_width, image_height, num_channels, train_pairs1) train_twin1_input2, train_twin2_input2 = reshape_input(image_width, image_height, num_channels, train_pairs2) return train_twin1_input1, train_twin2_input1, train_twin1_input2, train_twin2_input2, train_y1, train_y2
def configure_experiments(degree, strength): ''' Define the planned experiments here 1. load the data 2. transformed data 3. Create the positive and negative pairs 4. run experiment 5. output report @param : @return : ''' # 1. load the data x_original_train, y_train, x_original_test, y_test = assign2_utils.load_dataset( ) #2. transformed data if (degree != 0): train_pairs, train_y, val_pairs, val_y = transform_dataset( x_original_train, x_original_test, degree, strength) else: train_pairs, train_y, val_pairs, val_y = x_original_train, y_train, x_original_test, y_test # 3. Create the positive and negative pairs # (the total number of pairs, one pair(2 numbers) in the same or not same classification, 28*28 ) digit_indicesTrain = [np.where(train_y == i)[0] for i in range(10)] train_pairs, train_y = create_pairs(train_pairs, digit_indicesTrain) # digit_indicesTest = [np.where(val_y == i)[0] for i in range(10)] val_pairs, val_y = create_pairs(val_pairs, digit_indicesTest)
def initialize_dataset(dataset): ''' Generate datasets and save them into file. If there is not physical file, the dataset always be generated Arg: dataset: the dataset in SETTINGS which is SETTINGS['dataset'] ''' if not os.path.isfile('./mnist_dataset.npz') or dataset['create_original_dataset']: x_train, y_train, x_test, y_test = assign2_utils.load_dataset() np.savez('mnist_dataset.npz', x_train=x_train, y_train=y_train, x_test=x_test, y_test=y_test) if not os.path.isfile('./mnist_warped_dataset.npz') or dataset['create_warped_dataset']: generate_warped_dataset(dataset)
def noSplit_preprocess_Data(degree, strength): ''' This function prepares the data set for the training stage (and validation) 1. Load the data 2. Transform data (if warping is needed) 3. Create the positive and negative pairs 4. Reshape the pairs for 2D convolutional layer 5. Split into training / validation datasets @param degree: The max degree of the transformation strength: The strength of the transformation percentage : Percentage of dataset used for training @return : ''' # 1. load the data x_original_train, train_target, x_original_test, val_target = assign2_utils.load_dataset() x_original_train = x_original_train.astype('float32') x_original_test = x_original_test.astype('float32') x_original_train /= 255 # normalized the entries between 0 and 1 x_original_test /= 255 # 2. transformed data if (degree != 0 or strength !=0 ): train_pairs, val_pairs = transform_dataset(x_original_train, x_original_test, degree, strength) else: train_pairs, val_pairs = x_original_train, x_original_test # 3. Create the positive and negative pairs # the total number of pairs, one pair(2 numbers) in the same or not same classification, 28*28 digit_indicesTrain = [np.where(train_target == i)[0] for i in range(10)] digit_indicesTest = [np.where(val_target == i)[0] for i in range(10)] train_pairs, train_y = create_pairs(train_pairs, digit_indicesTrain) val_pairs, val_y = create_pairs(val_pairs, digit_indicesTest) # 4. reshape the pairs for 2D convolutional layer train_twin1_input, train_twin2_input = reshape_input(image_width, image_height, num_channels, train_pairs) val_twin1_input, val_twin2_input = reshape_input(image_width, image_height, num_channels, val_pairs) return train_twin1_input, train_twin2_input, val_twin1_input, val_twin2_input, train_y, val_y
def initialize_dataset(dataset): ''' Generate datasets and save them into file. If there is not physical file, the dataset always be generated Arg: dataset: the dataset in SETTINGS which is SETTINGS['dataset'] ''' if not os.path.isfile(dataset['original_file_name'] ) or dataset['create_original_dataset']: x_train, y_train, x_test, y_test = assign2_utils.load_dataset() np.savez(dataset['original_file_name'], x_train=x_train, y_train=y_train, x_test=x_test, y_test=y_test) if not os.path.isfile( dataset['hardset_file_name']) or dataset['create_hard_dataset']: generate_warped_dataset(dataset['original_file_name'], dataset['hardset_file_name'], dataset['hard_set'], dataset['hard_pair_rotation'], dataset['hard_pair_variation']) if not os.path.isfile( dataset['easyset_file_name']) or dataset['create_easy_dataset']: generate_warped_dataset(dataset['original_file_name'], dataset['easyset_file_name'], dataset['easy_set'], dataset['easy_pair_rotation'], dataset['easy_pair_variation']) if not os.path.isfile( './test_dataset.npz') or dataset['create_test_dataset']: generate_testset(dataset['original_file_name'], dataset['test_set'], dataset['testset_rotation'], dataset['testset_variation'])
def simplistic_solution(): ''' Train a Siamese network to predict whether two input images correspond to the same digit. WARNING: in your submission, you should use auxiliary functions to create the Siamese network, to train it, and to compute its performance. ''' def create_simplistic_base_network(input_dim): ''' Base network to be shared (eq. to feature extraction). ''' seq = keras.models.Sequential() seq.add(keras.layers.Dense(128, input_shape=(input_dim,), activation='relu')) seq.add(keras.layers.Dropout(0.1)) seq.add(keras.layers.Dense(128, activation='relu')) seq.add(keras.layers.Dropout(0.1)) seq.add(keras.layers.Dense(128, activation='relu')) return seq # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # load the dataset x_train, y_train, x_test, y_test = assign2_utils.load_dataset() # Example of magic numbers (6000, 784) # This should be avoided. Here we could/should have retrieve the # dimensions of the arrays using the numpy ndarray method shape x_train = x_train.reshape(60000, 784) x_test = x_test.reshape(10000, 784) x_train = x_train.astype('float32') x_test = x_test.astype('float32') x_train /= 255 # normalized the entries between 0 and 1 x_test /= 255 input_dim = 784 # 28x28 # epochs = 20 # create training+test positive and negative pairs digit_indices = [np.where(y_train == i)[0] for i in range(10)] tr_pairs, tr_y = create_pairs(x_train, digit_indices) digit_indices = [np.where(y_test == i)[0] for i in range(10)] te_pairs, te_y = create_pairs(x_test, digit_indices) # network definition base_network = create_simplistic_base_network(input_dim) input_a = keras.layers.Input(shape=(input_dim,)) input_b = keras.layers.Input(shape=(input_dim,)) # because we re-use the same instance `base_network`, # the weights of the network # will be shared across the two branches processed_a = base_network(input_a) processed_b = base_network(input_b) # node to compute the distance between the two vectors # processed_a and processed_a distance = keras.layers.Lambda(euclidean_distance)([processed_a, processed_b]) # Our model take as input a pair of images input_a and input_b # and output the Euclidian distance of the mapped inputs model = keras.models.Model([input_a, input_b], distance) callback = siamese_callback([te_pairs[:, 0], te_pairs[:, 1]], te_y) # filepath="weights.best.hdf5" # earlyStopping = EarlyStopping(monitor='val_loss', min_delta=2, patience=0, verbose=0, mode='auto') # checkpointer = ModelCheckpoint(filepath, monitor='val_loss', verbose=1, save_best_only=True, mode='min') callback_list = [callback] # train rms = keras.optimizers.RMSprop() model.compile(loss=contrastive_loss, optimizer=rms) # important code - donot delete line below for loading model from file # model = load_model('best_model.h5', custom_objects={'contrastive_loss': contrastive_loss}) model.fit([tr_pairs[:, 0], tr_pairs[:, 1]], tr_y, batch_size=128, epochs=epochs, validation_data=([te_pairs[:, 0], te_pairs[:, 1]], te_y), callbacks=callback_list) # compute final accuracy on training and test sets pred_train = model.predict([tr_pairs[:, 0], tr_pairs[:, 1]]) tr_acc = compute_accuracy(pred_train, tr_y) pred_test = model.predict([te_pairs[:, 0], te_pairs[:, 1]]) te_acc = compute_accuracy(pred_test, te_y) # print('* Accuracy on training set: %0.2f%%' % (100 * tr_acc)) print('* Accuracy on test set: %0.2f%%' % (100 * te_acc)) visualise_roc(pred_train, tr_y, pred_test, te_y)
print('* Accuracy on training set: %0.2f%%' % (100 * tr_acc)) print('* Accuracy on test set: %0.2f%%' % (100 * te_acc)) print('* Accuracy on test set (small warp): %0.2f%%' % (100 * te_S_acc)) print('* Accuracy on test set (large warp): %0.2f%%' % (100 * te_L_acc)) #------------------------------------------------------------------------------ #----------------------------- SETTINGS --------------------------------------- COLOR_INTENSITY = 255 # Scalar used to normalize values in the MNIST Dataset ROTATION = 45 # Maximum Rotational Scalar for Warped Dataset STRENGTH = 0.3 # Maximum Strength Value for Warped Dataset #------------------------ Load MNIST Dataset ---------------------------------- x_train, y_train, x_test, y_test = assign2_utils.load_dataset() input_dim = x_train.shape[1:3]# 28x28 #---=------------------------- Mixed Dataset ---------------------------------- x_a, y_a = create_warped_dataset(x_train,y_train,0,0,output_size=50000) # Unwarped Data x_b, y_b = create_warped_dataset(x_train,y_train,(ROTATION/2),(STRENGTH/2),output_size=25000) # Light Warped Data x_c, y_c = create_warped_dataset(x_train,y_train,ROTATION,STRENGTH,output_size=25000) # Heavy Warped Data # Concatinate Mixed Set together x_train_mix = np.concatenate((x_a,x_b,x_c)) y_train_mix = np.concatenate((y_a,y_b,y_c)) x_train_mix = x_train_mix.reshape(x_train_mix.shape[0],input_dim[0],input_dim[1],1) x_train_mix = x_train_mix.astype('float32') #--------------------------- Small Warp Dataset -------------------------------
def simplistic_solution(): ''' Train a Siamese network to predict whether two input images correspond to the same digit. WARNING: in your submission, you should use auxiliary functions to create the Siamese network, to train it, and to compute its performance. ''' def create_simplistic_base_network(input_dim): ''' Base network to be shared (eq. to feature extraction). ''' seq = keras.models.Sequential() seq.add( keras.layers.Dense(128, input_shape=(input_dim, ), activation='relu')) seq.add(keras.layers.Dropout(0.1)) seq.add(keras.layers.Dense(128, activation='relu')) seq.add(keras.layers.Dropout(0.1)) seq.add(keras.layers.Dense(128, activation='relu')) return seq # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # load the dataset x_train, y_train, x_test, y_test = assign2_utils.load_dataset() # Example of magic numbers (6000, 784) # This should be avoided. Here we could/should have retrieve the # dimensions of the arrays using the numpy ndarray method shape x_train = x_train.reshape(60000, 784) x_test = x_test.reshape(10000, 784) x_train = x_train.astype('float32') x_test = x_test.astype('float32') x_train /= 255 # normalized the entries between 0 and 1 x_test /= 255 input_dim = 784 # 28x28 # # create training+test positive and negative pairs digit_indices = [np.where(y_train == i)[0] for i in range(10)] train_pairs, train_y = create_pairs(x_train, digit_indices) digit_indices = [np.where(y_test == i)[0] for i in range(10)] val_pairs, val_y = create_pairs(x_test, digit_indices) # network definition base_network = create_simplistic_base_network(input_dim) input_a = keras.layers.Input(shape=(input_dim, )) input_b = keras.layers.Input(shape=(input_dim, )) # because we re-use the same instance `base_network`, # the weights of the network # will be shared across the two branches processed_a = base_network(input_a) processed_b = base_network(input_b) # node to compute the distance between the two vectors # processed_a and processed_a distance = keras.layers.Lambda(euclidean_distance)( [processed_a, processed_b]) # Our model take as input a pair of images input_a and input_b # and output the Euclidian distance of the mapped inputs model = keras.models.Model([input_a, input_b], distance) # train rms = keras.optimizers.RMSprop() model.compile(loss=contrastive_loss, optimizer=rms) model.fit([train_pairs[:, 0], train_pairs[:, 1]], train_y, validation_data=([val_pairs[:, 0], val_pairs[:, 1]], val_y)) # compute final accuracy on training and test sets pred = model.predict([train_pairs[:, 0], train_pairs[:, 1]]) tr_acc = compute_accuracy(pred, train_y) pred = model.predict([val_pairs[:, 0], val_pairs[:, 1]]) te_acc = compute_accuracy(pred, val_y) print('* Accuracy on training set: %0.2f%%' % (100 * tr_acc)) print('* Accuracy on test set: %0.2f%%' % (100 * te_acc))
#dropout2 seq.add(keras.layers.Dropout(dropout2_probability)) return seq #------------------------------------------------------------------------------ if __name__=='__main__': ''' architecture_flag:1 for the initial architecture. 2 is for the second architecutre degree1: degree2: 0 strength1: strength2: percentage: ''' x_original_train, train_target, x_original_test, val_target = assign2_utils.load_dataset() #train_pairs, val_pairs = transform_dataset(x_original_train, x_original_test, 30, 0.15) # 2. split the datset. x_original_train = x_original_train.astype('float32') x_original_test = x_original_test.astype('float32') normaliseValue = 255 x_original_train /= normaliseValue # normalized the entries between 0 and 1 x_original_test /= normaliseValue x_original_train1, x_original_train2, train_target1, train_target2 = split_Data(x_original_train,train_target, 0.4) #x_original_test1, x_original_test2 , val_target1, val_target2 = split_Data(x_original_test,val_target, percentage) # 3. transform the dataset. warped_pairs1 = np.array([assign2_utils.random_deform(x, 15, 0.1) for x in x_original_train1]) warped_pairs2 = np.array([assign2_utils.random_deform(x, 45, 0.3) for x in x_original_train2])
def stage_learning(): """ stage learning training the first 20% easy warped images first, then training the 80% hard warped images test all images predict the accuracy """ #expand x_train,y_train into a new x_train and y_train array with 100,000 x_train, y_train, x_test, y_test = assign2_utils.load_dataset() a = x_train[0:40000, :, :] x_train = np.concatenate((a, x_train), axis=0) b = y_train[0:40000] y_train = np.concatenate((b, y_train), axis=0) img_row = x_train.shape[1] img_col = x_train.shape[2] # normalized the input image x_train = x_train.astype('float32') x_test = x_test.astype('float32') x_train /= 255 x_test /= 255 #reshape data x_train = x_train.reshape(x_train.shape[0], img_row, img_col, 1) x_test = x_test.reshape(x_test.shape[0], img_row, img_col, 1) input_dim = (img_row, img_col, 1) epochs = 10 x_train_easy = x_train x_train_hard = x_train x_test_easy = x_test x_test_hard = x_test #warped images with with easy strength and easy degree for i in range(100000): x_train_easy[i] = assign2_utils.random_deform(x_train[i], 15, 0.1) for i in range(100000): x_train_hard[i] = assign2_utils.random_deform(x_train[i], 45, 0.3) #warped images with with hard strength and hard degree for i in range(10000): x_test_easy[i] = assign2_utils.random_deform(x_test[i], 15, 0.1) for i in range(10000): x_test_hard[i] = assign2_utils.random_deform(x_test[i], 45, 0.3) # create training+test positive and negative pairs digit_indices = [np.where(y_train == i)[0] for i in range(10)] tr_pairs_easy, tr_y_easy = create_pairs(x_train_easy, digit_indices) digit_indices = [np.where(y_train == i)[0] for i in range(10)] tr_pairs_hard, tr_y_hard = create_pairs(x_train_hard, digit_indices) digit_indices = [np.where(y_test == i)[0] for i in range(10)] te_pairs, te_y = create_pairs(x_test, digit_indices) # network definition base_network = create_simplistic_base_network(input_dim) input_a = keras.layers.Input(shape=input_dim) input_b = keras.layers.Input(shape=input_dim) # because we re-use the same instance `base_network`, # the weights of the network will be shared across the two branches processed_a = base_network(input_a) processed_b = base_network(input_b) # node to compute the distance between the two vectors # processed_a and processed_a distance = keras.layers.Lambda(euclidean_distance)( [processed_a, processed_b]) # Our model take as input a pair of images input_a and input_b # and output the Euclidian distance of the mapped inputs #model to fit the first 20% easy warped images model = keras.models.Model([input_a, input_b], distance) rms = keras.optimizers.RMSprop() model.compile(loss=contrastive_loss, optimizer=rms) model.fit([tr_pairs_easy[0:36096, 0], tr_pairs_easy[0:36096, 1]], tr_y_easy[0:36096], batch_size=128, epochs=epochs, validation_data=([te_pairs[0:3564, 0], te_pairs[0:3564, 1]], te_y[0:3564])) #model.save_weights("easy_warped.h5") #model to fit the last 80% hard warped images model2 = keras.models.Model([input_a, input_b], distance) rms = keras.optimizers.RMSprop() model2.compile(loss=contrastive_loss, optimizer=rms) #model2.load_weights("easy_warped.h5") model2.fit([tr_pairs_hard[36096:, 0], tr_pairs_hard[36096:, 1]], tr_y_hard[36096:], batch_size=128, epochs=epochs, validation_data=([te_pairs[3564:, 0], te_pairs[3564:, 1]], te_y[3564:])) #merge two tr_pairs dataset together tr_pairs = np.concatenate((tr_pairs_hard[36096:], tr_pairs_easy[0:36096]), axis=0) tr_y = np.concatenate((tr_y_hard[36096:], tr_y_easy[0:36096])) pred = model.predict([tr_pairs[:, 0], tr_pairs[:, 1]]) tr_acc = compute_accuracy(pred, tr_y) pred = model.predict([te_pairs[:, 0], te_pairs[:, 1]]) te_acc = compute_accuracy(pred, te_y) print('when epochs is {}'.format(epochs)) print('* Accuracy on training set: %0.2f%%' % (100 * tr_acc)) print('* Accuracy on test set: %0.2f%% \n\n' % (100 * te_acc))
def simplistic_solution(epochs, degree, strength): ''' Train a Siamese network to predict whether two input images correspond to the same digit. WARNING: in your submission, you should use auxiliary functions to create the Siamese network, to train it, and to compute its performance. ''' # load dataset and expand 60,000 to 100,000 x_train, y_train, x_test, y_test = assign2_utils.load_dataset() a = x_train[0:40000, :, :] x_train = np.concatenate((a, x_train), axis=0) b = y_train[0:40000] y_train = np.concatenate((b, y_train), axis=0) img_row = x_train.shape[1] img_col = x_train.shape[2] # normalized the input image x_train = x_train.astype('float32') x_test = x_test.astype('float32') x_train /= 255 x_test /= 255 def warped_images(x_train, x_test, degree, strength): """ warped dataset with degree and strength. @param: expanded x_train,x_test. degree: warped degree strength: warped strength @return: warped x_train, x_test """ print("This time is warped data with {} degree and {} strength".format( degree, strength)) for i in range(len(x_train)): x_train[i] = assign2_utils.random_deform(x_train[i], degree, strength) for i in range(len(x_test)): x_test[i] = assign2_utils.random_deform(x_test[i], degree, strength) return x_train, x_test #------------------------------------------------------------------------------ combo_warped = False if combo_warped: x_train_easy, x_test_easy = warped_images(x_train[0:20000], x_test[0:2000], 15, 0.1) x_train_hard, x_test_hard = warped_images(x_train[20000:], x_test[2000:], 45, 0.3) x_train = np.concatenate((x_train_easy, x_train_hard), axis=0) x_test = np.concatenate((x_test_easy, x_test_hard), axis=0) else: x_train, x_test = warped_images(x_train, x_test, degree, strength) #reshape data if K.image_data_format() == 'channels_first': x_train = x_train.reshape(x_train.shape[0], 1, img_row, img_col) x_test = x_test.reshape(x_test.shape[0], 1, img_row, img_col) input_dim = (1, img_row, img_col) else: x_train = x_train.reshape(x_train.shape[0], img_row, img_col, 1) x_test = x_test.reshape(x_test.shape[0], img_row, img_col, 1) input_dim = (img_row, img_col, 1) epochs = epochs # create training+test positive and negative pairs digit_indices = [np.where(y_train == i)[0] for i in range(10)] tr_pairs, tr_y = create_pairs(x_train, digit_indices) digit_indices = [np.where(y_test == i)[0] for i in range(10)] te_pairs, te_y = create_pairs(x_test, digit_indices) # print(len(te_y)) # print(len(te_pairs)) # network definition base_network = create_simplistic_base_network(input_dim) input_a = keras.layers.Input(shape=input_dim) input_b = keras.layers.Input(shape=input_dim) # because we re-use the same instance `base_network`, # the weights of the network will be shared across the two branches processed_a = base_network(input_a) processed_b = base_network(input_b) # node to compute the distance between the two vectors # processed_a and processed_a distance = keras.layers.Lambda(euclidean_distance)( [processed_a, processed_b]) # Our model take as input a pair of images input_a and input_b # and output the Euclidian distance of the mapped inputs model = keras.models.Model([input_a, input_b], distance) rms = keras.optimizers.RMSprop() model.compile(loss=contrastive_loss, optimizer=rms) model.fit([tr_pairs[:, 0], tr_pairs[:, 1]], tr_y, batch_size=128, epochs=epochs, validation_data=([te_pairs[:, 0], te_pairs[:, 1]], te_y)) # compute final accuracy on training and test sets pred = model.predict([tr_pairs[:, 0], tr_pairs[:, 1]]) tr_acc = compute_accuracy(pred, tr_y) pred = model.predict([te_pairs[:, 0], te_pairs[:, 1]]) te_acc = compute_accuracy(pred, te_y) print('when epochs is {}'.format(epochs)) print('* Accuracy on training set: %0.2f%%' % (100 * tr_acc)) print('* Accuracy on test set: %0.2f%%' % (100 * te_acc)) return tr_acc, te_acc