Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 84

Building a Feedforward Neural Network in PyTorch

Recommended resources

Hello! Welcome to the next lesson in our journey through Deep Learning with PyTorch.

In our previous lesson, we explored the powerful optimizers, like SGD and Adam, that use gradients from backpropagation to update our model's weights. We learned how to create an optimizer and use its core functions: zero_grad(), backward(), and step().

Today, we shift our focus to the heart of the system: the neural network model itself. You'll learn how to define the architecture of a feedforward neural network (FNN) for a classification task using PyTorch's elegant and powerful tools. This is where you get to be the architect, designing the layers and connections that will learn from the data.

By the end of this lesson, you will be able to structure, define, and instantiate a complete feedforward neural network class in PyTorch, ready for training.

1. What Are We Building?

A feedforward neural network is organized in layers: an input layer, one or more hidden layers, and an output layer. Information flows in one direction—forward—from the input, through the hidden layers where computation happens, to the output layer that produces the final prediction.

Feed Forward Neural Network Architecture
This diagram shows a typical feedforward neural network. Data enters the input layer, is processed by hidden layers, and a result is produced by the output layer. Our goal is to build this structure in code.

2. The Core Building Block: nn.Module

In PyTorch, every neural network you build is a Python class that inherits from torch.nn.Module. This base class provides all the essential functionality for a neural network, like tracking its layers and parameters.

Build the Neural Network

Let's start with the official PyTorch documentation to understand the foundational concept of nn.Module.

Read the sections 'Introduction' and 'Define the Class'. Focus on these two key points: All neural network models in PyTorch are subclasses of nn.Module. A model class requires two essential methods: __init__() to define the layers, and forward() to specify how data passes through them.

As the documentation highlights, building a model involves two main steps within your class:

  1. __init__() (The Constructor): Here, you define all the layers your network will contain. These are like the Lego bricks of your model. The most common layers for an FNN are:

    • nn.Linear(in_features, out_features): A fully connected layer that applies a linear transformation. in_features is the number of input neurons, and out_features is the number of output neurons.
    • nn.ReLU(): The Rectified Linear Unit activation function. This introduces non-linearity, allowing the network to learn complex patterns.
  2. forward(self, x) (The Forward Pass): Here, you define the sequence of operations. You specify the exact path the input data x takes as it flows through the layers you defined in __init__().


3. Building an FNN for Image Classification

Let's make this concrete by building a network to classify handwritten digits from the famous MNIST dataset. This is a classic problem where each input is a 28x28 pixel grayscale image of a digit (0-9).

The process generally follows these steps, which are laid out very clearly in the article "Feedforward Neural Network with PyTorch".

Feedforward Neural Network with PyTorch

This article from DeepLearingWizard provides an excellent step-by-step guide to building an FNN. We'll use its structure as our main reference.

Skim the section 'Building a Feedforward Neural Network with PyTorch' to see the 7-step plan. We will focus on steps 3 and 4 in this lesson, but it's good to see the whole picture.

Step 1: Define Hyperparameters and Load Data

Before we build the model, we need to define some key settings. The video below by Patrick Loeber provides a clear, practical walkthrough of setting up for an FNN project.

PyTorch Tutorial 13 - Feed-Forward Neural Network

Let's watch how to set up the environment, define hyperparameters, and load the MNIST dataset. This provides the context for our model's dimensions.

Watch from 01:18 to 05:39. Pay attention to the definition of these crucial hyperparameters: input_size = 784: This is because we flatten each 28x28 pixel image into a single 1D vector (28 * 28 = 784). hidden_size = 100: This is a design choice for the number of neurons in our hidden layer. num_classes = 10: Because there are 10 possible digits (0 through 9).

Step 2: Create the Model Class

Now for the main event. We will create a class named NeuralNet that inherits from nn.Module. It will have one hidden layer.

PyTorch Tutorial 13 - Feed-Forward Neural Network

Let's continue with the same video to see exactly how to write the NeuralNet class.

