Forward Propagation in Layers

Introduction

Welcome back to our course "Neural Network Fundamentals: Neurons and Layers"! You're making excellent progress. Previously in this course, we built a single artificial neuron, which we then enhanced with the Sigmoid activation function and finally combined multiple neurons into a DenseLayer.

Today, in our final lesson, we'll bring our neural network layer to life by implementing forward propagation — the process by which information travels through a neural network from input to output. This is where our layer actually processes data and produces meaningful activations.

By the end of this lesson, you'll have a functional dense layer that can take inputs, process them through multiple neurons simultaneously, and produce outputs that could be fed to another layer or used directly for predictions.

Understanding Forward Propagation

Before diving into code, let's understand what forward propagation means in the context of neural networks.

Forward propagation (or forward pass) is the process of taking input data and passing it through the network to generate an output. It's called "forward" because information flows forward through the network, from the input layer, through any hidden layers, to the output layer.

For our dense layer, forward propagation involves three key steps:

  1. Weighted Sum Calculation: Multiply each input feature by its corresponding weight.
  2. Bias Addition: Add the bias term to each weighted sum.
  3. Activation: Apply the activation function to introduce non-linearity.

This process transforms the input data into activations (outputs) that represent what the layer has "learned" about the input. These activations can then be used as inputs to subsequent layers in deeper networks.

Matrix Operations for Efficient Processing

As we learned in our previous lesson, we're using vector<vector<double>> to represent the weights and biases of our dense layer. This allows us to process multiple neurons simultaneously through matrix operations implemented with loops.

Let's review the key data structures involved in forward propagation:

  • Inputs: vector<vector<double>> with dimensions (n_samples, n_inputs), where each row represents one data sample.
  • Weights: vector<vector<double>> with dimensions (n_inputs, n_neurons), where each column represents the weights for one neuron.
  • Biases: vector<double> with size n_neurons, one bias per neuron.
  • Outputs: vector<vector<double>> with dimensions (n_samples, n_neurons), where each row will be the output for one sample.

The beauty of this approach is that it works not only for a single input sample but also for batches of samples. When we have multiple samples (a batch), we can process them all at once with the same code structure.

For example, if we have a batch of 4 samples, each with 3 features, and our layer has 2 neurons:

  • Inputs dimensions: 4 x 3, which means 4 samples, each with 3 features (inputs.size() = 4, inputs[0].size() = 3).
  • Weights dimensions: 3 x 2, meaning 3 inputs connected to 2 neurons (weights.size() = 3, weights[0].size() = 2).
  • Result of matrix multiplication: 4 x 2, or 4 samples, each producing 2 outputs.

This efficient batch processing is one of the key advantages of using matrix operations in neural networks.

NOTE: A sample is a unit of input that the model processes to produce a prediction. Suppose you're building a neural network to predict whether a person will buy a product based on 3 features: Age, Income, Number of previous purchases. Then each sample would be one person data, like [25, 40000, 2].

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal