Softmax
Implement the softmax function, a crucial component in neural networks that converts logits to probabilities. This process is essential for making predictions in classification problems.
The softmax function takes a vector of real numbers as input and outputs a vector of values in the range (0, 1) that add up to 1, making it suitable for representing a probability distribution. The softmax function is often used in the output layer of a neural network to ensure that the output values can be interpreted as probabilities.
To apply the softmax function, the following steps are involved:
- Exponentiate each input value,
- Calculate the sum of these exponentiated values,
- Divide each exponentiated value by the sum.
This technique is widely used in image classification and natural language processing tasks.
Example:
softmax([1, 2, 3])
[0.0900, 0.2447, 0.6652]
- First, exponentiate each input: e1β2.7183, e2β7.3891, e3β20.0855.
- Then, sum these exponentials: 2.7183+7.3891+20.0855β30.1929.
- Finally, divide each exponential by this sum:
- 2.7183/30.1929β0.0900
- 7.3891/30.1929β0.2447
- 20.0855/30.1929β0.6652
giving the output [0.0900,Β 0.2447,Β 0.6652].
Constraints:
- Return probabilities rounded to 4 decimal places
Softmax is a function that takes a vector of logits (real-valued scores) and converts them into a probability distribution: each output is between 0 and 1, and all outputs sum to 1. In neural networks, softmax is typically used in the final layer for multi-class classification so that the networkβs raw outputs can be interpreted as class probabilities and used with a loss like cross-entropy.
Mathematically, for an input vector x=[x1β,x2β,β¦,xnβ], the softmax of component xiβ is:
softmax(xiβ)=βj=1nβexjβexiββThis is a normalized exponential: the numerator magnifies differences between scores (larger logits get much larger exponentials), and the denominator ensures the outputs sum to 1. In practice, implementations must also consider numerical stability, because ex grows very fast and can overflow for large x.
1. Background Knowledge
-
Logits vs probabilities Neural networks usually output unbounded real numbers (logits). Softmax converts these into a probability vector:
-
piββ(0,1) for each class i
-
βiβpiβ=1 This makes them suitable for probabilistic interpretation and for computing losses like cross-entropy.
-
Shift invariance and stability Softmax is invariant to adding a constant to all inputs:
for any scalar c. This property is crucial for implementing a numerically stable version by subtracting the maximum logit from all logits before exponentiating.
2. Algorithm / Approach
The general algorithm pattern:
- Optionally stabilize the inputs by subtracting their maximum value.
- Exponentiate each (possibly shifted) input element.
- Compute the sum of all exponentials.
- Normalize each exponential by dividing by the sum.
- Return the resulting vector of probabilities.
Depending on the problem setting, you must:
- Handle 1D inputs (single vector of logits).
- Possibly handle 2D inputs (batch of vectors), applying the same logic row-wise (or along a chosen axis).
3. Step-by-Step Strategy
Assume a 1D array x of length n:
- Find the maximum value
x_max = max(x)
This is for numerical stability.
- Shift the inputs by subtracting x_max from each element:
shifted = [xi - x_max for xi in x]
- Exponentiate each shifted value:
exps = [math.exp(si) for si in shifted]
- Compute the sum of exponentials:
sum_exps = sum(exps)
- Normalize each exponential to get probabilities:
softmax = [ei / sum_exps for ei in exps]
- Return the softmax array.
For a 2D input (e.g., shape (batch_size, num_classes)), apply the above for each row independently.
4. Common Pitfalls
- Numerical overflow/underflow
- Directly computing exp(xi) when xi is large (e.g., 1000) can overflow.
- Always do the max-subtraction trick:
and then compute exp(yiβ).
-
Not normalizing correctly
-
Ensure you divide each exponential by the sum over the correct axis (e.g., per row in a batch), not by the sum over the entire array.
-
In-place modifications
-
If reusing input arrays, be careful about modifying them in place before youβve finished computing the sum of exponentials.
-
Precision issues with very small probabilities
-
When logits are very negative relative to the max, exponentials may underflow to zero. This is expected in extreme cases; the max-subtraction helps but cannot avoid all underflow.
5. Time & Space Complexity
Let n be the number of elements in the input vector (or per row for batched input):
-
Time complexity
-
Finding the max: O(n)
-
Computing exponentials: O(n)
-
Summing exponentials: O(n)
-
Normalizing: O(n)
-
Overall: O(n) per vector (or O(Bβ n) for batch size B).
-
Space complexity
-
If you store exponentials and output separately: O(n) extra space.
-
If you allow in-place and overwrite intermediate arrays carefully, you can keep extra space close to O(1) plus output storage.