// Two heuristics: func (alg *smo) examineExample() int { data := alg.s.supportVectors[alg.i1] alg.a2 = alg.s.alpha[alg.i2] alg.E2 = alg.errors[alg.i2] r2 := alg.E2 * data.Class() if (r2 < -alg.tolerance && alg.a2 < alg.C) || (r2 > alg.tolerance && alg.a2 > 0) { if alg.numNonBoundaryAlphas > 1 { // Second Choice Heuristic by biggest |E1 - E2| alg.i1 = 0 prev := gomath.AbsFloat32(alg.errors[alg.i1] - alg.E2) for i := 1; i < len(alg.s.supportVectors); i++ { test := gomath.AbsFloat32(alg.errors[i] - alg.E2) if test > prev { prev = test alg.i1 = i } } alg.E1 = prev if alg.takeStep() { return 1 } } for i, a := range alg.s.alpha { if a > 0 && a < alg.C { alg.i1 = i alg.E1 = alg.errors[i] if alg.takeStep() { return 1 } } } randomStart := rand.Intn(len(alg.s.alpha)) for i := 0; i < len(alg.s.alpha); i++ { alg.i1 = randomStart alg.E1 = alg.errors[randomStart] if alg.takeStep() { return 1 } randomStart = (randomStart + 1) % len(alg.s.alpha) } } return 0 }
func TestDotFloat32WithSameLength(t *testing.T) { N := 500000 a := genFloat32Array(N, LowFloat32, HighFloat32) b := genFloat32Array(N, LowFloat32, HighFloat32) Expected := 0.0 for i := range a { Expected += float64(a[i] * b[i]) } computed := DotFloat32(a, b) if gomath.AbsFloat32(computed-float32(Expected)) < LowFloat32 { t.Logf("Expected %f but computed %f\n", Expected, computed) t.FailNow() } }
func TestDotFloat32WithDiffLength(t *testing.T) { N := 1000 + rand.Intn(1000000) M := 1000 + rand.Intn(1000000) if N == M { N++ } a := genFloat32Array(N, LowFloat32, HighFloat32) b := genFloat32Array(M, LowFloat32, HighFloat32) Expected := 0.0 for i := range a { if i < N && i < M { Expected += float64(a[i] * b[i]) } else { break } } computed := DotFloat32(a, b) if gomath.AbsFloat32(computed-float32(Expected)) < LowFloat32 { t.Logf("Expected %f but computed %f\n", Expected, computed) t.FailNow() } }
func (alg *smo) takeStep() bool { result := false if alg.i1 != alg.i2 { fZero := float32(0) alpha1 := alg.s.alpha[alg.i1] alpha2 := alg.a2 alg.a1 = alpha1 alg.v1 = alg.s.supportVectors[alg.i1].Value() alg.y1 = alg.s.supportVectors[alg.i1].Class() alg.E1 = alg.s.Classify(alg.v1) - alg.y1 var L, H float32 if alg.y1 == alg.y2 { sum := alpha2 + alpha1 L = gomath.MaxFloat32(fZero, sum-alg.C) H = gomath.MinFloat32(alg.C, sum) } else { diff := alpha2 - alpha1 L = gomath.MaxFloat32(fZero, diff) H = gomath.MinFloat32(alg.C, alg.C+diff) } if L != H { k11 := alg.s.kernel.Dot(alg.v1, alg.v1) k12 := alg.s.kernel.Dot(alg.v1, alg.v2) k22 := alg.s.kernel.Dot(alg.v2, alg.v2) eta := 2*k12 - k11 - k22 if eta < 0 { alg.a2 = gomath.ClampFloat32(L, H, alpha1-alg.y2*(alg.E1-alg.E2)/eta) } else { Lobj := float32(5.0) Hobj := float32(5.0) if Lobj > Hobj+1E-3 { alg.a2 = L } else if Lobj < Hobj-1E-3 { alg.a2 = L } else { alg.a2 = alpha2 } if alg.a2 < 1E-8 { alg.a2 = 0 } else if alg.a2 > alg.C-1e-8 { alg.a2 = alg.C } if gomath.AbsFloat32(alg.a2-alpha2) >= alg.eps*(alg.a2+alpha2+alg.eps) { alg.s.alpha[alg.i1] = alg.a1 alg.s.alpha[alg.i2] = alg.a2 result = true } } } } return result }