MorganBrizon commited on
Commit
5c2024a
·
verified ·
1 Parent(s): ec8fb2d

Delete prediction.py

Browse files
Files changed (1) hide show
  1. prediction.py +0 -261
prediction.py DELETED
@@ -1,261 +0,0 @@
1
- import numpy as np
2
- import torch
3
- import tensorflow as tf
4
- import pandas as pd
5
- import joblib
6
- from sklearn.metrics import confusion_matrix, f1_score, accuracy_score
7
- from preprocessing import preprocess_eeg_file
8
- from preprocessing_2dcnn import convert_epoch_to_spectrogram
9
- from preprocessing_epilepsynet import *
10
- from EpilepsyNet_model import TimeSeriesAttentionClassifier
11
- from eegnet_model import EEGNet
12
-
13
-
14
-
15
- def aggregate_predictions(spectrogram_list, model, threshold=0.5):
16
-
17
- # Convert each spectrogram to channels-last format.
18
- X = np.array([np.transpose(s, (1, 2, 0)) for s in spectrogram_list])
19
- print(f'---Aggregating predictions from {len(spectrogram_list)} segments---')
20
- preds = model.predict(X)
21
- mean_prob = np.mean(preds[:, 1])
22
- final_label = 1 if mean_prob >= threshold else 0
23
- return final_label, mean_prob
24
-
25
- def predict_eeg_recording(edf_path, model_name='2DCNN', threshold=0.5):
26
-
27
-
28
- if model_name == '2DCNN':
29
-
30
- model = tf.keras.models.load_model('model1_2dcnn.h5')
31
- channels = ["EEG FP1-REF", "EEG FP2-REF", "EEG F3-REF", "EEG F4-REF", "EEG C3-REF"]
32
- #Process the edf file
33
- preprocessed_df = preprocess_eeg_file(edf_path, fmin=1.0, fmax=45.0, segment_lenght=5, overlap=2,desired=channels)
34
-
35
- if preprocessed_df is None or preprocessed_df.empty:
36
- raise ValueError("EEG file could not be preprocessed or no valid segments found.")
37
-
38
- # Convert each 5-second segment (each row) into a spectrogram.
39
- spectrogram_list = preprocessed_df.apply(
40
- lambda row: convert_epoch_to_spectrogram(row, channels, fs=250, nperseg=128, noverlap=64), axis=1
41
- ).tolist()
42
-
43
- return aggregate_predictions(spectrogram_list, model, threshold)
44
-
45
- elif model_name == 'EEGNet':
46
- loaded = joblib.load("eegnet_model.joblib")
47
- # Extract the actual state dictionary.
48
- state_dict = loaded["model_state_dict"]
49
-
50
- model = EEGNet(n_channels=21, n_samples=1250, num_classes=2)
51
- model.load_state_dict(state_dict)
52
-
53
- # Define the channels to use for EEGNet
54
- channels = [
55
- 'EEG FP1-REF', # Left frontal pole
56
- 'EEG FP2-REF', # Right frontal pole
57
- 'EEG F3-REF', # Left frontal
58
- 'EEG F4-REF', # Right frontal
59
- 'EEG C3-REF', # Left central
60
- 'EEG C4-REF', # Right central
61
- 'EEG P3-REF', # Left parietal
62
- 'EEG P4-REF', # Right parietal
63
- 'EEG O1-REF', # Left occipital
64
- 'EEG O2-REF', # Right occipital
65
- 'EEG F7-REF', # Left lateral frontal
66
- 'EEG F8-REF', # Right lateral frontal
67
- 'EEG T3-REF', # Left temporal (anterior)
68
- 'EEG T4-REF', # Right temporal (anterior)
69
- 'EEG T5-REF', # Left temporal (posterior)
70
- 'EEG T6-REF', # Right temporal (posterior)
71
- 'EEG FZ-REF', # Frontal midline
72
- 'EEG CZ-REF', # Central midline
73
- 'EEG PZ-REF', # Parietal midline
74
- 'EEG ROC-REF', # Right occipital (often used as reference or an extra site)
75
- 'EEG LOC-REF' # Left occipital (often used as reference or an extra site)
76
- ]
77
- # Process the edf file
78
- preprocessed_df = preprocess_eeg_file(
79
- edf_path, fmin=1.0, fmax=45.0, segment_lenght=5, overlap=0, desired=channels
80
- )
81
-
82
- if preprocessed_df is None or preprocessed_df.empty:
83
- raise ValueError("EEG file could not be preprocessed or no valid segments found.")
84
-
85
- # For EEGNet, we use the raw time series data directly.
86
- # Convert each 5-second segment (row) to a 2D timeseries array of shape (n_channels, n_samples)
87
- timeseries_list = preprocessed_df.apply(
88
- lambda row: convert_epoch_to_timeseries(row, channels), axis=1
89
- ).tolist()
90
-
91
- return aggregate_predictions_EEGNET(timeseries_list, model, threshold)
92
-
93
- elif model_name == 'EpilepsyNet':
94
-
95
- raw = mne.io.read_raw_edf(edf_path,
96
- preload=True,
97
- verbose='ERROR')
98
-
99
- eeg_cols = ['EEG FP1', 'EEG FP2', 'EEG F3', 'EEG F4',
100
- 'EEG C3', 'EEG C4', 'EEG P3', 'EEG P4',
101
- 'EEG O1', 'EEG O2', 'EEG F7', 'EEG F8',
102
- 'EEG T3', 'EEG T4', 'EEG T5', 'EEG T6',
103
- 'EEG T1', 'EEG T2', 'EEG FZ', 'EEG CZ',
104
- 'EEG PZ']
105
-
106
- parameters = {
107
- 'eeg_cols':eeg_cols,
108
- 'segment_duration':60.0, # 60 second segments
109
- 'n_segments_per_file':12, # Split into 12 epochs (5 sec each)
110
- 'samples_per_segment':1250, # 1250 samples per segment (250 Hz sampling rate)
111
- 'random_state':42
112
- }
113
-
114
- X = process_raw_files(
115
- raw_file=raw,
116
- eeg_cols=eeg_cols,
117
- segment_duration=parameters['segment_duration'],
118
- n_segments_per_file=parameters['n_segments_per_file'],
119
- random_state=parameters['random_state']
120
- )
121
-
122
- X_std = standardize_data(X)
123
- corr_matrix = compute_correlation_matrix(X_std)
124
- # print('Correlation matrix shape :',corr_matrix.shape)
125
-
126
- upper_triangle_matrix = extract_upper_triangle(corr_matrix)
127
- # print('Upper Triangle shape :',upper_triangle_matrix.shape)
128
-
129
- X_tensor = torch.tensor(upper_triangle_matrix, dtype=torch.float32)
130
- X_tensor = X_tensor.unsqueeze(0)
131
-
132
- # Model parameters
133
- input_dim = 210 # Size of flattened upper triangle (21*20/2)
134
- embed_dim = 256 # Embedding dimension
135
- num_heads = 16 # Number of attention heads7
136
-
137
- model = TimeSeriesAttentionClassifier(input_dim, embed_dim, num_heads)
138
- model.load_state_dict(torch.load('EpilepsyNet.pth'))
139
- model.eval()
140
- print('¨'*50)
141
- print('Model Prediction :')
142
-
143
- outputs, _ = model(X_tensor)
144
- # For binary classification with sigmoid, prediction is 1 if output > 0.5
145
- predicted = (outputs >= 0.5).float()
146
-
147
- return int(predicted), outputs.float().squeeze().item()
148
-
149
-
150
- def convert_epoch_to_timeseries(epoch_row, channels):
151
-
152
- ts_list = []
153
- for ch in channels:
154
- # Check if the channel is in the epoch_row; if not, skip it.
155
- if ch in epoch_row:
156
- ts = epoch_row[ch]
157
- ts_list.append(ts)
158
- return np.stack(ts_list, axis=0)
159
-
160
-
161
- def aggregate_predictions_EEGNET(segment_list, model, threshold):
162
- """
163
- Given a list of segments (raw time series data for EEGNet) and a trained
164
- PyTorch model, predict on each segment and then aggregate the predictions.
165
-
166
- For each segment, the model returns a probability vector.
167
- This function averages the predicted probabilities across segments,
168
- and then compares the average probability for class 1 with the provided threshold
169
- to decide the final predicted class.
170
-
171
- Parameters:
172
- segment_list : list of numpy arrays
173
- Each element is a 2D numpy array with shape (n_channels, n_samples)
174
- representing one EEG segment.
175
- model : a trained PyTorch model that accepts input of shape
176
- (batch_size, n_channels, n_samples) and outputs probabilities (or logits) for each class.
177
- threshold : float
178
- The probability threshold to decide class 1.
179
-
180
- Returns:
181
- final_class : int
182
- The aggregated predicted class (0 or 1).
183
- """
184
- model.eval()
185
- preds = []
186
-
187
- with torch.no_grad():
188
- for seg in segment_list:
189
- # Convert the segment to a torch tensor (float32)
190
- # Expected shape: (n_channels, n_samples)
191
- seg_tensor = torch.tensor(seg, dtype=torch.float32)
192
- # Add a batch dimension -> shape: (1, 1, n_channels, n_samples)
193
- seg_tensor = seg_tensor.unsqueeze(0).unsqueeze(0)
194
-
195
- # Forward pass: get the model's output.
196
- # If your model returns logits, you may need to apply softmax.
197
- output = model(seg_tensor)
198
-
199
- # Check if the output is probabilities already or logits.
200
- # For safety, let's apply softmax to ensure we have probabilities.
201
- prob = torch.softmax(output, dim=1)[0].cpu().numpy()
202
-
203
- preds.append(prob)
204
-
205
- # Average the predictions over all segments
206
- avg_pred = np.mean(preds, axis=0)
207
- # For binary classification assume avg_pred[1] is the probability for class 1.
208
- final_class = int(avg_pred[1] >= threshold)
209
-
210
- return final_class, avg_pred[1]
211
-
212
-
213
-
214
- import numpy as np
215
-
216
- def predict_ensemble_eeg_recording(edf_path, ensemble_method, threshold=0.5):
217
- """
218
- The function aggregates the probability scalars from each model and then:
219
- - For soft voting (method="average"): averages the probabilities
220
- - For hard voting (method="voting"): uses majority voting (each model votes 1 if
221
- its probability is >= threshold, else 0)
222
-
223
- Parameters:
224
- edf_path : str
225
- Path to the EEG EDF file.
226
- ensemble_method : str
227
- Aggregation method, either "average" for soft voting or "voting" for hard voting.
228
- threshold : float, default=0.5
229
- The probability threshold to decide class 1.
230
-
231
- Returns:
232
- final_class : int
233
- The final aggregated predicted class (0 or 1).
234
- aggregated : float or list
235
- For "average", the average probability as a float;
236
- for "voting", the list of votes from each model.
237
- """
238
- # Lists to collect probabilities and votes.
239
- pred_prob_list = []
240
- votes = []
241
-
242
- # Iterate over the three model types.
243
- for model_name in ["2DCNN", "EEGNet", "EpilepsyNet"]:
244
- pred_label, prob = predict_eeg_recording(edf_path, model_name=model_name, threshold=threshold)
245
- pred_prob_list.append(prob)
246
- votes.append(int(prob >= threshold))
247
- print(f"Prediction from {model_name}: label={pred_label}, probability={prob}")
248
-
249
- if ensemble_method.lower() == "average":
250
- # Soft voting: average the probabilities.
251
- avg_prob = np.mean(pred_prob_list)
252
- final_class = int(avg_prob >= threshold)
253
- print("Averaged probability:", avg_prob)
254
- return final_class, avg_prob
255
- elif ensemble_method.lower() == "voting":
256
- # Hard voting: majority decision.
257
- final_class = int(round(np.mean(votes)))
258
- print("Votes from each model:", votes)
259
- return final_class, votes
260
- else:
261
- raise ValueError("Ensemble method must be either 'average' or 'voting'.")