48 lines
1011 B
Go
48 lines
1011 B
Go
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
|||
|
|
// SPDX-License-Identifier: MIT
|
||
|
|
|
||
|
|
package grad
|
||
|
|
|
||
|
|
import (
|
||
|
|
"math"
|
||
|
|
|
||
|
|
"sourcedock.dev/petrbalvin/tensor/internal/core"
|
||
|
|
)
|
||
|
|
|
||
|
|
// numericGrad estimates the gradient of a scalar function at a by
|
||
|
|
// central differences, the reference the analytic backward is checked
|
||
|
|
// against.
|
||
|
|
func numericGrad(f func(a *core.Array) float64, a *core.Array) []float64 {
|
||
|
|
n := a.Len()
|
||
|
|
out := make([]float64, n)
|
||
|
|
for i := range n {
|
||
|
|
hi := 1e-6
|
||
|
|
up := cloneFlat(a)
|
||
|
|
down := cloneFlat(a)
|
||
|
|
up[i] += hi
|
||
|
|
down[i] -= hi
|
||
|
|
au, _ := core.FromFloats(up, a.Shape()...)
|
||
|
|
ad, _ := core.FromFloats(down, a.Shape()...)
|
||
|
|
out[i] = (f(au) - f(ad)) / (2 * hi)
|
||
|
|
}
|
||
|
|
return out
|
||
|
|
}
|
||
|
|
|
||
|
|
func cloneFlat(a *core.Array) []float64 {
|
||
|
|
out := make([]float64, a.Len())
|
||
|
|
for i := range a.Len() {
|
||
|
|
out[i] = a.FloatAt(i)
|
||
|
|
}
|
||
|
|
return out
|
||
|
|
}
|
||
|
|
|
||
|
|
func maxAbsDiff(a, b []float64) float64 {
|
||
|
|
m := 0.0
|
||
|
|
for i := range a {
|
||
|
|
if d := math.Abs(a[i] - b[i]); d > m {
|
||
|
|
m = d
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return m
|
||
|
|
}
|