@@ -47,7 +47,9 @@ class ModelRunnerNN(ModelRunner):
4747
4848 def __init__ (self , model : Optional [nn .Module ]= None , num_epoch :int = 3 , learning_rate :float = 1e-3 ,
4949 criterion :nn .Module = nn .MSELoss (), max_fractional_error : float = 0.10 ,
50- is_normalized :bool = False , is_report :bool = False ):
50+ is_normalized :bool = True ,
51+ noise_std : float = 0.1 , is_l1_regularization :bool = True , is_accuracy_regularization :bool = True ,
52+ is_report :bool = False ):
5153 """
5254 Args:
5355 model (nn.Module): Model being run
@@ -56,6 +58,11 @@ def __init__(self, model: Optional[nn.Module]=None, num_epoch:int=3, learning_ra
5658 is_normalized (bool, optional): Whether to normalize the input data (divide by std).
5759 Defaults to False.
5860 max_fractional_error (float): Maximum error desired for each prediction
61+ noise_std (float, optional): Standard deviation of noise to add to inputs.
62+ is_l1_regularization (bool, optional): Whether to use L1 regularization.
63+ Defaults to True.
64+ is_accuracy_regularization (bool, optional): Whether to use accuracy regularization.
65+ Defaults to True.
5966 is_report (bool, optional): Print text for progress.
6067 Defaults to False.
6168 """
@@ -66,6 +73,9 @@ def __init__(self, model: Optional[nn.Module]=None, num_epoch:int=3, learning_ra
6673 self .learning_rate = learning_rate
6774 self .is_normalized = is_normalized
6875 self .max_fractional_error = max_fractional_error
76+ self .noise_std = noise_std
77+ self .is_l1_regularization = is_l1_regularization
78+ self .is_accuracy_regularization = is_accuracy_regularization
6979 # Calculated state
7080 self .feature_std_tnsr = torch .tensor ([np .nan ])
7181 self .target_std_tnsr = torch .tensor ([np .nan ])
@@ -92,6 +102,27 @@ def _calculateAccuracy(self, feature_tnsr, target_tnsr)->float:
92102 accuracy = torch .sum (accurate_rows ) / accurate_rows .shape [0 ]
93103 return accuracy
94104
105+ def _calculateSmothedInaccuracy (self , feature_tnsr , target_tnsr )-> float :
106+ """Calculates the mean absolute maximum fractional error for each sample.
107+
108+ Args:
109+ feature_tnsr (nn.Tensor): features
110+ target_tnsr (nn.Tensor): target
111+
112+ Returns:
113+ accuracy (float)
114+ """
115+ prediction_tnsr = self .predict (feature_tnsr )
116+ prediction_arr = prediction_tnsr .cpu ().numpy ()
117+ target_arr = target_tnsr .cpu ().numpy ()
118+ # Find deiviations handling small and large predictions
119+ mae1_arr = np .max (np .abs (prediction_arr - target_arr ) / target_arr , axis = 1 )
120+ mae2_arr = np .max (np .abs (prediction_arr - target_arr ) / prediction_arr , axis = 1 )
121+ mae_arr = np .maximum (mae1_arr , mae2_arr )
122+ # Smooth the inaccuracy
123+ smoothed_inaccuracy = np .mean (mae_arr )
124+ return smoothed_inaccuracy
125+
95126 def fit (self , train_loader : DataLoader ) -> RunnerResultPredict :
96127 """
97128 Train the model. All calculations are on the accelerator device.
@@ -120,12 +151,11 @@ def calculate_std(is_feature: bool) -> torch.Tensor:
120151 self .feature_std_tnsr = calculate_std (is_feature = True ).to (cn .DEVICE )
121152 self .target_std_tnsr = calculate_std (is_feature = False ).to (cn .DEVICE )
122153 num_sample = full_feature_tnsr .size (0 )
123- reconstruction_loss_weight = 1 / torch .std (self .target_std_tnsr )
124154 # Initialize for training
125155 optimizer = optim .Adam (self .model .parameters (), lr = self .learning_rate )
126156 self .model .train ()
127157 losses = []
128- avg_loss = 0.0
158+ avg_loss = 1e10
129159 epoch_loss = np .inf
130160 accuracies :list = []
131161 mi_hidden1_input_epochs :list = []
@@ -146,14 +176,25 @@ def calculate_std(is_feature: bool) -> torch.Tensor:
146176 idx_tnsr = permutation [iter * batch_size :(iter + 1 )* batch_size ]
147177 feature_tnsr = full_feature_tnsr [idx_tnsr ]/ self .feature_std_tnsr
148178 target_tnsr = full_target_tnsr [idx_tnsr ]/ self .target_std_tnsr
179+ # Add noise to features for denoising autoencoder
180+ feature_tnsr = feature_tnsr + torch .randn_like (feature_tnsr ) * self .noise_std
149181 # Forward pass with a regularization loss
150182 prediction_tnsr = self .model (feature_tnsr )
151183 reconstruction_loss = self .criterion (prediction_tnsr , target_tnsr )
152- l1_loss = self ._l1_regularization ()
153- accuracy = self ._calculateAccuracy (full_feature_tnsr , full_target_tnsr )
154- accuracy_loss = ACCURACY_WEIGHT * (1 - accuracy )
184+ if self .is_accuracy_regularization :
185+ accuracy_loss = self ._calculateSmothedInaccuracy (full_feature_tnsr , full_target_tnsr )
186+ else :
187+ accuracy_loss = 0.0
188+ if self .is_l1_regularization :
189+ l1_loss = self ._l1_regularization ()
190+ else :
191+ l1_loss = 0.0
155192 # FIXME: May need to scale the losses.
156- total_loss = reconstruction_loss_weight * reconstruction_loss + l1_loss + 0.1 * accuracy_loss
193+ total_loss = reconstruction_loss + l1_loss + 0.01 * accuracy_loss
194+ if False :
195+ print (f"epoch={ epoch } , reconstruction_loss={ reconstruction_loss .item ():.4f} , "
196+ f"l1_loss={ l1_loss :.4f} , accuracy_loss={ accuracy_loss :.4f} " ,
197+ f"total_loss={ total_loss .item ():.4f} " )
157198 # Backward pass
158199 optimizer .zero_grad ()
159200 total_loss .backward ()
0 commit comments