Documentation ¶
Overview ¶
Package linear implements commonly used General Linear Models.
https://en.wikipedia.org/wiki/General_linear_model
Models implemented as of yet include:
- Ordinary Least Squares
- Logistic Regression
General Usage: Find the model you want to use. Then find the 'NewXXXXXX' function, such as
func NewLeastSquares(method base.OptimizationMethod, alpha, regularization float64, maxIterations int, trainingSet [][]float64, expectedResults []float64) *LeastSquares
load in the given parameters, then run
func Learn() error
Now you can predict off of the model!
func Predict([]float64) ([]float64, error)
Full example assuming testX is of type [][]float64 and testY is of type []float64 where there are 2 features being inputted (ie. the size of a house and the number of bedrooms being given as x[0] and x[1], respectively.) textY[i] should be the observed result of the inputs testX[i].:
Example Model Usage (Batch Ordinary Least Squares):
// optimization method: Batch Gradient Ascent // Learning rate: 1e-4 // Regulatization term: 6 // Max Iterations: 800 // Dataset to learn fron: testX // Expected results dataset: testY model := NewLeastSquares(base.BatchGA, 1e-4, 6, 800, testX, testY) err := model.Learn() if err != nil { panic("SOME ERROR!! RUN!") } // now I want to predict off of this // Ordinary Least Squares model! guess, err = model.Predict([]float64{10000,6}) if err != nil { panic("AAAARGGGH! SHIVER ME TIMBERS! THESE ROTTEN SCOUNDRELS FOUND AN ERROR!!!") }
Index ¶
- type LeastSquares
- func (l *LeastSquares) Dij(i int, j int) (float64, error)
- func (l *LeastSquares) Dj(j int) (float64, error)
- func (l *LeastSquares) Examples() int
- func (l *LeastSquares) J() (float64, error)
- func (l *LeastSquares) Learn() error
- func (l *LeastSquares) LearningRate() float64
- func (l *LeastSquares) MaxIterations() int
- func (l *LeastSquares) OnlineLearn(errors chan error, dataset chan base.Datapoint, onUpdate func([][]float64), ...)
- func (l *LeastSquares) PersistToFile(path string) error
- func (l *LeastSquares) Predict(x []float64, normalize ...bool) ([]float64, error)
- func (l *LeastSquares) RestoreFromFile(path string) error
- func (l *LeastSquares) String() string
- func (l *LeastSquares) Theta() []float64
- func (l *LeastSquares) UpdateLearningRate(a float64)
- func (l *LeastSquares) UpdateTrainingSet(trainingSet [][]float64, expectedResults []float64) error
- type LocalLinear
- func (l *LocalLinear) Dij(input []float64, i, j int) (float64, error)
- func (l *LocalLinear) Dj(input []float64, j int) (float64, error)
- func (l *LocalLinear) Examples() int
- func (l *LocalLinear) J() (float64, error)
- func (l *LocalLinear) LearningRate() float64
- func (l *LocalLinear) MaxIterations() int
- func (l *LocalLinear) Predict(x []float64, normalize ...bool) ([]float64, error)
- func (l *LocalLinear) String() string
- func (l *LocalLinear) UpdateLearningRate(a float64)
- func (l *LocalLinear) UpdateTrainingSet(trainingSet [][]float64, expectedResults []float64) error
- type Logistic
- func (l *Logistic) Dij(i int, j int) (float64, error)
- func (l *Logistic) Dj(j int) (float64, error)
- func (l *Logistic) Examples() int
- func (l *Logistic) Learn() error
- func (l *Logistic) LearningRate() float64
- func (l *Logistic) MaxIterations() int
- func (l *Logistic) OnlineLearn(errors chan error, dataset chan base.Datapoint, onUpdate func([][]float64), ...)
- func (l *Logistic) PersistToFile(path string) error
- func (l *Logistic) Predict(x []float64, normalize ...bool) ([]float64, error)
- func (l *Logistic) RestoreFromFile(path string) error
- func (l *Logistic) String() string
- func (l *Logistic) Theta() []float64
- func (l *Logistic) UpdateLearningRate(a float64)
- func (l *Logistic) UpdateTrainingSet(trainingSet [][]float64, expectedResults []float64) error
- type Softmax
- func (s *Softmax) Dij(i, k int) ([]float64, error)
- func (s *Softmax) Dj(k int) ([]float64, error)
- func (s *Softmax) Examples() int
- func (s *Softmax) Learn() error
- func (s *Softmax) LearningRate() float64
- func (s *Softmax) MaxIterations() int
- func (s *Softmax) OnlineLearn(errors chan error, dataset chan base.Datapoint, onUpdate func([][]float64), ...)
- func (s *Softmax) PersistToFile(path string) error
- func (s *Softmax) Predict(x []float64, normalize ...bool) ([]float64, error)
- func (s *Softmax) RestoreFromFile(path string) error
- func (s *Softmax) String() string
- func (s *Softmax) Theta() [][]float64
- func (s *Softmax) UpdateLearningRate(a float64)
- func (s *Softmax) UpdateTrainingSet(trainingSet [][]float64, expectedResults []float64) error
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type LeastSquares ¶
type LeastSquares struct { Parameters []float64 `json:"theta"` // Output is the io.Writer used for logging // and printing. Defaults to os.Stdout. Output io.Writer // contains filtered or unexported fields }
LeastSquares implements a standard linear regression model with a Least Squares cost function.
https://en.wikipedia.org/wiki/Least_squares
The model uses gradient descent, NOT regular equations.
func NewLeastSquares ¶
func NewLeastSquares(method base.OptimizationMethod, alpha, regularization float64, maxIterations int, trainingSet [][]float64, expectedResults []float64, features ...int) *LeastSquares
NewLeastSquares returns a pointer to the linear model initialized with the learning rate alpha, the training set trainingSet, and the expected results upon which to use the dataset to train, expectedResults.
if you're passing in no training set directly because you want to learn using the online method then just declare the number of features (it's an integer) as an extra arg after the rest of the arguments
Example Least Squares (Stochastic GA):
// optimization method: Stochastic Gradient Ascent // Learning rate: 1e-4 // Regularization term: 6 // Max Iterations: 800 // Dataset to learn from: testX // Expected results dataset: testY model := NewLeastSquares(base.StochasticGA, 1e-4, 6, 800, testX, testY) err := model.Learn() if err != nil { panic("SOME ERROR!! RUN!") } // now I want to predict off of this // Ordinary Least Squares model! guess, err = model.Predict([]float64{10000,6}) if err != nil { panic("AAAARGGGH! SHIVER ME TIMBERS! THESE ROTTEN SCOUNDRELS FOUND AN ERROR!!!") }
func (*LeastSquares) Dij ¶
func (l *LeastSquares) Dij(i int, j int) (float64, error)
Dij returns the derivative of the cost function J(θ) with respect to the j-th parameter of the hypothesis, θ[j], for the training example x[i]. Used in Stochastic Gradient Descent.
assumes that i,j is within the bounds of the data they are looking up! (because this is getting called so much, it needs to be efficient with comparisons)
func (*LeastSquares) Dj ¶
func (l *LeastSquares) Dj(j int) (float64, error)
Dj returns the partial derivative of the cost function J(θ) with respect to theta[j] where theta is the parameter vector associated with our hypothesis function Predict (upon which we are optimizing
func (*LeastSquares) Examples ¶
func (l *LeastSquares) Examples() int
Examples returns the number of training examples (m) that the model currently is training from.
func (*LeastSquares) J ¶
func (l *LeastSquares) J() (float64, error)
J returns the Least Squares cost function of the given linear model. Could be useful in testing convergence
func (*LeastSquares) Learn ¶
func (l *LeastSquares) Learn() error
Learn takes the struct's dataset and expected results and runs batch gradient descent on them, optimizing theta so you can predict based on those results
func (*LeastSquares) LearningRate ¶
func (l *LeastSquares) LearningRate() float64
LearningRate returns the learning rate α for gradient descent to optimize the model. Could vary as a function of something else later, potentially.
func (*LeastSquares) MaxIterations ¶
func (l *LeastSquares) MaxIterations() int
MaxIterations returns the number of maximum iterations the model will go through in GradientAscent, in the worst case
func (*LeastSquares) OnlineLearn ¶
func (l *LeastSquares) OnlineLearn(errors chan error, dataset chan base.Datapoint, onUpdate func([][]float64), normalize ...bool)
OnlineLearn runs similar to using a fixed dataset with Stochastic Gradient Descent, but it handles data by passing it as a channel, and returns errors through a channel, which lets it run responsive to inputted data from outside the model itself (like using data from the stock market at timed intervals or using realtime data about the weather.)
The onUpdate callback is called whenever the parameter vector theta is changed, so you are able to persist the model with the most up to date vector at all times (you could persist to a database within the callback, for example.) Don't worry about it taking too long and blocking, because the callback is spawned into another goroutine.
NOTE that this function is suggested to run in it's own goroutine, or at least is designed as such.
NOTE part 2: You can pass in an empty dataset, so long as it's not nil, and start pushing after.
NOTE part 3: each example is only looked at as it goes through the channel, so if you want to have each example looked at more than once you must manually pass the data yourself.
NOTE part 4: the optional parameter 'normalize' will not do anything with a linear model.It is included so the model fits the OnlineModel interface.
Example Online Linear Least Squares:
// create the channel of data and errors stream := make(chan base.Datapoint, 100) errors := make(chan error) // notice how we are adding another integer // to the end of the NewLogistic call. This // tells the model to use that number of features // (4) in leu of finding that from the dataset // like you would with batch/stochastic GD // // Also – the 'base.StochasticGA' doesn't affect // anything. You could put batch. model := NewLeastSquares(base.StochasticGA, .0001, 0, 0, nil, nil, 4) go model.OnlineLearn(errors, stream, func(theta [][]float64) { // do something with the new theta (persist // to database?) in here. }) go func() { for iterations := 0; iterations < 20; iterations++ { for i := -200.0; abs(i) > 1; i *= -0.75 { for j := -200.0; abs(j) > 1; j *= -0.75 { for k := -200.0; abs(k) > 1; k *= -0.75 { for l := -200.0; abs(l) > 1; l *= -0.75 { stream <- base.Datapoint{ X: []float64{i, j, k, l}, Y: []float64{i/2 + 2*k - 4*j + 2*l + 3}, } } } } } } // close the dataset to tell the model // to stop learning when it finishes reading // what's left in the channel close(stream) }() // this will block until the error // channel is closed in the learning // function (it will, don't worry!) for { err, more := <-errors if err != nil { panic("THERE WAS AN ERROR!!! RUN!!!!") } if !more { break } } // Below here all the learning is completed // predict like usual guess, err = model.Predict([]float64{42,6,10,-32}) if err != nil { panic("AAAARGGGH! SHIVER ME TIMBERS! THESE ROTTEN SCOUNDRELS FOUND AN ERROR!!!") }
func (*LeastSquares) PersistToFile ¶
func (l *LeastSquares) PersistToFile(path string) error
PersistToFile takes in an absolute filepath and saves the parameter vector θ to the file, which can be restored later. The function will take paths from the current directory, but functions
The data is stored as JSON because it's one of the most efficient storage method (you only need one comma extra per feature + two brackets, total!) And it's extendable.
func (*LeastSquares) Predict ¶
func (l *LeastSquares) Predict(x []float64, normalize ...bool) ([]float64, error)
Predict takes in a variable x (an array of floats,) and finds the value of the hypothesis function given the current parameter vector θ
if normalize is given as true, then the input will first be normalized to unit length. Only use this if you trained off of normalized inputs and are feeding an un-normalized input
func (*LeastSquares) RestoreFromFile ¶
func (l *LeastSquares) RestoreFromFile(path string) error
RestoreFromFile takes in a path to a parameter vector theta and assigns the model it's operating on's parameter vector to that.
The path must ba an absolute path or a path from the current directory
This would be useful in persisting data between running a model on data, or for graphing a dataset with a fit in another framework like Julia/Gadfly.
func (*LeastSquares) String ¶
func (l *LeastSquares) String() string
String implements the fmt interface for clean printing. Here we're using it to print the model as the equation h(θ)=... where h is the linear hypothesis model
func (*LeastSquares) Theta ¶
func (l *LeastSquares) Theta() []float64
Theta returns the parameter vector θ for use in persisting the model, and optimizing the model through gradient descent ( or other methods like Newton's Method)
func (*LeastSquares) UpdateLearningRate ¶
func (l *LeastSquares) UpdateLearningRate(a float64)
UpdateLearningRate set's the learning rate of the model to the given float64.
func (*LeastSquares) UpdateTrainingSet ¶
func (l *LeastSquares) UpdateTrainingSet(trainingSet [][]float64, expectedResults []float64) error
UpdateTrainingSet takes in a new training set (variable x) as well as a new result set (y). This could be useful if you want to retrain a model starting with the parameter vector of a previous training session, but most of the time wouldn't be used.
type LocalLinear ¶
type LocalLinear struct { Parameters []float64 `json:"theta"` // Output is the io.Writer used for logging // and printing. Defaults to os.Stdout. Output io.Writer // contains filtered or unexported fields }
LocalLinear implements a locally weighted linear least squares regression.
https://en.wikipedia.org/wiki/Least_squares http://cs229.stanford.edu/notes/cs229-notes1.pdf
Note that this is not modeled to work in an online setting, so the model does not implement that interface. Also, because a new hypothesis is needed for every point you try to predict, there is no 'Learn' function. Instead, when calling predict the model first learns from the data set with weights set with respect to the given input, then returns the trained hypothesis when evaluated at the given input.
While that may sound really inefficient, sometimes this model can perform well with little tweaking, especially if you're working with a smaller data set to train off of. Andrew Ng said in one of his Stanford CS229 lectures that Locally Weighted Linear Regression is one of his mentor's 'favourite' 'off-the-shelf' learning algorithm. Obviously model selection plays a large role in this.
NOTE that there is no file persistance of this model because you need to retrain at the time of every prediction anyway.
Example Locally Weighted Linear Regression Usage:
x := [][]float64{} y := []float64{} // throw in some junk points which // should be more-or-less ignored // by the weighting for i := -70.0; i < -65; i += 2 { for j := -70.0; j < -65; j += 2 { x = append(x, []float64{i, j}) y = append(y, 20*(rand.Float64()-0.5)) } } for i := 65.0; i < 70; i += 2 { for j := 65.0; j < 70; j += 2 { x = append(x, []float64{i, j}) y = append(y, 20*(rand.Float64()-0.5)) } } // put in some linear points for i := -20.0; i < 20; i++ { for j := -20.0; j < 20; j++ { x = append(x, []float64{i, j}) y = append(y, 5*i-5*j-10) } } model := NewLocalLinear(base.StochasticGA, 1e-4, 0, 0.75, 1500, x, y) // now when you predict it'll train off the // dataset, weighting points closer to the // targer evaluation more, then return // the prediction. guess, err := model.Predict([]float64{10.0, -13.666})
func NewLocalLinear ¶
func NewLocalLinear(method base.OptimizationMethod, alpha, regularization, bandwidth float64, maxIterations int, trainingSet [][]float64, expectedResults []float64) *LocalLinear
NewLocalLinear returns a pointer to the linear model initialized with the learning rate alpha, the training set trainingSet, and the expected results upon which to use the dataset to train, expectedResults.
if you're passing in no training set directly because you want to learn using the online method then just declare the number of features (it's an integer) as an extra arg after the rest of the arguments
Example Least Squares (Stochastic GA):
// optimization method: Stochastic Gradient Ascent // Learning rate: 1e-4 // Regulatization term: 6 // Weight Bandwidth: 1.0 // Max Iterations: 800 // Dataset to learn fron: testX // Expected results dataset: testY model := NewLocalLinear(base.StochasticGA, 1e-4, 6, 1.0, 800, testX, testY) err := model.Learn() if err != nil { panic("SOME ERROR!! RUN!") } // now I want to predict off of this // Ordinary Least Squares model! guess, err = model.Predict([]float64{10000,6}) if err != nil { panic("AAAARGGGH! SHIVER ME TIMBERS! THESE ROTTEN SCOUNDRELS FOUND AN ERROR!!!") }
func (*LocalLinear) Dij ¶
func (l *LocalLinear) Dij(input []float64, i, j int) (float64, error)
Dij returns the derivative of the cost function J(θ) with respect to the j-th parameter of the hypothesis, θ[j], for the training example x[i]. Used in Stochastic Gradient Descent.
assumes that i,j is within the bounds of the data they are looking up! (because this is getting called so much, it needs to be efficient with comparisons)
func (*LocalLinear) Dj ¶
func (l *LocalLinear) Dj(input []float64, j int) (float64, error)
Dj returns the partial derivative of the cost function J(θ) with respect to theta[j] where theta is the parameter vector associated with our hypothesis function Predict (upon which we are optimizing
func (*LocalLinear) Examples ¶
func (l *LocalLinear) Examples() int
Examples returns the number of training examples (m) that the model currently is training from.
func (*LocalLinear) J ¶
func (l *LocalLinear) J() (float64, error)
J returns the Least Squares cost function of the given linear model. Could be usefull in testing convergance
func (*LocalLinear) LearningRate ¶
func (l *LocalLinear) LearningRate() float64
LearningRate returns the learning rate α for gradient descent to optimize the model. Could vary as a function of something else later, potentially.
func (*LocalLinear) MaxIterations ¶
func (l *LocalLinear) MaxIterations() int
MaxIterations returns the number of maximum iterations the model will go through in GradientAscent, in the worst case
func (*LocalLinear) Predict ¶
func (l *LocalLinear) Predict(x []float64, normalize ...bool) ([]float64, error)
Predict takes in a variable x (an array of floats,) and finds the value of the hypothesis function given the current parameter vector θ
if normalize is given as true, then the input will first be normalized to unit length. Only use this if you trained off of normalized inputs and are feeding an un-normalized input
func (*LocalLinear) String ¶
func (l *LocalLinear) String() string
String implements the fmt interface for clean printing. Here we're using it to print the model as the equation h(θ)=... where h is the linear hypothesis model
func (*LocalLinear) UpdateLearningRate ¶
func (l *LocalLinear) UpdateLearningRate(a float64)
UpdateLearningRate set's the learning rate of the model to the given float64.
func (*LocalLinear) UpdateTrainingSet ¶
func (l *LocalLinear) UpdateTrainingSet(trainingSet [][]float64, expectedResults []float64) error
UpdateTrainingSet takes in a new training set (variable x) as well as a new result set (y). This could be useful if you want to retrain a model starting with the parameter vector of a previous training session, but most of the time wouldn't be used.
type Logistic ¶
type Logistic struct { Parameters []float64 `json:"theta"` // Output is the io.Writer used for logging // and printing. Defaults to os.Stdout. Output io.Writer // contains filtered or unexported fields }
Logistic represents the logistic classification model with a sigmoidal hypothesis
https://en.wikipedia.org/wiki/Logistic_regression
The model is currently optimized using Gradient Ascent, not Newton's method, etc.
The model expects all expected results in the []float64 to come as either a 0 or a 1, and will predict the probability that, based on inputs x, whether y is 1
func NewLogistic ¶
func NewLogistic(method base.OptimizationMethod, alpha, regularization float64, maxIterations int, trainingSet [][]float64, expectedResults []float64, features ...int) *Logistic
NewLogistic takes in a learning rate alpha, a regularization parameter value (0 means no regularization, higher value means higher bias on the model,) the maximum number of iterations the data can go through in gradient descent, as well as a training set and expected results for that training set.
if you're passing in no training set directly because you want to learn using the online method then just declare the number of features (it's an integer) as an extra arg after the rest of the arguments
DATA FORMAT: The Logistic model expects expected results to be either a 0 or a 1. Predict returns the probability that the item inputted is a 1. Obviously this means that the probability that the inputted x is a 0 is 1-TheGuess
Example Binary Logistic Regression (Batch GA):
// optimization method: Batch Gradient Ascent // Learning rate: 1e-4 // Regulatization term: 6 // Max Iterations: 800 // Dataset to learn fron: testX // Expected results dataset: testY model := NewLogistic(base.BatchGA, 1e-4, 6, 800, testX, testY) err := model.Learn() if err != nil { panic("SOME ERROR!! RUN!") } // now I want to predict off of this // Ordinary Least Squares model! guess, err = model.Predict([]float64{10000,6}) if err != nil { panic("AAAARGGGH! SHIVER ME TIMBERS! THESE ROTTEN SCOUNDRELS FOUND AN ERROR!!!") }
func (*Logistic) Dij ¶
Dij returns the derivative of the cost function J(θ) with respect to the j-th parameter of the hypothesis, θ[j], for the training example x[i]. Used in Stochastic Gradient Descent.
assumes that i,j is within the bounds of the data they are looking up! (because this is getting called so much, it needs to be efficient with comparisons)
func (*Logistic) Dj ¶
Dj returns the partial derivative of the cost function J(θ) with respect to theta[j] where theta is the parameter vector associated with our hypothesis function Predict (upon which we are optimizing
func (*Logistic) Examples ¶
Examples returns the number of training examples (m) that the model currently is training from.
func (*Logistic) Learn ¶
Learn takes the struct's dataset and expected results and runs batch gradient descent on them, optimizing theta so you can predict based on those results
func (*Logistic) LearningRate ¶
LearningRate returns the learning rate α for gradient descent to optimize the model. Could vary as a function of something else later, potentially.
func (*Logistic) MaxIterations ¶
MaxIterations returns the number of maximum iterations the model will go through in GradientAscent, in the worst case
func (*Logistic) OnlineLearn ¶
func (l *Logistic) OnlineLearn(errors chan error, dataset chan base.Datapoint, onUpdate func([][]float64), normalize ...bool)
OnlineLearn runs similar to using a fixed dataset with Stochastic Gradient Descent, but it handles data by passing it as a channal, and returns errors through a channel, which lets it run responsive to inputted data from outside the model itself (like using data from the stock market at timed intervals or using realtime data about the weather.)
The onUpdate callback is called whenever the parameter vector theta is changed, so you are able to persist the model with the most up to date vector at all times (you could persist to a database within the callback, for example.) Don't worry about it taking too long and blocking, because the callback is spawned into another goroutine.
NOTE that this function is suggested to run in it's own goroutine, or at least is designed as such.
NOTE part 2: You can pass in an empty dataset, so long as it's not nil, and start pushing after.
NOTE part 3: each example is only looked at as it goes through the channel, so if you want to have each example looked at more than once you must manually pass the data yourself.
NOTE part 4: the optional parameter 'normalize' will , if true, normalize all data streamed through the channel to unit length. This will affect the outcome of the hypothesis, though it could be favorable if your data comes in drastically different scales.
Example Online Logistic Regression:
// create the channel of data and errors stream := make(chan base.Datapoint, 100) errors := make(chan error) // notice how we are adding another integer // to the end of the NewLogistic call. This // tells the model to use that number of features // (4) in leu of finding that from the dataset // like you would with batch/stochastic GD // // Also – the 'base.StochasticGA' doesn't affect // anything. You could put batch. model := NewLogistic(base.StochasticGA, .0001, 0, 0, nil, nil, 4) go model.OnlineLearn(errors, stream, func(theta [][]float64) { // do something with the new theta (persist // to database?) in here. }) go func() { for iterations := 0; iterations < 20; iterations++ { for i := -200.0; abs(i) > 1; i *= -0.75 { for j := -200.0; abs(j) > 1; j *= -0.75 { for k := -200.0; abs(k) > 1; k *= -0.75 { for l := -200.0; abs(l) > 1; l *= -0.75 { if i/2+2*k-4*j+2*l+3 > 0 { stream <- base.Datapoint{ X: []float64{i, j, k, l}, Y: []float64{1.0}, } } else { stream <- base.Datapoint{ X: []float64{i, j, k, l}, Y: []float64{0.0}, } } } } } } } // close the dataset to tell the model // to stop learning when it finishes reading // what's left in the channel close(stream) }() // this will block until the error // channel is closed in the learning // function (it will, don't worry!) for { err, more := <-errors if err != nil { panic("THERE WAS AN ERROR!!! RUN!!!!") } if !more { break } } // Below here all the learning is completed // predict like usual guess, err = model.Predict([]float64{42,6,10,-32}) if err != nil { panic("AAAARGGGH! SHIVER ME TIMBERS! THESE ROTTEN SCOUNDRELS FOUND AN ERROR!!!") }
func (*Logistic) PersistToFile ¶
PersistToFile takes in an absolute filepath and saves the parameter vector θ to the file, which can be restored later. The function will take paths from the current directory, but functions
The data is stored as JSON because it's one of the most efficient storage method (you only need one comma extra per feature + two brackets, total!) And it's extendable.
func (*Logistic) Predict ¶
Predict takes in a variable x (an array of floats,) and finds the value of the hypothesis function given the current parameter vector θ
if normalize is given as true, then the input will first be normalized to unit length. Only use this if you trained off of normalized inputs and are feeding an un-normalized input
func (*Logistic) RestoreFromFile ¶
RestoreFromFile takes in a path to a parameter vector theta and assigns the model it's operating on's parameter vector to that.
The path must ba an absolute path or a path from the current directory
This would be useful in persisting data between running a model on data, or for graphing a dataset with a fit in another framework like Julia/Gadfly.
func (*Logistic) String ¶
String implements the fmt interface for clean printing. Here we're using it to print the model as the equation h(θ)=... where h is the logistic hypothesis model
func (*Logistic) Theta ¶
Theta returns the parameter vector θ for use in persisting the model, and optimizing the model through gradient descent ( or other methods like Newton's Method)
func (*Logistic) UpdateLearningRate ¶
UpdateLearningRate set's the learning rate of the model to the given float64.
func (*Logistic) UpdateTrainingSet ¶
UpdateTrainingSet takes in a new training set (variable x) as well as a new result set (y). This could be useful if you want to retrain a model starting with the parameter vector of a previous training session, but most of the time wouldn't be used.
type Softmax ¶
type Softmax struct { Parameters [][]float64 `json:"theta"` // Output is the io.Writer used for logging // and printing. Defaults to os.Stdout. Output io.Writer // contains filtered or unexported fields }
Softmax represents a softmax classification model in 'k' demensions. It is generally thought of as a generalization of the Logistic Regression model. Prediction will return a vector ([]float64) that corresponds to the probabilty (where i is the index) that the inputted features is 'i'. Softmax classification operates assuming the Multinomial probablility distribution of data.
TODO: add wikipedia link
Expected results expects an 'integer' (it's still passed as a float64) between 0 and k-1. K must be passed when creating the model.
func NewSoftmax ¶
func NewSoftmax(method base.OptimizationMethod, alpha, regularization float64, k, maxIterations int, trainingSet [][]float64, expectedResults []float64, features ...int) *Softmax
NewSoftmax takes in a learning rate alpha, a regularization parameter value (0 means no regularization, higher value means higher bias on the model,) the maximum number of iterations the data can go through in gradient descent, as well as a training set and expected results for that training set.
func (*Softmax) Dij ¶
Dij returns the derivative of the cost function J(θ) with respect to the j-th parameter of the hypothesis, θ[j], for the training example x[i]. Used in Stochastic Gradient Descent.
assumes that i,j is within the bounds of the data they are looking up! (because this is getting called so much, it needs to be efficient with comparisons)
func (*Softmax) Dj ¶
Dj returns the partial derivative of the cost function J(θ) with respect to theta[k] where theta is the parameter vector associated with our hypothesis function Predict (upon which we are optimizing.
k is the classification value you are finding the gradient for (because the parameter vactor is actually a vector _of_ vectors!)
func (*Softmax) Examples ¶
Examples returns the number of training examples (m) that the model currently is training from.
func (*Softmax) Learn ¶
Learn takes the struct's dataset and expected results and runs gradient descent on them, optimizing theta so you can predict accurately based on those results
func (*Softmax) LearningRate ¶
LearningRate returns the learning rate α for gradient descent to optimize the model. Could vary as a function of something else later, potentially.
func (*Softmax) MaxIterations ¶
MaxIterations returns the number of maximum iterations the model will go through in GradientAscent, in the worst case
func (*Softmax) OnlineLearn ¶
func (s *Softmax) OnlineLearn(errors chan error, dataset chan base.Datapoint, onUpdate func([][]float64), normalize ...bool)
OnlineLearn runs similar to using a fixed dataset with Stochastic Gradient Descent, but it handles data by passing it as a channal, and returns errors through a channel, which lets it run responsive to inputted data from outside the model itself (like using data from the stock market at timed intervals or using realtime data about the weather.)
The onUpdate callback is called whenever the parameter vector theta is changed, so you are able to persist the model with the most up to date vector at all times (you could persist to a database within the callback, for example.) Don't worry about it taking too long and blocking, because the callback is spawned into another goroutine.
NOTE that this function is suggested to run in it's own goroutine, or at least is designed as such.
NOTE part 2: You can pass in an empty dataset, so long as it's not nil, and start pushing after.
NOTE part 3: each example is only looked at as it goes through the channel, so if you want to have each example looked at more than once you must manually pass the data yourself.
NOTE part 4: the optional parameter 'normalize' will , if true, normalize all data streamed through the channel to unit length. This will affect the outcome of the hypothesis, though it could be favorable if your data comes in drastically different scales.
Example Online Logistic Regression:
// create the channel of data and errors stream := make(chan base.Datapoint, 100) errors := make(chan error) // notice how we are adding another integer // to the end of the NewSoftmax call. This // tells the model to use that number of features // (2) in leu of finding that from the dataset // like you would with batch/stochastic GD // // Also – the 'base.StochasticGA' doesn't affect // anything. You could put batch or any other model. model := NewSoftmax(base.StochasticGA, 5e-5, 0, 3, 0, nil, nil, 2) go model.OnlineLearn(errors, stream, func(theta [][]float64) { // do something with the new theta (persist // to database?) in here. }) go model.OnlineLearn(errors, stream, func(theta [][]float64) {}) // start passing data to our datastream // // we could have data already in our channel // when we instantiated the Perceptron, though go func() { for iter := 0; iter < 3; iter++ { for i := -2.0; i < 2.0; i += 0.15 { for j := -2.0; j < 2.0; j += 0.15 { if -2*i+j/2-0.5 > 0 && -1*i-j < 0 { stream <- base.Datapoint{ X: []float64{float64(i), float64(j)}, Y: []float64{2.0}, } } else if -2*i+j/2-0.5 > 0 && -1*i-j > 0 { stream <- base.Datapoint{ X: []float64{float64(i), float64(j)}, Y: []float64{1.0}, } } else { stream <- base.Datapoint{ X: []float64{float64(i), float64(j)}, Y: []float64{0.0}, } } } } } // close the dataset close(stream) }() // this will block until the error // channel is closed in the learning // function (it will, don't worry!) for { err, more := <-errors if err != nil { panic("THERE WAS AN ERROR!!! RUN!!!!") } if !more { break } } // Below here all the learning is completed // predict like usual guess, err = model.Predict([]float64{42,6,10,-32}) if err != nil { panic("AAAARGGGH! SHIVER ME TIMBERS! THESE ROTTEN SCOUNDRELS FOUND AN ERROR!!!") }
func (*Softmax) PersistToFile ¶
PersistToFile takes in an absolute filepath and saves the parameter vector θ to the file, which can be restored later. The function will take paths from the current directory, but functions
The data is stored as JSON because it's one of the most efficient storage method (you only need one comma extra per feature + two brackets, total!) And it's extendable.
func (*Softmax) Predict ¶
Predict takes in a variable x (an array of floats,) and finds the value of the hypothesis function given the current parameter vector θ
func (*Softmax) RestoreFromFile ¶
RestoreFromFile takes in a path to a parameter vector theta and assigns the model it's operating on's parameter vector to that.
The path must ba an absolute path or a path from the current directory
This would be useful in persisting data between running a model on data, or for graphing a dataset with a fit in another framework like Julia/Gadfly.
func (*Softmax) String ¶
String implements the fmt interface for clean printing. Here we're using it to print the model as the equation h(θ)=... where h is the softmax hypothesis model
func (*Softmax) Theta ¶
Theta returns the parameter vector θ for use in persisting the model, and optimizing the model through gradient descent ( or other methods like Newton's Method)
func (*Softmax) UpdateLearningRate ¶
UpdateLearningRate set's the learning rate of the model to the given float64.
func (*Softmax) UpdateTrainingSet ¶
UpdateTrainingSet takes in a new training set (variable x) as well as a new result set (y). This could be useful if you want to retrain a model starting with the parameter vector of a previous training session, but most of the time wouldn't be used.