func TestRegionFeedBack(t *testing.T) { l := NewRegion(RegionParameters{ Name: "Single Region", Learning: true, Height: 4, Width: 500, InputLength: 64, MaximumFiringColumns: 5, MinimumInputOverlap: 2, }) l.RandomizeColumns(32) inputA := data.NewBitset(64).Set(1, 5) inputB := data.NewBitset(64).Set(2, 10) maxAttempts := 77 for !l.SensedInput().Equals(*inputB) && maxAttempts > 0 { maxAttempts-- l.ConsumeInput(*inputA) l.ConsumeInput(*inputB) } oB := l.Output().Clone() l.ConsumeInput(*inputA) oA := l.Output().Clone() fA := l.FeedBack(*oA) if !fA.Equals(*inputA) { t.Errorf("Feedback for A=%v does not match: %v", *inputA, *fA) } fB := l.FeedBack(*oB) if !fB.Equals(*inputB) { t.Errorf("Feedback for B=%v does not match: %v", *inputB, *fB) } }
func TestTp_AAxB(t *testing.T) { if testing.Short() { t.SkipNow() } test := NewTpTest(t) test.Verify = false random := data.NewBitset(test.layer0.InputLength) for i := 0; i < 8000; i++ { test.Step(*test.inputA) test.Step(*test.inputA) random.Reset().Set(rand.Intn(test.layer0.InputLength)) test.Step(*random) test.Step(*test.inputB) } aOrB := data.NewBitset(test.layer0.InputLength) aOrB.ResetTo(*test.inputA) aOrB.Or(*test.inputB) // After ...,B comes A. test.checkPredictedInput(*test.inputA) // After ...,A comes A. test.Step(*test.inputA) test.checkPredictedInput(*test.inputA) // After ...,A,A comes anything. test.Step(*test.inputA) test.Log("Predict anything:", test.layer0.PredictedInput()) // Then comes B. random.Reset().Set(rand.Intn(test.layer0.InputLength)) test.Step(*random) test.checkPredictedInput(*test.inputB) }
func TestFindBestSegment(t *testing.T) { c := NewColumn(64, 4) active1 := data.NewBitset(64).Set(2, 20, 22) active2 := data.NewBitset(64).Set(11, 31) update := c.distal[1].CreateUpdate(-1, *active1, 2) c.distal[1].Apply(update, true) update = c.distal[2].CreateUpdate(-1, *active2, 2) c.distal[2].Apply(update, true) state := data.NewBitset(64).Set(2) cell, s, overlap := c.FindBestSegment(*state, 1, false) if cell != 1 || s != 0 || overlap != 1 { t.Errorf("FindBestSegment(%v,minOverlap=%d): %d, %v, %d", *state, 1, cell, s, overlap) } cell, s, overlap = c.FindBestSegment(*state, 2, false) if cell != -1 || s != -1 { t.Errorf("FindBestSegment(%v,minOverlap=%d): %d, %v, %d", *state, 2, cell, s, overlap) } state.Set(22) cell, s, overlap = c.FindBestSegment(*state, 2, false) if cell != 1 || s != 0 || overlap != 2 { t.Errorf("FindBestSegment(%v,minOverlap=%d): %d, %v, %d", *state, 2, cell, s, overlap) } state.Reset().Set(2, 20, 11, 31) }
func TestPredict(t *testing.T) { c := NewColumn(64, 4) active1 := data.NewBitset(64).Set(2, 20) active2 := data.NewBitset(64).Set(11, 31) update := c.distal[1].CreateUpdate(-1, *active1, 2) c.distal[1].Apply(update, true) update = c.distal[2].CreateUpdate(-1, *active2, 2) c.distal[2].Apply(update, true) state := data.NewBitset(64).Set(2) c.Predict(*state, 1) pred := c.Predictive() if !pred.AllSet(1) || pred.NumSetBits() != 1 { t.Errorf("Should have predicted only cell 1, but got %v", pred) t.Log(*c.distal[1]) } state.Set(11) c.Predict(*state, 1) pred = c.Predictive() if !pred.AllSet(1, 2) || pred.NumSetBits() != 2 { t.Errorf("Should have predicted cells 1 and 2, but got %v", pred) t.Log(*c.distal[1]) t.Log(*c.distal[2]) } }
func NewPermanenceMap(numBits int) *PermanenceMap { result := &PermanenceMap{ config: DefaultPermanenceConfig, permanence: make(map[int]float32), synapses: data.NewBitset(numBits), receptiveField: data.NewBitset(numBits), } return result }
func BenchmarkColumnOverlap(b *testing.B) { c := NewColumn(64, 1) connections := []int{1, 3, 5, 8, 11} c.ResetConnections(connections) input := data.NewBitset(64).Set(1, 5, 22) result := data.NewBitset(64).Set(1, 5, 22, 60) b.ResetTimer() for i := 0; i < b.N; i++ { result.Overlap(*input) } }
func NewColumn(inputSize, height int) *Column { result := &Column{ active: data.NewBitset(height), predictive: data.NewBitset(height), proximal: segment.NewDendriteSegment(inputSize), learning: -1, learningTarget: 0, distal: make([]*segment.DistalSegmentGroup, height), } for i := 0; i < height; i++ { result.distal[i] = segment.NewDistalSegmentGroup() } return result }
func TestLearn64PatternAB_5(t *testing.T) { if testing.Short() { t.SkipNow() } rand.Seed(1979) ds := segment.NewDendriteSegment(64) ds.Reset(1, 3, 5, 8, 13, 21) patternA := data.NewBitset(64) patternA.Set(2, 4, 22, 24, 42, 44, 62) patternB := data.NewBitset(64) patternB.Set(22, 23, 24, 25, 26) TryToLearn(t, 90, ds, 5, *patternA, *patternB) t.Log(ds.Connected()) }
func (d *Drop) InitializeNetwork() { params := htm.RegionParameters{ Name: "0-drop", Width: 640, Height: 8, MinimumInputOverlap: 1, InputLength: 64, Learning: true, } params.MaximumFiringColumns = params.Width / 50 d.step = 0 d.region0 = htm.NewRegion(params) d.region0.RandomizeColumns(params.InputLength / 2) params.Name = "1-drop" params.Width = 2000 params.Height = 5 params.InputLength = d.region0.Output().Len() params.MaximumFiringColumns = params.Width / 100 d.region1 = htm.NewRegion(params) d.region1.RandomizeColumns(params.InputLength / 2) params.Name = "final" params.Width = 200 params.Height = 3 params.InputLength = d.region1.Output().Len() params.MaximumFiringColumns = 1 d.region3 = htm.NewRegion(params) d.region3.RandomizeColumns(params.InputLength / 2) d.predicted = data.NewBitset(d.region3.PredictiveState().Len()) d.patterns = make(map[string]string) }
func TestBroadenSynapses(t *testing.T) { ds := NewDendriteSegment(64) ds.Reset(1, 3, 5, 8, 13) input := data.NewBitset(64) input.Set(1, 5, 22) for i := 0; i < 1000 && ds.permanence[3] >= ds.Config().Minimum; i++ { ds.narrow(*input) } if ds.permanence[22] != 0 { t.Errorf("Permanence for non-connected should be zero: %v", ds.permanence) } input.Reset() input.Set(1, 8, 22) overlap := ds.broaden(*input, 0) if overlap != 1 { t.Errorf("Only bit 1 should overlap, not %d: %v", overlap, *ds) } if ds.permanence[1] <= ds.permanence[3] { t.Errorf("Permanence scores did not improve: %v", ds.permanence) } if ds.permanence[1] != ds.permanence[5] { t.Errorf("Permanence scores must be uniform: %v", ds.permanence) } if ds.permanence[8] != ds.Config().Minimum || ds.permanence[22] != ds.Config().Minimum { t.Errorf("Permanence for broadened synapse should be %f: %v", ds.Config().Minimum, ds.permanence) } }
func TryToLearn(t *testing.T, maxTries int, ds *segment.DendriteSegment, minOverlap int, inputs ...data.Bitset) int { result := 0 overlap := data.NewBitset(inputs[0].Len()) for !ds.Connected().Equals(inputs[0]) { input := inputs[result%len(inputs)] overlap.ResetTo(input) overlap.And(ds.Connected()) active := overlap.NumSetBits() >= minOverlap || rand.Float32()+ds.Boost > 3.0 ds.Learn(input, active, minOverlap) result++ if active { fmt.Print("N") } else { fmt.Print("B") } if result > maxTries { t.Error(fmt.Sprintf("Failed after %d rounds.", maxTries)) return result } } fmt.Println() t.Log(fmt.Sprintf("Learned in %d rounds.", result)) return result }
func TestMinOverlap(t *testing.T) { l := NewRegion(RegionParameters{ Name: "Single Region", Learning: true, Height: 4, Width: 100, InputLength: 2048, MaximumFiringColumns: 40, MinimumInputOverlap: 1, }) columnRand.Seed(0) l.RandomizeColumns(20) input := data.NewBitset(2048) input.SetRange(0, 20) l.ConsumeInput(*input) output := l.Output() if output.IsZero() { t.Errorf("Output is empty: %v", output) } t.Log(output) l.MinimumInputOverlap = 4 l.ConsumeInput(*input) output = l.Output() if !output.IsZero() { t.Errorf("Output should be empty: %v", output) } }
func TestCategoryEncoder(t *testing.T) { s, err := NewCategorySensor(64, 4, "A", "B", "C") if err != nil { t.Fatal(err) } if err = s.Encode("A"); err != nil { t.Error(err) } b := data.NewBitset(64).SetRange(0, 4) if !s.Get().Equals(*b) { t.Errorf("Encode failed. Expected: %v, but got: %v", *b, s.Get()) } if v := s.Decode(*b); v != "A" { t.Errorf("Decode failed. Expected: %v, but got: %v (%v)", "A", v, *s) } if err = s.Encode("B"); err != nil { t.Error(err) } b.Reset().SetRange(4, 8) if !s.Get().Equals(*b) { t.Errorf("Encode failed. Expected: %v, but got: %v", *b, s.Get()) } if v := s.Decode(*b); v != "B" { t.Errorf("Decode failed. Expected: %v, but got: %v (%v)", "B", v, *s) } err = s.Encode("Other") if err == nil { t.Error("Should have failed to encode unknown category \"Other\":", *s) } }
func TestTp_LearnAAB(t *testing.T) { if testing.Short() { t.SkipNow() } test := NewTpTest(t) test.Verify = false for i := 0; i < 100; i++ { test.Step(*test.inputA) test.Step(*test.inputA) test.Step(*test.inputB) } aOrB := data.NewBitset(test.layer0.InputLength) aOrB.ResetTo(*test.inputA) aOrB.Or(*test.inputB) // After ...,B comes A. test.checkPredictedInput(*test.inputA) // After ...,A comes A. test.Step(*test.inputA) test.checkPredictedInput(*test.inputA) // After ...,A,A comes A or B. test.Step(*test.inputA) test.checkPredictedInput(*aOrB) }
func (d *Drop) AddNoise() { noise := data.NewBitset(d.region0.InputLength) noise.Set(rand.Intn(noise.Len()), rand.Intn(noise.Len())) d.region0.ConsumeInput(*noise) d.region1.ConsumeInput(d.region0.Output()) d.region3.ConsumeInput(d.region1.Output()) }
func BenchmarkNarrowSynapses(b *testing.B) { pm := NewPermanenceMap(64) pm.Reset(1, 3, 5, 8, 13) input := data.NewBitset(64) input.Set(1, 5, 22) for i := 0; i < b.N; i++ { pm.narrow(*input) } }
func (l *Region) PredictedInput() data.Bitset { dest := data.NewBitset(l.InputLength) for _, col := range l.columns { if !col.Predictive().IsZero() { dest.Or(col.Connected()) } } return *dest }
func TestDistalSegmentGroup(t *testing.T) { group := NewDistalSegmentGroup() v1 := data.NewBitset(64).Set(1, 10) v2 := data.NewBitset(64).Set(2, 20) u1 := group.CreateUpdate(-1, *v1, 2) u2 := group.CreateUpdate(-1, *v2, 2) group.AddUpdate(u1) group.AddUpdate(u2) active := data.NewBitset(64).Set(10) if group.HasActiveSegment(*active, 1) { t.Errorf("Test is broken, group should be empty. %v", *group) } group.ApplyAll(true) if !group.HasActiveSegment(*active, 1) { t.Errorf("Expected at least one active segment: %v", *group) } sIndex, sOverlap := group.ComputeActive(*active, 1, false) if sIndex != 0 { t.Errorf("Unexpected active segment. Expected: %d, but got: %d. %v", 0, sIndex, *group) } if sOverlap != 1 { t.Errorf("Unexpected overlap. Expected: %d, but got: %d. %v", 1, sOverlap, *group) } // Disconnect bits 2 and 20 in segment @1. config := group.segments[1].Config() group.segments[1].Set(2, config.Minimum) group.segments[1].Set(20, config.Minimum) // Make active state weakly better connected to @1 but strongly to @0. active.Reset().Set(1, 2, 20) sIndex, _ = group.ComputeActive(*active, 1, true) if sIndex != 1 { t.Errorf("Unexpected active segment. Expected: %d, but got: %d. %v", 0, sIndex, *group) } sIndex, _ = group.ComputeActive(*active, 1, false) if sIndex != 0 { t.Errorf("Unexpected active segment. Expected: %d, but got: %d. %v", 0, sIndex, *group) } }
func TestLearn64PatternA_5(t *testing.T) { if testing.Short() { t.SkipNow() } rand.Seed(1979) ds := segment.NewDendriteSegment(64) ds.Reset(1, 3, 5, 8, 13, 21) patternA := data.NewBitset(64) patternA.Set(2, 4, 22, 24, 42, 44, 62) TryToLearn(t, 80, ds, 5, *patternA) t.Log(ds) }
func (l *Region) FeedBack(output data.Bitset) *data.Bitset { dest := data.NewBitset(l.InputLength) output.Foreach(func(cellId int) { col := l.columns[cellId/l.Height()] cell := cellId % l.Height() if !col.Distal(cell).HasActiveSegment(output, l.MinimumInputOverlap) { // Not a predicted cell, must be active from fast-forward. dest.Or(col.Connected()) } }) return dest }
func TestIntEncoder(t *testing.T) { s, err := NewScalarSensor(64, 2, -100, 100) if err != nil { t.Fatal(err) } if s.MinValue != -100 || s.MaxValue != 100 { t.Error("Initialization error:", *s) } if s.BucketSize != 200.0/63.0 { t.Errorf("Bucket size should be %f, but is %f", 200.0/63.0, s.BucketSize) } // First bucket is [0..2], which corresponds to [-100..-98). if err = s.Encode(-100); err != nil { t.Fatal(err) } b := data.NewBitset(64).SetRange(0, 2) if !s.Get().Equals(*b) { t.Errorf("Encode failed. Expected: %v, but got: %v", *b, s.Get()) } s.Encode(-99) if !s.Get().Equals(*b) { t.Errorf("Encode(%d) failed. Expected: %v, but got: %v", -99, *b, s.Get()) } s.Encode(-98) if !s.Get().Equals(*b) { t.Errorf("Encode(%d) failed. Expected: %v, but got: %v", -98, *b, s.Get()) } v := s.DecodeInt(*b) if v != -99 { t.Errorf("Decode failed. Expected: %v, but got: %v", -99, v) } // Next bucket is [1..3], which corresponds to [-97..-95). b.Reset().SetRange(1, 3) v = s.DecodeInt(*b) if v != -96 { t.Errorf("Decode failed. Expected: %v, but got: %v", -96, v) } // Last bucket is [62..64], which corresponds to [98..100) b.Reset().SetRange(62, 64) s.Encode(99) if !s.Get().Equals(*b) { t.Errorf("Encode(%d) failed. Expected: %v, but got: %v (%v)", 98, *b, s.Get(), *s) } if v = s.DecodeInt(*b); v != 98 { t.Errorf("Decode failed. Expected: %v, but got: %v (%v)", 98, v, *s) } }
func (g *DistalSegmentGroup) CreateUpdate(sIndex int, activeState data.Bitset, minSynapses int) *SegmentUpdate { state := data.NewBitset(activeState.Len()) if sIndex >= 0 { s := g.segments[sIndex] state.ResetTo(s.Connected()) } state.Or(activeState) for num := state.NumSetBits(); num < minSynapses; num = state.NumSetBits() { // TODO(tms): optimize. indices := segmentRand.Perm(state.Len())[num:minSynapses] state.Set(indices...) } return NewSegmentUpdate(sIndex, state) }
func NewTpTest(t LoggerInterface) *TpTest { params := htm.RegionParameters{ Name: "0-tp", Learning: true, Height: 8, Width: 64, InputLength: 64, MinimumInputOverlap: 1, MaximumFiringColumns: 2, } result := &TpTest{ LoggerInterface: t, step: 0, inputA: data.NewBitset(64), inputB: data.NewBitset(64), layer0: htm.NewRegion(params), expected0: data.NewBitset(params.Width * params.Height), active0: data.NewBitset(params.Width * params.Height), predicted0: data.NewBitset(params.Width * params.Height), Verify: true, } odds := make([]int, 32) evens := make([]int, 32) for j := 0; j < 32; j++ { odds[j] = j + 1 evens[j] = j } result.inputA.Set(1) result.inputB.Set(8) for i := 0; i < params.Width; i++ { result.layer0.ResetColumnSynapses(i, i) } return result }
func BenchmarkBroadenSynapses(b *testing.B) { ds := NewDendriteSegment(2048) ds.Reset(1, 3, 50, 800, 2013) input := data.NewBitset(2048) input.Set(1, 50, 2047) for i := 0; i < 1000 && ds.permanence[3] >= ds.Config().Minimum; i++ { ds.narrow(*input) } input.Reset() input.Set(1, 50, 800, 2013, 2047) b.ResetTimer() for i := 0; i < b.N; i++ { input.Set(i % 2048) ds.broaden(*input, 1) input.Unset(i % 2048) } }
func TestPermanence(t *testing.T) { pm := NewPermanenceMap(64) pm.Reset(1, 10, 20, 30, 40, 50, 60) pm.Set(10, pm.Config().Minimum) if pm.Connected().IsSet(10) { t.Errorf("Should have disconnected bit 10: %v", *pm) } pm.Set(8, pm.Config().Threshold) if !pm.Connected().IsSet(8) { t.Errorf("Should have connected bit 8: %v", *pm) } input := data.NewBitset(64).Set(1, 10, 20, 21, 22, 23) if pm.Overlap(*input, false) != 2 { t.Errorf("Bad strong overlap with input=%v: %v", *input, *pm) } if pm.Overlap(*input, true) != 3 { t.Errorf("Bad weak overlap with input=%v: %v", *input, *pm) } }
// Creates a new named region with the given parameters. func NewRegion(params RegionParameters) *Region { result := &Region{ RegionParameters: params, columns: make([]*Column, params.Width), output: data.NewBitset(params.Width * params.Height), active: data.NewBitset(params.Width * params.Height), lastActive: data.NewBitset(params.Width * params.Height), predictive: data.NewBitset(params.Width * params.Height), lastPredictive: data.NewBitset(params.Width * params.Height), learnActiveState: data.NewBitset(params.Width * params.Height), learnActiveStateLast: data.NewBitset(params.Width * params.Height), learnPredictiveState: data.NewBitset(params.Width * params.Height), scores: make([]ScoredElement, 0, params.MaximumFiringColumns+1), } for i := 0; i < params.Width; i++ { result.columns[i] = NewColumn(params.InputLength, params.Height) result.columns[i].Index = i } log.HtmLogger.Printf("Region created: %+v", params) return result }
func TestPeriodicEncoder(t *testing.T) { // Monday to Sunday. mo, tu, we, th, fr, sa, su := 1, 2, 3, 4, 5, 6, 7 week := []int{mo, tu, we, th, fr, sa, su} s, err := NewPeriodicSensor(64, mo, su) if err != nil { t.Fatal(err) } for _, day := range week { if err = s.Encode(day); err != nil { t.Error("Could not encode day: ", day, ", error: ", err) } } if t.Failed() { return } s.Encode(mo) eMo := s.Get().Clone() if eMo.NumSetBits() != s.W { t.Errorf("Should have %d bits set, but has %d.", s.W, eMo.NumSetBits()) } if mo != s.Decode(*eMo) { t.Errorf("Decode failed, expected %d but got: %d (%v)", mo, s.Decode(*eMo), *s) } eTu := data.NewBitset(s.N) eMo.Foreach(func(i int) { eTu.Set((i + 1) % (su - mo)) }) if tu != s.Decode(*eTu) { t.Errorf("Decode(%v) failed, expected %d but got: %d (%v)", eTu, tu, s.Decode(*eTu), *s) } s.Encode(su) eSu := s.Get().Clone() if eSu.Overlap(*eMo) != 2 { t.Errorf("Sunday(%v) and Monday(%v) should overlap on two bits.", eSu, eMo) } if eSu.Overlap(*eTu) != 1 { t.Errorf("Sunday(%v) and Monday(%v) should overlap on one bit.", eSu, eTu) } }
func TestWeakenSynapses(t *testing.T) { pm := NewPermanenceMap(64) pm.Reset(1, 10, 20) pm.Set(30, pm.Config().Threshold+pm.Config().Decrement) input := data.NewBitset(64).Set(10, 30) pm.weaken(*input) if pm.Get(10) != pm.Config().Initial-pm.Config().Decrement { t.Errorf("Bad permanence value @%d after weaken: %v", 10, *pm) } if pm.Get(30) != pm.Config().Threshold { t.Errorf("Bad permanence value @%d after weaken: %v", 30, *pm) } if !pm.Connected().IsSet(30) { t.Error("Should be connected @30:", *pm) } pm.weaken(*input) if pm.Connected().IsSet(30) { t.Error("Should not be connected @30:", *pm) } }
func BenchmarkLearnRegion(b *testing.B) { l := NewRegion(RegionParameters{ Name: "Single Region", Learning: true, Height: 32, Width: 500, InputLength: 2048, MaximumFiringColumns: 10, MinimumInputOverlap: 1, }) l.Learning = false l.RandomizeColumns(28) input := data.NewBitset(2048) input.Set(columnRand.Perm(2048)[0:28]...) b.ResetTimer() for i := 0; i < b.N; i++ { l.Learn(*input) } }
func TestNarrowSynapses(t *testing.T) { connections := []int{1, 3, 5, 8, 13} pm := NewPermanenceMap(64) pm.Reset(connections...) input := data.NewBitset(64) input.Set(1, 5, 22) pm.narrow(*input) pm.narrow(*input) t.Log(pm.permanence) if pm.permanence[1] == pm.permanence[3] { t.Errorf("Permanence scores did not improve: %v", pm.permanence) } if pm.permanence[1] != pm.permanence[5] { t.Errorf("Permanence scores must be uniform: %v", pm.permanence) } if pm.permanence[22] != 0 { t.Errorf("Permanence for non-connected should be zero: %v", pm.permanence) } if pm.Connected().NumSetBits() != 2 { t.Errorf("Should have kept only 2 connections: %v", pm.permanence) } }