Concept units

A linear layer: weighted sums

Intermediate

Read these first if they are new to you

The idea in one paragraph

A linear layer takes a list of numbers in and gives a list of numbers out. Each output is a weighted sum of all the inputs, plus a constant. The weights and the constants are numbers the model learns during training. Written with a matrix, the whole layer is one line: y = Wx + b. Neural networks are built mostly from layers like this one.

Each output adds up the inputs, each with its own weight

Start with three input numbers, x1, x2 and x3. They might be the three coordinates of a point, or three measurements of anything. One output of the layer is computed like this:

y1 = w11x1 + w12x2 + w13x3 + b1

Each weight w says how much one input counts toward this output. A large weight makes that input matter a lot. A negative weight makes the input pull the output down. A weight of zero ignores the input. The bias b is a constant added at the end. It sets the output's value when every input is zero.

A layer usually has several outputs. Each output has its own weights and its own bias, so each one adds up the same inputs in a different way.

Try it. In the figure, the inputs x1 = 1 and x3 = 2 stay fixed. Predict from the weights which value of x2 makes y1 exactly 0. Then move the slider to check.

A layer with three inputs and two outputs has six weights and two biases
positive weightnegative weightline width: size of the weight
Each output is a weighted sum of all three inputs, plus its bias. Notice that y2 rises as y1 falls, because x2 has weight −1 into y1 and +1 into y2.
Answer for the goal

y1 = 2 × 1 − x2 + 0.5 × 2 + 1 = 4 − x2, so y1 is 0 when x2 = 4. Each step of 1 in x2 moves y1 by exactly its weight, −1. Outputs of a linear layer always move in such even steps.

Worked example: two outputs from three inputs

The layer in the figure has these weights and biases:

  • output 1: weights 2, −1, 0.5 and bias 1;
  • output 2: weights 0, 1, 1 and bias −2.

Feed in x = (1, 3, 2).

  1. y1 = 2 × 1 + (−1) × 3 + 0.5 × 2 + 1 = 2 − 3 + 1 + 1 = 1.
  2. y2 = 0 × 1 + 1 × 3 + 1 × 2 − 2 = 0 + 3 + 2 − 2 = 3.

So the layer turns the three numbers (1, 3, 2) into the two numbers (1, 3).

Your turn. Feed in x = (0, 0, 0). What comes out, and why?

Answer

(1, −2). Every weighted term is zero, so only the biases are left.

A matrix holds all the weights, one row per output

Write the weights as a weight matrix W: row 1 holds output 1's weights, row 2 holds output 2's. Put the biases in a vector b. Then the whole layer is a matrix times a vector, plus a vector:

y = Wx + b,   W = [[2, −1, 0.5], [0, 1, 1]],   b = (1, −2)

A layer with n inputs and m outputs has an m × n weight matrix: m rows, n columns. The input size and output size are free choices. A layer can make the list longer, shorter, or keep its length.

Training picks the weights, and there are many of them

Nobody types in the weights of a real network. They start as small random numbers. Training then adjusts them, step by step, so that the network's outputs get closer to the right answers. The unit on gradient descent shows how. Numbers that training adjusts are called the model's parameters.

A layer with n inputs and m outputs has n × m weights and m biases. The small layer above has 3 × 2 + 2 = 8 parameters. A layer from 512 numbers to 2,048 numbers has 512 × 2,048 + 2,048 = 1,050,624.

"Linear" is used loosely here

Strictly, a map with a bias added is called affine, not linear. Machine-learning writing calls it linear anyway. Either way, its outputs depend on its inputs along straight lines. So two linear layers in a row can be rewritten as one linear layer, and stacking them gains nothing. The unit on activation functions shows what breaks that.

In code, a layer handles a whole batch of inputs at once

Programs usually pass many inputs through a layer together: one input per row of an array. For a batch X with one input per row, the layer computes X @ W.T + b. Each row of the result is the output for that row's input. This is the same arithmetic, done for all rows at once.

linear_layer_numpy.py

import numpy as np

W = np.array([[2.0, -1.0, 0.5],
              [0.0,  1.0, 1.0]])   # 2 outputs, 3 inputs
b = np.array([1.0, -2.0])
x = np.array([1.0, 3.0, 2.0])

y = W @ x + b
print(y)                # one input vector

X = np.array([[1.0, 3.0, 2.0],
              [0.0, 0.0, 0.0]])  # a batch: one input per row
print(X @ W.T + b)      # one output per row
[1. 3.]
[[ 1.  3.]
 [ 1. -2.]]

PyTorch's nn.Linear holds W and b for you and starts them at random values. It stores W with one row per output, as above.

linear_layer_torch.py

import torch

layer = torch.nn.Linear(3, 2)   # 3 inputs, 2 outputs
print(layer.weight.shape, layer.bias.shape)
print(sum([p.numel() for p in layer.parameters()]))  # count the numbers in W and b

with torch.no_grad():            # set the weights by hand
    layer.weight.copy_(torch.tensor([[2.0, -1.0, 0.5],
                                     [0.0,  1.0, 1.0]]))
    layer.bias.copy_(torch.tensor([1.0, -2.0]))
print(layer(torch.tensor([1.0, 3.0, 2.0])).detach())
torch.Size([2, 3]) torch.Size([2])
8
tensor([1., 3.])

torch.tensor turns a list into a tensor, PyTorch's version of an array (see tensors on the GPU). PyTorch records every step that uses the layer's weights, so that it can compute gradients later. Inside torch.no_grad() it stops recording (see automatic gradients), so the code may overwrite the weights with copy_. .detach() gives the output without that record, so only its numbers print.

Check yourself

  1. Use the layer from the worked example. What does it output for x = (2, 0, 4)?

    Answer

    y1 = 2 × 2 − 0 + 0.5 × 4 + 1 = 7 and y2 = 0 + 0 + 4 − 2 = 2, so (7, 2).

  2. A layer takes 10 numbers in and gives 4 out. What shape is its weight matrix, and how many parameters does it have?

    Answer

    W is 4 × 10 (one row per output). It has 40 weights and 4 biases, so 44 parameters.

  3. You pass a batch of 32 inputs, each 3 numbers long, through nn.Linear(3, 2). What shape is the result?

    Answer

    32 × 2: one row of 2 outputs for each of the 32 inputs.

  4. A layer has all biases equal to zero. You double every input. What happens to the outputs?

    Answer

    Every output doubles too, since each is a sum of weight × input terms. With nonzero biases this is no longer exactly true, because the bias does not double.

Go further

Optional background, for readers who want more than this page.

Where this shows up

Units that build on this one