Ancient

 view release on metacpan or  search on metacpan

t/lib/NeuralNet/Layer.pm  view on Meta::CPAN

    weights $self, \@w;

    # Initialize biases to zero
    biases $self, [(0) x $out];

    # Initialize gradient accumulators
    weight_grads $self, [map { [(0) x $in] } 1 .. $out];
    bias_grads $self, [(0) x $out];
}

sub forward {
    my ($self, $input) = @_;
    last_input $self, $input;

    my $w = weights $self;
    my $b = biases $self;
    my $out_size = output_size $self;

    my @output;
    for my $i (0 .. $out_size - 1) {
        my $sum = $b->[$i];
        for my $j (0 .. @$input - 1) {
            $sum += $w->[$i][$j] * $input->[$j];
        }
        push @output, $sum;
    }

    last_output $self, \@output;
    return \@output;
}

sub backward {
    my ($self, $grad) = @_;
    my $input = last_input $self;
    my $w = weights $self;
    my $in_size = input_size $self;
    my $out_size = output_size $self;

    # Compute weight gradients
    my $wg = weight_grads $self;
    my $bg = bias_grads $self;

    for my $i (0 .. $out_size - 1) {
        $bg->[$i] += $grad->[$i];
        for my $j (0 .. $in_size - 1) {
            $wg->[$i][$j] += $grad->[$i] * $input->[$j];
        }
    }

    # Compute gradient w.r.t. input
    my @input_grad = (0) x $in_size;
    for my $j (0 .. $in_size - 1) {
        for my $i (0 .. $out_size - 1) {
            $input_grad[$j] += $w->[$i][$j] * $grad->[$i];
        }
    }

    return \@input_grad;
}

sub update {
    my ($self, $lr) = @_;
    my $w = weights $self;
    my $b = biases $self;
    my $wg = weight_grads $self;
    my $bg = bias_grads $self;

    my $out_size = output_size $self;
    my $in_size = input_size $self;

    # Update weights and biases
    for my $i (0 .. $out_size - 1) {
        $b->[$i] -= $lr * $bg->[$i];
        $bg->[$i] = 0;  # Reset gradient
        for my $j (0 .. $in_size - 1) {
            $w->[$i][$j] -= $lr * $wg->[$i][$j];
            $wg->[$i][$j] = 0;  # Reset gradient
        }
    }
}

sub num_params {
    my ($self) = @_;
    my $in = input_size $self;
    my $out = output_size $self;
    return $in * $out + $out;  # weights + biases
}

1;

__END__

=head1 NAME

NeuralNet::Layer - Dense layer with typed slots

=head1 SYNOPSIS

    use NeuralNet::Layer;

    my $layer = NeuralNet::Layer->new(
        input_size  => 4,
        output_size => 2,
    );
    $layer->BUILD;

    my $out = $layer->forward([1, 2, 3, 4]);

=head1 DESCRIPTION

Demonstrates typed slots (Int:required), ArrayRef slots,
function-style accessors, and custom methods.

=cut



( run in 2.069 seconds using v1.01-cache-2.11-cpan-63c85eba8c4 )