fix this code: import numpy as np

np.random.seed(0)

class Layer_Dense:
    def __init__(self, n_inputs, n_neurons, learning_rate=0.001):
        self.weights = np.random.randn(n_inputs, n_neurons)
        self.biases = np.zeros((1, n_neurons))
        self.learning_rate = learning_rate

    def forward(self, inputs):
        self.inputs = inputs
        self.output = np.dot(inputs, self.weights) + self.biases

class Activation_tanh:
    def forward(self, inputs):
        self.output = np.tanh(inputs)

class Activation_Dtanh:
    def backward(self, inputs):
        self.output = 1 - np.tanh(inputs)**2
        return self.output

# X = [1,2,3.2,-1.2,0.003]
# y = [0.1,0.2,0.3,0.4,1]

layer1 = Layer_Dense(32, 32)
layer2 = Layer_Dense(32, 32)
layer3 = Layer_Dense(32, 32)
layer4 = Layer_Dense(32, 32)

x_train_split = np.random.randn(100, 1)  # Dummy data for demonstration
y_train_split = np.random.randn(100, 1)  # Dummy data for demonstration

for i in range(len(x_train_split)):
    activation1 = Activation_tanh()
    layer1.forward(x_train_split[i])
    activation1.forward(layer1.output)

    activation2 = Activation_tanh()
    layer2.forward(activation1.output)
    activation2.forward(layer2.output)

    activation3 = Activation_tanh()
    layer3.forward(activation2.output)
    activation3.forward(layer3.output)

    activation4 = Activation_tanh()
    layer4.forward(activation3.output)
    activation4.forward(layer4.output)

    curr_active_output = activation4.output
    prev_active_output = activation3.output
    prev_output = layer3.output
    curr_output = layer4.output

    def BackProp_OutputLayer(y, learning_rate, curr_output, prev_output, prev_active_output, curr_active_output):
        error = y[i] - curr_active_output
        activation = Activation_Dtanh()
        phi_dash = activation.backward(curr_output)
        local_gradient = error * phi_dash
        del_w = learning_rate * np.dot(prev_active_output.T, local_gradient)
        return del_w, local_gradient, error, phi_dash

    learning_rate = 0.001

    del_w, local_gradient, error, phi_dash = BackProp_OutputLayer(y_train_split, learning_rate, curr_output,
                                                                  prev_output, prev_active_output,
                                                                  curr_active_output)

    layer4.weights += del_w

    curr_active_output = activation3.output
    next_active_output = activation4.output
    next_output = layer4.output
    curr_output = layer3.output
    prev_output = layer2.output
    prev_active_output = activation2.output
    next_local_grad = local_gradient

    def BackProp_middle_Layer(learning_rate, prev_active_output, curr_output, curr_active_output, next_output,
                          next_active_output, loc_grad):
        next_local_gradient = loc_grad.T  # Transpose to make shapes compatible
        activation = Activation_Dtanh()
        phi_dash_curr = activation.backward(curr_output)
        next_weights = layer4.weights
        current_local_gradient = phi_dash_curr * np.dot(next_local_gradient, next_weights)
        del_w = learning_rate * np.dot(prev_active_output.T, current_local_gradient)
        return del_w, current_local_gradient

    new_del_w, curr_loc_grad = BackProp_middle_Layer(learning_rate, prev_active_output, curr_output,
                                                     curr_active_output, next_output, next_active_output,
                                                     next_local_grad)

    layer3.weights += new_del_w

    curr_active_output = activation2.output
    next_active_output = activation3.output
    next_output = layer3.output
    curr_output = layer2.output
    prev_output = layer1.output
    prev_active_output = x_train_split[i]
    next_local_grad = curr_loc_grad

    new_del_w, curr_loc_grad, a, b = BackProp_middle_Layer(learning_rate, prev_active_output, curr_output,
                                                            curr_active_output, next_output, next_active_output,
                                                            next_local_grad)

    layer2.weights += new_del_w

    layer1.weights += new_del_w