good_prediction=lambda df: df.target.iloc[0], ).loc[lambda df: df.target].agg('mean'))).agg('mean'))] scores = pd.DataFrame(scores)[[ 'score', 'average_precision', 'good_prediction' ]] plt.clf() scores.boxplot() plt.savefig(output_folder / 'scores_boxplot.png') plt.clf() scores.good_prediction.hist() plt.savefig(output_folder / 'scores_good_predictions.png') scores.to_csv(output_folder / 'scores.csv', index=False) #%% Export classification model with SavedModel model.load_weights(str(output_folder / 'kernel_loss_best_loss_weights.h5')) classifier = Sequential([ siamese_nets.get_layer('branch_model'), Classification(kernel=siamese_nets.get_layer('head_model')), Activation('softmax'), ]) tf.saved_model.save(classifier, str(output_folder / 'saved_model/1/')) #%% Example of use as classifier classifier.get_layer('classification').set_support_set( support_tensors=tf.convert_to_tensor(support_set_embeddings, tf.float32), support_labels=tf.convert_to_tensor( pd.get_dummies(support_set.label.values).values, tf.float32), ) y = classifier.predict_generator(test_sequence, verbose=1)
model = Sequential([ BasicCNN((32, 32, 3), i), GramMatrix(kernel), ]) model.summary() model.compile( optimizer='adam', loss=binary_crossentropy(), metrics=[mean_score_classification_loss, min_eigenvalue], ) model.fit(X_train, y_train, validation_split=0.2, epochs=20, batch_size=32) embeddings = model.layers[0].predict(X_train) classifier = Sequential([ model.layers[0], Classification(kernel), ]) classifier.layers[1].set_support_set(embeddings, y_train) classifier.compile(loss='binary_crossentropy', optimizer='adam') classifier.evaluate(X_test, y_test, verbose=1) y_pred = classifier.predict(X_test, verbose=1) confusion_matrix = pd.crosstab( index=pd.Categorical(np.argmax(y_pred, axis=1), categories=list(range(10))), columns=pd.Categorical(np.argmax(y_test, axis=1), categories=list(range(10))), margins=True, dropna=False, rownames=['pred'], colnames=['true'], ) accuracies.append(np.diag(confusion_matrix)[:-1].sum() / np.diag(confusion_matrix)[-1])
#%% Train with binary crossentropy and gram matrix accuracies = [] for i in range(1, 21): kernel = Lambda( lambda inputs: tf.reduce_sum(inputs[0] * inputs[1], axis=1)) model = Sequential([BasicCNN((32, 32, 3), i), GramMatrix(kernel)]) model.summary() model.compile( optimizer="adam", loss=binary_crossentropy(), metrics=[mean_score_classification_loss, min_eigenvalue], ) model.fit(X_train, y_train, validation_split=0.2, epochs=20, batch_size=32) embeddings = model.layers[0].predict(X_train) classifier = Sequential([model.layers[0], Classification(kernel)]) classifier.layers[1].set_support_set(embeddings, y_train) classifier.compile(loss="binary_crossentropy", optimizer="adam") classifier.evaluate(X_test, y_test, verbose=1) y_pred = classifier.predict(X_test, verbose=1) confusion_matrix = pd.crosstab( index=pd.Categorical(np.argmax(y_pred, axis=1), categories=list(range(10))), columns=pd.Categorical(np.argmax(y_test, axis=1), categories=list(range(10))), margins=True, dropna=False, rownames=["pred"], colnames=["true"], ) accuracies.append(
def train(base_dir): #%% Init model encoder = keras_applications.MobileNet(input_shape=(224, 224, 3), include_top=False, pooling="avg") support_layer = GramMatrix(kernel={ "name": "MixedNorms", "init": { "norms": [ lambda x: 1 - tf.nn.l2_normalize(x[0]) * tf.nn.l2_normalize(x[ 1]), lambda x: tf.math.abs(x[0] - x[1]), lambda x: tf.nn.softmax(tf.math.abs(x[0] - x[1])), lambda x: tf.square(x[0] - x[1]), ], "use_bias": True, }, }, ) model = Sequential([encoder, support_layer]) #%% Init training callbacks = [ TensorBoard(base_dir, write_images=True, histogram_freq=1), ModelCheckpoint(str(base_dir / "best_loss.h5"), save_best_only=True), ReduceLROnPlateau(), ] #%% Init data @tf.function(input_signature=(tf.TensorSpec(shape=[None, None, 3], dtype=tf.uint8))) def preprocessing(input_tensor): output_tensor = tf.cast(input_tensor, dtype=tf.float32) output_tensor = tf.image.resize_with_pad(output_tensor, target_height=224, target_width=224) output_tensor = keras_applications.mobilenet.preprocess_input( output_tensor, data_format="channels_last") return output_tensor @tf.function(input_signature=(tf.TensorSpec(shape=[None, None, 3], dtype=tf.float32))) def data_augmentation(input_tensor): output_tensor = tf.image.random_flip_left_right(input_tensor) output_tensor = tf.image.random_flip_up_down(output_tensor) output_tensor = tf.image.random_brightness(output_tensor, max_delta=0.25) return output_tensor all_annotations = pd.read_csv(base_dir / "annotations" / "all_annotations.csv") class_count = all_annotations.groupby("split").apply( lambda group: group.label.value_counts()) #%% Train model margin = 0.05 k_shot = 4 cache = base_dir / "cache" datasets = all_annotations.groupby("split").apply(lambda group: ( group.pipe( ToKShotDataset( k_shot=k_shot, preprocessing=compose(preprocessing, data_augmentation), cache=str(cache / group.name), reset_cache=False, dataset_mode="with_cache", # max_shuffle_buffer_size=max(class_count), # can slow down a lot if classes are big )))) batch_size = 64 encoder.trainable = False optimizer = Adam(lr=1e-4) model.compile( optimizer=optimizer, loss=class_consistency_loss, metrics=[ accuracy(margin), binary_crossentropy(), max_crossentropy, std_crossentropy, same_image_score, top_score_classification_accuracy, ], ) model.fit( datasets["train"].batch(batch_size).repeat(), steps_per_epoch=len(class_count["train"]) * k_shot // batch_size * 150, validation_data=datasets["val"].batch(batch_size).repeat(), validation_steps=max( len(class_count["val"]) * k_shot // batch_size, 100), initial_epoch=0, epochs=3, callbacks=callbacks, ) encoder.trainable = True optimizer = Adam(lr=1e-5) model.compile( optimizer=optimizer, loss=class_consistency_loss, metrics=[ accuracy(margin), binary_crossentropy(), max_crossentropy, std_crossentropy, same_image_score, top_score_classification_accuracy, ], ) model.fit( datasets["train"].batch(batch_size).repeat(), steps_per_epoch=len(class_count["train"]) * k_shot // batch_size * 150, validation_data=datasets["val"].batch(batch_size).repeat(), validation_steps=max( len(class_count["val"]) * k_shot // batch_size, 100), initial_epoch=3, epochs=30, callbacks=callbacks, ) #%% Evaluate on test set. Each batch is a k_shot, n_way=batch_size / k_shot task model.load_weights(str(base_dir / "best_loss.h5")) model.evaluate(datasets["test"].batch(batch_size).repeat(), steps=max( len(class_count["test"]) * k_shot // batch_size, 100)) #%% Export artifacts classifier = Sequential([encoder, Classification(support_layer.kernel)]) tf.saved_model.save(classifier, "siamese_nets_classifier/1", signatures={"preprocessing": preprocessing})