fooof icon indicating copy to clipboard operation
fooof copied to clipboard

General Questions on Fixing Model Overfit

Open RADAXE opened this issue 7 months ago • 1 comments

Hello!

I have been tasked with implementing a FOOOF function within our EEG processing pipeline; specifically, we are analyzing alpha waves in occipital electrodes. I am a novice coder and new to working within Python and had some questions regarding working with FOOOF.

Specifically, how best to adapt FOOOFs settings to fit our data; presently, I believe the model is overfitting our data based on high R2 of the model fit (>0.98), and low error of the model fit (<0.04) in addition to a high number of peaks detected within very close proximity. I believe this is indicative of the model fitting small fluctuations whether due to noise, or just small bumps present in the data. Additionally, I am wondering if I would be better served to fit the model with a knee, I had decided not based on the small range of frequencies with which I am fitting the data (1 - 45 Hz), and when I do fit with a knee, the outputs are strange and hard to interpret.

I have reviewed the tutorial on fitting the aperiodic model (tutorial #5) and tuning & troubleshooting (tutorial #7) and have adjusted some of the model parameters (limiting peaks, peak width, and minimum peak height) but have stalled in my progress.

Any additional help you may have to offer would be greatly appreciated!

See some code below and snippets of output for reference:

## Run Initial FOOOF Model on a single Epoched File

import mne import numpy as np import matplotlib.pyplot as plt from fooof import FOOOF from fooof.plts.spectra import plot_spectra from fooof.plts.annotate import plot_annotated_model

def run_fixed_fooof(filepath, channel='Oz', fmin=1, fmax=100, fit_range=[1, 45], mode='fixed', plot=True, plot_annotated_fx=False, return_model=True): """ Run FOOOF analysis on a single epoched EEG file.

Parameters:
- filepath : str
    Path to the MNE epochs .fif file
- channel : str
    EEG channel to analyze (e.g., 'Oz')
- fmin, fmax : float
    Frequency range for computing PSD
- fit_range : list of two floats
    Frequency range to fit FOOOF model
- mode : 'fixed' or 'knee'
    Type of FOOOF aperiodic model
- plot : bool
    Whether to plot the spectrum and model
- return_model : bool
    Whether to return the FOOOF model or just the parameters

Returns:
- model : FOOOF object (optional)
- results : dict of model parameters
"""

# Load epoched data
epochs = mne.read_epochs(filepath, preload=True)

# Pick channel if specified
if channel:
    epochs.pick_channels([channel])

# Compute PSD
psd = epochs.compute_psd(method='welch', fmin=fmin, fmax=fmax, n_fft=350)
freqs = psd.freqs
spectrum = psd.get_data().mean(axis=0).mean(axis=0)

# Fit FOOOF model
fm = FOOOF(aperiodic_mode=mode, peak_width_limits=[1.5, 6],
           min_peak_height=0.15, max_n_peaks=6)
fm.fit(freqs, spectrum, fit_range)

if plot:
    fm.plot(plt_log=True)

if plot_annotated_fx:
    plot_annotated_model(fm, plt_log=True)

results = {
    'aperiodic_params': fm.aperiodic_params_,
    'peak_params': fm.peak_params_,
    'r_squared': fm.r_squared_,
    'error': fm.error_,
    'linear_powers': [10**pw for _, pw, _ in fm.peak_params_],
    'fm.print_results()': fm.print_results(),
}

return (fm, results) if return_model else `results`

Image Image Image

Thanks so much!

RADAXE avatar Jun 24 '25 09:06 RADAXE

That doesn't exactly look like overfitting. R**2 tend to be quite high.

But have you looked at our tuning and troubleshooting guide?

https://fooof-tools.github.io/fooof/auto_tutorials/plot_07-TroubleShooting.html#sphx-glr-auto-tutorials-plot-07-troubleshooting-py

voytek avatar Jun 24 '25 17:06 voytek