1- import os
21import glob
2+ import os
3+
34import numpy as np
45import scipy .io as sio
56
67from cnsd import Dataset
78from cnsd .diagnosis .system import CNSD
89from cnsd .physics import PhysicsConfig
910
10- def load_pu_domain_split (data_dir = r"E:\301\PU-dataset" , window_size = 8192 ):
11+
12+ def load_pu_domain_split (data_dir = r'E:\301\PU-dataset' , window_size = 8192 ):
1113 """
1214 Loads authentic PU dataset and strictly splits by RPM (Domain Shift).
1315 Train: N09 (900 RPM)
1416 Test/Calib: N15 (1500 RPM)
1517 """
1618 X_train , y_train , cond_train = [], [], []
1719 X_target , y_target , cond_target = [], [], []
18-
19- categories = [(" K0*" , 0 ), (" KA*" , 1 ), (" KI*" , 2 )]
20-
20+
21+ categories = [(' K0*' , 0 ), (' KA*' , 1 ), (' KI*' , 2 )]
22+
2123 for prefix , label in categories :
22- pattern = os .path .join (data_dir , prefix , " *.mat" )
24+ pattern = os .path .join (data_dir , prefix , ' *.mat' )
2325 files = glob .glob (pattern )
2426 for fpath in files :
2527 fname = os .path .basename (fpath )
2628 key = fname .replace ('.mat' , '' )
27-
29+
2830 rpm_code = fname .split ('_' )[0 ]
2931 if rpm_code == 'N09' :
3032 rpm = 900.0
@@ -33,30 +35,30 @@ def load_pu_domain_split(data_dir=r"E:\301\PU-dataset", window_size=8192):
3335 rpm = 1500.0
3436 is_train = False
3537 else :
36- continue # ignore other speeds if they exist
37-
38+ continue # ignore other speeds if they exist
39+
3840 try :
3941 mat = sio .loadmat (fpath )
4042 if key not in mat :
4143 continue
42-
43- y_struct = mat [key ]['Y' ][0 ,0 ]
44-
44+
45+ y_struct = mat [key ]['Y' ][0 , 0 ]
46+
4547 vib_idx = - 1
4648 for i in range (y_struct ['Name' ].shape [1 ]):
47- if 'vibration' in str (y_struct ['Name' ][0 ,i ][0 ]).lower ():
49+ if 'vibration' in str (y_struct ['Name' ][0 , i ][0 ]).lower ():
4850 vib_idx = i
4951 break
50-
52+
5153 if vib_idx == - 1 :
5254 continue
53-
54- sig = y_struct ['Data' ][0 ,vib_idx ].flatten ()
55-
55+
56+ sig = y_struct ['Data' ][0 , vib_idx ].flatten ()
57+
5658 for i in range (0 , len (sig ) - window_size , window_size ):
57- segment = sig [i : i + window_size ]
59+ segment = sig [i : i + window_size ]
5860 segment = (segment - np .mean (segment )) / (np .std (segment ) + 1e-8 )
59-
61+
6062 if is_train :
6163 X_train .append (segment )
6264 y_train .append (label )
@@ -65,12 +67,16 @@ def load_pu_domain_split(data_dir=r"E:\301\PU-dataset", window_size=8192):
6567 X_target .append (segment )
6668 y_target .append (label )
6769 cond_target .append (rpm )
68-
70+
6971 except Exception as e :
70- print (f"Error loading { fname } : { e } " )
71-
72- return (np .array (X_train , dtype = np .float32 ), np .array (y_train ), np .array (cond_train )), \
73- (np .array (X_target , dtype = np .float32 ), np .array (y_target ), np .array (cond_target ))
72+ print (f'Error loading { fname } : { e } ' )
73+
74+ return (np .array (X_train , dtype = np .float32 ), np .array (y_train ), np .array (cond_train )), (
75+ np .array (X_target , dtype = np .float32 ),
76+ np .array (y_target ),
77+ np .array (cond_target ),
78+ )
79+
7480
7581def headline_accuracy_by_verdict (report , y_true ):
7682 pred = np .array ([r ['predicted_class' ] for r in report .records ])
@@ -83,95 +89,132 @@ def headline_accuracy_by_verdict(report, y_true):
8389 out [v ] = {'n' : int (m .sum ()), 'cnn_accuracy' : float (correct [m ].mean ())}
8490 return out
8591
86- if __name__ == "__main__" :
87- print ("Loading Authentic PU dataset (Cross-Domain RPM Split)..." )
92+
93+ if __name__ == '__main__' :
94+ print ('Loading Authentic PU dataset (Cross-Domain RPM Split)...' )
8895 (X_train , y_train , cond_train ), (X_target , y_target , cond_target ) = load_pu_domain_split ()
89-
96+
9097 # Split target domain into Calib (50%) and Test (50%)
9198 indices = np .arange (len (y_target ))
9299 np .random .shuffle (indices )
93100 calib_size = len (indices ) // 2
94-
101+
95102 calib_idx = indices [:calib_size ]
96103 test_idx = indices [calib_size :]
97-
104+
98105 X_calib , y_calib , cond_calib = X_target [calib_idx ], y_target [calib_idx ], cond_target [calib_idx ]
99106 X_test , y_test , cond_test = X_target [test_idx ], y_target [test_idx ], cond_target [test_idx ]
100-
107+
101108 # Shuffle train set
102109 train_indices = np .arange (len (y_train ))
103110 np .random .shuffle (train_indices )
104- X_train , y_train , cond_train = X_train [train_indices ], y_train [train_indices ], cond_train [train_indices ]
105-
106- print (f"Data split: Train (900 RPM)={ len (y_train )} | Calib (1500 RPM)={ len (y_calib )} | Test (1500 RPM)={ len (y_test )} " )
107-
111+ X_train , y_train , cond_train = (
112+ X_train [train_indices ],
113+ y_train [train_indices ],
114+ cond_train [train_indices ],
115+ )
116+
117+ print (
118+ f'Data split: Train (900 RPM)={ len (y_train )} | Calib (1500 RPM)={ len (y_calib )} | Test (1500 RPM)={ len (y_test )} '
119+ )
120+
108121 unique_rpm = set (cond_train ).union (set (cond_calib )).union (set (cond_test ))
109122 rpm_map = {float (r ): float (r ) for r in unique_rpm }
110-
123+
111124 pu_physics = PhysicsConfig (
112125 bearing = {'n_balls' : 8 , 'd_ball' : 6.75 , 'd_pitch' : 28.5 , 'contact_angle' : 0.0 },
113126 cond_to_rpm = rpm_map ,
114127 fs = 64000 ,
115- name = 'PU-6203'
128+ name = 'PU-6203' ,
116129 )
117-
130+
118131 pu_taxonomy = {
119132 0 : ('Normal' , 'None' ),
120133 1 : ('Outer Race' , 'Medium' ),
121134 2 : ('Inner Race' , 'High' ),
122135 }
123-
124- train_data = Dataset .from_arrays (X_train , y_train , cond_train , fs = 64000 , physics = pu_physics , taxonomy = pu_taxonomy , name = "PU_Train" )
125- calib_data = Dataset .from_arrays (X_calib , y_calib , cond_calib , fs = 64000 , physics = pu_physics , taxonomy = pu_taxonomy , name = "PU_Calib" )
126- test_data = Dataset .from_arrays (X_test , y_test , cond_test , fs = 64000 , physics = pu_physics , taxonomy = pu_taxonomy , name = "PU_Test" )
127-
136+
137+ train_data = Dataset .from_arrays (
138+ X_train ,
139+ y_train ,
140+ cond_train ,
141+ fs = 64000 ,
142+ physics = pu_physics ,
143+ taxonomy = pu_taxonomy ,
144+ name = 'PU_Train' ,
145+ )
146+ calib_data = Dataset .from_arrays (
147+ X_calib ,
148+ y_calib ,
149+ cond_calib ,
150+ fs = 64000 ,
151+ physics = pu_physics ,
152+ taxonomy = pu_taxonomy ,
153+ name = 'PU_Calib' ,
154+ )
155+ test_data = Dataset .from_arrays (
156+ X_test ,
157+ y_test ,
158+ cond_test ,
159+ fs = 64000 ,
160+ physics = pu_physics ,
161+ taxonomy = pu_taxonomy ,
162+ name = 'PU_Test' ,
163+ )
164+
128165 model = CNSD ()
129-
130- print (" \n [1] Training Neural Network on 900 RPM Data..." )
166+
167+ print (' \n [1] Training Neural Network on 900 RPM Data...' )
131168 model .fit (train_data , epochs = 20 )
132-
133- print (" \n [2] Calibrating Tau threshold on 1500 RPM Data..." )
169+
170+ print (' \n [2] Calibrating Tau threshold on 1500 RPM Data...' )
134171 taus = np .arange (1.0 , 4.1 , 0.5 )
135172 best_gap = - np .inf
136173 best_tau = 1.0
137-
174+
138175 for tau in taus :
139176 model .symbolic .tau = float (tau )
140177 report = model .diagnose (calib_data )
141-
178+
142179 hb = headline_accuracy_by_verdict (report , y_calib )
143-
180+
144181 conf_acc = hb .get ('CONFIRMED' , {}).get ('cnn_accuracy' , 0.0 )
145182 cnfl_acc = hb .get ('CONFLICT' , {}).get ('cnn_accuracy' , 0.0 )
146183 gap = conf_acc - cnfl_acc if 'CONFIRMED' in hb and 'CONFLICT' in hb else 0.0
147-
148- print (f" Calib tau={ tau :.1f} | Conf={ conf_acc :.3f} | Cnfl={ cnfl_acc :.3f} | Gap={ gap :+.3f} " )
184+
185+ print (f' Calib tau={ tau :.1f} | Conf={ conf_acc :.3f} | Cnfl={ cnfl_acc :.3f} | Gap={ gap :+.3f} ' )
149186 if gap > best_gap :
150187 best_gap = gap
151188 best_tau = float (tau )
152-
153- print (f" \n => Selected optimal tau: { best_tau } " )
189+
190+ print (f' \n => Selected optimal tau: { best_tau } ' )
154191 model .symbolic .tau = best_tau
155-
156- print (" \n [3] Evaluating on Test Set (1500 RPM)..." )
192+
193+ print (' \n [3] Evaluating on Test Set (1500 RPM)...' )
157194 report = model .diagnose (test_data )
158-
195+
159196 hb = headline_accuracy_by_verdict (report , y_test )
160-
197+
161198 # Calculate baseline CNN accuracy
162199 pred = np .array ([r ['predicted_class' ] for r in report .records ])
163200 baseline_acc = float ((pred == np .asarray (y_test )).mean ())
164-
165- print (" \n --- FINAL TEST RESULTS (CROSS-DOMAIN PU) ---" )
166- print (f" Baseline CNN Acc: { baseline_acc :.3f} " )
201+
202+ print (' \n --- FINAL TEST RESULTS (CROSS-DOMAIN PU) ---' )
203+ print (f' Baseline CNN Acc: { baseline_acc :.3f} ' )
167204 if 'CONFIRMED' in hb :
168- print (f"Physics-Confirmed Acc: { hb ['CONFIRMED' ]['cnn_accuracy' ]:.3f} (n={ hb ['CONFIRMED' ]['n' ]} )" )
205+ print (
206+ f'Physics-Confirmed Acc: { hb ["CONFIRMED" ]["cnn_accuracy" ]:.3f} (n={ hb ["CONFIRMED" ]["n" ]} )'
207+ )
169208 if 'CONFLICT' in hb :
170- print (f"Physics-Conflict Acc: { hb ['CONFLICT' ]['cnn_accuracy' ]:.3f} (n={ hb ['CONFLICT' ]['n' ]} )" )
209+ print (
210+ f'Physics-Conflict Acc: { hb ["CONFLICT" ]["cnn_accuracy" ]:.3f} (n={ hb ["CONFLICT" ]["n" ]} )'
211+ )
171212 if 'INCONCLUSIVE' in hb :
172- print (f"Physics-Inconclusive Acc:{ hb ['INCONCLUSIVE' ]['cnn_accuracy' ]:.3f} (n={ hb ['INCONCLUSIVE' ]['n' ]} )" )
173-
213+ print (
214+ f'Physics-Inconclusive Acc:{ hb ["INCONCLUSIVE" ]["cnn_accuracy" ]:.3f} (n={ hb ["INCONCLUSIVE" ]["n" ]} )'
215+ )
216+
174217 if 'CONFIRMED' in hb and 'CONFLICT' in hb :
175218 gap = hb ['CONFIRMED' ]['cnn_accuracy' ] - hb ['CONFLICT' ]['cnn_accuracy' ]
176- print (f" GAP (CONF - CNFL): { gap :+.3f} " )
177- print (" --------------------------------------------" )
219+ print (f' GAP (CONF - CNFL): { gap :+.3f} ' )
220+ print (' --------------------------------------------' )
0 commit comments