138 lines
3.4 KiB
Go
138 lines
3.4 KiB
Go
|
package main
|
|||
|
|
|||
|
import (
|
|||
|
"encoding/csv"
|
|||
|
"fmt"
|
|||
|
"math"
|
|||
|
"os"
|
|||
|
"path/filepath"
|
|||
|
"strconv"
|
|||
|
"time"
|
|||
|
|
|||
|
"gonum.org/v1/gonum/mat"
|
|||
|
)
|
|||
|
|
|||
|
const DATA_DIR string = "data"
|
|||
|
|
|||
|
type layer struct {
|
|||
|
weights *mat.Dense
|
|||
|
biases *mat.Dense
|
|||
|
}
|
|||
|
|
|||
|
func array_flatten(two_d_array [][]string) []float64 {
|
|||
|
var result []float64
|
|||
|
for _, line := range two_d_array {
|
|||
|
for _, value := range line {
|
|||
|
float_value, _ := strconv.ParseFloat(value, 64)
|
|||
|
result = append(result, float_value)
|
|||
|
}
|
|||
|
}
|
|||
|
return result
|
|||
|
}
|
|||
|
|
|||
|
func load_matrix_from_csv(file_path string) (*mat.Dense, error) {
|
|||
|
f, err := os.Open(file_path)
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
defer f.Close()
|
|||
|
data, err := csv.NewReader(f).ReadAll()
|
|||
|
return mat.NewDense(len(data), len(data[0]), array_flatten(data)), err
|
|||
|
}
|
|||
|
|
|||
|
func load_test_data(dir string) (*mat.Dense, []layer, error) {
|
|||
|
inputs, err := load_matrix_from_csv(filepath.Join(dir, "inputs.csv"))
|
|||
|
if err != nil { return nil, nil, err }
|
|||
|
var layers []layer
|
|||
|
var weights *mat.Dense
|
|||
|
var biases *mat.Dense
|
|||
|
var path string
|
|||
|
|
|||
|
for n := 1; n < 100; n++ {
|
|||
|
path = filepath.Join(dir, fmt.Sprintf("weights%02d.csv", n))
|
|||
|
_, err = os.Stat(path)
|
|||
|
if err != nil { break }
|
|||
|
weights, err = load_matrix_from_csv(path)
|
|||
|
if err != nil { return nil, nil, err }
|
|||
|
|
|||
|
path = filepath.Join(dir, fmt.Sprintf("biases%02d.csv", n))
|
|||
|
_, err = os.Stat(path)
|
|||
|
if err != nil { break }
|
|||
|
biases, err = load_matrix_from_csv(path)
|
|||
|
if err != nil { return nil, nil, err }
|
|||
|
|
|||
|
layers = append(layers, layer{weights, biases})
|
|||
|
}
|
|||
|
return inputs, layers, nil
|
|||
|
}
|
|||
|
|
|||
|
func sigmoid_scalar(x float64) float64 {
|
|||
|
return 1 / (1 + math.Exp(-x))
|
|||
|
}
|
|||
|
|
|||
|
func sigmoid_element(i, j int, value float64) float64 {
|
|||
|
return sigmoid_scalar(value)
|
|||
|
}
|
|||
|
|
|||
|
func sigmoid_matrix(x mat.Matrix) *mat.Dense {
|
|||
|
var y mat.Dense
|
|||
|
y.Apply(sigmoid_element, x)
|
|||
|
return &y
|
|||
|
}
|
|||
|
|
|||
|
func layer_func(inputs *mat.Dense, weights *mat.Dense, biases *mat.Dense, activation func(x mat.Matrix) *mat.Dense) *mat.Dense {
|
|||
|
var output mat.Dense
|
|||
|
output.Mul(weights, inputs)
|
|||
|
output.Add(&output, biases)
|
|||
|
return sigmoid_matrix(&output)
|
|||
|
}
|
|||
|
|
|||
|
func feed_forward(x *mat.Dense, layers []layer) *mat.Dense {
|
|||
|
var y *mat.Dense = x
|
|||
|
for _, l := range layers {
|
|||
|
y = layer_func(y, l.weights, l.biases, sigmoid_matrix)
|
|||
|
}
|
|||
|
return y
|
|||
|
}
|
|||
|
|
|||
|
func time_feed_forward(n int) {
|
|||
|
inputs, layers, _ := load_test_data(DATA_DIR)
|
|||
|
t0 := time.Now()
|
|||
|
for i := 0; i < n; i++ { feed_forward(inputs, layers) }
|
|||
|
elapsed := time.Since(t0)
|
|||
|
fmt.Printf("%.5f\n", elapsed.Seconds())
|
|||
|
}
|
|||
|
|
|||
|
func examples() {
|
|||
|
x := mat.NewDense(2, 1, []float64{0, 2})
|
|||
|
w1 := mat.NewDense(2, 2, []float64{1, 0, 2, 4})
|
|||
|
b1 := mat.NewDense(2, 1, []float64{0, 1})
|
|||
|
w2 := mat.NewDense(2, 2, []float64{1, 0, 2, 4})
|
|||
|
b2 := mat.NewDense(2, 1, []float64{-0.5, 1})
|
|||
|
layers := []layer{{w1, b1}, {w2, b2}}
|
|||
|
|
|||
|
pre := " "
|
|||
|
fmt.Printf("x1 = %v\n", mat.Formatted(x, mat.Prefix(pre)))
|
|||
|
|
|||
|
fmt.Printf("w1 = %v\n", mat.Formatted(w1, mat.Prefix(pre)))
|
|||
|
fmt.Printf("b1 = %v\n", mat.Formatted(b1, mat.Prefix(pre)))
|
|||
|
fmt.Println("σ(w1 * x1 + b1) = ")
|
|||
|
x2 := layer_func(x, w1, b1, sigmoid_matrix)
|
|||
|
fmt.Printf("x2 = %v\n\n", mat.Formatted(x2, mat.Prefix(pre)))
|
|||
|
|
|||
|
fmt.Printf("w2 = %v\n", mat.Formatted(w2, mat.Prefix(pre)))
|
|||
|
fmt.Printf("b2 = %v\n", mat.Formatted(b2, mat.Prefix(pre)))
|
|||
|
fmt.Println("σ(w2 * x2 + b2) = ")
|
|||
|
x3 := feed_forward(x, layers)
|
|||
|
fmt.Printf("x3 = %v\n", mat.Formatted(x3, mat.Prefix(pre)))
|
|||
|
}
|
|||
|
|
|||
|
func main() {
|
|||
|
n, err := strconv.Atoi(os.Args[1])
|
|||
|
if err != nil {
|
|||
|
fmt.Println(err)
|
|||
|
os.Exit(2)
|
|||
|
}
|
|||
|
time_feed_forward(n)
|
|||
|
}
|