Noise#
Noise modifiers add stochastic variance to function evaluations. They test how optimizers handle noisy objective functions.
Why Add Noise?#
Real-world optimization problems often have noisy evaluations:
Machine learning: Cross-validation variance
Simulations: Monte Carlo sampling
Physical experiments: Measurement uncertainty
A/B testing: Statistical fluctuations
Testing on noisy functions reveals:
How many evaluations your optimizer needs
Whether it handles variance correctly
If it converges to the true optimum or gets stuck
Available Noise Types#
Gaussian Noise#
Adds normally distributed noise to the objective value.
from surfaces.test_functions.algebraic import SphereFunction
from surfaces.modifiers import GaussianNoise
# Create function with Gaussian noise (standard deviation 0.1)
noisy = SphereFunction(
n_dim=3,
modifiers=[GaussianNoise(sigma=0.1)]
)
# Multiple evaluations at same point give different results
point = {"x0": 1.0, "x1": 1.0, "x2": 1.0}
results = [noisy(point) for _ in range(10)]
print(f"Mean: {sum(results)/len(results):.3f}")
print(f"Std: {(sum((r-sum(results)/len(results))**2 for r in results)/len(results))**0.5:.3f}")
Parameters:
sigma: Standard deviation of the noise
Uniform Noise#
Adds uniformly distributed noise.
from surfaces.modifiers import UniformNoise
noisy = SphereFunction(
n_dim=3,
modifiers=[UniformNoise(low=-0.1, high=0.1)]
)
Parameters:
low: Lower bound of uniform distributionhigh: Upper bound of uniform distribution
Noise Levels#
The noise level significantly affects optimization difficulty:
Sigma |
Difficulty |
Use Case |
|---|---|---|
0.01 |
Low |
Most optimizers handle this well |
0.1 |
Medium |
Requires noise-tolerant algorithms |
1.0 |
High |
Very challenging, needs many samples |
Signal-to-Noise Ratio#
Consider the noise level relative to the function’s range:
from surfaces.test_functions.algebraic import SphereFunction
from surfaces.modifiers import GaussianNoise
base = SphereFunction(n_dim=3)
# Get function range
space = base.search_space()
samples = [base({f"x{i}": space[f"x{i}"][j] for i in range(3)})
for j in range(100)]
func_range = max(samples) - min(samples)
# Choose noise relative to range
sigma = 0.01 * func_range # 1% noise
noisy = SphereFunction(
n_dim=3,
modifiers=[GaussianNoise(sigma=sigma)]
)
Reproducibility#
For reproducible benchmarks, set a random seed:
from surfaces.test_functions.algebraic import SphereFunction
from surfaces.modifiers import GaussianNoise
# Use seed parameter for reproducibility
noisy = SphereFunction(
n_dim=3,
modifiers=[GaussianNoise(sigma=0.1, seed=42)]
)
point = {"x0": 1.0, "x1": 1.0, "x2": 1.0}
# Create another function with same seed
noisy2 = SphereFunction(
n_dim=3,
modifiers=[GaussianNoise(sigma=0.1, seed=42)]
)
# Results are reproducible across instances with same seed
result1 = noisy(point)
result2 = noisy2(point)
assert result1 == result2
Optimizer Strategies#
When optimizing noisy functions:
Multiple evaluations: Average several evaluations at each point
Larger populations: Use population-based methods
Surrogate models: Build noise-robust surrogate approximations
Statistical tests: Use proper comparison methods
# Example: Averaging multiple evaluations
def robust_evaluate(func, params, n_samples=5):
results = [func(params) for _ in range(n_samples)]
return sum(results) / len(results)
avg_result = robust_evaluate(noisy, point, n_samples=10)
Next Steps#
Test Functions - Test functions to apply noise to
Noise - Complete noise API reference