11import os
22import sys
3+ import argparse
34import traceback
45
56import numpy as np
67import scipy .stats as stats
78
89try :
910 os .environ ['TF_CPP_MIN_LOG_LEVEL' ] = '2'
10-
1111 import tensorflow as tf
1212
1313 from cnsd import Dataset
1414 from cnsd .diagnosis .system import CNSD
1515 from cnsd .perception .cnn import _train_cnn
16- from cnsd .physics import PhysicsConfig
17- from validate_pu import load_pu_domain_split
18-
19- print ('Loading Authentic PU dataset (Cross-Domain RPM Split)...' )
20- (X_train_full , y_train_full , cond_train_full ), (X_target , y_target , cond_target ) = (
21- load_pu_domain_split ()
22- )
23-
24- unique_rpm = set (cond_train_full ).union (set (cond_target ))
25- rpm_map = {float (r ): float (r ) for r in unique_rpm }
26- pu_physics = PhysicsConfig (
27- bearing = {'n_balls' : 8 , 'd_ball' : 6.75 , 'd_pitch' : 28.5 , 'contact_angle' : 0.0 },
28- cond_to_rpm = rpm_map ,
29- fs = 64000 ,
30- name = 'PU-6203' ,
31- )
32- pu_taxonomy = {
33- 0 : ('Normal' , 'None' ),
34- 1 : ('Outer Race' , 'Medium' ),
35- 2 : ('Inner Race' , 'High' ),
36- }
16+
17+ # Argparse
18+ parser = argparse .ArgumentParser ()
19+ parser .add_argument ('--dataset' , type = str , required = True , choices = ['cwru' , 'pu' , 'xjtusy' ])
20+ args = parser .parse_args ()
21+
22+ print (f'Loading { args .dataset .upper ()} dataset...' )
23+
24+ if args .dataset == 'pu' :
25+ from cnsd .physics import PhysicsConfig
26+ from validate_pu import load_pu_domain_split
27+ (X_train_full , y_train_full , cond_train_full ), (X_target , y_target , cond_target ) = load_pu_domain_split ()
28+ unique_rpm = set (cond_train_full ).union (set (cond_target ))
29+ rpm_map = {float (r ): float (r ) for r in unique_rpm }
30+ physics = PhysicsConfig (
31+ bearing = {'n_balls' : 8 , 'd_ball' : 6.75 , 'd_pitch' : 28.5 , 'contact_angle' : 0.0 },
32+ cond_to_rpm = rpm_map ,
33+ fs = 64000 ,
34+ name = 'PU-6203' ,
35+ )
36+ taxonomy = {0 : ('Normal' , 'None' ), 1 : ('Outer Race' , 'Medium' ), 2 : ('Inner Race' , 'High' )}
37+ fs = 64000
38+
39+ elif args .dataset == 'cwru' :
40+ from validate_run import load_cwru , CWRU , TAXONOMY
41+ X , y , cond = load_cwru ()
42+ X = np .asarray (X , np .float32 )
43+ y = np .asarray (y )
44+ cond = np .asarray (cond )
45+
46+ train_mask = cond < 3
47+ target_mask = cond == 3
48+
49+ X_train_full = X [train_mask ]
50+ y_train_full = y [train_mask ]
51+ cond_train_full = cond [train_mask ]
52+
53+ X_target = X [target_mask ]
54+ y_target = y [target_mask ]
55+ cond_target = cond [target_mask ]
56+
57+ physics = CWRU
58+ taxonomy = TAXONOMY
59+ fs = 12000
60+
61+ elif args .dataset == 'xjtusy' :
62+ from cnsd .datasets .xjtusy import load_xjtusy_domain_split
63+ from cnsd .physics .configs import XJTUSY_PHYSICS
64+ train_ds , target_ds = load_xjtusy_domain_split (window_size = 4096 )
65+
66+ X_train_full = train_ds .X
67+ y_train_full = train_ds .y
68+ cond_train_full = train_ds .cond
69+
70+ X_target = target_ds .X
71+ y_target = target_ds .y
72+ cond_target = target_ds .cond
73+
74+ physics = target_ds .physics
75+ taxonomy = target_ds .taxonomy
76+ fs = target_ds .fs
3777
3878 def get_matched_coverage_gap (score , correct , target_n ):
3979 if target_n == 0 :
4080 return float ('nan' )
4181 # Score is higher for MORE confident
42- # Sort descending by score
4382 sorted_indices = np .argsort (score )[::- 1 ]
4483 hi_indices = sorted_indices [:target_n ]
4584
@@ -73,13 +112,8 @@ def clone_for_mc(layer):
73112
74113 # Test data processing
75114 test_ds = Dataset .from_arrays (
76- X_target ,
77- y_target ,
78- cond_target ,
79- fs = 64000 ,
80- physics = pu_physics ,
81- taxonomy = pu_taxonomy ,
82- name = 'PU_Test' ,
115+ X_target , y_target , cond_target ,
116+ fs = fs , physics = physics , taxonomy = taxonomy , name = f'{ args .dataset .upper ()} _Test'
83117 )
84118 sig_te = np .stack ([test_ds .X [i ].reshape (- 1 ) for i in range (len (test_ds .X ))]).astype (np .float32 )
85119 yte = test_ds .y
@@ -100,22 +134,14 @@ def clone_for_mc(layer):
100134 train_idx = indices [:split_idx ]
101135 calib_idx = indices [split_idx :]
102136
103- X_tr , y_tr , cond_tr = (
104- X_train_full [train_idx ],
105- y_train_full [train_idx ],
106- cond_train_full [train_idx ],
107- )
108- X_ca , y_ca , cond_ca = (
109- X_train_full [calib_idx ],
110- y_train_full [calib_idx ],
111- cond_train_full [calib_idx ],
112- )
137+ X_tr , y_tr , cond_tr = X_train_full [train_idx ], y_train_full [train_idx ], cond_train_full [train_idx ]
138+ X_ca , y_ca , cond_ca = X_train_full [calib_idx ], y_train_full [calib_idx ], cond_train_full [calib_idx ]
113139
114140 train_ds = Dataset .from_arrays (
115- X_tr , y_tr , cond_tr , fs = 64000 , physics = pu_physics , taxonomy = pu_taxonomy , name = 'PU_Train '
141+ X_tr , y_tr , cond_tr , fs = fs , physics = physics , taxonomy = taxonomy , name = f' { args . dataset . upper () } _Train '
116142 )
117143 calib_ds = Dataset .from_arrays (
118- X_ca , y_ca , cond_ca , fs = 64000 , physics = pu_physics , taxonomy = pu_taxonomy , name = 'PU_Calib '
144+ X_ca , y_ca , cond_ca , fs = fs , physics = physics , taxonomy = taxonomy , name = f' { args . dataset . upper () } _Calib '
119145 )
120146
121147 # 2. Train Primary Model (Bypass SCM to prevent multiprocess deadlocks)
@@ -135,9 +161,7 @@ def clone_for_mc(layer):
135161 ens .append (m_cnn )
136162
137163 # 4. Calibrate Tau
138- sig_ca = np .stack ([calib_ds .X [i ].reshape (- 1 ) for i in range (len (calib_ds .X ))]).astype (
139- np .float32
140- )
164+ sig_ca = np .stack ([calib_ds .X [i ].reshape (- 1 ) for i in range (len (calib_ds .X ))]).astype (np .float32 )
141165 Xin_ca = sig_ca [..., None ]
142166 probs_ca = model .cnn .predict (Xin_ca , batch_size = 128 , verbose = 0 )
143167 pred_ca = probs_ca .argmax (1 )
@@ -148,10 +172,7 @@ def clone_for_mc(layer):
148172 for tau in [1.0 , 1.5 , 2.0 , 2.5 , 3.0 ]:
149173 model .symbolic .tau = float (tau )
150174 verds = np .array (
151- [
152- model .symbolic .diagnose (sig_ca [i ], pred_ca [i ], calib_ds .cond [i ])['verdict' ]
153- for i in range (len (sig_ca ))
154- ]
175+ [model .symbolic .diagnose (sig_ca [i ], pred_ca [i ], calib_ds .cond [i ])['verdict' ] for i in range (len (sig_ca ))]
155176 )
156177 conf = verds == 'CONFIRMED'
157178 cnfl = verds == 'CONFLICT'
@@ -172,10 +193,7 @@ def clone_for_mc(layer):
172193
173194 # Physics evaluation
174195 verds = np .array (
175- [
176- model .symbolic .diagnose (sig_te [i ], pred_te [i ], cond_te [i ])['verdict' ]
177- for i in range (len (sig_te ))
178- ]
196+ [model .symbolic .diagnose (sig_te [i ], pred_te [i ], cond_te [i ])['verdict' ] for i in range (len (sig_te ))]
179197 )
180198 conf = verds == 'CONFIRMED'
181199 cnfl = verds == 'CONFLICT'
@@ -209,20 +227,15 @@ def clone_for_mc(layer):
209227 results ['mc_gap' ].append (mc_gap )
210228
211229 # Ensemble at matched coverage
212- ens_preds_probs = np .stack (
213- [m .predict (Xin_te , batch_size = 128 , verbose = 0 ) for m in ens ]
214- ) # (3, n, c)
215- ens_mean = ens_preds_probs .mean (0 ) # (n, c)
230+ ens_preds_probs = np .stack ([m .predict (Xin_te , batch_size = 128 , verbose = 0 ) for m in ens ])
231+ ens_mean = ens_preds_probs .mean (0 )
216232 ens_pred_class = ens_mean .argmax (1 )
217233 ens_correct = ens_pred_class == yte
218- # Score = negative entropy of ensemble mean
219234 ens_score = (ens_mean * np .log (ens_mean + eps )).sum (1 )
220235 ens_gap = get_matched_coverage_gap (ens_score , ens_correct , target_n )
221236 results ['ens_gap' ].append (ens_gap )
222237
223- print (
224- f'Matched Coverage GAPs -> Softmax:{ soft_gap :+.3f} | MC-Drop:{ mc_gap :+.3f} | Ens:{ ens_gap :+.3f} '
225- )
238+ print (f'Matched Coverage GAPs -> Softmax:{ soft_gap :+.3f} | MC-Drop:{ mc_gap :+.3f} | Ens:{ ens_gap :+.3f} ' )
226239
227240 # 6. Noise Test
228241 rng = np .random .RandomState (seed )
@@ -235,19 +248,13 @@ def clone_for_mc(layer):
235248 sig_n = sig_te + rng .randn (* sig_te .shape ).astype (np .float32 ) * np .sqrt (npow )
236249
237250 Xin_n = sig_n [..., None ]
238- # Use ensemble mode vote to define 'unanimous' exactly like Abhi's template
239- ep_class = np .stack (
240- [m .predict (Xin_n , batch_size = 128 , verbose = 0 ).argmax (1 ) for m in ens ]
241- )
251+ ep_class = np .stack ([m .predict (Xin_n , batch_size = 128 , verbose = 0 ).argmax (1 ) for m in ens ])
242252 v = stats .mode (ep_class , axis = 0 , keepdims = False ).mode
243253 unan = (ep_class == v ).all (0 )
244254 ok = v == yte
245255
246256 pv = np .array (
247- [
248- model .symbolic .diagnose (sig_n [i ], v [i ], cond_te [i ])['verdict' ]
249- for i in range (len (sig_n ))
250- ]
257+ [model .symbolic .diagnose (sig_n [i ], v [i ], cond_te [i ])['verdict' ] for i in range (len (sig_n ))]
251258 )
252259 pc = pv == 'CONFLICT'
253260 uw = unan & (~ ok )
@@ -257,16 +264,10 @@ def clone_for_mc(layer):
257264 print (f' Noise={ s :>5} | catch_rate={ catch :.3f} ' )
258265
259266 print ('\n ' + '=' * 60 + f'\n FINAL AGGREGATED RESULTS ({ len (seeds )} Seeds)\n ' + '=' * 60 )
260- print (
261- f'Physics GAP: { np .nanmean (results ["phys_gap" ]):+.3f} ± { np .nanstd (results ["phys_gap" ]):.3f} '
262- )
263- print (
264- f'Softmax GAP: { np .nanmean (results ["soft_gap" ]):+.3f} ± { np .nanstd (results ["soft_gap" ]):.3f} '
265- )
267+ print (f'Physics GAP: { np .nanmean (results ["phys_gap" ]):+.3f} ± { np .nanstd (results ["phys_gap" ]):.3f} ' )
268+ print (f'Softmax GAP: { np .nanmean (results ["soft_gap" ]):+.3f} ± { np .nanstd (results ["soft_gap" ]):.3f} ' )
266269 print (f'MC-Drop GAP: { np .nanmean (results ["mc_gap" ]):+.3f} ± { np .nanstd (results ["mc_gap" ]):.3f} ' )
267- print (
268- f'Ensemble GAP: { np .nanmean (results ["ens_gap" ]):+.3f} ± { np .nanstd (results ["ens_gap" ]):.3f} '
269- )
270+ print (f'Ensemble GAP: { np .nanmean (results ["ens_gap" ]):+.3f} ± { np .nanstd (results ["ens_gap" ]):.3f} ' )
270271
271272 t_stat , p_val = stats .ttest_rel (results ['phys_gap' ], results ['ens_gap' ])
272273 avg_ncov = np .mean (results ['ncov' ])
0 commit comments