Skip to content

Commit

Permalink
Add Sigmoid and Softmax functions
Browse files Browse the repository at this point in the history
  • Loading branch information
montanaflynn committed Jan 16, 2019
1 parent 713f294 commit 63fbb25
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 5 deletions.
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ All the functions can be seen in [examples/main.go](https://github.com/montanafl

```go
// start with some source data to use
data := []float64{1, 2, 3, 4, 4, 5}
data := []float64{1.0, 2.1, 3.2, 4.823, 4.1, 5.8}

// you could also use different number types like this
// data := stats.LoadRawData([]interface{}{1.1, "2", 3.0, 4, "5"})
// you could also use different types like this
// data := stats.LoadRawData([]int{1, 2, 3, 4, 5})
// data := stats.LoadRawData([]interface{}{1.1, "2", 3})
// etc...

median, _ := stats.Median(data)
fmt.Println(median) // 3.5
fmt.Println(median) // 3.65

roundedMedian, _ := stats.Round(median, 0)
fmt.Println(roundedMedian) // 4
Expand Down Expand Up @@ -90,6 +92,8 @@ func PopulationVariance(input Float64Data) (pvar float64, err error) {}
func Round(input float64, places int) (rounded float64, err error) {}
func Sample(input Float64Data, takenum int, replacement bool) ([]float64, error) {}
func SampleVariance(input Float64Data) (svar float64, err error) {}
func Sigmoid(input Float64Data) ([]float64, error) {}
func SoftMax(input Float64Data) ([]float64, error) {}
func StandardDeviation(input Float64Data) (sdev float64, err error) {}
func StandardDeviationPopulation(input Float64Data) (sdev float64, err error) {}
func StandardDeviationSample(input Float64Data) (sdev float64, err error) {}
Expand Down
11 changes: 10 additions & 1 deletion examples/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import (

func main() {

d := stats.LoadRawData([]interface{}{1.1, "2", 3.0, 4, "5"})
// d := stats.LoadRawData([]interface{}{1.1, "2", 3.0, 4, "5"})
d := stats.LoadRawData([]int{1, 2, 3, 4, 5})

a, _ := stats.Min(d)
fmt.Println(a)
Expand Down Expand Up @@ -156,4 +157,12 @@ func main() {
ac, _ := stats.AutoCorrelation([]float64{1, 2, 3, 4, 5}, 1)
fmt.Println(ac)
// Output: 0.4

sig, _ := stats.Sigmoid([]float64{3.0, 1.0, 0.2})
fmt.Println(s)
// Output: [0.9525741268224334 0.7310585786300049 0.549833997312478]

sm, _ := stats.SoftMax([]float64{3.0, 1.0, 0.2})
fmt.Println(sm)
// Output: [0.8360188027814407 0.11314284146556013 0.05083835575299916]
}
18 changes: 18 additions & 0 deletions sigmoid.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package stats

import "math"

// Sigmoid returns the input values in the range of -1 to 1
// along the sigmoid or s-shaped curve, commonly used in
// machine learning while training neural networks as an
// activation function.
func Sigmoid(input Float64Data) ([]float64, error) {
if input.Len() == 0 {
return Float64Data{}, EmptyInput
}
s := make([]float64, len(input))
for i, v := range input {
s[i] = 1 / (1 + math.Exp(-v))
}
return s, nil
}
41 changes: 41 additions & 0 deletions sigmoid_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package stats

import (
"fmt"
"testing"
)

func ExampleSigmoid() {
s, _ := Sigmoid([]float64{3.0, 1.0, 0.2})
fmt.Println(s)
// Output: [0.9525741268224334 0.7310585786300049 0.549833997312478]
}

func TestSigmoidEmptyInput(t *testing.T) {
_, err := Sigmoid([]float64{})
if err != EmptyInputErr {
t.Errorf("Should have returned empty input error")
}
}

func TestSigmoid(t *testing.T) {
sm, err := Sigmoid([]float64{-0.54761371, 17.04850603, 4.86054302})
if err != nil {
t.Error(err)
}

a := 0.3664182235138545
if sm[0] != a {
t.Errorf("%v != %v", sm[0], a)
}

a = 0.9999999605608187
if sm[1] != a {
t.Errorf("%v != %v", sm[1], a)
}

a = 0.9923132671908277
if sm[2] != a {
t.Errorf("%v != %v", sm[2], a)
}
}
25 changes: 25 additions & 0 deletions softmax.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package stats

import "math"

// SoftMax returns the input values in the range of 0 to 1
// with sum of all the probabilities being equal to one. It
// is commonly used in machine learning neural networks.
func SoftMax(input Float64Data) ([]float64, error) {
if input.Len() == 0 {
return Float64Data{}, EmptyInput
}

s := 0.0
c, _ := Max(input)
for _, e := range input {
s += math.Exp(e - c)
}

sm := make([]float64, len(input))
for i, v := range input {
sm[i] = math.Exp(v-c) / s
}

return sm, nil
}
41 changes: 41 additions & 0 deletions softmax_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package stats

import (
"fmt"
"testing"
)

func ExampleSoftMax() {
sm, _ := SoftMax([]float64{3.0, 1.0, 0.2})
fmt.Println(sm)
// Output: [0.8360188027814407 0.11314284146556013 0.05083835575299916]
}

func TestSoftMaxEmptyInput(t *testing.T) {
_, err := SoftMax([]float64{})
if err != EmptyInputErr {
t.Errorf("Should have returned empty input error")
}
}

func TestSoftMax(t *testing.T) {
sm, err := SoftMax([]float64{3.0, 1.0, 0.2})
if err != nil {
t.Error(err)
}

a := 0.8360188027814407
if sm[0] != a {
t.Errorf("%v != %v", sm[0], a)
}

a = 0.11314284146556013
if sm[1] != a {
t.Errorf("%v != %v", sm[1], a)
}

a = 0.05083835575299916
if sm[2] != a {
t.Errorf("%v != %v", sm[1], a)
}
}

0 comments on commit 63fbb25

Please sign in to comment.