| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- package nn
- import (
- "math"
- "makarna/pkg/backend/cpu"
- )
- // Sigmoid applies the sigmoid function: 1 / (1 + exp(-x))
- // Uses numerically stable computation for both positive and negative inputs.
- func Sigmoid(x float32) float32 {
- if x >= 0 {
- z := float32(math.Exp(float64(-x)))
- return 1 / (1 + z)
- }
- z := float32(math.Exp(float64(x)))
- return z / (1 + z)
- }
- // SigmoidInplace applies sigmoid to each element of the slice in-place.
- func SigmoidInplace(data []float32) {
- for i := range data {
- data[i] = Sigmoid(data[i])
- }
- }
- // SigmoidTensor applies sigmoid in-place to a tensor.
- func SigmoidTensor(x *cpu.Tensor) error {
- SigmoidInplace(x.DataFloat32())
- return nil
- }
- // Softplus computes log(1 + exp(x)), with numerical stability for large x.
- func Softplus(x float32) float32 {
- if x > 20 {
- return x
- }
- return float32(math.Log1p(math.Exp(float64(x))))
- }
- // SoftplusInplace applies softplus to each element of the slice in-place.
- func SoftplusInplace(data []float32) {
- for i := range data {
- data[i] = Softplus(data[i])
- }
- }
- // SoftplusTensor applies softplus in-place to a tensor.
- func SoftplusTensor(x *cpu.Tensor) error {
- SoftplusInplace(x.DataFloat32())
- return nil
- }
- // L2NormInplace normalizes a vector to unit length in-place.
- // eps is added to prevent division by zero.
- func L2NormInplace(x []float32, eps float32) {
- if len(x) == 0 {
- return
- }
- ss := float32(0)
- for _, v := range x {
- ss += v * v
- }
- inv := float32(1.0 / math.Sqrt(float64(ss+eps)))
- for i := range x {
- x[i] *= inv
- }
- }
- // L2NormHeads normalizes Q and K vectors per-head for multi-head attention.
- // Shape: [tokens, numHeads * headDim], normalizes each [headDim] segment.
- func L2NormHeads(q, k []float32, tokens, numHeads, headDim int, eps float32) {
- stride := numHeads * headDim
- for t := 0; t < tokens; t++ {
- base := t * stride
- for h := 0; h < numHeads; h++ {
- off := base + h*headDim
- L2NormInplace(q[off:off+headDim], eps)
- L2NormInplace(k[off:off+headDim], eps)
- }
- }
- }
- // Exp computes e^x
- func Exp(x float32) float32 {
- return float32(math.Exp(float64(x)))
- }
- // ExpInplace applies exp to each element of the slice in-place.
- func ExpInplace(data []float32) {
- for i := range data {
- data[i] = Exp(data[i])
- }
- }
|