Skip to content

Model comparison

This module contains functions for use in model comparison analyses.

model_comparison

Functions:

calculate_confusion_and_inversion

calculate_confusion_and_inversion(df: DataFrame, metric: str = 'waic') -> (ndarray, ndarray)

Calculate confusion and inversion matrices based on WAIC values.

This function computes the confusion matrix and inversion matrix normalized from a DataFrame containing simulation results. The confusion matrix reflects how often each model is selected as the best model when each model is true (i.e., P(estimated | true)). The inversion matrix normalized represents the proportion of times each model is estimated to be the best given each true model (i.e., P(true | estimated)).

Parameters:

  • df

    (DataFrame) –

    A DataFrame containing the following columns:

    • "simulated_model": Label of the model used for simulation.
    • "estimation_model": Label of the model used for estimation.
    • "iteration": Iteration identifier (i.e., the iteration of the model comparison procedure, where multiple datasets are simulated and then fitted).

    A further column corresponding to the given metric should also be present. This column should correspond to the value of the metric argument.

  • metric

    (str, default: 'waic' ) –

    The name of the column to be used as the metric for

Returns:

  • (ndarray, ndarray)

    np.ndarray: The confusion matrix representing how often each model is estimated to be the best when each model is true.

  • (ndarray, ndarray)

    np.ndarray: The inversion matrix normalized, indicating the proportion of times each model is the true generating model given each estimated model.

Example

confusion_matrix, inversion_matrix = calculate_confusion_and_inversion(results)

Here, results is expected to be a DataFrame with at least the columns "simulated_model", "estimation_model", "iteration", and "waic".

The results can then be plotted using model_fit_tools.plotting.plot_matrices:

model_fit_tools.plotting.plot_matrices(confusion_matrix, inversion_matrix, models)

Source code in model_fit_tools/model_comparison.py
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
def calculate_confusion_and_inversion(
    df: pd.DataFrame, metric: str = "waic"
) -> (np.ndarray, np.ndarray):
    """
    Calculate confusion and inversion matrices based on WAIC values.

    This function computes the confusion matrix and inversion matrix normalized
    from a DataFrame containing simulation results. The confusion matrix
    reflects how often each model is selected as the best model when each model
    is true (i.e., `P(estimated | true)`). The inversion matrix normalized
    represents the proportion of times each model is estimated to be the best
    given each true model (i.e., `P(true | estimated)`).

    Args:
        df (pd.DataFrame): A DataFrame containing the following columns:\n
            - `"simulated_model"`: Label of the model used for simulation.
            - `"estimation_model"`: Label of the model used for estimation.
            - `"iteration"`: Iteration identifier (i.e., the iteration of
            the model comparison procedure, where multiple datasets are
            simulated and then fitted).\n
            A further column corresponding to the given metric should also be
            present. This column should correspond to the value of the
            `metric` argument.
        metric (str): The name of the column to be used as the metric for
        selecting
            the winning model. Higher values should indicate better models.
            Defaults to "waic".

    Returns:
        np.ndarray: The confusion matrix representing how often each model is
            estimated to be the best when each model is true.

        np.ndarray: The inversion matrix normalized, indicating the proportion
            of times each model is the true generating model given each
            estimated model.

    Example:
        `confusion_matrix, inversion_matrix =
        calculate_confusion_and_inversion(results)`

        Here, `results` is expected to be a DataFrame with at least the columns
        "simulated_model", "estimation_model", "iteration", and "waic".

        The results can then be plotted using
        `model_fit_tools.plotting.plot_matrices`:

        `model_fit_tools.plotting.plot_matrices(confusion_matrix,
        inversion_matrix, models)`


    """

    # Extract unique models and initialize matrix
    models = df["simulated_model"].unique()
    n_models = len(models)
    confusion_matrix = np.zeros((n_models, n_models))

    # Ensure the metric column exists in the dataframe
    if metric not in df.columns:
        raise ValueError(
            f"Metric {metric} is not a column in the provided DataFrame."
        )

    # Calculate confusion matrix
    for n, simulated_model in enumerate(models):
        for i in df["iteration"].unique():
            # Extract relevant run results
            run_results = df[
                (df["iteration"] == i)
                & (df["simulated_model"] == simulated_model)
            ].copy()

            # Convert the 'estimation_model' column to a Categorical type with
            # custom order
            run_results["estimation_model"] = pd.Categorical(
                run_results["estimation_model"],
                categories=models,
                ordered=True,
            )

            # Sort the DataFrame by 'estimation_model'
            run_results = run_results.sort_values("estimation_model")

            # Update confusion matrix
            confusion_matrix[np.argmax(run_results[metric].values), n] += 1

    # Normalize confusion matrix
    confusion_matrix = confusion_matrix / len(df["iteration"].unique())

    # Calculate inversion matrix
    inversion_matrix = confusion_matrix.T

    return confusion_matrix, inversion_matrix