File size: 3,820 Bytes
17b6eea e76e0a5 d44a21f 17b6eea d44a21f 2021001 d44a21f 2021001 d44a21f 2021001 d44a21f 2021001 d44a21f 17b6eea d44a21f 2021001 17b6eea e76e0a5 2021001 e76e0a5 17b6eea e76e0a5 2021001 17b6eea 2021001 17b6eea e76e0a5 2021001 17b6eea e76e0a5 2021001 e76e0a5 2021001 e76e0a5 2021001 e76e0a5 2021001 e76e0a5 2021001 17b6eea | 1 2 3 4 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 98 99 100 101 102 103 104 105 | import gradio as gr
import torch
import torch.nn as nn
import numpy as np
import joblib
# 1. MODEL ARCHITECTURE (BHI_Net)
class BHI_Net(nn.Module):
def __init__(self, num_classes=6, channels=19, samples=2500):
super(BHI_Net, self).__init__()
self.conv_block = nn.Sequential(
nn.Conv1d(channels, 32, kernel_size=15, stride=1, padding=7),
nn.BatchNorm1d(32), nn.ReLU(), nn.MaxPool1d(2),
nn.Conv1d(32, 64, kernel_size=15, stride=1, padding=7),
nn.BatchNorm1d(64), nn.ReLU(), nn.MaxPool1d(2),
nn.Conv1d(64, 128, kernel_size=15, stride=1, padding=7),
nn.BatchNorm1d(128), nn.ReLU(), nn.MaxPool1d(4)
)
self.avgpool = nn.AdaptiveAvgPool1d(10)
self.classifier = nn.Sequential(
nn.Linear(128 * 10, 256), nn.ReLU(), nn.Dropout(0.5),
nn.Linear(256, num_classes)
)
def forward(self, x):
x = self.conv_block(x)
x = self.avgpool(x)
x = torch.flatten(x, 1)
return self.classifier(x)
# 2. LOAD ASSETS
device = torch.device("cpu")
label_names = ["Healthy", "Alzheimers", "Parkinsons", "Epilepsy", "Depression", "Anxiety"]
# Load Models
model_n = BHI_Net(num_classes=4)
model_n.load_state_dict(torch.load('neuro_best_model.pth', map_location=device))
model_n.eval()
model_m = BHI_Net(num_classes=3)
model_m.load_state_dict(torch.load('mental_best_model.pth', map_location=device))
model_m.eval()
# Load Data and Scalers
X_data = np.load('X_master.npy', mmap_mode='r')
Y_data = np.load('Y_master.npy')
n_test_idx = np.load('neuro_unseen_indices.npy')
m_test_idx = np.load('mental_unseen_indices.npy')
n_scaler = joblib.load('neuro_platt_scaler.pkl')
m_scaler = joblib.load('mental_platt_scaler.pkl')
# Recreate Test Indices (Logic from your notebook)
mental_mask = (Y_data == 0) | (Y_data == 4) | (Y_data == 5)
global_mental_indices = np.where(mental_mask)[0][m_test_idx]
all_test_indices = np.unique(np.concatenate([n_test_idx, global_mental_indices]))
# 3. DIAGNOSTIC FUNCTION
def get_preloaded_diagnosis(patient_id):
idx = int(patient_id)
input_tensor = torch.from_numpy(X_data[idx]).float().unsqueeze(0)
actual_label = label_names[Y_data[idx]]
with torch.no_grad():
n_logits = model_n(input_tensor).numpy()
n_probs = n_scaler.predict_proba(n_logits)[0]
m_logits = model_m(input_tensor).numpy()
m_probs = m_scaler.predict_proba(m_logits)[0]
# Consensus Logic (Matching your notebook)
STUCK_THRESHOLD = 0.305
DISEASE_BOOST = 1.4
if n_probs[3] > 0.85:
diag, conf = "Epilepsy", n_probs[3] * 100
elif n_probs[1] < STUCK_THRESHOLD and n_probs[0] < 0.5:
m_idx = np.argmax(m_probs)
diag = ["Healthy", "Depression", "Anxiety"][m_idx]
conf = m_probs[m_idx] * 100
else:
n_probs[1:3] *= DISEASE_BOOST
n_idx = np.argmax(n_probs)
diag = ["Healthy", "Alzheimers", "Parkinsons", "Epilepsy"][n_idx]
conf = n_probs[n_idx] * 100
result_emoji = "✅ CORRECT" if diag == actual_label else "❌ INCORRECT"
report = f"🏥 CLINICAL EEG DIAGNOSTIC SUMMARY\n"
report += "="*45 + "\n"
report += f"PATIENT ID : {idx}\n"
report += f"ACTUAL DIAGNOSIS: {actual_label}\n"
report += f"AI PREDICTION : {diag} ({conf:.1f}%)\n"
report += f"RESULT : {result_emoji}\n"
report += "="*45
return report
# 4. INTERFACE
demo = gr.Interface(
fn=get_preloaded_diagnosis,
inputs=gr.Dropdown(choices=[str(i) for i in all_test_indices], label="Select Patient from Study"),
outputs=gr.Textbox(label="Clinical Report", lines=10),
title="Clinical EEG Specialist AI",
description="Select a Patient ID from the unseen test set to view the AI's diagnostic summary."
)
demo.launch() |