Automated Model Card Generation V3 From Moabb Examples

I ran two examples from MOABB:

  1. The Simple Motor Imagery tutorial. The self-stated example description is:

In this example, we will go through all the steps to make a simple BCI classification task, downloading a dataset and using a standard classifier. We choose the dataset 2a from BCI Competition IV, a motor imagery task. We will use a CSP to enhance the signal-to-noise ratio of the EEG epochs and a LDA to classify these signals.

  1. The Cross-session motor imagery with deep learning EEGNet v4 model example. The self-stated example description is:

This example shows how to use BrainDecode in combination with MOABB evaluation. In this example, we use the architecture EEGNetv4.

I had to manually filter and truncate the stack traces from these scripts from their original size of ~10-25 MB down to something that fits within the 128k token context window of GPT4o (~300 KB). Using the same pipeline as in Automated Model Card Generation v2 , I then generated model cards using the “main.py” file (what I refer to as the experiment file, or the script that the user runs) and the stack trace from script run.

Overall, it appears to work. It picks up and pulls out the preprocessing method used in MNE and the relevant parameters, additional steps such as spatial filtering with mne.decoding (in example 1) and classification information. I myself am pleased with the output in the Classification section of the model card for example #2, which used a deep learning classifier. While it only picked up the name of the model (“EEGNetv4”), with improvements we would be able to capture more detailed information like the actual architecture of the network (number of layers, types of operations in each layer, etc) – and fill in the relevant references if it is a “known” model like EEGNetv4.

While using the stack trace has its challenges with respect to parsing the amount of information for the relevant details, I can see particular advantages like the exact information of neural network layers, orders, input shapes, etc. In other words, the exact neural network used. I myself have often run into issues where the “described network” the exact network used don’t always align, due to inherent differences in the data (such as the input shape).

Below are the JSON outputs. You can view them in a Tree format on JSON Crack or a Table format on JSON2Table.

1. Simple Motor Imagery example

