// x = n x c // U = n x c // D = c x c // V = c x c func (r *Ridge) Train(y []float64) error { // standarize matrix and have y_bar = 0 r.x.Normalize() y = subtractMean(y) r.response = y epsilon := math.Pow(2, -52.0) small := math.Pow(2, -966.0) svd := mat64.SVD(mat64.DenseCopyOf(r.x.data), epsilon, small, true, true) U := svd.U // D[0] >= D[1] >= ... >= D[n-1] d := svd.Sigma V := svd.V // convert the c x c diagonal matrix D into a mat64.Dense matrix D := mat64.NewDense(r.c, r.c, rep(0.0, r.c*r.c)) for i := 0; i < r.c; i++ { val := d[i] / (d[i] + r.lambda) D.Set(i, i, val) } // solve for beta_ridge beta := &mat64.Dense{} beta.Mul(V, D) beta.Mul(beta, U.T()) Y := mat64.NewDense(len(y), 1, y) beta.Mul(beta, Y) // save beta values r.beta_ridge = beta.Col(nil, 0) // find the fitted values : X * \beta_ridge fitted := &mat64.Dense{} fitted.Mul(r.x.data, beta) r.fitted = fitted.Col(nil, 0) // get residuals fitted.Sub(fitted, Y) r.residuals = fitted.Col(nil, 0) return nil }
//RotatorTranslatorToSuper superimposes the set of cartesian coordinates given as the rows of the matrix test on the gnOnes of the rows //of the matrix templa. Returns the transformed matrix, the rotation matrix, 2 translation row vectors //For the superposition plus an error. In order to perform the superposition, without using the transformed //the first translation vector has to be added first to the moving matrix, then the rotation must be performed //and finally the second translation has to be added. //This is a low level function, although one can use it directly since it returns the transformed matrix. //The math for this function is by Prof. Veronica Jimenez-Curihual, University of Concepcion, Chile. func RotatorTranslatorToSuper(test, templa *v3.Matrix) (*v3.Matrix, *v3.Matrix, *v3.Matrix, *v3.Matrix, error) { tmr, tmc := templa.Dims() tsr, tsc := test.Dims() if tmr != tsr || tmc != 3 || tsc != 3 { return nil, nil, nil, nil, CError{"goChem: Ill-formed matrices", []string{"RotatorTranslatorToSuper"}} } var Scal float64 Scal = float64(1.0) / float64(tmr) j := gnOnes(tmr, 1) //Mass is not important for this matter so we'll just use this. ctest, distest, err := MassCenter(test, test, j) if err != nil { return nil, nil, nil, nil, errDecorate(err, "RotatorTranslatorToSuper") } ctempla, distempla, err := MassCenter(templa, templa, j) if err != nil { return nil, nil, nil, nil, errDecorate(err, "RotatorTranslatorToSuper") } Mid := gnEye(tmr) jT := gnT(j) ScaledjProd := gnMul(j, jT) ScaledjProd.Scale(Scal, ScaledjProd) aux2 := gnMul(gnT(ctempla), Mid) r, _ := aux2.Dims() Maux := v3.Zeros(r) Maux.Mul(aux2, ctest) Maux.Tr() //Dont understand why this is needed factors := mat64.SVD(v3.Matrix2Dense(Maux), appzero, math.SmallestNonzeroFloat64, true, true) U := factors.U V := factors.V // if err != nil { // return nil, nil, nil, nil, err //I'm not sure what err is this one // } U.Scale(-1, U) V.Scale(-1, V) //SVD gives different results here than in numpy. U and V are multiplide by -1 in one of them //and gomatrix gives as V the transpose of the matrix given as V by numpy. I guess is not an //error, but don't know for sure. vtr, _ := V.Dims() Rotation := v3.Zeros(vtr) Rotation.Mul(V, gnT(U)) Rotation.Tr() //Don't know why does this work :( RightHand := gnEye(3) if det(Rotation) < 0 { RightHand.Set(2, 2, -1) Rotation.Mul(V, RightHand) Rotation.Mul(Rotation, gnT(U)) //If I get this to work Ill arrange so gnT(U) is calculated once, not twice as now. Rotation.Tr() //TransposeTMP contains the transpose of the original Rotation //Same, no ide why I need this //return nil, nil, nil, nil, fmt.Errorf("Got a reflection instead of a translations. The objects may be specular images of each others") } jT.Scale(Scal, jT) subtempla := v3.Zeros(tmr) subtempla.Copy(ctempla) sub := v3.Zeros(ctest.NVecs()) sub.Mul(ctest, Rotation) subtempla.Sub(subtempla, sub) jtr, _ := jT.Dims() Translation := v3.Zeros(jtr) Translation.Mul(jT, subtempla) Translation.Add(Translation, distempla) //This alings the transformed with the original template, not the mean centrate one transformed := v3.Zeros(ctest.NVecs()) transformed.Mul(ctest, Rotation) transformed.AddVec(transformed, Translation) //end transformed distest.Scale(-1, distest) return transformed, Rotation, distest, Translation, nil }