Watch from 08:06 to 11:38. This is the core of our lesson. Observe how the layers (nn.Linear, nn.ReLU) are first defined in __init__ and then used in the forward method to process the input x.

Here is the code for the model, as shown in the video. Let's break it down:

import torch.nn as nn

class NeuralNet(nn.Module):
    def __init__(self, input_size, hidden_size, num_classes):
        # Always call the superclass constructor first
        super(NeuralNet, self).__init__()
        
        # Define the layers
        self.fc1 = nn.Linear(input_size, hidden_size)  # First linear layer (input -> hidden)
        self.relu = nn.ReLU()                          # Activation function
        self.fc2 = nn.Linear(hidden_size, num_classes) # Second linear layer (hidden -> output)
    
    def forward(self, x):
        # Define the data flow
        out = self.fc1(x)       # Pass input through the first linear layer
        out = self.relu(out)    # Apply the ReLU activation
        out = self.fc2(out)     # Pass through the second linear layer
        # No softmax here!
        return out

A Crucial Note: You might wonder why there is no nn.Softmax layer at the end. For classification tasks, the standard loss function is nn.CrossEntropyLoss. This PyTorch function conveniently combines the Softmax activation and the cross-entropy loss calculation. Doing this is more numerically stable than applying them separately. So, the raw output of our final linear layer (called "logits") is exactly what nn.CrossEntropyLoss expects.

Step 3: Instantiate the Model, Loss, and Optimizer

With our class defined, we can now create an instance of our network. We also set up the loss function and the optimizer, connecting all the pieces we've learned.

PyTorch Tutorial 13 - Feed-Forward Neural Network

Finally, let's see how to create an object from our NeuralNet class and prepare the loss and optimizer.

Watch from 11:23 to 12:50. This short clip shows how to: Create the model object from our class. Instantiate nn.CrossEntropyLoss as the criterion. Instantiate torch.optim.Adam, passing it model.parameters() to tell it which weights to update.

The code to do this is simple and clean:

# Assuming hyperparameters are defined
# input_size = 784
# hidden_size = 100
# num_classes = 10
# learning_rate = 0.001

model = NeuralNet(input_size, hidden_size, num_classes)

# Loss
criterion = nn.CrossEntropyLoss()

# Optimizer
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

At this point, our model is a fully defined neural network, and we have the criterion to measure its error and the optimizer to update its weights. It's ready to be trained!

Test your understanding!

You are building an FNN for a different classification task. The input data is a vector of 50 features. You want to use a hidden layer with 128 neurons and predict one of 4 possible classes.

How would you define the __init__ method for this new model?

Show answer

You would set input_size=50, hidden_size=128, and num_classes=4.

def __init__(self):
    super(MyNewNet, self).__init__()
    self.fc1 = nn.Linear(50, 128)  # Input is 50, hidden is 128
    self.relu = nn.ReLU()
    self.fc2 = nn.Linear(128, 4)   # Hidden is 128, output is 4

Conclusion

Great work! You've successfully designed the blueprint for a feedforward neural network in PyTorch. You now know how to structure a model as a class, define its layers, and specify the forward pass.

Key Takeaways:

  • PyTorch neural networks are built by creating a class that inherits from nn.Module.
  • The __init__ method is where you declare the network's layers (e.g., nn.Linear, nn.ReLU).
  • The forward method defines the computational graph, specifying how data flows through the layers.
  • The dimensions of your nn.Linear layers must match your data's input size, your desired hidden layer sizes, and the number of output classes.
  • For multi-class classification, you should output the raw logits from the final linear layer and use nn.CrossEntropyLoss, as it includes the Softmax function internally.

Preview of the Next Lesson:
We have now defined the data loading, the model architecture, the loss function, and the optimizer. All the pieces are on the table. In the next lesson, "Implement a complete training loop in PyTorch," we will assemble them all into a single script to train our network, watch it learn, and evaluate its performance on the test data.