{
  "BCI Model card version": "0.0.0.1",
  "Pipeline Name": "Simple Motor Imagery BCI",
  "Pipeline Steps": [
    {
      "Step": "Generic",
      "Used": false,
      "From": null,
      "Function": null,
      "Description": null,
      "Details": null,
      "parameters": {
        "param_1": {
          "type": null,
          "description": null,
          "value": null
        },
        "param_2": {
          "type": null,
          "description": null,
          "value": null
        },
        "param_N": {
          "type": null,
          "description": null,
          "value": null
        }
      }
    },
    {
      "Step": "Resampling",
      "Used": false,
      "From": null,
      "Function": null,
      "Description": null,
      "Details": null,
      "parameters": {
        "param_1": {
          "type": null,
          "description": null,
          "value": null
        },
        "param_2": {
          "type": null,
          "description": null,
          "value": null
        },
        "param_N": {
          "type": null,
          "description": null,
          "value": null
        }
      }
    },
    {
      "Step": "Preprocessing",
      "Used": true,
      "From": "mne",
      "Function": "filter_data",
      "Description": "Bandpass filter the data",
      "Details": null,
      "parameters": {
        "l_freq": {
          "type": "float",
          "description": "Low cutoff frequency",
          "value": 8.0
        },
        "h_freq": {
          "type": "float",
          "description": "High cutoff frequency",
          "value": 32.0
        },
        "sfreq": {
          "type": "float",
          "description": "Sampling frequency of the data",
          "value": 250.0
        },
        "method": {
          "type": "string",
          "description": "Filtering method",
          "value": "iir"
        },
        "iir_params": {
          "type": "dict",
          "description": "Parameters for IIR filter",
          "value": {
            "order": 4,
            "ftype": "butter",
            "output": "sos"
          }
        }
      }
    },
    {
      "Step": "Feature selection",
      "Used": false,
      "From": null,
      "Function": null,
      "Description": null,
      "Details": null,
      "parameters": {
        "param_1": {
          "type": null,
          "description": null,
          "value": null
        },
        "param_2": {
          "type": null,
          "description": null,
          "value": null
        },
        "param_N": {
          "type": null,
          "description": null,
          "value": null
        }
      }
    },
    {
      "Step": "Channel selection",
      "Used": false,
      "From": null,
      "Function": null,
      "Description": null,
      "Details": null,
      "parameters": {
        "param_1": {
          "type": null,
          "description": null,
          "value": null
        },
        "param_2": {
          "type": null,
          "description": null,
          "value": null
        },
        "param_N": {
          "type": null,
          "description": null,
          "value": null
        }
      }
    },
    {
      "Step": "Spatial filtering",
      "Used": true,
      "From": "mne.decoding",
      "Function": "CSP",
      "Description": "Common Spatial Pattern (CSP) for spatial filtering",
      "Details": null,
      "parameters": {
        "n_components": {
          "type": "int",
          "description": "Number of components to keep",
          "value": 8
        },
        "cov_est": {
          "type": "string",
          "description": "Covariance estimation method",
          "value": "concat"
        },
        "transform_into": {
          "type": "string",
          "description": "Transform into",
          "value": "average_power"
        }
      }
    },
    {
      "Step": "Classification",
      "Used": true,
      "From": "sklearn.discriminant_analysis",
      "Function": "LinearDiscriminantAnalysis",
      "Description": "Linear Discriminant Analysis (LDA) for classification",
      "Details": null,
      "parameters": {
        "Model architecture": {
          "type": {
            "type": "string",
            "description": "Type of classifier used",
            "value": "LDA"
          }
        },
        "Hyperparameters": {
          "solver": {
            "type": "string",
            "description": "Solver to use in the computational routines",
            "value": "svd"
          }
        },
        "Training parameters": {
          "param_1": {
            "type": null,
            "description": null,
            "value": null
          },
          "param_2": {
            "type": null,
            "description": null,
            "value": null
          },
          "param_N": {
            "type": null,
            "description": null,
            "value": null
          }
        }
      }
    }
  ],
  "Individual Fields": {
    "name": "Participant Name",
    "channels selection": {
      "channels rejected": null,
      "channels selected": null
    },
    "classifier performance": {
      "accuracy": null,
      "AUC": null,
      "precision": null,
      "recall": null
    }
  },
  "Population Fields": {
    "name": "Participant Name",
    "Population database": null,
    "Population metrics": {
      "accuracy": null,
      "AUC": null,
      "precision": null,
      "recall": null
    }
  }
}

2. Motor imagery with EEGNetv4 deep learning model

