Skip to content

Training Pipeline

Training with Experimental Data

hyperparameter_tuning(batch_size_num, learning_rate_num, cfg_ml_train)

Training with a specific batch_size and learning_rate combination

Parameters:

Name Type Description Default
batch_size_num int

batch size

required
learning_rate_num int

learning rate

required

Returns:

Name Type Description
float float

best validation accuracy for the specific combination

Source code in scripts/ml_training.py
def hyperparameter_tuning(batch_size_num: int,learning_rate_num: int, cfg_ml_train) -> float:
    """
    Training with a specific batch_size and learning_rate combination

    Args:
        batch_size_num (int): batch size 
        learning_rate_num (int): learning rate

    Returns:
        float: best validation accuracy for the specific combination
    """
    print(f"\n>>> Training with batch size = {batch_size_num} and learning rate = {learning_rate_num}")

    train_features = np.load(cfg_ml_train["data_dir"] + "16O_size800_train_features.npy")
    train_labels = np.load(cfg_ml_train["data_dir"] + "16O_size800_train_labels.npy")
    print("Training data shape:", train_features.shape)
    train_ds = tf.data.Dataset.from_tensor_slices((train_features[:,:,:3], train_labels))
    train_ds = train_ds.batch(batch_size=batch_size_num, drop_remainder=False)

    val_features = np.load(cfg_ml_train["data_dir"] + "16O_size800_val_features.npy")
    val_labels = np.load(cfg_ml_train["data_dir"] + "16O_size800_val_labels.npy")
    val_ds = tf.data.Dataset.from_tensor_slices((val_features[:,:,:3], val_labels))
    val_ds = val_ds.batch(batch_size=batch_size_num, drop_remainder=True)


    #early stopping
    early_stopping = EarlyStopping(
        monitor = "val_sparse_categorical_accuracy",
        mode = "max",
        patience = 10,
        restore_best_weights = True,
    )

    # build and train event-wise classification model and plot learning curve
    model = create_pointnet_model(num_points=800, 
                          num_classes=5, 
                          num_dimensions=3, #for changing number of features
                          is_regression=False,
                          is_pointwise_prediction=False)
    #model.summary()
    model.compile(loss="sparse_categorical_crossentropy",
                  optimizer=keras.optimizers.Adam(learning_rate=learning_rate_num),
                  metrics=["sparse_categorical_accuracy"])


    #checkpointing
    history = model.fit(train_ds, validation_data=val_ds, epochs=cfg_ml_train["epochs_limit"], callbacks=[early_stopping],verbose=2) #early stopping

    best_val_acc = np.max(history.history["val_sparse_categorical_accuracy"])
    print(f"Best val_accuracy={best_val_acc:.4f}")   
    return best_val_acc

load_classfication_model(cfg_ml_train)

Evaluating the performance on the model with best hyperparameters

Returns:

Type Description
None

None

Source code in scripts/ml_training.py
def load_classfication_model(cfg_ml_train) -> None:
    """
    Evaluating the performance on the model with best hyperparameters 

    Args:
        None

    Returns:
        None
    """
    tf.keras.backend.clear_session() 
    test_features = np.load(cfg_ml_train["data_dir"] + "16O_size800_test_features.npy")
    test_features = test_features[:,:,:3]
    test_labels = np.load(cfg_ml_train["data_dir"] + "16O_size800_test_labels.npy")

    print("Shape of test_features:", test_features.shape)

    model = create_pointnet_model(num_points=800, 
                          num_classes=5, 
                          num_dimensions=3, #for changing number of features
                          is_regression=False, #no regression
                          is_pointwise_prediction=False) # we just want classification

    model.compile(loss="sparse_categorical_crossentropy",
                  optimizer=keras.optimizers.Adam(learning_rate=5e-06),
                  metrics=["sparse_categorical_accuracy"])

    model.summary()
    loss, accuracy_d = model.evaluate(test_features,test_labels,verbose=2)
    print("Untrained model, accuracy: {:5.2f}%".format(100 * accuracy_d))
    print("Unique label values:", np.unique(test_labels))

    model = tf.keras.models.load_model(cfg_ml_train["best_model_path"])
    loss, accuracy_d = model.evaluate(test_features,test_labels,verbose=2)
    print("Restored model, accuracy: {:5.2f}%".format(100 * accuracy_d))

    y_pred = model.predict(test_features)
    predicted_classes = np.argmax(y_pred, axis=1)

    f1 = f1_score(test_labels, predicted_classes, average='weighted')
    f1_cl2 = f1_score(test_labels, predicted_classes, labels=[2], average='weighted')
    cf_matrix = confusion_matrix(test_labels, predicted_classes)

    print(f"F1 Score: {f1}")
    print(f"F1 Score Class 2: {f1_cl2}")
    print("Confusion Matrix:")
    #print(cm)

    group_counts = ["{0:0.0f}".format(value) for value in
                cf_matrix.flatten()]
    group_percentages = ["{0:.2%}".format(value) for value in
                     cf_matrix.flatten()/np.sum(cf_matrix)]
    labels = [f"{v1}\n{v2}" for v1, v2 in
          zip(group_counts,group_percentages)]
    labels = np.asarray(labels).reshape(5,5)
    class_names = ["Class 0", "Class 1", "Class 2", "Class 3", "Class 4"]  # Change to your labels

    report = classification_report(test_labels, predicted_classes, target_names=class_names)
    print(report)

    svm = sns.heatmap(cf_matrix, annot=labels, fmt='', cmap='Reds')
    svm.set_xlabel("Predicted Labels")
    svm.set_ylabel("True Labels")
    svm.set_xticklabels(class_names)
    svm.set_yticklabels(class_names, rotation=0) 
    plt.savefig(cfg_ml_train["confusion_matrix_path"])

