Exemplo n.º 1
0
//Replaces row with true values at specified indices
func (sm *DenseBinaryMatrix) ReplaceRowByIndices(row int, indices []int) {
	sm.validateRow(row)
	start := row * sm.Width
	for i := 0; i < sm.Width; i++ {
		sm.entries[start+i] = utils.ContainsInt(i, indices)
	}
}
Exemplo n.º 2
0
/*
 The primary method in charge of learning. Adapts the permanence values of
the synapses based on the input vector, and the chosen columns after
inhibition round. Permanence values are increased for synapses connected to
input bits that are turned on, and decreased for synapses connected to
inputs bits that are turned off.

Parameters:
----------------------------
inputVector: a numpy array of 0's and 1's thata comprises the input to
the spatial pooler. There exists an entry in the array
for every input bit.
activeColumns: an array containing the indices of the columns that
survived inhibition.
*/
func (sp *SpatialPooler) adaptSynapses(inputVector []bool, activeColumns []int) {
	var inputIndices []int
	for i, val := range inputVector {
		if val {
			inputIndices = append(inputIndices, i)
		}
	}

	permChanges := make([]float64, sp.numInputs)
	utils.FillSliceFloat64(permChanges, -1*sp.SynPermInactiveDec)
	for _, val := range inputIndices {
		permChanges[val] = sp.SynPermActiveInc
	}

	for _, ac := range activeColumns {
		perm := make([]float64, sp.numInputs)
		mask := sp.potentialPools.GetRowIndices(ac)
		for j := 0; j < sp.numInputs; j++ {
			if utils.ContainsInt(j, mask) {
				perm[j] = permChanges[j] + sp.permanences.Get(ac, j)
			} else {
				perm[j] = sp.permanences.Get(ac, j)
			}

		}
		sp.updatePermanencesForColumn(perm, ac, true)
	}

}
Exemplo n.º 3
0
//helper
func (tm *TemporalMemory) lrnOnSegments(segments []int,
	isLearningSegments bool,
	prevActiveSynapsesForSegment map[int][]int,
	winnerCells []int,
	prevWinnerCells []int,
	connections *TemporalMemoryConnections) {

	for _, segment := range segments {
		isFromWinnerCell := utils.ContainsInt(connections.CellForSegment(segment), winnerCells)
		activeSynapses := tm.getConnectedActiveSynapsesForSegment(segment,
			prevActiveSynapsesForSegment,
			0,
			connections)

		if isLearningSegments || isFromWinnerCell {
			tm.adaptSegment(segment, activeSynapses, connections)
		}

		if isLearningSegments {
			n := tm.params.MaxNewSynapseCount - len(activeSynapses)
			for _, sourceCell := range tm.pickCellsToLearnOn(n,
				segment,
				winnerCells,
				connections) {
				connections.CreateSynapse(segment, sourceCell, tm.params.InitialPermanence)
			}
		}

	}

}
Exemplo n.º 4
0
/*
Phase 2: Burst unpredicted columns.
Pseudocode:
- for each unpredicted active column
- mark all cells as active
- mark the best matching cell as winner cell
- (learning)
- if it has no matching segment
- (optimization) if there are prev winner cells
- add a segment to it
- mark the segment as learning
*/
func (tm *TemporalMemory) burstColumns(activeColumns []int,
	predictedColumns []int,
	prevActiveSynapsesForSegment map[int][]int,
	connections *TemporalMemoryConnections) (activeCells []int,
	winnerCells []int,
	learningSegments []int) {

	unpredictedColumns := utils.Complement(activeColumns, predictedColumns)

	for _, column := range unpredictedColumns {
		cells := connections.CellsForColumn(column)
		activeCells = utils.Add(activeCells, cells)

		bestCell, bestSegment := tm.getBestMatchingCell(column,
			prevActiveSynapsesForSegment,
			connections)

		winnerCells = append(winnerCells, bestCell)

		if bestSegment == -1 {
			//TODO: (optimization) Only do this if there are prev winner cells
			bestSegment = connections.CreateSegment(bestCell)
		}
		//TODO: change to set data structure
		if !utils.ContainsInt(bestSegment, learningSegments) {
			learningSegments = append(learningSegments, bestSegment)
		}
	}

	return activeCells, winnerCells, learningSegments
}
Exemplo n.º 5
0
/*
 Maps a column to its input bits. This method encapsultes the topology of
the region. It takes the index of the column as an argument and determines
what are the indices of the input vector that are located within the
column's potential pool. The return value is a list containing the indices
of the input bits. The current implementation of the base class only
supports a 1 dimensional topology of columsn with a 1 dimensional topology
of inputs. To extend this class to support 2-D topology you will need to
override this method. Examples of the expected output of this method:
* If the potentialRadius is greater than or equal to the entire input
space, (global visibility), then this method returns an array filled with
all the indices
* If the topology is one dimensional, and the potentialRadius is 5, this
method will return an array containing 5 consecutive values centered on
the index of the column (wrapping around if necessary).
* If the topology is two dimensional (not implemented), and the
potentialRadius is 5, the method should return an array containing 25
'1's, where the exact indices are to be determined by the mapping from
1-D index to 2-D position.

Parameters:
----------------------------
index: The index identifying a column in the permanence, potential
and connectivity matrices.
wrapAround: A boolean value indicating that boundaries should be
region boundaries ignored.
*/
func (sp *SpatialPooler) mapPotential(index int, wrapAround bool) []bool {
	// Distribute column over inputs uniformly
	ratio := float64(index) / float64(mathutil.Max((sp.numColumns-1), 1))
	index = int(float64(sp.numInputs-1) * ratio)

	var indices []int
	indLen := 2*sp.PotentialRadius + 1

	for i := 0; i < indLen; i++ {
		temp := (i + index - sp.PotentialRadius)
		if wrapAround {
			temp = temp % sp.numInputs
			if temp < 0 {
				temp = sp.numInputs + temp
			}
		} else {
			if !(temp >= 0 && temp < sp.numInputs) {
				continue
			}
		}
		//no dupes
		if !utils.ContainsInt(temp, indices) {
			indices = append(indices, temp)
		}
	}

	// Select a subset of the receptive field to serve as the
	// the potential pool

	//shuffle indices
	for i := range indices {
		j := rand.Intn(i + 1)
		indices[i], indices[j] = indices[j], indices[i]
	}

	sampleLen := int(utils.RoundPrec(float64(len(indices))*sp.PotentialPct, 0))
	sample := indices[:sampleLen]
	//project indices onto input mask
	mask := make([]bool, sp.numInputs)
	for i, _ := range mask {
		mask[i] = utils.ContainsInt(i, sample)
	}

	return mask
}
Exemplo n.º 6
0
//Returns # of rows with at least 1 true value
func (sm *SparseBinaryMatrix) TotalTrueRows() int {
	var hitRows []int
	for _, val := range sm.entries {
		if !utils.ContainsInt(val.Row, hitRows) {
			hitRows = append(hitRows, val.Row)
		}
	}
	return len(hitRows)
}
Exemplo n.º 7
0
//Returns # of cols with at least 1 true value
func (sm *SparseBinaryMatrix) TotalTrueCols() int {
	var hitCols []int
	for _, val := range sm.entries {
		if !utils.ContainsInt(val.Col, hitCols) {
			hitCols = append(hitCols, val.Col)
		}
	}
	return len(hitCols)
}
Exemplo n.º 8
0
//Returns row indexes with at least 1 true column
func (sm *SparseBinaryMatrix) NonZeroRows() []int {
	var result []int

	for _, val := range sm.entries {
		if !utils.ContainsInt(val.Row, result) {
			result = append(result, val.Row)
		}
	}

	return result
}
Exemplo n.º 9
0
/*
Phase 1: Activate the correctly predictive cells.
Pseudocode:
- for each prev predictive cell
- if in active column
- mark it as active
- mark it as winner cell
- mark column as predicted
*/
func (tm *TemporalMemory) activateCorrectlyPredictiveCells(prevPredictiveCells []int,
	activeColumns []int,
	connections *TemporalMemoryConnections) (activeCells []int,
	winnerCells []int,
	predictedColumns []int) {

	for _, cell := range prevPredictiveCells {
		column := connections.ColumnForCell(cell)
		if utils.ContainsInt(column, activeColumns) {
			activeCells = append(activeCells, cell)
			winnerCells = append(winnerCells, cell)
			//TODO: change this to a set data structure
			if !utils.ContainsInt(column, predictedColumns) {
				predictedColumns = append(predictedColumns, column)
			}
		}
	}

	return activeCells, winnerCells, predictedColumns
}
Exemplo n.º 10
0
// Updates synapses on segment.
// Strengthens active synapses; weakens inactive synapses.
func (tm *TemporalMemory) adaptSegment(segment int, activeSynapses []int,
	connections *TemporalMemoryConnections) {

	for _, synIdx := range connections.SynapsesForSegment(segment) {
		syn := connections.DataForSynapse(synIdx)
		perm := syn.Permanence

		if utils.ContainsInt(synIdx, activeSynapses) {
			perm += tm.params.PermanenceIncrement
		} else {
			perm -= tm.params.PermanenceDecrement
		}
		//enforce min/max bounds
		perm = math.Max(0.0, math.Min(1.0, perm))
		connections.UpdateSynapsePermanence(synIdx, perm)
	}

}
Exemplo n.º 11
0
func (sp *SpatialPooler) getNeighborsND(columnIndex int, dimensions []int, radius int, wrapAround bool) []int {
	if len(dimensions) < 1 {
		panic("Dimensions empty")
	}

	bounds := append(dimensions[1:], 1)
	bounds = utils.RevCumProdInt(bounds)

	columnCoords := make([]int, len(bounds))
	for j := 0; j < len(bounds); j++ {
		columnCoords[j] = utils.Mod(columnIndex/bounds[j], dimensions[j])
	}

	rangeND := make([][]int, len(dimensions))
	for i := 0; i < len(dimensions); i++ {
		if wrapAround {
			cRange := make([]int, (radius*2)+1)
			for j := 0; j < (2*radius)+1; j++ {
				cRange[j] = utils.Mod((columnCoords[i]-radius)+j, dimensions[i])
			}
			rangeND[i] = cRange
		} else {
			var cRange []int
			for j := 0; j < (radius*2)+1; j++ {
				temp := columnCoords[i] - radius + j
				if temp >= 0 && temp < dimensions[i] {
					cRange = append(cRange, temp)
				}
			}
			rangeND[i] = cRange
		}
	}

	cp := utils.CartProductInt(rangeND)
	var neighbors []int
	for i := 0; i < len(cp); i++ {
		val := utils.DotInt(bounds, cp[i])
		if val != columnIndex && !utils.ContainsInt(val, neighbors) {
			neighbors = append(neighbors, val)
		}
	}

	return neighbors
}
Exemplo n.º 12
0
/*
 This is the primary public method of the SpatialPooler class. This
 function takes a input vector and outputs the indices of the active columns.
 If 'learn' is set to True, this method also updates the permanences of the
 columns.

Parameters:
----------------------------
inputVector: a numpy array of 0's and 1's thata comprises the input to
			 the spatial pooler. The array will be treated as a one
			 dimensional array, therefore the dimensions of the array
			 do not have to much the exact dimensions specified in the
			 class constructor. In fact, even a list would suffice.
			The number of input bits in the vector must, however,
			match the number of bits specified by the call to the
			constructor. Therefore there must be a '0' or '1' in the
			array for every input bit.
learn: a boolean value indicating whether learning should be
	   performed. Learning entails updating the permanence
	   values of the synapses, and hence modifying the 'state'
	   of the model. Setting learning to 'off' freezes the SP
	   and has many uses. For example, you might want to feed in
	   various inputs and examine the resulting SDR's.
activeArray: an array whose size is equal to the number of columns.
	   Before the function returns this array will be populated
       with 1's at the indices of the active columns, and 0's
	   everywhere else.
*/
func (sp *SpatialPooler) Compute(inputVector []bool, learn bool, activeArray []bool, inhibitColumns inhibitColFunc) {
	if len(inputVector) != sp.numInputs {
		panic("input != numimputs")
	}

	sp.updateBookeepingVars(learn)
	overlaps := sp.calculateOverlap(inputVector)
	boostedOverlaps := make([]float64, len(overlaps))
	// Apply boosting when learning is on
	if learn {
		for i, val := range sp.boostFactors {
			boostedOverlaps[i] = float64(overlaps[i]) * val
		}
	}

	// Apply inhibition to determine the winning columns
	activeColumns := inhibitColumns(boostedOverlaps, sp.inhibitColumnsGlobal, sp.inhibitColumnsLocal)
	overlapsf := make([]float64, len(overlaps))
	for i, val := range overlaps {
		overlapsf[i] = float64(val)
	}

	if learn {
		sp.adaptSynapses(inputVector, activeColumns)
		sp.updateDutyCycles(overlapsf, activeColumns)
		sp.bumpUpWeakColumns()
		sp.updateBoostFactors()
		if sp.isUpdateRound() {
			sp.updateInhibitionRadius(sp.avgConnectedSpanForColumnND, sp.avgColumnsPerInput)
			sp.updateMinDutyCycles()
		}

	} else {
		activeColumns = sp.stripNeverLearned(activeColumns)
	}

	if len(activeColumns) > 0 {
		for i, _ := range activeArray {
			activeArray[i] = utils.ContainsInt(i, activeColumns)
		}
	}

}
Exemplo n.º 13
0
//Returns row indexes with at least 1 true column
func (sm *DenseBinaryMatrix) NonZeroRows() []int {
	counts := make(map[int]int, sm.Height)

	for idx, val := range sm.entries {
		if val {
			r, _ := sm.toIndex(idx)
			counts[r]++

		}
	}

	result := make([]int, 0, sm.Height)
	for k, v := range counts {
		if v > 0 && !utils.ContainsInt(k, result) {
			result = append(result, k)
		}
	}
	return result
}
Exemplo n.º 14
0
/*
 This function applies segment update information to a segment in a
cell.

Synapses on the active list get their permanence counts incremented by
permanenceInc. All other synapses get their permanence counts decremented
by permanenceDec.

We also increment the positiveActivations count of the segment.

param segUpdate SegmentUpdate instance
returns True if some synapses were decremented to 0 and the segment is a
candidate for trimming
*/
func (segUpdate *SegmentUpdate) adaptSegments(tp *TemporalPooler) bool {
	// This will be set to True if detect that any syapses were decremented to 0
	trimSegment := false

	// segUpdate.segment is None when creating a new segment
	//c, i, segment := segUpdate.columnIdx, segUpdate.cellIdx, segUpdate.segment
	c := segUpdate.columnIdx
	i := segUpdate.cellIdx
	segment := segUpdate.segment

	// update.activeSynapses can be empty.
	// If not, it can contain either or both integers and tuples.
	// The integers are indices of synapses to update.
	// The tuples represent new synapses to create (src col, src cell in col).
	// We pre-process to separate these various element types.
	// synToCreate is not empty only if positiveReinforcement is True.
	// NOTE: the synapse indices start at *1* to skip the segment flags.
	activeSynapses := segUpdate.activeSynapses

	var synToUpdate []int
	for _, val := range activeSynapses {
		if !val.New {
			synToUpdate = append(synToUpdate, val.Index)
		}
	}

	//fmt.Printf("Entering adapt seg %v %v \n", segment, len(activeSynapses))

	if segment != nil {

		if tp.params.Verbosity >= 4 {
			fmt.Printf("Reinforcing segment #%v for cell[%v,%v] \n", segment.segId, c, i)
		}

		//modify existing segment
		// Mark it as recently useful
		segment.lastActiveIteration = tp.lrnIterationIdx

		// Update frequency and positiveActivations
		segment.positiveActivations++
		segment.dutyCycle(true, false)

		// First, decrement synapses that are not active
		lastSynIndex := len(segment.syns) - 1

		var inactiveSynIndices []int
		for i := 0; i < lastSynIndex+1; i++ {
			if !utils.ContainsInt(i, synToUpdate) {
				inactiveSynIndices = append(inactiveSynIndices, i)
			}
		}

		trimSegment = segment.updateSynapses(inactiveSynIndices, -tp.params.PermanenceDec)

		// Now, increment active synapses
		var activeSynIndices []int
		for _, val := range activeSynapses {
			if val.Index <= lastSynIndex {
				activeSynIndices = append(activeSynIndices, val.Index)
			}
		}

		segment.updateSynapses(activeSynIndices, tp.params.PermanenceInc)

		// Finally, create new synapses if needed
		var synsToAdd []SynapseUpdateState
		for _, val := range activeSynapses {
			if val.New {
				synsToAdd = append(synsToAdd, val)
			}
		}

		// If we have fixed resources, get rid of some old syns if necessary
		if tp.params.MaxSynapsesPerSegment > 0 && len(synsToAdd)+len(segment.syns) > tp.params.MaxSynapsesPerSegment {
			numToFree := (len(segment.syns) + len(synsToAdd)) - tp.params.MaxSynapsesPerSegment
			segment.freeNSynapses(numToFree, inactiveSynIndices)
		}

		for _, val := range synsToAdd {
			segment.AddSynapse(val.Index, val.CellIndex, tp.params.InitialPerm)
		}

	} else {
		//create new segment
		newSegment := NewSegment(tp, segUpdate.sequenceSegment)

		for _, val := range activeSynapses {
			newSegment.AddSynapse(val.Index, val.CellIndex, tp.params.InitialPerm)
		}

		if tp.params.Verbosity >= 3 {
			fmt.Printf("New segment #%v for cell[%v,%v] \n", tp.segId, c, i)
			fmt.Print(newSegment.ToString())
		}

		tp.cells[c][i] = append(tp.cells[c][i], *newSegment)
	}

	return trimSegment
}
Exemplo n.º 15
0
func TestGetNeighborsND(t *testing.T) {
	sp := SpatialPooler{}

	dimensions := []int{5, 7, 2}
	var layout [5][7][2]int

	counter := 0
	for i := range layout {
		for j := range layout[i] {
			for k := range layout[i][j] {
				layout[i][j][k] = counter
				counter++
			}
		}
	}

	radius := 1
	x := 1
	y := 3
	z := 2

	columnIndex := layout[z][y][x]

	neighbors := sp.getNeighborsND(columnIndex, dimensions, radius, true)

	var expected []int

	for i := radius * -1; i <= radius; i++ {
		for j := radius * -1; j <= radius; j++ {
			for k := radius * -1; k <= radius; k++ {
				zprime := (z + i) % dimensions[0]
				yprime := (y + j) % dimensions[1]
				xprime := (x + k) % dimensions[2]
				if layout[zprime][yprime][xprime] != columnIndex && !utils.ContainsInt(layout[zprime][yprime][xprime], expected) {
					expected = append(expected, layout[zprime][yprime][xprime])
				}

			}
		}
	}

	assert.Equal(t, expected, neighbors)

	dimensions = []int{5, 7, 9}
	var layoutb [5][7][9]int
	counter = 0
	for i := range layoutb {
		for j := range layoutb[i] {
			for k := range layoutb[i][j] {
				layoutb[i][j][k] = counter
				counter++
			}
		}
	}

	radius = 3
	x = 0
	y = 0
	z = 3
	columnIndex = layoutb[z][y][x]
	neighbors = sp.getNeighborsND(columnIndex, dimensions, radius, true)
	expected = []int{}
	for i := radius * -1; i <= radius; i++ {
		for j := radius * -1; j <= radius; j++ {
			for k := radius * -1; k <= radius; k++ {
				zprime := utils.Mod((z + i), (dimensions[0]))
				yprime := utils.Mod((y + j), (dimensions[1]))
				xprime := utils.Mod((x + k), (dimensions[2]))

				if layoutb[zprime][yprime][xprime] != columnIndex && !utils.ContainsInt(layoutb[zprime][yprime][xprime], expected) {
					expected = append(expected, layoutb[zprime][yprime][xprime])
				}

			}
		}
	}

	assert.Equal(t, expected, neighbors)

	dimensions = []int{5, 10, 7, 6}
	var layoutc [5][10][7][6]int
	counter = 0
	for i := range layoutc {
		for j := range layoutc[i] {
			for k := range layoutc[i][j] {
				for m := range layoutc[i][j][k] {
					layoutc[i][j][k][m] = counter
					counter++
				}
			}
		}
	}

	radius = 4
	w := 2
	x = 5
	y = 6
	z = 2
	columnIndex = layoutc[z][y][x][w]
	neighbors = sp.getNeighborsND(columnIndex, dimensions, radius, true)
	expected = []int{}
	for i := radius * -1; i <= radius; i++ {
		for j := radius * -1; j <= radius; j++ {
			for k := radius * -1; k <= radius; k++ {
				for m := radius * -1; m <= radius; m++ {
					zprime := utils.Mod((z + i), (dimensions[0]))
					yprime := utils.Mod((y + j), (dimensions[1]))
					xprime := utils.Mod((x + k), (dimensions[2]))
					wprime := utils.Mod((w + m), (dimensions[3]))

					if layoutc[zprime][yprime][xprime][wprime] != columnIndex && !utils.ContainsInt(layoutc[zprime][yprime][xprime][wprime], expected) {
						expected = append(expected, layoutc[zprime][yprime][xprime][wprime])
					}

				}

			}
		}
	}

	assert.Equal(t, expected, neighbors)

	layoutd := []bool{false, false, true, false, true, false, false, false}
	columnIndex = 3
	dimensions = []int{8}
	radius = 1
	mask := sp.getNeighborsND(columnIndex, dimensions, radius, true)
	t.Log("mask", mask)

	for idx, val := range layoutd {
		if utils.ContainsInt(idx, mask) {
			assert.Equal(t, true, val)
		} else {
			assert.Equal(t, false, val)
		}
	}

	layoute := []bool{false, true, true, false, true, true, false, false}
	columnIndex = 3
	dimensions = []int{8}
	radius = 2

	mask = sp.getNeighborsND(columnIndex, dimensions, radius, true)
	t.Log("mask", mask)

	for idx, val := range layoute {
		if utils.ContainsInt(idx, mask) {
			assert.Equal(t, true, val)
		} else {
			assert.Equal(t, false, val)
		}
	}

	// Wrap around
	layoutf := []bool{false, true, true, false, false, false, true, true}
	columnIndex = 0
	dimensions = []int{8}
	radius = 2

	mask = sp.getNeighborsND(columnIndex, dimensions, radius, true)
	t.Log("mask", mask)

	for idx, val := range layoutf {
		if utils.ContainsInt(idx, mask) {
			assert.Equal(t, true, val)
		} else {
			assert.Equal(t, false, val)
		}
	}

	//Radius too big
	layoutg := []bool{true, true, true, true, true, true, false, true}
	columnIndex = 6
	dimensions = []int{8}
	radius = 20

	mask = sp.getNeighborsND(columnIndex, dimensions, radius, true)
	t.Log("mask", mask)

	for idx, val := range layoutg {
		if utils.ContainsInt(idx, mask) {
			assert.Equal(t, true, val)
		} else {
			assert.Equal(t, false, val)
		}
	}

	//These are all the same tests from 2D
	ints := [][]int{{0, 0, 0, 0, 0},
		{0, 0, 0, 0, 0},
		{0, 1, 1, 1, 0},
		{0, 1, 0, 1, 0},
		{0, 1, 1, 1, 0},
		{0, 0, 0, 0, 0}}

	layouth := NewDenseBinaryMatrixFromInts(ints)
	t.Log(layouth.ToString())

	columnIndex = 3*5 + 2
	dimensions = []int{6, 5}
	radius = 1

	mask = sp.getNeighborsND(columnIndex, dimensions, radius, true)
	t.Log("mask", mask)
	t.Log("1d", layouth.Flatten())
	for idx, val := range layouth.Flatten() {
		if utils.ContainsInt(idx, mask) {
			assert.Equal(t, true, val)
		} else {
			assert.Equal(t, false, val)
		}
	}

	ints = [][]int{{0, 0, 0, 0, 0},
		{1, 1, 1, 1, 1},
		{1, 1, 1, 1, 1},
		{1, 1, 0, 1, 1},
		{1, 1, 1, 1, 1},
		{1, 1, 1, 1, 1}}

	layoutj := NewDenseBinaryMatrixFromInts(ints)
	t.Log(layouth.ToString())

	columnIndex = 3*5 + 2
	radius = 2

	mask = sp.getNeighborsND(columnIndex, dimensions, radius, true)
	t.Log("mask", mask)
	t.Log("1d", layouth.Flatten())
	for idx, val := range layoutj.Flatten() {
		if utils.ContainsInt(idx, mask) {
			assert.Equal(t, true, val)
		} else {
			assert.Equal(t, false, val)
		}
	}

	//Radius too big
	ints = [][]int{{1, 1, 1, 1, 1},
		{1, 1, 1, 1, 1},
		{1, 1, 1, 1, 1},
		{1, 1, 0, 1, 1},
		{1, 1, 1, 1, 1},
		{1, 1, 1, 1, 1}}

	layoutk := NewDenseBinaryMatrixFromInts(ints)
	t.Log(layouth.ToString())

	columnIndex = 3*5 + 2
	radius = 7

	mask = sp.getNeighborsND(columnIndex, dimensions, radius, true)
	t.Log("mask", mask)
	t.Log("1d", layoutk.Flatten())
	for idx, val := range layoutk.Flatten() {
		if utils.ContainsInt(idx, mask) {
			assert.Equal(t, true, val)
		} else {
			assert.Equal(t, false, val)
		}
	}

	//Wrap-around
	ints = [][]int{{1, 0, 0, 1, 1},
		{0, 0, 0, 0, 0},
		{0, 0, 0, 0, 0},
		{0, 0, 0, 0, 0},
		{1, 0, 0, 1, 1},
		{1, 0, 0, 1, 0}}

	layoutl := NewDenseBinaryMatrixFromInts(ints)
	t.Log(layoutl.ToString())

	columnIndex = 29
	radius = 1

	mask = sp.getNeighborsND(columnIndex, dimensions, radius, true)
	t.Log("mask", mask)
	t.Log("1d", layoutl.Flatten())
	for idx, val := range layoutl.Flatten() {
		if utils.ContainsInt(idx, mask) {
			assert.Equal(t, true, val)
		} else {
			assert.Equal(t, false, val)
		}
	}

	//No wrap around
	columnIndex = 8
	radius = 2
	dimensions = []int{10}
	neighbors = sp.getNeighborsND(columnIndex, dimensions, radius, false)
	expected = []int{6, 7, 9}
	assert.Equal(t, expected, neighbors)

}
Exemplo n.º 16
0
/*
Free up some synapses in this segment. We always free up inactive
synapses (lowest permanence freed up first) before we start to free up
active ones.

param numToFree number of synapses to free up
param inactiveSynapseIndices list of the inactive synapse indices.
*/
func (s *Segment) freeNSynapses(numToFree int, inactiveSynapseIndices []int) {
	//Make sure numToFree isn't larger than the total number of syns we have
	if numToFree > len(s.syns) {
		panic("Number to free cannot be larger than existing synapses.")
	}

	if s.tp.params.Verbosity >= 5 {
		fmt.Println("freeNSynapses with numToFree=", numToFree)
		fmt.Println("inactiveSynapseIndices= ", inactiveSynapseIndices)
	}

	var candidates []int
	// Remove the lowest perm inactive synapses first
	if len(inactiveSynapseIndices) > 0 {
		perms := make([]float64, len(inactiveSynapseIndices))
		for idx, _ := range perms {
			perms[idx] = s.syns[idx].Permanence
		}
		var indexes []int
		floats.Argsort(perms, indexes)
		//sort perms
		cSize := mathutil.Min(numToFree, len(perms))
		candidates = make([]int, cSize)
		//indexes[0:cSize]
		for i := 0; i < cSize; i++ {
			candidates[i] = inactiveSynapseIndices[indexes[i]]
		}
	}

	// Do we need more? if so, remove the lowest perm active synapses too
	var activeSynIndices []int
	if len(candidates) < numToFree {
		for i := 0; i < len(s.syns); i++ {
			if !utils.ContainsInt(i, inactiveSynapseIndices) {
				activeSynIndices = append(activeSynIndices, i)
			}
		}

		perms := make([]float64, len(activeSynIndices))
		for i := range perms {
			perms[i] = s.syns[i].Permanence
		}
		var indexes []int
		floats.Argsort(perms, indexes)

		moreToFree := numToFree - len(candidates)
		//moreCandidates := make([]int, moreToFree)
		for i := 0; i < moreToFree; i++ {
			candidates = append(candidates, activeSynIndices[indexes[i]])
		}
	}

	if s.tp.params.Verbosity >= 4 {
		fmt.Printf("Deleting %v synapses from segment to make room for new ones: %v \n",
			len(candidates), candidates)
		fmt.Println("Before:", s.ToString())
	}

	// Delete candidate syns by copying undeleted to new slice
	var newSyns []Synapse
	for idx, val := range s.syns {
		if !utils.ContainsInt(idx, candidates) {
			newSyns = append(newSyns, val)
		}
	}
	s.syns = newSyns

	if s.tp.params.Verbosity >= 4 {
		fmt.Println("After:", s.ToString())
	}

}
Exemplo n.º 17
0
/*
 This function produces goodness-of-match scores for a set of input patterns,
by checking for their presence in the current and predicted output of the
TP. Returns a global count of the number of extra and missing bits, the
confidence scores for each input pattern, and (if requested) the
bits in each input pattern that were not present in the TP's prediction.

param patternNZs a list of input patterns that we want to check for. Each
element is a list of the non-zeros in that pattern.
param output The output of the TP. If not specified, then use the
TP's current output. This can be specified if you are
trying to check the prediction metric for an output from
the past.
param colConfidence The column confidences. If not specified, then use the
TP's current colConfidence. This can be specified if you
are trying to check the prediction metrics for an output
from the past.
param details if True, also include details of missing bits per pattern.

returns list containing:

[
totalExtras,
totalMissing,
[conf_1, conf_2, ...],
[missing1, missing2, ...]
]

retval totalExtras a global count of the number of 'extras', i.e. bits that
are on in the current output but not in the or of all the
passed in patterns
retval totalMissing a global count of all the missing bits, i.e. the bits
that are on in the or of the patterns, but not in the
current output
retval conf_i the confidence score for the i'th pattern inpatternsToCheck
This consists of 3 items as a tuple:
(predictionScore, posPredictionScore, negPredictionScore)
retval missing_i the bits in the i'th pattern that were missing
in the output. This list is only returned if details is
True.
*/
func (tp *TemporalPooler) checkPrediction2(patternNZs [][]int, output *SparseBinaryMatrix,
	colConfidence []float64, details bool) (int, int, []confidence, []int) {

	// Get the non-zeros in each pattern
	numPatterns := len(patternNZs)

	// Compute the union of all the expected patterns
	var orAll []int
	for _, row := range patternNZs {
		for _, col := range row {
			if !utils.ContainsInt(col, orAll) {
				orAll = append(orAll, col)
			}
		}
	}

	var outputIdxs []int

	// Get the list of active columns in the output
	if output == nil {
		if tp.CurrentOutput == nil {
			panic("Expected tp output")
		}
		outputIdxs = tp.CurrentOutput.NonZeroRows()
	} else {
		outputIdxs = output.NonZeroRows()
	}

	// Compute the total extra and missing in the output
	totalExtras := 0
	totalMissing := 0

	for _, val := range outputIdxs {
		if !utils.ContainsInt(val, orAll) {
			totalExtras++
		}
	}

	for _, val := range orAll {
		if !utils.ContainsInt(val, outputIdxs) {
			totalMissing++
		}
	}

	// Get the percent confidence level per column by summing the confidence
	// levels of the cells in the column. During training, each segment's
	// confidence number is computed as a running average of how often it
	// correctly predicted bottom-up activity on that column. A cell's
	// confidence number is taken from the first active segment found in the
	// cell. Note that confidence will only be non-zero for predicted columns.

	if colConfidence == nil {
		if tp.params.Verbosity >= 5 {
			fmt.Println("Col confidence nil, copying from tp state...")
		}
		colConfidence = make([]float64, len(tp.DynamicState.ColConfidence))
		copy(colConfidence, tp.DynamicState.ColConfidence)
	}

	// Assign confidences to each pattern
	var confidences []confidence

	for i := 0; i < numPatterns; i++ {
		// Sum of the column confidences for this pattern
		//positivePredictionSum = colConfidence[patternNZs[i]].sum()
		positivePredictionSum := floats.Sum(floats.SubSet(colConfidence, patternNZs[i]))

		// How many columns in this pattern
		positiveColumnCount := len(patternNZs[i])

		// Sum of all the column confidences
		totalPredictionSum := floats.Sum(colConfidence)
		// Total number of columns
		totalColumnCount := len(colConfidence)

		negativePredictionSum := totalPredictionSum - positivePredictionSum
		negativeColumnCount := totalColumnCount - positiveColumnCount

		positivePredictionScore := 0.0
		// Compute the average confidence score per column for this pattern
		if positiveColumnCount != 0 {
			positivePredictionScore = positivePredictionSum
		}

		// Compute the average confidence score per column for the other patterns
		negativePredictionScore := 0.0
		if negativeColumnCount != 0 {
			negativePredictionScore = negativePredictionSum
		}

		// Scale the positive and negative prediction scores so that they sum to
		// 1.0
		currentSum := negativePredictionScore + positivePredictionScore
		if currentSum > 0 {
			positivePredictionScore *= 1.0 / currentSum
			negativePredictionScore *= 1.0 / currentSum
		}

		predictionScore := positivePredictionScore - negativePredictionScore
		newConf := confidence{predictionScore, positivePredictionScore, negativePredictionScore}
		confidences = append(confidences, newConf)

	}

	// Include detail? (bits in each pattern that were missing from the output)
	if details {
		var missingPatternBits []int
		for _, pattern := range patternNZs {
			for _, val := range pattern {
				if !utils.ContainsInt(val, outputIdxs) &&
					!utils.ContainsInt(val, missingPatternBits) {
					missingPatternBits = append(missingPatternBits, val)
				}
			}

		}
		return totalExtras, totalMissing, confidences, missingPatternBits
	} else {
		return totalExtras, totalMissing, confidences, nil
	}

}