{
  "BCI Model card version": "0.0.0.1",
  "Pipeline Name": "Cross-session motor imagery with deep learning EEGNet v4 model",
  "Pipeline Steps": [
    {
      "Step": "Generic",
      "Used": false,
      "From": null,
      "Function": null,
      "Description": null,
      "Details": null,
      "parameters": {
        "param_1": {
          "type": null,
          "description": null,
          "value": null
        },
        "param_2": {
          "type": null,
          "description": null,
          "value": null
        },
        "param_N": {
          "type": null,
          "description": null,
          "value": null
        }
      }
    },
    {
      "Step": "Resampling",
      "Used": false,
      "From": null,
      "Function": null,
      "Description": null,
      "Details": null,
      "parameters": {
        "param_1": {
          "type": null,
          "description": null,
          "value": null
        },
        "param_2": {
          "type": null,
          "description": null,
          "value": null
        },
        "param_N": {
          "type": null,
          "description": null,
          "value": null
        }
      }
    },
    {
      "Step": "Preprocessing",
      "Used": true,
      "From": "mne",
      "Function": "filter",
      "Description": "Bandpass filtering of the EEG data",
      "Details": null,
      "parameters": {
        "l_freq": {
          "type": "float",
          "description": "Lower frequency of the bandpass filter",
          "value": 4
        },
        "h_freq": {
          "type": "float",
          "description": "Higher frequency of the bandpass filter",
          "value": 100
        },
        "picks": {
          "type": "array",
          "description": "Channels to include",
          "value": [
            0,
            1,
            2,
            3,
            4,
            5,
            6,
            7,
            8,
            9,
            10,
            11,
            12,
            13,
            14,
            15,
            16,
            17,
            18,
            19,
            20,
            21
          ]
        },
        "method": {
          "type": "string",
          "description": "Method used for filtering",
          "value": "iir"
        },
        "iir_params": {
          "type": "dict",
          "description": "Parameters for IIR filter",
          "value": {
            "order": 4,
            "ftype": "butter",
            "output": "sos"
          }
        }
      }
    },
    {
      "Step": "Feature selection",
      "Used": false,
      "From": null,
      "Function": null,
      "Description": null,
      "Details": null,
      "parameters": {
        "param_1": {
          "type": null,
          "description": null,
          "value": null
        },
        "param_2": {
          "type": null,
          "description": null,
          "value": null
        },
        "param_N": {
          "type": null,
          "description": null,
          "value": null
        }
      }
    },
    {
      "Step": "Channel selection",
      "Used": false,
      "From": null,
      "Function": null,
      "Description": null,
      "Details": null,
      "parameters": {
        "param_1": {
          "type": null,
          "description": null,
          "value": null
        },
        "param_2": {
          "type": null,
          "description": null,
          "value": null
        },
        "param_N": {
          "type": null,
          "description": null,
          "value": null
        }
      }
    },
    {
      "Step": "Spatial filtering",
      "Used": false,
      "From": null,
      "Function": null,
      "Description": null,
      "Details": null,
      "parameters": {
        "param_1": {
          "type": null,
          "description": null,
          "value": null
        },
        "param_2": {
          "type": null,
          "description": null,
          "value": null
        },
        "param_N": {
          "type": null,
          "description": null,
          "value": null
        }
      }
    },
    {
      "Step": "Classification",
      "Used": true,
      "From": "braindecode.classification",
      "Function": "EEGClassifier",
      "Description": "EEG classification using EEGNet v4 model",
      "Details": "The model is trained using a cross-session evaluation procedure",
      "parameters": {
        "Model architecture": {
          "module": {
            "type": "class",
            "description": "Neural network architecture",
            "value": "EEGNetv4"
          }
        },
        "Hyperparameters": {
          "optimizer": {
            "type": "class",
            "description": "Optimizer used for training",
            "value": "torch.optim.Adam"
          },
          "optimizer__lr": {
            "type": "float",
            "description": "Learning rate for the optimizer",
            "value": 0.000625
          },
          "batch_size": {
            "type": "int",
            "description": "Batch size for training",
            "value": 64
          },
          "max_epochs": {
            "type": "int",
            "description": "Maximum number of epochs for training",
            "value": 10
          },
          "train_split": {
            "type": "class",
            "description": "Validation split strategy",
            "value": "ValidSplit(0.2, random_state=42)"
          },
          "device": {
            "type": "string",
            "description": "Device used for training",
            "value": "cuda"
          },
          "callbacks": {
            "type": "list",
            "description": "Callbacks used during training",
            "value": [
              "EarlyStopping(monitor='valid_loss', patience=3)",
              "EpochScoring(scoring='accuracy', on_train=True, name='train_acc', lower_is_better=False)",
              "EpochScoring(scoring='accuracy', on_train=False, name='valid_acc', lower_is_better=False)"
            ]
          }
        },
        "Training parameters": {
          "seed": {
            "type": "int",
            "description": "Random seed for reproducibility",
            "value": 42
          }
        }
      }
    }
  ],
  "Individual Fields": {
    "name": "Participant Name",
    "channels selection": {
      "channels rejected": null,
      "channels selected": null
    },
    "classifier performance": {
      "accuracy": null,
      "AUC": null,
      "precision": null,
      "recall": null
    }
  },
  "Population Fields": {
    "name": "Participant Name",
    "Population database": null,
    "Population metrics": {
      "accuracy": null,
      "AUC": null,
      "precision": null,
      "recall": null
    }
  }
}