run_experiment(cfg_ml_train)

Finding the best batch size and learning rate combination

Returns:

Name Type Description
tuple tuple

best parameters (batch_size, learning_rate)

Source code in scripts/ml_training.py
def run_experiment(cfg_ml_train) -> tuple:
    """
    Finding the best batch size and learning rate combination 

    Args:
        None

    Returns:
        tuple: best parameters (batch_size, learning_rate)
    """
    batch_options = cfg_ml_train["batch_options"]
    lr_options = cfg_ml_train["lr_options"]
    results = {}

    for bs, lr in itertools.product(batch_options,lr_options):
        val_acc = hyperparameter_tuning(bs,lr,cfg_ml_train)
        results[(bs,lr)] = val_acc

    opt_params = max(results, key=results.get)
    print(f"\n Best parameter pair is {opt_params} with the accuracy of {results[opt_params]}")

    return opt_params

train_best_model(cfg_ml_train)

Training the model with the best parameters

Returns:

Type Description
None

None

Source code in scripts/ml_training.py
def train_best_model(cfg_ml_train) -> None:
    """
    Training the model with the best parameters 

    Args:
        None

    Returns:
        None
    """
    batch_size_num, learning_rate_num = run_experiment(cfg_ml_train)
    print(f"\n>>> Training with optimised batch size = {batch_size_num} and learning rate = {learning_rate_num}")

    train_features = np.load(cfg_ml_train["data_dir"] + "16O_size800_train_features.npy")
    train_labels = np.load(cfg_ml_train["data_dir"] + "16O_size800_train_labels.npy")
    print("Training data shape:", train_features.shape)
    train_ds = tf.data.Dataset.from_tensor_slices((train_features[:,:,:3], train_labels))
    train_ds = train_ds.batch(batch_size=batch_size_num, drop_remainder=False)

    val_features = np.load(cfg_ml_train["data_dir"] + "16O_size800_val_features.npy")
    val_labels = np.load(cfg_ml_train["data_dir"] + "16O_size800_val_labels.npy")
    val_ds = tf.data.Dataset.from_tensor_slices((val_features[:,:,:3], val_labels))
    val_ds = val_ds.batch(batch_size=batch_size_num, drop_remainder=True)

    #early stopping
    early_stopping = EarlyStopping(
        monitor = "val_sparse_categorical_accuracy",
        mode = "max",
        patience = 10,
        restore_best_weights = True,
    )

    best_model_callback = tf.keras.callbacks.ModelCheckpoint(
    filepath= cfg_ml_train["best_model_path"],
    monitor="val_sparse_categorical_accuracy",
    mode="max",
    save_best_only=True,
    verbose=1,
)

    # build and train event-wise classification model and plot learning curve
    model = create_pointnet_model(num_points=800, 
                          num_classes=5, 
                          num_dimensions=3, #for changing number of features
                          is_regression=False,
                          is_pointwise_prediction=False)

    model.summary()
    model.compile(loss="sparse_categorical_crossentropy",
                  optimizer=keras.optimizers.Adam(learning_rate=learning_rate_num),
                  metrics=["sparse_categorical_accuracy"])


    #checkpointing
    history = model.fit(train_ds, validation_data=val_ds, epochs=cfg_ml_train["epochs_limit"], callbacks=[early_stopping,best_model_callback],verbose=2) #early stopping
    plot_learning_curve(history, cfg_ml_train["learning_curve_path"],batch_size_num,learning_rate_num)

    best_epoch = np.argmax(history.history["val_sparse_categorical_accuracy"]) + 1
    best_val_acc = np.max(history.history["val_sparse_categorical_accuracy"])
    print(f"Best model was at epoch {best_epoch} with val_accuracy={best_val_acc:.4f}")