SGD Parameter Update
Problem Statement
Perform a single Stochastic Gradient Descent update step.
Background
In SGD, parameters are updated using gradients and a learning rate Ξ± (alpha):
W=WβΞ±β dW
This simple rule moves parameters in the direction that reduces the loss.
Your Task
Write a function sgd_update(weights, gradients, learning_rate) that performs a single SGD update on a list of weights.
Output Format
Return a list of updated weights. Round each value to 4 decimal places.
Example:
weights=[1.0], gradients=[0.5], learning_rate=0.1
[0.95]
1.0 - (0.1Γ0.5) = 1.0 - 0.05 = 0.95
Constraints:
- -1000 <= weights[i], gradients[i] <= 1000
- 0 < learning_rate <= 1
- List length: 1 to 100 elements
1. Background Knowledge
Stochastic Gradient Descent (SGD) is a foundational optimization algorithm in machine learning for minimizing loss functions L(\mathbf{w}) where w represents model parameters (weights). The core update rule is:
wβwβΞ±βL(w)
Here, Ξ± is the learning rate (step size), and βL(\mathbf{w}) is the gradient. In full-batch GD, the gradient uses all data; in SGD, it uses a single (or mini-batch) example, making it stochastic but computationally efficient for large datasets.
Key prerequisites:
- Vectors/matrices: Weights wβRn, gradients dwβRn
- Element-wise operations: Update applies independently per parameter: wiββwiββ\alphaβ dwiβ
- Numerical stability: Round to 4 decimals as specified to handle floating-point precision.
2. Algorithm Approach
The problem requires vanilla SGD (no momentum, adaptive rates like Adam, or variance reduction). Standard techniques:
- Element-wise vector subtraction: Use NumPy broadcasting for efficiency.
- Simultaneous update: Compute all new weights before overwriting (avoids using updated values prematurely).
- Common libraries: numpy for vectorized operations (assumed available).
Pseudocode:
for each i in 0 to n-1:
new_weights[i] = weights[i] - learning_rate * gradients[i]
return round(new_weights, 4)
3. Step-by-Step Strategy
- Validate inputs: Ensure weights and gradients have identical length (1-100 elements per constraints).
- Initialize output list: Create new list same size as input.
- Compute updates: For each index i, calculate wiβ²β=wiββ\alphaβ dwiβ.
- Apply rounding: Round each wiβ²β to 4 decimal places using round(value, 4).
- Return result: Output as Python list.
Sample Implementation:
def sgd_update(weights, gradients, learning_rate):
if len(weights) != len(gradients):
raise ValueError("Weights and gradients must have same length")
updated = []
for w, dw in zip(weights, gradients):
new_w = w - learning_rate * dw
updated.append(round(new_w, 4))
return updated
Vectorized (NumPy) version:
import numpy as np
def sgd_update(weights, gradients, learning_rate):
w = np.array(weights)
dw = np.array(gradients)
return np.round(w - learning_rate * dw, 4).tolist()
Verification: [1.0] - 0.1 * [0.5] = [0.95] β
4. Common Pitfalls
- In-place updates: weights[i] -= alpha * gradients[i] uses partially updated values, causing errors in multi-parameter cases.
- No rounding: Output [0.949999999] instead of [0.95] fails tests.
- Integer division: Use float inputs/operations (Python 3 handles this).
- Empty lists: Constraints guarantee 1+ elements, but edge case n=1 needs testing.
- Sign error: Remember subtract gradient (negative direction reduces loss).
- List vs. NumPy: Return Python list, not array.
| Pitfall | Wrong | Correct |
|---|---|---|
| In-place | weights -=... | New list |
| Rounding | 0.95 | round(0.95, 4) |
| Type | np.array return | .tolist() |
5. Time & Space Complexity
- Time: O(n) where n= list length (1-100). Single pass with constant-time operations per element.
- Space: O(n) for output list + O(n) temporary storage. In-place impossible without errors.
LaTeX notation: O(n) time, O(n) space.
This covers vanilla SGD parameter update completelyβsimple but fundamental to all deep learning optimizers!