@@ -51,7 +51,9 @@ def __init__(self, features: list[list[float]], labels: list[int]) -> None:
5151 self .y = np .array (labels )
5252 self .class_weights = {0 : 1.0 , 1 : 1.0 }
5353
54- def get_train_test_data (self ) -> tuple [list [np .ndarray ], list [np .ndarray ], list [np .ndarray ], list [np .ndarray ]]:
54+ def get_train_test_data (
55+ self
56+ ) -> tuple [list [np .ndarray ], list [np .ndarray ], list [np .ndarray ], list [np .ndarray ]]:
5557 """
5658 Splits the data into training and testing sets.
5759 Here, we manually split the data.
@@ -63,13 +65,17 @@ def get_train_test_data(self) -> tuple[list[np.ndarray], list[np.ndarray], list[
6365 - Test data
6466 - Test labels
6567 """
66- train_data = np .array ([self .X [0 ], self .X [1 ], self .X [2 ]]) # First 3 samples for training
67- train_labels = [np .array ([self .y [0 ]]), np .array ([self .y [1 ]]), np .array ([self .y [2 ]])]
68+ train_data = np .array ([self .X [0 ], self .X [1 ], self .X [2 ]])
69+ train_labels = \
70+ [np .array ([self .y [0 ]]), np .array ([self .y [1 ]]), np .array ([self .y [2 ]])]
6871 test_data = np .array ([self .X [3 ]]) # Last sample for testing
6972 test_labels = [np .array ([self .y [3 ]])] # Labels as np.ndarray
7073 return train_data , train_labels , test_data , test_labels
7174
72- def shuffle_data (self , paired_data : list [tuple [np .ndarray , int ]]) -> list [tuple [np .ndarray , int ]]:
75+ def shuffle_data (
76+ self ,
77+ paired_data : list [tuple [np .ndarray , int ]]
78+ ) -> list [tuple [np .ndarray , int ]]:
7379 """
7480 Shuffles the data randomly.
7581
@@ -84,7 +90,8 @@ def shuffle_data(self, paired_data: list[tuple[np.ndarray, int]]) -> list[tuple[
8490 return paired_data
8591
8692 def get_inout_dim (self ) -> tuple [int , int ]:
87- train_data , train_labels , test_data , test_labels = self .get_train_test_data ()
93+ train_data , train_labels , test_data , test_labels = (
94+ self .get_train_test_data ())
8895 in_dim = train_data [0 ].shape [0 ]
8996 out_dim = len (train_labels )
9097 return in_dim , out_dim
@@ -203,9 +210,11 @@ def initialize(self) -> tuple[np.ndarray, np.ndarray]:
203210 (2, 3)
204211 """
205212
206- in_dim , out_dim = self .dataloader .get_inout_dim () # in_dim here is image dim
207- w1 = rng .standard_normal ((in_dim + 1 , self .hidden_dim )) * np .sqrt (2.0 / in_dim )
208- w2 = rng .standard_normal ((self .hidden_dim , out_dim )) * np .sqrt (2.0 / self .hidden_dim )
213+ in_dim , out_dim = self .dataloader .get_inout_dim ()
214+ w1 = (rng .standard_normal ((in_dim + 1 , self .hidden_dim ))
215+ * np .sqrt (2.0 / in_dim ))
216+ w2 = (rng .standard_normal ((self .hidden_dim , out_dim ))
217+ * np .sqrt (2.0 / self .hidden_dim ))
209218 return w1 , w2
210219
211220 def relu (self , input_array : np .ndarray ) -> np .ndarray :
@@ -256,7 +265,8 @@ def forward(
256265 no_gradient: If True, returns output without storing intermediates.
257266
258267 Returns:
259- Output of the network after forward pass, shape (batch_size, output_dim).
268+ Output of the network after forward pass,
269+ shape (batch_size, output_dim).
260270
261271 Examples:
262272 >>> mlp = MLP(None, 1, 0.1, hidden_dim=2)
@@ -334,11 +344,11 @@ def back_prop(
334344
335345 grad_w2 = (
336346 np .dot (a1 .T , delta_k ) / batch_size
337- ) # (hidden, batch).dot(batch, output) = (hidden, output)
338- input_data_flat = input_data .reshape (input_data .shape [0 ], - 1 ) # (batch_size, input_dim)
347+ )
348+ input_data_flat = input_data .reshape (input_data .shape [0 ], - 1 )
339349 grad_w1 = (
340350 np .dot (input_data_flat .T , delta_j ) / batch_size
341- ) # (input_dim, batch_size).dot(batch, hidden) = (input, hidden)
351+ )
342352
343353 return grad_w1 , grad_w2
344354
@@ -351,11 +361,14 @@ def update_weights(
351361 learning_rate : float
352362 ) -> tuple [np .ndarray , np .ndarray ]:
353363 """
354- Updates the weight matrices using the computed gradients and learning rate.
364+ Updates the weight matrices using
365+ the computed gradients and learning rate.
355366
356367 Args:
357- w1: Weight matrix for input to hidden layer, shape (input_dim + 1, hidden_dim).
358- w2: Weight matrix for hidden to output layer, shape (hidden_dim, output_dim).
368+ w1: Weight matrix for input to hidden layer, shape
369+ (input_dim + 1, hidden_dim).
370+ w2: Weight matrix for hidden to output layer, shape
371+ (hidden_dim, output_dim).
359372 grad_w1: Gradient for w1, shape (input_dim + 1, hidden_dim).
360373 grad_w2: Gradient for w2, shape (hidden_dim, output_dim).
361374 learning_rate: Learning rate for weight updates.
@@ -405,7 +418,8 @@ def update_learning_rate(self, learning_rate: float) -> float:
405418 @staticmethod
406419 def accuracy (label : np .ndarray , y_hat : np .ndarray ) -> float :
407420 """
408- Computes the accuracy of predictions by comparing predicted and true labels.
421+ Computes the accuracy of predictions
422+ by comparing predicted and true labels.
409423
410424 Args:
411425 label: True labels, shape (batch_size, num_classes).
@@ -426,7 +440,8 @@ def accuracy(label: np.ndarray, y_hat: np.ndarray) -> float:
426440 @staticmethod
427441 def loss (output : np .ndarray , label : np .ndarray ) -> float :
428442 """
429- Computes the mean squared error loss between predictions and true labels.
443+ Computes the mean squared error loss
444+ between predictions and true labels.
430445
431446 Args:
432447 output: Predicted outputs, shape (batch_size, num_classes).
@@ -465,9 +480,11 @@ def get_acc_loss(self) -> tuple[list[float], list[float]]:
465480
466481 def train (self ) -> None :
467482 """
468- Trains the MLP model using the provided dataloader for multiple folds and epochs.
483+ Trains the MLP model using the provided dataloader
484+ for multiple folds and epochs.
469485
470- Saves the best model parameters for each fold and records accuracy/loss.
486+ Saves the best model parameters
487+ for each fold and records accuracy/loss.
471488
472489 Examples:
473490 >>> X = [[0.0, 0.0], [1.0, 1.0], [1.0, 0.0], [0.0, 1.0]]
@@ -479,7 +496,8 @@ def train(self) -> None:
479496 """
480497
481498 learning_rate = self .learning_rate
482- train_data , train_labels , test_data , test_labels = self .dataloader .get_train_test_data ()
499+ train_data , train_labels , test_data , test_labels = (
500+ self .dataloader .get_train_test_data ())
483501
484502 train_data = np .c_ [train_data , np .ones (train_data .shape [0 ])]
485503 test_data = np .c_ [test_data , np .ones (test_data .shape [0 ])]
@@ -498,12 +516,16 @@ def train(self) -> None:
498516 batch_size = 1
499517
500518 for j in tqdm (range (self .epoch )):
501- for k in range (0 , train_data .shape [0 ], batch_size ): # retrieve every image
519+ for k in range (0 , train_data .shape [0 ], batch_size ):
502520
503521 batch_imgs = train_data [k : k + batch_size ]
504522 batch_labels = train_labels [k : k + batch_size ]
505523
506- output = self .forward (input_data = batch_imgs , w1 = w1 , w2 = w2 , no_gradient = False )
524+ output = self .forward (
525+ input_data = batch_imgs ,
526+ w1 = w1 ,
527+ w2 = w2 ,
528+ no_gradient = False )
507529
508530 grad_w1 , grad_w2 = self .back_prop (
509531 input_data = batch_imgs ,
0 commit comments