FullyConnectedLayer
class FullyConnectedLayer(Layer):
def __init__(
self,
n_neurons: Optional[int] = None,
n_inputs: Optional[int] = None,
activation: Optional[Activation] = ReLU,
optimizer: Optional[Optimizer] = SGD,
loss_fn: Optional[LossFunction] = MeanSquaredError,
initializer: Optional[Initializer] = HeNormal(),
weights_initializer: Optional[Initializer] = HeNormal(),
bias_initializer: Optional[Initializer] = Zero(),
name: Optional[str] = ""
):
super().__init__(n_neurons, n_inputs, activation, optimizer, loss_fn, name=name)
def forward_propagation(self, inputs: np.ndarray, no_save: Optional[bool] = False) -> tuple[np.ndarray, int]:
"""
inputs:
An array of features (should be a numpy array)
Returns:
An array of the output values from each neuron in the layer.
Function:
Performs forward propagation by calculating the weighted sum for each neuron
and applying the activation function
"""
self.initialize_params(inputs)
# calculate weighted sum: Wx + b
weighted_sum = np.dot(self.W, self.inputs) + self.b
# activate each neuron with self.activation function
activated = self.activation.apply(weighted_sum)
# if saving: (bad var name i guess)
if not no_save:
self.z = weighted_sum
self.activated = activated
return activated
def back_propagation(self, next_layer: Layer, learning_rate: float) -> np.ndarray:
da_dz = self.activation.derivative(self.z)
dl_dz = (next_layer.old_W.T @ next_layer.gradients) * da_dz
self.old_W = self.W.copy()
dz_dw = self.inputs.T
dl_dw = dl_dz @ dz_dw
dl_db = dl_dz
self.gradients = dl_dz
self.W, self.b = self.optimizer.apply(self.W, dl_dw, self.b, dl_db)
Last updated