func TestInclinedLineShouldFail2(t *testing.T) {
	var err error
	model := NewLeastSquares(base.StochasticGA, 1e-4, 1e3, 300, increasingX, increasingY)
	err = model.Learn()
	assert.Nil(t, err, "Learning error should be nil")
	var guess []float64
	var faliures int
	for i := -20; i < 20; i += 2 {
		guess, err = model.Predict([]float64{float64(i)})
		assert.Len(t, guess, 1, "Length of a LeastSquares model output from the hypothesis should always be a 1 dimensional vector. Never multidimensional.")
		if abs(float64(i)-guess[0]) > 1e-2 {
			faliures++
		}
		assert.Nil(t, err, "Prediction error should be nil")
	}
	assert.True(t, faliures > 15, "There should be more faliures than half of the training set")
}
same as above but with StochasticGA
package linear
import (
	"fmt"
	"math/rand"
	"os"
	"testing"
	"github.com/cdipaolo/goml/base"
	"github.com/stretchr/testify/assert"
)
var flatX [][]float64
var flatY []float64
var increasingX [][]float64
var increasingY []float64
var threeDLineX [][]float64
var threeDLineY []float64
var normX [][]float64
var normY []float64
var noisyX [][]float64
var noisyY []float64
func init() {
	err := os.MkdirAll("/tmp/.goml", os.ModePerm)
	if err != nil {
		panic(fmt.Sprintf("You should be able to create the directory for goml model persistance testing.\n\tError returned: %v\n", err.Error()))
	}
	flatX = [][]float64{}
	flatY = []float64{}
	for i := -10; i < 10; i++ {
		for j := -10; j < 10; j++ {
			for k := -10; k < 10; k++ {
				flatX = append(flatX, []float64{float64(i), float64(j), float64(k)})
				flatY = append(flatY, 3.0)
			}
		}
	}
	increasingX = [][]float64{}
	increasingY = []float64{}
	for i := -10; i < 10; i++ {
		increasingX = append(increasingX, []float64{float64(i)})
		increasingY = append(increasingY, float64(i))
	}
	threeDLineX = [][]float64{}
	threeDLineY = []float64{}
	normX = [][]float64{}
	normY = []float64{}
	for i := -10; i < 10; i++ {
		for j := -10; j < 10; j++ {
			threeDLineX = append(threeDLineX, []float64{float64(i), float64(j)})
			threeDLineY = append(threeDLineY, 10+float64(i)/10+float64(j)/5)
			normX = append(normX, []float64{float64(i), float64(j)})
		}
	}
	base.Normalize(normX)
	for i := range normX {
		normY = append(normY, 10+float64(normX[i][0])/10+float64(normX[i][1])/5)
	}
	rand.Seed(42)
	noisyX = [][]float64{}
	noisyY = []float64{}
	for i := 256.0; i < 1024; i += 2 {
		noisyX = append(noisyX, []float64{i + (rand.Float64()-0.5)*3})
		noisyY = append(noisyY, 0.5*i+rand.NormFloat64()*25)
	}
	base.SaveDataToCSV("/tmp/.goml/noisy_linear.csv", noisyX, noisyY, true)
}
func TestFlatLineShouldPass1(t *testing.T) {
	var err error
	model := NewLeastSquares(base.BatchGA, .000001, 0, 800, flatX, flatY)
	err = model.Learn()
	assert.Nil(t, err, "Learning error should be nil")
	var guess []float64
	for i := -20; i < 20; i += 10 {
		for j := -20; j < 20; j += 10 {
			for k := -20; k < 20; k += 10 {
				guess, err = model.Predict([]float64{float64(i), float64(j), float64(k)})
				assert.Len(t, guess, 1, "Length of a LeastSquares model output from the hypothesis should always be a 1 dimensional vector. Never multidimensional.")
				assert.InDelta(t, 3, guess[0], 1e-2, "Guess should be really close to 3 (within 1e-2) for y=3")
				assert.Nil(t, err, "Prediction error should be nil")
			}
		}
	}
}
func TestFlatLineShouldPass2(t *testing.T) {
	var err error
	model := NewLeastSquares(base.StochasticGA, .000001, 0, 800, flatX, flatY)
	err = model.Learn()
	assert.Nil(t, err, "Learning error should be nil")
	var guess []float64
	for i := -20; i < 20; i += 10 {
		for j := -20; j < 20; j += 10 {
			for k := -20; k < 20; k += 10 {
				guess, err = model.Predict([]float64{float64(i), float64(j), float64(k)})
				assert.Len(t, guess, 1, "Length of a LeastSquares model output from the hypothesis should always be a 1 dimensional vector. Never multidimensional.")
				assert.InDelta(t, 3, guess[0], 1e-2, "Guess should be really close to 3 (within 1e-2) for y=3")
				assert.Nil(t, err, "Prediction error should be nil")
			}
		}
	}
}
func TestFlatLineShouldFail1(t *testing.T) {
	var err error
	model := NewLeastSquares(base.BatchGA, .000001, 0, 1, flatX, flatY)
	err = model.Learn()
	assert.Nil(t, err, "Learning error should be nil")
	var guess []float64
	var faliures int
	for i := -20; i < 20; i += 10 {
		for j := -20; j < 20; j += 10 {
			for k := -20; k < 20; k += 10 {
				guess, err = model.Predict([]float64{float64(i), float64(j), float64(k)})
				assert.Len(t, guess, 1, "Length of a LeastSquares model output from the hypothesis should always be a 1 dimensional vector. Never multidimensional.")
				if abs(3.0-guess[0]) > 1e-2 {
					faliures++
				}
				assert.Nil(t, err, "Prediction error should be nil")
			}
		}
	}
	assert.True(t, faliures > 40, "There should be more faliures than half of the training set")
}
func TestFlatLineShouldFail2(t *testing.T) {
	var err error
	model := NewLeastSquares(base.StochasticGA, .000001, 0, 1, flatX, flatY)
	err = model.Learn()
	assert.Nil(t, err, "Learning error should be nil")
	var guess []float64
	var faliures int
	for i := -20; i < 20; i += 10 {
		for j := -20; j < 20; j += 10 {
			for k := -20; k < 20; k += 10 {
				guess, err = model.Predict([]float64{float64(i), float64(j), float64(k)})
				assert.Len(t, guess, 1, "Length of a LeastSquares model output from the hypothesis should always be a 1 dimensional vector. Never multidimensional.")
				if abs(3.0-guess[0]) > 1e-2 {
					faliures++
				}
				assert.Nil(t, err, "Prediction error should be nil")
			}
		}
	}
	assert.True(t, faliures > 40, "There should be more faliures than half of the training set")
}
func TestFlatLineShouldFail3(t *testing.T) {
	var err error
	model := NewLeastSquares(base.BatchGA, 1, 0, 800, [][]float64{}, flatY)
	err = model.Learn()
	assert.NotNil(t, err, "Learning error should not be nil")
	model = NewLeastSquares(base.BatchGA, 1, 0, 800, [][]float64{[]float64{}, []float64{}}, flatY)
	err = model.Learn()
	assert.NotNil(t, err, "Learning error should not be nil")
	model = NewLeastSquares(base.BatchGA, 1, 0, 800, nil, flatY)
	err = model.Learn()
	assert.NotNil(t, err, "Learning error should not be nil")
}
func TestFlatLineShouldFail4(t *testing.T) {
	var err error
	model := NewLeastSquares(base.StochasticGA, 1, 0, 800, [][]float64{}, flatY)
	err = model.Learn()
	assert.NotNil(t, err, "Learning error should not be nil")
	model = NewLeastSquares(base.StochasticGA, 1, 0, 800, [][]float64{[]float64{}, []float64{}}, flatY)
	err = model.Learn()
	assert.NotNil(t, err, "Learning error should not be nil")
	model = NewLeastSquares(base.StochasticGA, 1, 0, 800, nil, flatY)
	err = model.Learn()
	assert.NotNil(t, err, "Learning error should not be nil")
}
func TestFlatLineShouldFail5(t *testing.T) {
	var err error
	model := NewLeastSquares(base.BatchGA, 1, 0, 800, flatX, []float64{})
	err = model.Learn()
	assert.NotNil(t, err, "Learning error should not be nil")
	model = NewLeastSquares(base.BatchGA, 1, 0, 800, flatX, nil)
	err = model.Learn()
	assert.NotNil(t, err, "Learning error should not be nil")
}
func TestFlatLineShouldFail6(t *testing.T) {
	var err error
	model := NewLeastSquares(base.OptimizationMethod("Not A Method!!!"), 1, 0, 800, flatX, flatY)
	err = model.Learn()
	assert.NotNil(t, err, "Learning error should not be nil")
}
func TestInclinedLineShouldPass1(t *testing.T) {
	var err error
	model := NewLeastSquares(base.BatchGA, .0001, 0, 500, increasingX, increasingY)
	err = model.Learn()
	assert.Nil(t, err, "Learning error should be nil")
	var guess []float64
	for i := -20; i < 20; i++ {
		guess, err = model.Predict([]float64{float64(i)})
		assert.Len(t, guess, 1, "Length of a LeastSquares model output from the hypothesis should always be a 1 dimensional vector. Never multidimensional.")
		assert.InDelta(t, i, guess[0], 1e-2, "Guess should be really close to input (within 1e-2) for y=x")
		assert.Nil(t, err, "Prediction error should be nil")
	}
}
func TestInclinedLineShouldPass2(t *testing.T) {
	var err error
	model := NewLeastSquares(base.StochasticGA, .0001, 0, 500, increasingX, increasingY)
	err = model.Learn()
	assert.Nil(t, err, "Learning error should be nil")
	var guess []float64
	for i := -20; i < 20; i++ {
		guess, err = model.Predict([]float64{float64(i)})
		assert.Len(t, guess, 1, "Length of a LeastSquares model output from the hypothesis should always be a 1 dimensional vector. Never multidimensional.")
		assert.InDelta(t, i, guess[0], 1e-2, "Guess should be really close to input (within 1e-2) for y=x")
		assert.Nil(t, err, "Prediction error should be nil")
	}
}
func TestInclinedLineShouldFail1(t *testing.T) {
	var err error
	model := NewLeastSquares(base.BatchGA, .0001, 1e3, 500, increasingX, increasingY)
	err = model.Learn()
	assert.Nil(t, err, "Learning error should be nil")
	var guess []float64
	var faliures int
	for i := -20; i < 20; i += 2 {
		guess, err = model.Predict([]float64{float64(i)})
		assert.Len(t, guess, 1, "Length of a LeastSquares model output from the hypothesis should always be a 1 dimensional vector. Never multidimensional.")
		if abs(float64(i)-guess[0]) > 1e-2 {
			faliures++
		}
		assert.Nil(t, err, "Prediction error should be nil")
	}
	assert.True(t, faliures > 15, "There should be more faliures than half of the training set")
}