1
0
mirror of https://github.com/sjwhitworth/golearn.git synced 2025-04-28 13:48:56 +08:00

Merge pull request #206 from Sentimentron/gonum

Update gonum to the latest version
This commit is contained in:
Richard Townsend 2018-03-24 00:32:46 +00:00 committed by GitHub
commit 623af61265
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 177 additions and 169 deletions

View File

@ -1,7 +1,9 @@
language: go language: go
go: go:
- 1.7 - "1.7"
- 1.8 - "1.8"
- "1.9"
- "1.10"
env: env:
# Temporary workaround for go 1.6 # Temporary workaround for go 1.6
- GODEBUG=cgocheck=0 - GODEBUG=cgocheck=0

View File

@ -1,7 +1,7 @@
package base package base
import ( import (
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
) )
// Classifier implementations predict categorical class labels. // Classifier implementations predict categorical class labels.
@ -37,7 +37,7 @@ type BaseClassifier struct {
} }
type BaseRegressor struct { type BaseRegressor struct {
Data mat64.Dense Data mat.Dense
Name string Name string
Labels []float64 Labels []float64
} }

View File

@ -3,7 +3,7 @@ package base
import ( import (
"fmt" "fmt"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
) )
func checkAllAttributesAreFloat(attrs []Attribute) error { func checkAllAttributesAreFloat(attrs []Attribute) error {
@ -18,8 +18,8 @@ func checkAllAttributesAreFloat(attrs []Attribute) error {
// ConvertRowToMat64 takes a list of Attributes, a FixedDataGrid // ConvertRowToMat64 takes a list of Attributes, a FixedDataGrid
// and a row number, and returns the float values of that row // and a row number, and returns the float values of that row
// in a mat64.Dense format. // in a mat.Dense format.
func ConvertRowToMat64(attrs []Attribute, f FixedDataGrid, r int) (*mat64.Dense, error) { func ConvertRowToMat64(attrs []Attribute, f FixedDataGrid, r int) (*mat.Dense, error) {
err := checkAllAttributesAreFloat(attrs) err := checkAllAttributesAreFloat(attrs)
if err != nil { if err != nil {
@ -27,7 +27,7 @@ func ConvertRowToMat64(attrs []Attribute, f FixedDataGrid, r int) (*mat64.Dense,
} }
// Allocate the return value // Allocate the return value
ret := mat64.NewDense(1, len(attrs), nil) ret := mat.NewDense(1, len(attrs), nil)
// Resolve all the attributes // Resolve all the attributes
attrSpecs := ResolveAttributes(f, attrs) attrSpecs := ResolveAttributes(f, attrs)
@ -42,8 +42,8 @@ func ConvertRowToMat64(attrs []Attribute, f FixedDataGrid, r int) (*mat64.Dense,
} }
// ConvertAllRowsToMat64 takes a list of Attributes and returns a vector // ConvertAllRowsToMat64 takes a list of Attributes and returns a vector
// of all rows in a mat64.Dense format. // of all rows in a mat.Dense format.
func ConvertAllRowsToMat64(attrs []Attribute, f FixedDataGrid) ([]*mat64.Dense, error) { func ConvertAllRowsToMat64(attrs []Attribute, f FixedDataGrid) ([]*mat.Dense, error) {
// Check for floats // Check for floats
err := checkAllAttributesAreFloat(attrs) err := checkAllAttributesAreFloat(attrs)
@ -53,14 +53,14 @@ func ConvertAllRowsToMat64(attrs []Attribute, f FixedDataGrid) ([]*mat64.Dense,
// Return value // Return value
_, rows := f.Size() _, rows := f.Size()
ret := make([]*mat64.Dense, rows) ret := make([]*mat.Dense, rows)
// Resolve all attributes // Resolve all attributes
attrSpecs := ResolveAttributes(f, attrs) attrSpecs := ResolveAttributes(f, attrs)
// Set the values in each return value // Set the values in each return value
for i := 0; i < rows; i++ { for i := 0; i < rows; i++ {
cur := mat64.NewDense(1, len(attrs), nil) cur := mat.NewDense(1, len(attrs), nil)
for j, a := range attrSpecs { for j, a := range attrSpecs {
cur.Set(0, j, UnpackBytesToFloat(f.Get(a, i))) cur.Set(0, j, UnpackBytesToFloat(f.Get(a, i)))
} }

View File

@ -7,7 +7,7 @@ import (
"encoding/gob" "encoding/gob"
"io/ioutil" "io/ioutil"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
) )
// An Estimator is object that can ingest some data and train on it. // An Estimator is object that can ingest some data and train on it.
@ -27,7 +27,7 @@ type Model interface {
} }
type BaseEstimator struct { type BaseEstimator struct {
Data *mat64.Dense Data *mat.Dense
} }
// SaveEstimatorToGob serialises an estimator to a provided filepath, in gob format. // SaveEstimatorToGob serialises an estimator to a provided filepath, in gob format.

View File

@ -3,18 +3,18 @@ package base
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
) )
type Mat64Instances struct { type Mat64Instances struct {
attributes []Attribute attributes []Attribute
classAttrs map[int]bool classAttrs map[int]bool
Data *mat64.Dense Data *mat.Dense
rows int rows int
} }
// InstancesFromMat64 returns a new Mat64Instances from a literal provided. // InstancesFromMat64 returns a new Mat64Instances from a literal provided.
func InstancesFromMat64(rows, cols int, data *mat64.Dense) *Mat64Instances { func InstancesFromMat64(rows, cols int, data *mat.Dense) *Mat64Instances {
var ret Mat64Instances var ret Mat64Instances
for i := 0; i < cols; i++ { for i := 0; i < cols; i++ {

View File

@ -1,15 +1,15 @@
package base package base
import ( import (
"github.com/gonum/matrix/mat64"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
"gonum.org/v1/gonum/mat"
"testing" "testing"
) )
func TestInlineMat64Creation(t *testing.T) { func TestInlineMat64Creation(t *testing.T) {
Convey("Given a literal array...", t, func() { Convey("Given a literal array...", t, func() {
mat := mat64.NewDense(4, 3, []float64{ mat := mat.NewDense(4, 3, []float64{
1, 0, 1, 1, 0, 1,
0, 1, 1, 0, 1, 1,
0, 0, 0, 0, 0, 0,

View File

@ -72,7 +72,7 @@ func tarPrefix(prefix string, suffix string) string {
if prefix == "" { if prefix == "" {
return suffix return suffix
} }
return fmt.Sprintf("%s/%s") return fmt.Sprintf("%s/%s", prefix, suffix)
} }
// ClassifierMetadataV1 is what gets written into METADATA // ClassifierMetadataV1 is what gets written into METADATA

View File

@ -164,16 +164,19 @@ func DeserializeInstancesFromTarReader(tr *FunctionalTarReader, prefix string) (
// Finally, read the values out of the data section // Finally, read the values out of the data section
for i := 0; i < rowCount; i++ { for i := 0; i < rowCount; i++ {
for _, s := range specs { for j, s := range specs {
r := ret.Get(s, i) r := ret.Get(s, i)
n, err := reader.Read(r) n, err := reader.Read(r)
if n != len(r) { if n != len(r) {
return nil, fmt.Errorf("Expected %d bytes (read %d) on row %d", len(r), n, i) return nil, WrapError(fmt.Errorf("Expected %d bytes (read %d) on row %d", len(r), n, i))
}
if err != nil {
return nil, fmt.Errorf("Read error: %s", err)
} }
ret.Set(s, i, r) ret.Set(s, i, r)
if err != nil {
if i == rowCount-1 && j == len(specs)-1 && err == io.EOF {
break
}
return nil, WrapError(fmt.Errorf("Read error in data section (at row %d from %d, attr %d from %d): %s", i, rowCount, j, len(specs), err))
}
} }
} }
@ -300,6 +303,9 @@ func SerializeInstancesToTarWriter(inst FixedDataGrid, tw *tar.Writer, prefix st
} }
allSpecs := ResolveAttributes(inst, allAttrs) allSpecs := ResolveAttributes(inst, allAttrs)
if len(allSpecs) != len(allAttrs) {
return WrapError(fmt.Errorf("Error resolving all Attributes: resolved %d, expected %d", len(allSpecs), len(allAttrs)))
}
// First, estimate the amount of data we'll need... // First, estimate the amount of data we'll need...
dataLength := int64(0) dataLength := int64(0)

View File

@ -1,7 +1,7 @@
package clustering package clustering
import ( import (
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
"github.com/sjwhitworth/golearn/base" "github.com/sjwhitworth/golearn/base"
"github.com/sjwhitworth/golearn/metrics/pairwise" "github.com/sjwhitworth/golearn/metrics/pairwise"
"math/big" "math/big"
@ -22,7 +22,7 @@ type DBSCANParameters struct {
MinCount int MinCount int
} }
func regionQuery(p int, ret *big.Int, dist *mat64.Dense, eps float64) *big.Int { func regionQuery(p int, ret *big.Int, dist *mat.Dense, eps float64) *big.Int {
rows, _ := dist.Dims() rows, _ := dist.Dims()
// Return any points within the Eps neighbourhood // Return any points within the Eps neighbourhood
for i := 0; i < rows; i++ { for i := 0; i < rows; i++ {
@ -33,7 +33,7 @@ func regionQuery(p int, ret *big.Int, dist *mat64.Dense, eps float64) *big.Int {
return ret return ret
} }
func computePairwiseDistances(inst base.FixedDataGrid, attrs []base.Attribute, metric pairwise.PairwiseDistanceFunc) (*mat64.Dense, error) { func computePairwiseDistances(inst base.FixedDataGrid, attrs []base.Attribute, metric pairwise.PairwiseDistanceFunc) (*mat.Dense, error) {
// Compute pair-wise distances // Compute pair-wise distances
// First convert everything to floats // First convert everything to floats
mats, err := base.ConvertAllRowsToMat64(attrs, inst) mats, err := base.ConvertAllRowsToMat64(attrs, inst)
@ -43,7 +43,7 @@ func computePairwiseDistances(inst base.FixedDataGrid, attrs []base.Attribute, m
// Next, do an n^2 computation of all pairwise distances // Next, do an n^2 computation of all pairwise distances
_, rows := inst.Size() _, rows := inst.Size()
dist := mat64.NewDense(rows, rows, nil) dist := mat.NewDense(rows, rows, nil)
for i := 0; i < rows; i++ { for i := 0; i < rows; i++ {
for j := i + 1; j < rows; j++ { for j := i + 1; j < rows; j++ {
d := metric.Distance(mats[i], mats[j]) d := metric.Distance(mats[i], mats[j])

View File

@ -2,7 +2,7 @@ package clustering
import ( import (
"bufio" "bufio"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
"github.com/sjwhitworth/golearn/base" "github.com/sjwhitworth/golearn/base"
"github.com/sjwhitworth/golearn/metrics/pairwise" "github.com/sjwhitworth/golearn/metrics/pairwise"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
@ -76,8 +76,8 @@ func TestDBSCANDistanceMetric(t *testing.T) {
Convey("Check the distance function is sane...", t, func() { Convey("Check the distance function is sane...", t, func() {
d1 := mat64.NewDense(1, 2, nil) d1 := mat.NewDense(1, 2, nil)
d2 := mat64.NewDense(1, 2, nil) d2 := mat.NewDense(1, 2, nil)
d1.Set(0, 0, 0.494260967249) d1.Set(0, 0, 0.494260967249)
d1.Set(0, 1, 1.45106696541) d1.Set(0, 1, 1.45106696541)

View File

@ -2,7 +2,7 @@ package kdtree
import ( import (
"errors" "errors"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
"github.com/sjwhitworth/golearn/metrics/pairwise" "github.com/sjwhitworth/golearn/metrics/pairwise"
"sort" "sort"
) )
@ -140,8 +140,8 @@ func (t *Tree) Search(k int, disType pairwise.PairwiseDistanceFunc, target []flo
func (t *Tree) searchHandle(k int, disType pairwise.PairwiseDistanceFunc, target []float64, h *heap, n *node) { func (t *Tree) searchHandle(k int, disType pairwise.PairwiseDistanceFunc, target []float64, h *heap, n *node) {
if n.feature == -1 { if n.feature == -1 {
vectorX := mat64.NewDense(len(target), 1, target) vectorX := mat.NewDense(len(target), 1, target)
vectorY := mat64.NewDense(len(target), 1, n.value) vectorY := mat.NewDense(len(target), 1, n.value)
length := disType.Distance(vectorX, vectorY) length := disType.Distance(vectorX, vectorY)
h.insert(n.value, length, n.srcRowNo) h.insert(n.value, length, n.srcRowNo)
return return
@ -157,8 +157,8 @@ func (t *Tree) searchHandle(k int, disType pairwise.PairwiseDistanceFunc, target
t.searchHandle(k, disType, target, h, n.right) t.searchHandle(k, disType, target, h, n.right)
} }
vectorX := mat64.NewDense(len(target), 1, target) vectorX := mat.NewDense(len(target), 1, target)
vectorY := mat64.NewDense(len(target), 1, n.value) vectorY := mat.NewDense(len(target), 1, n.value)
length := disType.Distance(vectorX, vectorY) length := disType.Distance(vectorX, vectorY)
if k > h.size() { if k > h.size() {
@ -177,8 +177,8 @@ func (t *Tree) searchHandle(k int, disType pairwise.PairwiseDistanceFunc, target
t.searchAllNodes(k, disType, target, h, n.left) t.searchAllNodes(k, disType, target, h, n.left)
} }
} else { } else {
vectorX = mat64.NewDense(1, 1, []float64{target[n.feature]}) vectorX = mat.NewDense(1, 1, []float64{target[n.feature]})
vectorY = mat64.NewDense(1, 1, []float64{n.value[n.feature]}) vectorY = mat.NewDense(1, 1, []float64{n.value[n.feature]})
length = disType.Distance(vectorX, vectorY) length = disType.Distance(vectorX, vectorY)
if h.maximum().length > length { if h.maximum().length > length {
@ -192,8 +192,8 @@ func (t *Tree) searchHandle(k int, disType pairwise.PairwiseDistanceFunc, target
} }
func (t *Tree) searchAllNodes(k int, disType pairwise.PairwiseDistanceFunc, target []float64, h *heap, n *node) { func (t *Tree) searchAllNodes(k int, disType pairwise.PairwiseDistanceFunc, target []float64, h *heap, n *node) {
vectorX := mat64.NewDense(len(target), 1, target) vectorX := mat.NewDense(len(target), 1, target)
vectorY := mat64.NewDense(len(target), 1, n.value) vectorY := mat.NewDense(len(target), 1, n.value)
length := disType.Distance(vectorX, vectorY) length := disType.Distance(vectorX, vectorY)
if k > h.size() { if k > h.size() {

View File

@ -8,7 +8,7 @@ import (
"fmt" "fmt"
"github.com/gonum/matrix" "github.com/gonum/matrix"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
"github.com/sjwhitworth/golearn/base" "github.com/sjwhitworth/golearn/base"
"github.com/sjwhitworth/golearn/kdtree" "github.com/sjwhitworth/golearn/kdtree"
"github.com/sjwhitworth/golearn/metrics/pairwise" "github.com/sjwhitworth/golearn/metrics/pairwise"
@ -434,11 +434,11 @@ func (KNN *KNNRegressor) Fit(values []float64, numbers []float64, rows int, cols
panic(matrix.ErrShape) panic(matrix.ErrShape)
} }
KNN.Data = mat64.NewDense(rows, cols, numbers) KNN.Data = mat.NewDense(rows, cols, numbers)
KNN.Values = values KNN.Values = values
} }
func (KNN *KNNRegressor) Predict(vector *mat64.Dense, K int) float64 { func (KNN *KNNRegressor) Predict(vector *mat.Dense, K int) float64 {
// Get the number of rows // Get the number of rows
rows, _ := KNN.Data.Dims() rows, _ := KNN.Data.Dims()
rownumbers := make(map[int]float64) rownumbers := make(map[int]float64)

View File

@ -7,7 +7,7 @@ import (
"fmt" "fmt"
_ "github.com/gonum/blas" _ "github.com/gonum/blas"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
) )
var ( var (
@ -59,8 +59,8 @@ func (lr *LinearRegression) Fit(inst base.FixedDataGrid) error {
// Split into two matrices, observed results (dependent variable y) // Split into two matrices, observed results (dependent variable y)
// and the explanatory variables (X) - see http://en.wikipedia.org/wiki/Linear_regression // and the explanatory variables (X) - see http://en.wikipedia.org/wiki/Linear_regression
observed := mat64.NewDense(rows, 1, nil) observed := mat.NewDense(rows, 1, nil)
explVariables := mat64.NewDense(rows, cols, nil) explVariables := mat.NewDense(rows, cols, nil)
// Build the observed matrix // Build the observed matrix
inst.MapOverRows(classAttrSpecs, func(row [][]byte, i int) (bool, error) { inst.MapOverRows(classAttrSpecs, func(row [][]byte, i int) (bool, error) {
@ -80,13 +80,13 @@ func (lr *LinearRegression) Fit(inst base.FixedDataGrid) error {
}) })
n := cols n := cols
qr := new(mat64.QR) qr := new(mat.QR)
qr.Factorize(explVariables) qr.Factorize(explVariables)
var q, reg mat64.Dense var q, reg mat.Dense
q.QFromQR(qr) qr.QTo(&q)
reg.RFromQR(qr) qr.RTo(&reg)
var transposed, qty mat64.Dense var transposed, qty mat.Dense
transposed.Clone(q.T()) transposed.Clone(q.T())
qty.Mul(&transposed, observed) qty.Mul(&transposed, observed)

View File

@ -176,7 +176,7 @@ func (m *OneVsAllModel) LoadWithPrefix(reader *base.ClassifierDeserializer, pref
attrMap := make(map[base.Attribute]base.Attribute) attrMap := make(map[base.Attribute]base.Attribute)
for j := 0; j < int(numAttrsInMapU64); j++ { for j := 0; j < int(numAttrsInMapU64); j++ {
mapTupleKey := reader.Prefix(mapPrefix, fmt.Sprintf("%d")) mapTupleKey := reader.Prefix(mapPrefix, fmt.Sprintf("%d", j))
mapKeyKeyKey := reader.Prefix(mapTupleKey, "KEY") mapKeyKeyKey := reader.Prefix(mapTupleKey, "KEY")
mapKeyValKey := reader.Prefix(mapTupleKey, "VAL") mapKeyValKey := reader.Prefix(mapTupleKey, "VAL")
@ -289,7 +289,7 @@ func (m *OneVsAllModel) SaveWithPrefix(writer *base.ClassifierSerializer, prefix
} }
j := 0 j := 0
for key := range f.attrs { for key := range f.attrs {
mapTupleKey := writer.Prefix(mapPrefix, fmt.Sprintf("%d")) mapTupleKey := writer.Prefix(mapPrefix, fmt.Sprintf("%d", j))
mapKeyKeyKey := writer.Prefix(mapTupleKey, "KEY") mapKeyKeyKey := writer.Prefix(mapTupleKey, "KEY")
mapKeyValKey := writer.Prefix(mapTupleKey, "VAL") mapKeyValKey := writer.Prefix(mapTupleKey, "VAL")

View File

@ -4,7 +4,7 @@ import (
"math" "math"
"github.com/gonum/matrix" "github.com/gonum/matrix"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
) )
type Chebyshev struct{} type Chebyshev struct{}
@ -13,7 +13,7 @@ func NewChebyshev() *Chebyshev {
return &Chebyshev{} return &Chebyshev{}
} }
func (c *Chebyshev) Distance(vectorX *mat64.Dense, vectorY *mat64.Dense) float64 { func (c *Chebyshev) Distance(vectorX *mat.Dense, vectorY *mat.Dense) float64 {
r1, c1 := vectorX.Dims() r1, c1 := vectorX.Dims()
r2, c2 := vectorY.Dims() r2, c2 := vectorY.Dims()
if r1 != r2 || c1 != c2 { if r1 != r2 || c1 != c2 {

View File

@ -3,17 +3,17 @@ package pairwise
import ( import (
"testing" "testing"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
) )
func TestChebyshev(t *testing.T) { func TestChebyshev(t *testing.T) {
var vectorX, vectorY *mat64.Dense var vectorX, vectorY *mat.Dense
chebyshev := NewChebyshev() chebyshev := NewChebyshev()
Convey("Given two vectors", t, func() { Convey("Given two vectors", t, func() {
vectorX = mat64.NewDense(4, 1, []float64{1, 2, 3, 4}) vectorX = mat.NewDense(4, 1, []float64{1, 2, 3, 4})
vectorY = mat64.NewDense(4, 1, []float64{-5, -6, 7, 8}) vectorY = mat.NewDense(4, 1, []float64{-5, -6, 7, 8})
Convey("When calculating distance with two vectors", func() { Convey("When calculating distance with two vectors", func() {
result := chebyshev.Distance(vectorX, vectorY) result := chebyshev.Distance(vectorX, vectorY)

View File

@ -3,7 +3,7 @@ package pairwise
import ( import (
"math" "math"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
) )
type Cosine struct{} type Cosine struct{}
@ -13,17 +13,17 @@ func NewCosine() *Cosine {
} }
// Dot computes dot value of vectorX and vectorY. // Dot computes dot value of vectorX and vectorY.
func (c *Cosine) Dot(vectorX *mat64.Dense, vectorY *mat64.Dense) float64 { func (c *Cosine) Dot(vectorX *mat.Dense, vectorY *mat.Dense) float64 {
subVector := mat64.NewDense(0, 0, nil) subVector := mat.NewDense(0, 0, nil)
subVector.MulElem(vectorX, vectorY) subVector.MulElem(vectorX, vectorY)
result := mat64.Sum(subVector) result := mat.Sum(subVector)
return result return result
} }
// Distance computes Cosine distance. // Distance computes Cosine distance.
// It will return distance which represented as 1-cos() (ranged from 0 to 2). // It will return distance which represented as 1-cos() (ranged from 0 to 2).
func (c *Cosine) Distance(vectorX *mat64.Dense, vectorY *mat64.Dense) float64 { func (c *Cosine) Distance(vectorX *mat.Dense, vectorY *mat.Dense) float64 {
dotXY := c.Dot(vectorX, vectorY) dotXY := c.Dot(vectorX, vectorY)
lengthX := math.Sqrt(c.Dot(vectorX, vectorX)) lengthX := math.Sqrt(c.Dot(vectorX, vectorX))
lengthY := math.Sqrt(c.Dot(vectorY, vectorY)) lengthY := math.Sqrt(c.Dot(vectorY, vectorY))

View File

@ -3,17 +3,17 @@ package pairwise
import ( import (
"testing" "testing"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
) )
func TestCosine(t *testing.T) { func TestCosine(t *testing.T) {
var vectorX, vectorY *mat64.Dense var vectorX, vectorY *mat.Dense
cosine := NewCosine() cosine := NewCosine()
Convey("Given two vectors", t, func() { Convey("Given two vectors", t, func() {
vectorX = mat64.NewDense(3, 1, []float64{1, 2, 3}) vectorX = mat.NewDense(3, 1, []float64{1, 2, 3})
vectorY = mat64.NewDense(3, 1, []float64{2, 4, 6}) vectorY = mat.NewDense(3, 1, []float64{2, 4, 6})
Convey("When doing inner Dot", func() { Convey("When doing inner Dot", func() {
result := cosine.Dot(vectorX, vectorY) result := cosine.Dot(vectorX, vectorY)

View File

@ -4,7 +4,7 @@ import (
"math" "math"
"github.com/gonum/matrix" "github.com/gonum/matrix"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
) )
type Cranberra struct{} type Cranberra struct{}
@ -20,7 +20,7 @@ func cranberraDistanceStep(num float64, denom float64) float64 {
return num / denom return num / denom
} }
func (c *Cranberra) Distance(vectorX *mat64.Dense, vectorY *mat64.Dense) float64 { func (c *Cranberra) Distance(vectorX *mat.Dense, vectorY *mat.Dense) float64 {
r1, c1 := vectorX.Dims() r1, c1 := vectorX.Dims()
r2, c2 := vectorY.Dims() r2, c2 := vectorY.Dims()
if r1 != r2 || c1 != c2 { if r1 != r2 || c1 != c2 {

View File

@ -3,16 +3,16 @@ package pairwise
import ( import (
"testing" "testing"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
) )
func TestCranberrra(t *testing.T) { func TestCranberrra(t *testing.T) {
var vectorX, vectorY *mat64.Dense var vectorX, vectorY *mat.Dense
cranberra := NewCranberra() cranberra := NewCranberra()
Convey("Given two vectors that are same", t, func() { Convey("Given two vectors that are same", t, func() {
vec := mat64.NewDense(7, 1, []float64{0, 1, -2, 3.4, 5, -6.7, 89}) vec := mat.NewDense(7, 1, []float64{0, 1, -2, 3.4, 5, -6.7, 89})
distance := cranberra.Distance(vec, vec) distance := cranberra.Distance(vec, vec)
Convey("The result should be 0", func() { Convey("The result should be 0", func() {
@ -21,8 +21,8 @@ func TestCranberrra(t *testing.T) {
}) })
Convey("Given two vectors", t, func() { Convey("Given two vectors", t, func() {
vectorX = mat64.NewDense(5, 1, []float64{1, 2, 3, 4, 9}) vectorX = mat.NewDense(5, 1, []float64{1, 2, 3, 4, 9})
vectorY = mat64.NewDense(5, 1, []float64{-5, -6, 7, 4, 3}) vectorY = mat.NewDense(5, 1, []float64{-5, -6, 7, 4, 3})
Convey("When calculating distance with two vectors", func() { Convey("When calculating distance with two vectors", func() {
result := cranberra.Distance(vectorX, vectorY) result := cranberra.Distance(vectorX, vectorY)

View File

@ -3,7 +3,7 @@ package pairwise
import ( import (
"math" "math"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
) )
type Euclidean struct{} type Euclidean struct{}
@ -13,17 +13,17 @@ func NewEuclidean() *Euclidean {
} }
// InnerProduct computes a Eucledian inner product. // InnerProduct computes a Eucledian inner product.
func (e *Euclidean) InnerProduct(vectorX *mat64.Dense, vectorY *mat64.Dense) float64 { func (e *Euclidean) InnerProduct(vectorX *mat.Dense, vectorY *mat.Dense) float64 {
subVector := mat64.NewDense(0, 0, nil) subVector := mat.NewDense(0, 0, nil)
subVector.MulElem(vectorX, vectorY) subVector.MulElem(vectorX, vectorY)
result := mat64.Sum(subVector) result := mat.Sum(subVector)
return result return result
} }
// Distance computes Euclidean distance (also known as L2 distance). // Distance computes Euclidean distance (also known as L2 distance).
func (e *Euclidean) Distance(vectorX *mat64.Dense, vectorY *mat64.Dense) float64 { func (e *Euclidean) Distance(vectorX *mat.Dense, vectorY *mat.Dense) float64 {
subVector := mat64.NewDense(0, 0, nil) subVector := mat.NewDense(0, 0, nil)
subVector.Sub(vectorX, vectorY) subVector.Sub(vectorX, vectorY)
result := e.InnerProduct(subVector, subVector) result := e.InnerProduct(subVector, subVector)

View File

@ -3,17 +3,17 @@ package pairwise
import ( import (
"testing" "testing"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
) )
func TestEuclidean(t *testing.T) { func TestEuclidean(t *testing.T) {
var vectorX, vectorY *mat64.Dense var vectorX, vectorY *mat.Dense
euclidean := NewEuclidean() euclidean := NewEuclidean()
Convey("Given two vectors", t, func() { Convey("Given two vectors", t, func() {
vectorX = mat64.NewDense(3, 1, []float64{1, 2, 3}) vectorX = mat.NewDense(3, 1, []float64{1, 2, 3})
vectorY = mat64.NewDense(3, 1, []float64{2, 4, 5}) vectorY = mat.NewDense(3, 1, []float64{2, 4, 5})
Convey("When doing inner product", func() { Convey("When doing inner product", func() {
result := euclidean.InnerProduct(vectorX, vectorY) result := euclidean.InnerProduct(vectorX, vectorY)

View File

@ -4,7 +4,7 @@ import (
"math" "math"
"github.com/gonum/matrix" "github.com/gonum/matrix"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
) )
type Manhattan struct{} type Manhattan struct{}
@ -15,7 +15,7 @@ func NewManhattan() *Manhattan {
// Distance computes the Manhattan distance, also known as L1 distance. // Distance computes the Manhattan distance, also known as L1 distance.
// == the sum of the absolute values of elements. // == the sum of the absolute values of elements.
func (m *Manhattan) Distance(vectorX *mat64.Dense, vectorY *mat64.Dense) float64 { func (m *Manhattan) Distance(vectorX *mat.Dense, vectorY *mat.Dense) float64 {
r1, c1 := vectorX.Dims() r1, c1 := vectorX.Dims()
r2, c2 := vectorY.Dims() r2, c2 := vectorY.Dims()
if r1 != r2 || c1 != c2 { if r1 != r2 || c1 != c2 {

View File

@ -3,16 +3,16 @@ package pairwise
import ( import (
"testing" "testing"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
) )
func TestManhattan(t *testing.T) { func TestManhattan(t *testing.T) {
var vectorX, vectorY *mat64.Dense var vectorX, vectorY *mat.Dense
manhattan := NewManhattan() manhattan := NewManhattan()
Convey("Given two vectors that are same", t, func() { Convey("Given two vectors that are same", t, func() {
vec := mat64.NewDense(7, 1, []float64{0, 1, -2, 3.4, 5, -6.7, 89}) vec := mat.NewDense(7, 1, []float64{0, 1, -2, 3.4, 5, -6.7, 89})
distance := manhattan.Distance(vec, vec) distance := manhattan.Distance(vec, vec)
Convey("The result should be 0", func() { Convey("The result should be 0", func() {
@ -21,8 +21,8 @@ func TestManhattan(t *testing.T) {
}) })
Convey("Given two vectors", t, func() { Convey("Given two vectors", t, func() {
vectorX = mat64.NewDense(3, 1, []float64{2, 2, 3}) vectorX = mat.NewDense(3, 1, []float64{2, 2, 3})
vectorY = mat64.NewDense(3, 1, []float64{1, 4, 5}) vectorY = mat.NewDense(3, 1, []float64{1, 4, 5})
Convey("When calculating distance with column vectors", func() { Convey("When calculating distance with column vectors", func() {
result := manhattan.Distance(vectorX, vectorY) result := manhattan.Distance(vectorX, vectorY)

View File

@ -2,9 +2,9 @@
package pairwise package pairwise
import ( import (
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
) )
type PairwiseDistanceFunc interface { type PairwiseDistanceFunc interface {
Distance(vectorX *mat64.Dense, vectorY *mat64.Dense) float64 Distance(vectorX *mat.Dense, vectorY *mat.Dense) float64
} }

View File

@ -3,7 +3,7 @@ package pairwise
import ( import (
"math" "math"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
) )
type PolyKernel struct { type PolyKernel struct {
@ -17,18 +17,18 @@ func NewPolyKernel(degree int) *PolyKernel {
// InnerProduct computes the inner product through a kernel trick // InnerProduct computes the inner product through a kernel trick
// K(x, y) = (x^T y + 1)^d // K(x, y) = (x^T y + 1)^d
func (p *PolyKernel) InnerProduct(vectorX *mat64.Dense, vectorY *mat64.Dense) float64 { func (p *PolyKernel) InnerProduct(vectorX *mat.Dense, vectorY *mat.Dense) float64 {
subVectorX := vectorX.ColView(0) subVectorX := vectorX.ColView(0)
subVectorY := vectorY.ColView(0) subVectorY := vectorY.ColView(0)
result := mat64.Dot(subVectorX, subVectorY) result := mat.Dot(subVectorX, subVectorY)
result = math.Pow(result+1, float64(p.degree)) result = math.Pow(result+1, float64(p.degree))
return result return result
} }
// Distance computes distance under the polynomial kernel (maybe not needed?) // Distance computes distance under the polynomial kernel (maybe not needed?)
func (p *PolyKernel) Distance(vectorX *mat64.Dense, vectorY *mat64.Dense) float64 { func (p *PolyKernel) Distance(vectorX *mat.Dense, vectorY *mat.Dense) float64 {
subVector := mat64.NewDense(0, 0, nil) subVector := mat.NewDense(0, 0, nil)
subVector.Sub(vectorX, vectorY) subVector.Sub(vectorX, vectorY)
result := p.InnerProduct(subVector, subVector) result := p.InnerProduct(subVector, subVector)

View File

@ -3,17 +3,17 @@ package pairwise
import ( import (
"testing" "testing"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
) )
func TestPolyKernel(t *testing.T) { func TestPolyKernel(t *testing.T) {
var vectorX, vectorY *mat64.Dense var vectorX, vectorY *mat.Dense
polyKernel := NewPolyKernel(3) polyKernel := NewPolyKernel(3)
Convey("Given two vectors", t, func() { Convey("Given two vectors", t, func() {
vectorX = mat64.NewDense(3, 1, []float64{1, 2, 3}) vectorX = mat.NewDense(3, 1, []float64{1, 2, 3})
vectorY = mat64.NewDense(3, 1, []float64{2, 4, 5}) vectorY = mat.NewDense(3, 1, []float64{2, 4, 5})
Convey("When doing inner product", func() { Convey("When doing inner product", func() {
result := polyKernel.InnerProduct(vectorX, vectorY) result := polyKernel.InnerProduct(vectorX, vectorY)

View File

@ -3,7 +3,7 @@ package pairwise
import ( import (
"math" "math"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
) )
type RBFKernel struct { type RBFKernel struct {
@ -17,7 +17,7 @@ func NewRBFKernel(gamma float64) *RBFKernel {
// InnerProduct computes the inner product through a kernel trick // InnerProduct computes the inner product through a kernel trick
// K(x, y) = exp(-gamma * ||x - y||^2) // K(x, y) = exp(-gamma * ||x - y||^2)
func (r *RBFKernel) InnerProduct(vectorX *mat64.Dense, vectorY *mat64.Dense) float64 { func (r *RBFKernel) InnerProduct(vectorX *mat.Dense, vectorY *mat.Dense) float64 {
euclidean := NewEuclidean() euclidean := NewEuclidean()
distance := euclidean.Distance(vectorX, vectorY) distance := euclidean.Distance(vectorX, vectorY)

View File

@ -3,17 +3,17 @@ package pairwise
import ( import (
"testing" "testing"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
) )
func TestRBFKernel(t *testing.T) { func TestRBFKernel(t *testing.T) {
var vectorX, vectorY *mat64.Dense var vectorX, vectorY *mat.Dense
rbfKernel := NewRBFKernel(0.1) rbfKernel := NewRBFKernel(0.1)
Convey("Given two vectors", t, func() { Convey("Given two vectors", t, func() {
vectorX = mat64.NewDense(3, 1, []float64{1, 2, 3}) vectorX = mat.NewDense(3, 1, []float64{1, 2, 3})
vectorY = mat64.NewDense(3, 1, []float64{2, 4, 5}) vectorY = mat.NewDense(3, 1, []float64{2, 4, 5})
Convey("When doing inner product", func() { Convey("When doing inner product", func() {
result := rbfKernel.InnerProduct(vectorX, vectorY) result := rbfKernel.InnerProduct(vectorX, vectorY)

View File

@ -212,7 +212,7 @@ func (nb *BernoulliNBClassifier) Fit(X base.FixedDataGrid) {
docsContainingTerm := make(map[string][]int) docsContainingTerm := make(map[string][]int)
// This algorithm could be vectorized after binarizing the data // This algorithm could be vectorized after binarizing the data
// matrix. Since mat64 doesn't have this function, a iterative // matrix. Since mat doesn't have this function, a iterative
// version is used. // version is used.
X.MapOverRows(featAttrSpecs, func(docVector [][]byte, r int) (bool, error) { X.MapOverRows(featAttrSpecs, func(docVector [][]byte, r int) (bool, error) {
class := base.GetClass(X, r) class := base.GetClass(X, r)

View File

@ -2,7 +2,7 @@ package neural
import ( import (
"fmt" "fmt"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
"github.com/sjwhitworth/golearn/base" "github.com/sjwhitworth/golearn/base"
"github.com/sjwhitworth/golearn/filters" "github.com/sjwhitworth/golearn/filters"
"math" "math"
@ -105,7 +105,7 @@ func (m *MultiLayerNet) Predict(X base.FixedDataGrid) base.FixedDataGrid {
} }
// Create the activation vector // Create the activation vector
a := mat64.NewDense(m.network.size, 1, make([]float64, m.network.size)) a := mat.NewDense(m.network.size, 1, make([]float64, m.network.size))
// Resolve the input AttributeSpecs // Resolve the input AttributeSpecs
inputAs := base.ResolveAttributes(insts, inputAttrs) inputAs := base.ResolveAttributes(insts, inputAttrs)
@ -277,9 +277,9 @@ func (m *MultiLayerNet) Fit(X base.FixedDataGrid) {
} }
// Create the training activation vector // Create the training activation vector
trainVec := mat64.NewDense(size, 1, make([]float64, size)) trainVec := mat.NewDense(size, 1, make([]float64, size))
// Create the error vector // Create the error vector
errVec := mat64.NewDense(size, 1, make([]float64, size)) errVec := mat.NewDense(size, 1, make([]float64, size))
// Resolve training AttributeSpecs // Resolve training AttributeSpecs
trainAs := base.ResolveAllAttributes(insts) trainAs := base.ResolveAllAttributes(insts)
@ -322,7 +322,7 @@ func (m *MultiLayerNet) Fit(X base.FixedDataGrid) {
} }
// Update total error // Update total error
totalError += math.Abs(mat64.Sum(errVec)) totalError += math.Abs(mat.Sum(errVec))
// Back-propagate the error // Back-propagate the error
b := m.network.Error(trainVec, errVec, totalLayers) b := m.network.Error(trainVec, errVec, totalLayers)

View File

@ -1,7 +1,7 @@
package neural package neural
import ( import (
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
"github.com/sjwhitworth/golearn/base" "github.com/sjwhitworth/golearn/base"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
"testing" "testing"
@ -129,7 +129,7 @@ func TestLayeredXOR(t *testing.T) {
} }
}) })
out := mat64.NewDense(6, 1, []float64{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}) out := mat.NewDense(6, 1, []float64{1.0, 0.0, 0.0, 0.0, 0.0, 0.0})
net.network.Activate(out, 2) net.network.Activate(out, 2)
So(out.At(5, 0), ShouldAlmostEqual, 1.0, 0.1) So(out.At(5, 0), ShouldAlmostEqual, 1.0, 0.1)
@ -160,7 +160,7 @@ func TestLayeredXORInline(t *testing.T) {
Convey("Given an inline XOR dataset...", t, func() { Convey("Given an inline XOR dataset...", t, func() {
data := mat64.NewDense(4, 3, []float64{ data := mat.NewDense(4, 3, []float64{
1, 0, 1, 1, 0, 1,
0, 1, 1, 0, 1, 1,
0, 0, 0, 0, 0, 0,
@ -186,7 +186,7 @@ func TestLayeredXORInline(t *testing.T) {
} }
}) })
out := mat64.NewDense(6, 1, []float64{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}) out := mat.NewDense(6, 1, []float64{1.0, 0.0, 0.0, 0.0, 0.0, 0.0})
net.network.Activate(out, 2) net.network.Activate(out, 2)
So(out.At(5, 0), ShouldAlmostEqual, 1.0, 0.1) So(out.At(5, 0), ShouldAlmostEqual, 1.0, 0.1)

View File

@ -3,7 +3,7 @@ package neural
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
"math" "math"
) )
@ -11,8 +11,8 @@ import (
// Weights are stored in a dense matrix, each can have its own // Weights are stored in a dense matrix, each can have its own
// NeuralFunction. // NeuralFunction.
type Network struct { type Network struct {
origWeights *mat64.Dense origWeights *mat.Dense
weights *mat64.Dense // n * n weights *mat.Dense // n * n
biases []float64 // n for each neuron biases []float64 // n for each neuron
funcs []NeuralFunction // for each neuron funcs []NeuralFunction // for each neuron
size int size int
@ -27,7 +27,7 @@ type Network struct {
// connected to themselves for propagation. // connected to themselves for propagation.
func NewNetwork(size int, input int, f NeuralFunction) *Network { func NewNetwork(size int, input int, f NeuralFunction) *Network {
ret := new(Network) ret := new(Network)
ret.weights = mat64.NewDense(size, size, make([]float64, size*size)) ret.weights = mat.NewDense(size, size, make([]float64, size*size))
ret.biases = make([]float64, size) ret.biases = make([]float64, size)
ret.funcs = make([]NeuralFunction, size) ret.funcs = make([]NeuralFunction, size)
ret.size = size ret.size = size
@ -104,7 +104,7 @@ func (n *Network) GetBias(node int) float64 {
// should be set to the number of layers. // should be set to the number of layers.
// //
// This function overwrites whatever's stored in its first argument. // This function overwrites whatever's stored in its first argument.
func (n *Network) Activate(with *mat64.Dense, maxIterations int) { func (n *Network) Activate(with *mat.Dense, maxIterations int) {
// Add bias and feed to activation // Add bias and feed to activation
biasFunc := func(r, c int, v float64) float64 { biasFunc := func(r, c int, v float64) float64 {
@ -114,7 +114,7 @@ func (n *Network) Activate(with *mat64.Dense, maxIterations int) {
return n.funcs[r].Forward(v) return n.funcs[r].Forward(v)
} }
tmp := new(mat64.Dense) tmp := new(mat.Dense)
tmp.Clone(with) tmp.Clone(with)
// Main loop // Main loop
@ -128,10 +128,10 @@ func (n *Network) Activate(with *mat64.Dense, maxIterations int) {
// UpdateWeights takes an output size * 1 output vector and a size * 1 // UpdateWeights takes an output size * 1 output vector and a size * 1
// back-propagated error vector, as well as a learnRate and updates // back-propagated error vector, as well as a learnRate and updates
// the internal weights matrix. // the internal weights matrix.
func (n *Network) UpdateWeights(out, err *mat64.Dense, learnRate float64) { func (n *Network) UpdateWeights(out, err *mat.Dense, learnRate float64) {
if n.origWeights == nil { if n.origWeights == nil {
n.origWeights = mat64.DenseCopyOf(n.weights) n.origWeights = mat.DenseCopyOf(n.weights)
} }
// Multiply that by the learning rate // Multiply that by the learning rate
@ -151,7 +151,7 @@ func (n *Network) UpdateWeights(out, err *mat64.Dense, learnRate float64) {
// UpdateBias computes B = B + l.E and updates the bias weights // UpdateBias computes B = B + l.E and updates the bias weights
// from a size * 1 back-propagated error vector. // from a size * 1 back-propagated error vector.
func (n *Network) UpdateBias(err *mat64.Dense, learnRate float64) { func (n *Network) UpdateBias(err *mat.Dense, learnRate float64) {
for i, b := range n.biases { for i, b := range n.biases {
if i < n.input { if i < n.input {
@ -172,11 +172,11 @@ func (n *Network) UpdateBias(err *mat64.Dense, learnRate float64) {
// //
// If the network is conceptually organised into n layers, maxIterations // If the network is conceptually organised into n layers, maxIterations
// should be set to n. // should be set to n.
func (n *Network) Error(outArg, errArg *mat64.Dense, maxIterations int) *mat64.Dense { func (n *Network) Error(outArg, errArg *mat.Dense, maxIterations int) *mat.Dense {
// Copy the arguments // Copy the arguments
out := mat64.DenseCopyOf(outArg) out := mat.DenseCopyOf(outArg)
err := mat64.DenseCopyOf(errArg) err := mat.DenseCopyOf(errArg)
// err should be the difference between observed and expected // err should be the difference between observed and expected
// for observation nodes only (everything else should be zero) // for observation nodes only (everything else should be zero)
@ -187,7 +187,7 @@ func (n *Network) Error(outArg, errArg *mat64.Dense, maxIterations int) *mat64.D
panic("Unsupported output size") panic("Unsupported output size")
} }
ret := mat64.NewDense(outRows, 1, make([]float64, outRows)) ret := mat.NewDense(outRows, 1, make([]float64, outRows))
// Do differential calculation // Do differential calculation
diffFunc := func(r, c int, v float64) float64 { diffFunc := func(r, c int, v float64) float64 {
@ -196,7 +196,7 @@ func (n *Network) Error(outArg, errArg *mat64.Dense, maxIterations int) *mat64.D
out.Apply(diffFunc, out) out.Apply(diffFunc, out)
// Transpose weights matrix // Transpose weights matrix
reverseWeights := mat64.DenseCopyOf(n.weights) reverseWeights := mat.DenseCopyOf(n.weights)
reverseWeights.Clone(n.weights.T()) reverseWeights.Clone(n.weights.T())
// We only need a certain number of passes // We only need a certain number of passes

View File

@ -1,7 +1,7 @@
package neural package neural
import ( import (
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
"testing" "testing"
) )
@ -29,7 +29,7 @@ func TestNetworkWith1Layer(t *testing.T) {
// Create the Activation vector // Create the Activation vector
// NewDense is rows then columns // NewDense is rows then columns
a := mat64.NewDense(6, 1, make([]float64, 6)) a := mat.NewDense(6, 1, make([]float64, 6))
// Set is rows then columns // Set is rows then columns
a.Set(0, 0, 1) a.Set(0, 0, 1)
a.Set(2, 0, 1) a.Set(2, 0, 1)
@ -42,7 +42,7 @@ func TestNetworkWith1Layer(t *testing.T) {
So(a.At(3, 0), ShouldAlmostEqual, 0.332, 0.01) So(a.At(3, 0), ShouldAlmostEqual, 0.332, 0.01)
// Set the observed error on the output node // Set the observed error on the output node
e := mat64.NewDense(6, 1, make([]float64, 6)) e := mat.NewDense(6, 1, make([]float64, 6))
e.Set(5, 0, 1.0-a.At(5, 0)) e.Set(5, 0, 1.0-a.At(5, 0))
// Run back-propagated error // Run back-propagated error

View File

@ -2,7 +2,7 @@
package neural package neural
import ( import (
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
) )
type ActivationFunction func(float64) float64 type ActivationFunction func(float64) float64
@ -16,4 +16,4 @@ type NeuralFunction struct {
// LayerFuncs are vectorised layer value transformation functions // LayerFuncs are vectorised layer value transformation functions
// (e.g. sigmoid). They must operate in-place. // (e.g. sigmoid). They must operate in-place.
type LayerFunc func(*mat64.Dense) type LayerFunc func(*mat.Dense)

View File

@ -2,13 +2,12 @@
package pca package pca
import ( import (
"github.com/gonum/matrix" "gonum.org/v1/gonum/mat"
"github.com/gonum/matrix/mat64"
) )
type PCA struct { type PCA struct {
Num_components int Num_components int
svd *mat64.SVD svd *mat.SVD
} }
// Number of components. 0 - by default, use number of features as number of components // Number of components. 0 - by default, use number of features as number of components
@ -18,19 +17,19 @@ func NewPCA(num_components int) *PCA {
// Fit PCA model and transform data // Fit PCA model and transform data
// Need return is base.FixedDataGrid // Need return is base.FixedDataGrid
func (pca *PCA) FitTransform(X *mat64.Dense) *mat64.Dense { func (pca *PCA) FitTransform(X *mat.Dense) *mat.Dense {
return pca.Fit(X).Transform(X) return pca.Fit(X).Transform(X)
} }
// Fit PCA model // Fit PCA model
func (pca *PCA) Fit(X *mat64.Dense) *PCA { func (pca *PCA) Fit(X *mat.Dense) *PCA {
// Mean to input data // Mean to input data
M := mean(X) M := mean(X)
X = matrixSubVector(X, M) X = matrixSubVector(X, M)
// Get SVD decomposition from data // Get SVD decomposition from data
pca.svd = &mat64.SVD{} pca.svd = &mat.SVD{}
ok := pca.svd.Factorize(X, matrix.SVDThin) ok := pca.svd.Factorize(X, mat.SVDThin)
if !ok { if !ok {
panic("Unable to factorize") panic("Unable to factorize")
} }
@ -42,41 +41,41 @@ func (pca *PCA) Fit(X *mat64.Dense) *PCA {
} }
// Need return is base.FixedDataGrid // Need return is base.FixedDataGrid
func (pca *PCA) Transform(X *mat64.Dense) *mat64.Dense { func (pca *PCA) Transform(X *mat.Dense) *mat.Dense {
if pca.svd == nil { if pca.svd == nil {
panic("You should to fit PCA model first") panic("You should to fit PCA model first")
} }
num_samples, num_features := X.Dims() num_samples, num_features := X.Dims()
vTemp := new(mat64.Dense) vTemp := new(mat.Dense)
vTemp.VFromSVD(pca.svd) pca.svd.VTo(vTemp)
//Compute to full data //Compute to full data
if pca.Num_components == 0 || pca.Num_components > num_features { if pca.Num_components == 0 || pca.Num_components > num_features {
return compute(X, vTemp) return compute(X, vTemp)
} }
X = compute(X, vTemp) X = compute(X, vTemp)
result := mat64.NewDense(num_samples, pca.Num_components, nil) result := mat.NewDense(num_samples, pca.Num_components, nil)
result.Copy(X.View(0, 0, num_samples, pca.Num_components)) result.Copy(X)
return result return result
} }
//Helpful private functions //Helpful private functions
//Compute mean of the columns of input matrix //Compute mean of the columns of input matrix
func mean(matrix *mat64.Dense) *mat64.Dense { func mean(matrix *mat.Dense) *mat.Dense {
rows, cols := matrix.Dims() rows, cols := matrix.Dims()
meanVector := make([]float64, cols) meanVector := make([]float64, cols)
for i := 0; i < cols; i++ { for i := 0; i < cols; i++ {
sum := mat64.Sum(matrix.ColView(i)) sum := mat.Sum(matrix.ColView(i))
meanVector[i] = sum / float64(rows) meanVector[i] = sum / float64(rows)
} }
return mat64.NewDense(1, cols, meanVector) return mat.NewDense(1, cols, meanVector)
} }
// After computing of mean, compute: X(input matrix) - X(mean vector) // After computing of mean, compute: X(input matrix) - X(mean vector)
func matrixSubVector(mat, vec *mat64.Dense) *mat64.Dense { func matrixSubVector(mat, vec *mat.Dense) *mat.Dense {
rowsm, colsm := mat.Dims() rowsm, colsm := mat.Dims()
_, colsv := vec.Dims() _, colsv := vec.Dims()
if colsv != colsm { if colsv != colsm {
@ -91,8 +90,8 @@ func matrixSubVector(mat, vec *mat64.Dense) *mat64.Dense {
} }
//Multiplication of X(input data) and V(from SVD) //Multiplication of X(input data) and V(from SVD)
func compute(X, Y mat64.Matrix) *mat64.Dense { func compute(X, Y mat.Matrix) *mat.Dense {
var ret mat64.Dense var ret mat.Dense
ret.Mul(X, Y) ret.Mul(X, Y)
return &ret return &ret
} }

View File

@ -3,13 +3,13 @@ package pca
import ( import (
"testing" "testing"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
) )
func TestPCAWithZeroComponents(t *testing.T) { func TestPCAWithZeroComponents(t *testing.T) {
Convey("Set to pca 0 components with first matrix", t, func() { Convey("Set to pca 0 components with first matrix", t, func() {
X1 := mat64.NewDense(3, 7, []float64{6, 5, 4, 3, 8, 2, 9, 5, 1, 10, 2, 3, 8, 7, 5, 14, 2, 3, 6, 3, 2}) X1 := mat.NewDense(3, 7, []float64{6, 5, 4, 3, 8, 2, 9, 5, 1, 10, 2, 3, 8, 7, 5, 14, 2, 3, 6, 3, 2})
pca := NewPCA(0) pca := NewPCA(0)
rows, cols := pca.FitTransform(X1).Dims() rows, cols := pca.FitTransform(X1).Dims()
So(rows, ShouldEqual, 3) So(rows, ShouldEqual, 3)
@ -17,7 +17,7 @@ func TestPCAWithZeroComponents(t *testing.T) {
}) })
Convey("Set to pca 0 components with second matrix", t, func() { Convey("Set to pca 0 components with second matrix", t, func() {
X1 := mat64.NewDense(10, 5, []float64{ X1 := mat.NewDense(10, 5, []float64{
0.52984892, 0.1141001, 0.91599294, 0.9574267, 0.15361222, 0.52984892, 0.1141001, 0.91599294, 0.9574267, 0.15361222,
0.07057588, 0.46371013, 0.73091854, 0.84641034, 0.08122213, 0.07057588, 0.46371013, 0.73091854, 0.84641034, 0.08122213,
0.96221946, 0.60367214, 0.69851546, 0.91965564, 0.27040597, 0.96221946, 0.60367214, 0.69851546, 0.91965564, 0.27040597,
@ -37,7 +37,7 @@ func TestPCAWithZeroComponents(t *testing.T) {
func TestPCAWithNComponents(t *testing.T) { func TestPCAWithNComponents(t *testing.T) {
Convey("Set to pca 3 components with 5x5 matrix", t, func() { Convey("Set to pca 3 components with 5x5 matrix", t, func() {
X := mat64.NewDense(5, 5, []float64{ X := mat.NewDense(5, 5, []float64{
0.23030838, 0.05669317, 0.3187813, 0.34455114, 0.98062806, 0.23030838, 0.05669317, 0.3187813, 0.34455114, 0.98062806,
0.38995469, 0.2996771, 0.99043575, 0.04443827, 0.99527955, 0.38995469, 0.2996771, 0.99043575, 0.04443827, 0.99527955,
0.27266308, 0.14068906, 0.46999473, 0.03296131, 0.90855405, 0.27266308, 0.14068906, 0.46999473, 0.03296131, 0.90855405,
@ -50,7 +50,7 @@ func TestPCAWithNComponents(t *testing.T) {
}) })
Convey("Set to pca 2 components with 3x5 matrix", t, func() { Convey("Set to pca 2 components with 3x5 matrix", t, func() {
X := mat64.NewDense(3, 5, []float64{ X := mat.NewDense(3, 5, []float64{
0.12294845, 0.55170713, 0.67572832, 0.60615516, 0.38184551, 0.12294845, 0.55170713, 0.67572832, 0.60615516, 0.38184551,
0.93486821, 0.15120374, 0.89760169, 0.74715672, 0.81373931, 0.93486821, 0.15120374, 0.89760169, 0.74715672, 0.81373931,
0.42821569, 0.47457753, 0.18960954, 0.42466159, 0.34166049}) 0.42821569, 0.47457753, 0.18960954, 0.42466159, 0.34166049})
@ -63,7 +63,7 @@ func TestPCAWithNComponents(t *testing.T) {
func TestPCAFitAndTransformSeparately(t *testing.T) { func TestPCAFitAndTransformSeparately(t *testing.T) {
Convey("Set to pca 3 components with 5x5 matrix", t, func() { Convey("Set to pca 3 components with 5x5 matrix", t, func() {
X := mat64.NewDense(5, 5, []float64{ X := mat.NewDense(5, 5, []float64{
0.23030838, 0.05669317, 0.3187813, 0.34455114, 0.98062806, 0.23030838, 0.05669317, 0.3187813, 0.34455114, 0.98062806,
0.38995469, 0.2996771, 0.99043575, 0.04443827, 0.99527955, 0.38995469, 0.2996771, 0.99043575, 0.04443827, 0.99527955,
0.27266308, 0.14068906, 0.46999473, 0.03296131, 0.90855405, 0.27266308, 0.14068906, 0.46999473, 0.03296131, 0.90855405,

View File

@ -4,7 +4,7 @@ package utilities
import ( import (
"sort" "sort"
"github.com/gonum/matrix/mat64" "gonum.org/v1/gonum/mat"
) )
type sortedIntMap struct { type sortedIntMap struct {
@ -37,11 +37,12 @@ func SortIntMap(m map[int]float64) []int {
return sm.s return sm.s
} }
func FloatsToMatrix(floats []float64) *mat64.Dense { func FloatsToMatrix(floats []float64) *mat.Dense {
return mat64.NewDense(1, len(floats), floats) return mat.NewDense(1, len(floats), floats)
} }
func VectorToMatrix(vector *mat64.Vector) *mat64.Dense { func VectorToMatrix(vector mat.Vector) *mat.Dense {
vec := vector.RawVector() denseCopy := mat.VecDenseCopyOf(vector)
return mat64.NewDense(1, len(vec.Data), vec.Data) vec := denseCopy.RawVector()
return mat.NewDense(1, len(vec.Data), vec.Data)
} }