Пример #1
0
func randmatmul(n int) matrix.MatrixRO {
	a := matrix.Zeros(n, n)
	b := matrix.Zeros(n, n)
	for i := 0; i < n; i++ {
		for k := 0; k < n; k++ {
			a.Set(i, k, rand.Float64())
			b.Set(i, k, rand.Float64())
		}
	}
	return matrix.Product(a, b)
}
Пример #2
0
/*
Weights returns the weight vector obtained during the fitting process. If Fit()
has not been executed yet, then the behavior of this method is undefined.

Returns
=======
a column vector of weights (including an additional weight for the bias)
*/
func (self SGD) Weights() mat.DenseMatrix {
	if self.f != nil {
		return self.f.Weights
	} else {
		return *mat.Zeros(1, 1)
	}
}
Пример #3
0
// Covariance test against R
func TestCovariance(t *testing.T) {
	fmt.Println("Covariance test against R")
	data := GetData()
	out := SCov(data)

	//known values
	dist := [...]float64{1.773643, -0.3381504, 0.4803343, -0.8050336, 0.3154475, 0.2026154, 0.5576372, -0.3982494, 0.2083944, 0.1306447,
		-0.3381504, 0.8108673, 0.1696915, 0.5268912, -0.1279332, -0.0810701, 0.4332097, -0.01344127, 0.3683854, -0.1976432,
		0.4803343, 0.1696915, 0.4986279, 0.02131043, 0.2643708, -0.3654575, 0.6973307, -0.3021538, -0.221391, -0.07286902,
		-0.8050336, 0.5268912, 0.02131043, 0.7320278, 0.01051328, -0.4524992, 0.0321159, -0.1932133, 0.1346962, 0.003491767,
		0.3154475, -0.1279332, 0.2643708, 0.01051328, 0.4088249, -0.3923959, 0.2455576, -0.3880454, -0.2810396, 0.1249063,
		0.2026154, -0.0810701, -0.3654575, -0.4524992, -0.3923959, 0.8562731, -0.3241916, 0.5470234, 0.3595004, -0.1266668,
		0.5576372, 0.4332097, 0.6973307, 0.0321159, 0.2455576, -0.3241916, 1.149185, -0.1579107, -0.3901415, -0.3014224,
		-0.3982494, -0.01344127, -0.3021538, -0.1932133, -0.3880454, 0.5470234, -0.1579107, 0.7091816, -0.2188541, -0.3055508,
		0.2083944, 0.3683854, -0.221391, 0.1346962, -0.2810396, 0.3595004, -0.3901415, -0.2188541, 1.283379, 0.2383891,
		0.1306447, -0.1976432, -0.07286902, 0.003491767, 0.1249063, -0.1266668, -0.3014224, -0.3055508, 0.2383891, 0.2644874}

	cols := data.Cols()
	known := mtx.Zeros(cols, cols)
	for i := 0; i < cols; i++ {
		for j := i + 1; j < cols; j++ {
			known.Set(i, j, dist[i*cols+j])
		}
	}

	// check
	for i := 0; i < cols; i++ {
		for j := i + 1; j < cols; j++ {
			if !check(out.Get(i, j), known.Get(i, j)) {
				t.Error()
				fmt.Println(i, j, out.Get(i, j), known.Get(i, j))
			}
		}
	}
}
Пример #4
0
/*
LinearFitAndReturnMSE is used to test linear FunctionApproximators. It
generates a collection of samples according to a 1-d linear function, fits the
function approximator with the training samples, and then returns the Mean
Squared Error (MSE). The training set is purposefully equal to the test set so
that we can test that the passed function approximator learns the training data.

The targets of the linear function are perturbed by a small amount of Gaussian
noise.

Input
=====
fa : a function approximator
t : a testing instance

Returns
=======
the MSE of the fa on samples from the linear function
*/
func LinearFitAndReturnMSE(fa FunctionApproximator, t *testing.T) float64 {
	n := 100
	x := mat.Zeros(n, 1)
	y := mat.Zeros(n, 1)
	for i := 0; i < n; i++ {
		fi := float64(i)
		fn := float64(n)
		fx := fi / fn
		fy := (0.25*fx - 0.5) + rand.NormFloat64()*LINEAR_NOISE
		x.Set(i, 0, fx)
		y.Set(i, 0, fy)
	}
	err := fa.Fit(x, y)
	if err != nil {
		t.Error(err)
	}

	// Test bulk prediction
	yhatM, err := fa.PredictM(x)
	if err != nil {
		t.Error(err)
	}

	sqErrM := 0.0
	diffM, err := y.Minus(yhatM)
	if err != nil {
		t.Error(err)
	}

	sqErr := 0.0
	for i := 0; i < n; i++ {
		sqErrM += diffM.Get(i, 0) * diffM.Get(i, 0)

		v, err := fa.Predict(x.GetRowVector(i))
		if err != nil {
			t.Error(err)
		}
		diff := y.Get(i, 0) - v
		sqErr += diff * diff
	}

	mse := math.Max(sqErr, sqErrM) / float64(n)
	return mse
}
Пример #5
0
/*
 M is r x c, o x i
 Sigma is r x r, o x o
 Phi is c x c, i x i

 Sigma matches Y o x 1 output dimension
 Phi matches X i x 1 input dimension
*/
func NewKnownVarianceLRPosterior(M, Sigma, Phi *mx.DenseMatrix) (this *KnownVarianceLRPosterior) {
	if M.Rows() != Sigma.Rows() {
		panic("M.Rows != Sigma.Rows")
	}
	if M.Cols() != Phi.Cols() {
		panic("M.Cols != Phi.Cols")
	}
	if Sigma.Rows() != Sigma.Cols() {
		panic("Sigma is not square")
	}
	if Phi.Rows() != Phi.Cols() {
		panic("Phi is not square")
	}
	this = &KnownVarianceLRPosterior{
		M:     M,
		Sigma: Sigma,
		Phi:   Phi,
		XXt:   mx.Zeros(Phi.Cols(), Phi.Cols()),
		YXt:   mx.Zeros(Sigma.Cols(), Phi.Cols()),
	}

	return
}
Пример #6
0
/*
Apply applies the function f to each element in A and returns a new matrix with
the results.

Input
=====
A : a matrix
f : a function from scalar values to scalar values

Returns
=======
a matrix derived by applying f to each element in A. If f is nil, then this
function just returns A.
*/
func Apply(A mat.MatrixRO, f SFunction) mat.MatrixRO {
	if f == nil {
		return A
	}
	B := mat.Zeros(A.Rows(), A.Cols())
	for r := 0; r < A.Rows(); r++ {
		for c := 0; c < A.Cols(); c++ {
			x := A.Get(r, c)
			y := f(x)
			B.Set(r, c, y)
		}
	}
	return B
}
Пример #7
0
func Wishart(n int, V *m.DenseMatrix) func() *m.DenseMatrix {
	p := V.Rows()
	zeros := m.Zeros(p, 1)
	rowGen := MVNormal(zeros, V)
	return func() *m.DenseMatrix {
		x := make([][]float64, n)
		for i := 0; i < n; i++ {
			x[i] = rowGen().Array()
		}
		X := m.MakeDenseMatrixStacked(x)
		S, _ := X.Transpose().TimesDense(X)
		return S
	}
}
Пример #8
0
func MatrixT(M, Omega, Sigma *mx.DenseMatrix, n int) func() (T *mx.DenseMatrix) {
	checkMatrixT(M, Omega, Sigma, n)

	fmt.Println("M:", M)
	fmt.Println("Sigma:", Sigma)
	fmt.Println("Omega:", Omega)

	p := M.Rows()
	m := M.Cols()

	OmegaInv, err := Omega.Inverse()
	if err != nil {
		panic(err)
	}

	Sdist := Wishart(n+p-1, OmegaInv)

	Xdist := MatrixNormal(mx.Zeros(p, m), mx.Eye(p), Sigma)

	return func() (T *mx.DenseMatrix) {
		S := Sdist()
		Sinv, err := S.Inverse()
		if err != nil {
			panic(err)
		}
		Sinvc, err := Sinv.Cholesky()
		if err != nil {
			panic(err)
		}
		X := Xdist()
		fmt.Println("Sinvc:", Sinvc)
		fmt.Println("X:", X)
		T, err = Sinvc.Transpose().TimesDense(X)
		if err != nil {
			panic(err)
		}
		err = T.AddDense(M)
		if err != nil {
			panic(err)
		}
		return
	}
}
Пример #9
0
func randmatstat(t int) (float64, float64) {
	n := 5
	var v stats.Stats
	var w stats.Stats
	for i := 0; i < t; i++ {
		a := matrix.Zeros(n, n)
		b := matrix.Zeros(n, n)
		c := matrix.Zeros(n, n)
		d := matrix.Zeros(n, n)
		for j := 0; j < n; j++ {
			for k := 0; k < n; k++ {
				a.Set(j, k, rand.NormFloat64())
				b.Set(j, k, rand.NormFloat64())
				c.Set(j, k, rand.NormFloat64())
				d.Set(j, k, rand.NormFloat64())
			}
		}
		P := matrix.Zeros(n, 4*n)
		for j := 0; j < n; j++ {
			for k := 0; k < n; k++ {
				P.Set(j, k, a.Get(j, k))
				P.Set(j, n+k, b.Get(j, k))
				P.Set(j, 2*n+k, c.Get(j, k))
				P.Set(j, 3*n+k, d.Get(j, k))
			}
		}
		Q := matrix.Zeros(2*n, 2*n)
		for j := 0; j < n; j++ {
			for k := 0; k < n; k++ {
				Q.Set(j, k, a.Get(j, k))
				Q.Set(j, n+k, b.Get(j, k))
				Q.Set(n+j, k, c.Get(j, k))
				Q.Set(n+j, n+k, d.Get(j, k))
			}
		}
		P = matrix.Product(matrix.Transpose(P), P)
		P = matrix.Product(P, P)
		P = matrix.Product(P, P)
		Q = matrix.Product(matrix.Transpose(Q), Q)
		Q = matrix.Product(Q, Q)
		Q = matrix.Product(Q, Q)
		v.Update(P.Trace())
		w.Update(Q.Trace())
	}
	return v.PopulationStandardDeviation() / float64(v.Count()) / v.Mean(), w.PopulationStandardDeviation() / float64(w.Count()) / w.Mean()
}
// zerosMatrix returns a matrix filled with zeroes of a given size
// Params: rows int -- number of rows to fill
// Params: cols int -- number of cols to fill
// Returns: *goMatrix.DenseMatrix
func zerosMatrix(rows, cols int) *goMatrix.DenseMatrix {
	return goMatrix.Zeros(rows, cols)
}
// generateReturns generates performance specifically for assets, and returns
// separately by asset class as a map
// Receiver: SimulationData
// Params: numberOfMonths int -- number of periods to model
// Returns: returnResultsByAsset
func (s *SimulationData) generateReturns(numberOfMonths int) returnResultsByAsset {
	assetPerformanceData := s.AssetPerformanceData // map[string]Distribution
	assetClassIds := s.assetClassIds()             // []string
	numberOfAssets := len(assetClassIds)

	choleskyApplied := s.applyCholeskyDecomposition(numberOfMonths)

	prices := goMatrix.Zeros(numberOfMonths, numberOfAssets)

	for row := 0; row < prices.Rows(); row++ {
		for column := 0; column < prices.Cols(); column++ {
			var startingValue float64
			if row == 0 {
				startingValue = 0.0
			} else {
				startingValue = prices.Get((row - 1), column)
			}

			assetId := assetClassIds[column] // These are sorted alphabetically
			assetStats := assetPerformanceData[assetId]
			assetMeanReturn := assetStats.Mean
			assetStdDev := assetStats.StdDev

			b := assetMeanReturn - 0.5*math.Pow(assetStdDev, 2)
			c := assetStdDev * choleskyApplied.Get(row, column)

			// Can't do the exp(x) in the same step as you need to use the previous value as a starting price!
			prices.Set(row, column, (startingValue + b + c))
		}

	}

	for row := 0; row < prices.Rows(); row++ {
		for column := 0; column < prices.Cols(); column++ {
			basePrice := prices.Get(row, column)
			expPrice := math.Exp(basePrice)
			prices.Set(row, column, expPrice)
		}
	}

	/* Convert prices to relative returns. */
	// Add T=0, price=1.0
	initialPrices := goMatrix.Ones(1, numberOfAssets)
	augmentedPrices, _ := initialPrices.Stack(prices)

	// Create base matrix
	asRelativeReturns := goMatrix.Zeros(numberOfMonths, numberOfAssets)

	// Each row in the prices matrix is a list of asset prices in each year - NOT
	// the progression of a single asset. We'll need to grab columns for that.
	for column := 0; column < augmentedPrices.Cols(); column++ {
		priceValues := augmentedPrices.GetColVector(column).Array() // []float64
		for periodIndex, periodPrice := range priceValues {
			if periodIndex == 0 {
				// Nothing to do on the first column
				continue
			}
			lastPrice := priceValues[periodIndex-1]
			pctReturn := (periodPrice - lastPrice) / lastPrice
			asRelativeReturns.Set((periodIndex - 1), column, pctReturn)
		}
	}
	/* */

	results := asRelativeReturns.Arrays()    // [][]float64
	resultsByAsset := returnResultsByAsset{} // map[string][]float64
	for _, assetClassId := range assetClassIds {
		resultsByAsset[assetClassId] = make([]float64, numberOfMonths)
	}

	for periodIndex, resultSet := range results {
		for assetIndex, returnResult := range resultSet {
			assetClassId := assetClassIds[assetIndex]
			resultsByAsset[assetClassId][periodIndex] = returnResult
		}
	}

	return resultsByAsset
}
Пример #12
0
func (self *SGD) Fit(x mat.MatrixRO, y mat.MatrixRO) error {
	if x.Rows() != y.Rows() {
		return fmt.Errorf("The number of rows in x (%d) does not match the number of rows in y (%d). The matrix x should contain one input vector per row and the vector y should be a column vector containing labels for each input vector.", x.Rows(), y.Rows())
	}
	if y.Cols() != 1 {
		return fmt.Errorf("y must be a column vector.")
	}

	// The number of samples in the data set
	n := x.Rows()
	// Get a dense version of the input matrix
	dx := x.DenseMatrix()

	// If there is no LinearModel yet, then we add one.
	if self.f == nil {
		self.inputDims = x.Cols()
		self.f = new(LinearFunction)
		self.f.Weights = *mat.Zeros(self.inputDims+1, 1)
		self.f.AFunc = self.afunc
	} else if self.inputDims != x.Cols() {
		// If there is an existing linear model, then we only train on
		// additional samples if they match the dimensionality of the previous
		// training data.
		return fmt.Errorf("The number of columns in matrix x does not match the dimension of previous training data. Please construct a new SGD instance.")
	}

	for i := 0; i < self.NumIterations; i++ {
		index := rand.Intn(n)
		xrow := dx.GetRowVector(index)
		xrowb := self.addBiasToMatrix(xrow)
		yhat, err := self.f.Predict(xrowb)
		if err != nil {
			return fmt.Errorf("Error while predicting with internal linear model. %v", err)
		}

		// Compute the activation function's derivative
		yhatPrime := 0.0
		if self.afunc != nil {
			yNoAct, err := xrowb.Times(&self.f.Weights)
			if err != nil {
				return fmt.Errorf("Error while predicting before applying the activation function. %v", err)
			}
			yhatPrime = self.afunc.Deriv(yNoAct.Get(0, 0))
		} else {
			yhatPrime = 1
		}

		diff := y.Get(index, 0) - yhat
		for j := 0; j < self.inputDims+1; j++ {
			// Get the old weight value
			oldw := self.f.Weights.Get(j, 0)
			// Calculate the gradient of the squared error
			grad := 0.0
			if j < self.inputDims {
				grad = (diff * yhatPrime * -xrow.Get(0, j))
			} else {
				// Gradient for the bias
				grad = -diff * yhatPrime
			}

			// Calculate the gradient of the regularization penalty
			gpen := 0.0
			if self.PenaltyType == L1_PENALTY {
				gpen = self.Lambda * signum(oldw)
			} else {
				gpen = self.Lambda * oldw
			}
			// Calculate the change in weight
			alpha := self.LearningRate / float64(self.inputDims)
			deltaw := alpha * (grad + gpen)
			neww := oldw - deltaw
			// Set the new weight
			self.f.Weights.Set(j, 0, neww)
		}
	}

	return nil
}