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()