예제 #1
0
	def __init__(self, parentNode, name):
		"""
		Initializes a new instance of the Node class.
		"""

		Node.__init__(self, parentNode, name, NodeType.sensor)

		#region Instance fields

		self.bits = []
		"""An array of the bit objects that compose the current output of this node."""

		self.inputFormat = InputFormat.htm
		"""Format of the node (HTM or raw data)"""

		self.encoder = None
		"""Optional encoder to convert raw data to htm input and vice-versa."""

		self.dataSourceType = DataSourceType.file
		"""Type of the data source (File or Database)"""

		self.fileName = ''
		"""The input file name to be handled. Returns the input file name only if it is in the project directory, full path otherwise."""

		self._file = None
		"""File stream to handle the file."""

		self.databaseConnectionString = ""
		"""Connection string of the database."""

		self.databaseTable = ''
		"""Target table of the database."""

		self.databaseField = ''
		"""Target field of the database table."""
예제 #2
0
	def nextStep(self):
		"""
		Performs actions related to time step progression.
		"""

		# Update states machine by remove the first element and add a new element in the end
		if self.inputFormat == InputFormat.raw:
			if len(self.currentValue) > maxPreviousSteps:
				self.currentValue.remove(self.currentValue[0])
				self.predictedValues.remove(self.predictedValues[0])
			self.currentValue.append(None)
			self.predictedValues.append(None)

		Node.nextStep(self)
		for bit in self.bits:
			bit.nextStep()

		# Get record value from data source
		recordValue = None
		if self.dataSourceType == DataSourceType.file:
			recordValue = self.__getNextFileRecord()
		elif self.dataSourceType == DataSourceType.database:
			pass

		# Handle the value according to its type
		self._output = []
		if self.inputFormat == InputFormat.htm:

			# Initialize the array for representing the current record
			self._output = recordValue
		elif self.inputFormat == InputFormat.raw:

			# Convert the value to its respective data type
			rawValue = None
			if self.inputRawDataType == InputRawDataType.boolean:
				rawValue = bool(recordValue)
			elif self.inputRawDataType == InputRawDataType.integer:
				rawValue = int(recordValue)
			elif self.inputRawDataType == InputRawDataType.decimal:
				rawValue = float(recordValue)
			elif self.inputRawDataType == InputRawDataType.dateTime:
				rawValue = datetime.datetime.strptime(recordValue, "%m/%d/%y %H:%M")
			elif self.inputRawDataType == InputRawDataType.string:
				rawValue = str(recordValue)
			self.currentValue[maxPreviousSteps - 1] = rawValue

			# Pass raw value to encoder and get its respective array
			self._output = self.encoder.encode(rawValue)

		# Update sensor bits
		for i in range(len(self._output)):
			if self._output[i] > 0.:
				self.bits[i].isActive[maxPreviousSteps - 1] = True
			else:
				self.bits[i].isActive[maxPreviousSteps - 1] = False

		# Mark falsely predicted bits
		for bit in self.bits:
			if bit.isPredicted[maxPreviousSteps - 2] and not bit.isActive[maxPreviousSteps - 1]:
				bit.isFalselyPredicted[maxPreviousSteps - 1] = True
예제 #3
0
	def nextStep(self):
		"""
		Perfoms actions related to time step progression.
		"""

		Node.nextStep(self)
		for child in self.children:
			child.nextStep()
		for column in self.columns:
			column.nextStep()

		# Get input from sensors or lower regions and put into a single input map.
		input = self.getInput()

		# Send input to Spatial Pooler and get processed output (i.e. the active columns)
		# First initialize the vector for representing the current record
		columnDimensions = (self.width, self.height)
		columnNumber = numpy.array(columnDimensions).prod()
		activeColumns = numpy.zeros(columnNumber)
		self.spatialPooler.compute(input, self.enableSpatialPooling, activeColumns)

		# Send active columns to Temporal Pooler and get processed output (i.e. the predicting cells)
		# First convert active columns from float array to integer set
		activeColumnsSet = set()
		for colIdx in range(len(activeColumns)):
			if activeColumns[colIdx] == 1:
				activeColumnsSet.add(colIdx)
		self.temporalPooler.compute(activeColumnsSet, self.enableTemporalPooling)

		# Update elements regarding spatial pooler
		self.updateSpatialElements(activeColumns)

		# Update elements regarding temporal pooler
		self.updateTemporalElements()
예제 #4
0
    def __init__(self, parentNode, name):
        """
		Initializes a new instance of this class.
		"""

        Node.__init__(self, parentNode, name, NodeType.sensor)

        #region Instance fields

        self.bits = []
        """An array of the bit objects that compose the current output of this node."""

        self.inputFormat = InputFormat.htm
        """Format of the node (HTM or raw data)"""

        self.encoder = None
        """Optional encoder to convert raw data to htm input and vice-versa."""

        self.dataSourceType = DataSourceType.file
        """Type of the data source (File or Database)"""

        self.fileName = ''
        """The input file name to be handled. Returns the input file name only if it is in the project directory, full path otherwise."""

        self._file = None
        """File stream to handle the file."""

        self.databaseConnectionString = ""
        """Connection string of the database."""

        self.databaseTable = ''
        """Target table of the database."""

        self.databaseField = ''
        """Target field of the database table."""
예제 #5
0
    def nextStep(self):
        """
		Perfoms actions related to time step progression.
		"""

        Node.nextStep(self)
        for bit in self.bits:
            bit.nextStep()

        if self.dataSourceType == DataSourceType.file:
            self.__getNextFileRecord()
        elif self.dataSourceType == DataSourceType.database:
            pass
예제 #6
0
    def nextStep(self):
        """
		Perfoms actions related to time step progression.
		"""

        Node.nextStep(self)
        for bit in self.bits:
            bit.nextStep()

        if self.dataSourceType == DataSourceType.file:
            self.__getNextFileRecord()
        elif self.dataSourceType == DataSourceType.database:
            pass
예제 #7
0
    def __init__(self, name):
        """
		Initializes a new instance of this class.
		"""

        Node.__init__(self, name, NodeType.sensor)

        #region Instance fields

        self.bits = []
        """An array of the bit objects that compose the current output of this node."""

        self.dataSource = None
        """Data source which provides records to fed into a region."""

        self.dataSourceType = DataSourceType.file
        """Type of the data source (File or Database)"""

        self.fileName = ''
        """The input file name to be handled. Returns the input file name only if it is in the project directory, full path otherwise."""

        self.databaseConnectionString = ""
        """Connection string of the database."""

        self.databaseTable = ''
        """Target table of the database."""

        self.encoder = None
        """Multi-encoder which concatenate sub-encodings to convert raw data to htm input and vice-versa."""

        self.encodings = []
        """List of sub-encodings that handles the input from database"""

        self.predictionsMethod = PredictionsMethod.reconstruction
        """Method used to get predicted values and their probabilities."""

        self.enableClassificationLearning = True
        """Switch for classification learning"""

        self.enableClassificationInference = True
        """Switch for classification inference"""

        #endregion

        #region Statistics properties

        self.statsPrecisionRate = 0.
예제 #8
0
	def nextTimeStep(self):
		"""
		Perfoms actions related to time step progression.
		"""

		Node.nextTimeStep(self)

		for child in self.children:
			child.nextTimeStep()

		for column in self.columns:
			column.nextTimeStep()

		# Get input from sensors or lower regions and put into a single input map.
		input = self.getInput()

		# Perform spatial activation process given an input map
		self.performSpatialProcess(input)

		# Perform temporal activation process given the result of the spatial activation
		self.performTemporalProcess()
예제 #9
0
    def nextStep(self):
        """
		Perfoms actions related to time step progression.
		"""

        Node.nextStep(self)
        for column in self.columns:
            column.nextStep()

        # Get input from sensors or lower regions and put into a single input map.
        input = self.getInput()

        # Send input to Spatial Pooler and get processed output (i.e. the active columns)
        # First initialize the vector for representing the current record
        columnDimensions = (self.width, self.height)
        columnNumber = numpy.array(columnDimensions).prod()
        activeColumns = numpy.zeros(columnNumber)
        self.spatialPooler.compute(input, self.enableSpatialLearning,
                                   activeColumns)

        # Send active columns to Temporal Pooler and get processed output (i.e. the predicting cells)
        # First convert active columns from float array to integer set
        activeColumnsSet = set()
        for colIdx in range(len(activeColumns)):
            if activeColumns[colIdx] == 1:
                activeColumnsSet.add(colIdx)
        self.temporalPooler.compute(activeColumnsSet,
                                    self.enableTemporalLearning)

        # Update elements regarding spatial pooler
        self.updateSpatialElements(activeColumns)

        # Update elements regarding temporal pooler
        self.updateTemporalElements()

        # Get the predicted values
        self.getPredictions()
예제 #10
0
	def initialize(self):
		"""
		Initialize this node.
		"""

		Node.initialize(self)

		for child in self.children:
			child.initialize()

		# Create the input map
		# An input map is a set of input elements (cells or sensor bits) that can be are grouped or combined
		# For example, if we have 2 children (#1 and #2) with dimensions 6 and 12 respectively,
		# a grouped input map would be something like:
		#   111111222222222222
		# while a combined one would be something like: 
		#   122122122122122122
		self._inputMap = []
		sumDimension = 0
		self.inputMapType = InputMapType.grouped
		if self.inputMapType == InputMapType.grouped:
			for child in self.children:
				dimension = child.width * child.height
				sumDimension += dimension

				# Arrange input from child into input map of this region
				if child.type == NodeType.region:
					for column in child.columns:
						inputElem = column.cells[0]
						self._inputMap.append(inputElem)
				else:
					for bit in child.bits:
						inputElem = bit
						self._inputMap.append(inputElem)
		elif self.inputMapType == InputMapType.combined:
			# Get the overall dimension and the minimum dimension among all children
			minDimension = self.children[0].width * self.children[0].height
			for child in self.children:
				dimension = child.width * child.height
				sumDimension += dimension
				if dimension < minDimension:
					minDimension = dimension

			# Use the minimum dimension as a multiplication common factor to determine the frequency of each child element in a sequence
			frequencies = []
			nextIdx = []
			for child in self.children:
				dimension = child.width * child.height
				if dimension % minDimension == 0:
					frequency = dimension / minDimension
					frequencies.append(frequency)
					nextIdx.append(0)
				else:
					QtGui.QMessageBox.warning(None, "Warning", "Children dimensions should have a common multiple factor!")
					return

			# Distribute alternatively child elements into input map according to their frequencies
			for elemIdx in range(sumDimension):
				for childIdx in range(len(self.children)):
					child = self.children[childIdx]

					# Start distribution taking in account the last inserted element
					i0 = nextIdx[childIdx]
					iN = i0 + frequencies[childIdx]
					nextIdx[childIdx] = iN + 1
					for i in range(i0, iN):
						if child.type == NodeType.region:
							inputElem = child.columns[i].cells[0]
							self._inputMap.append(inputElem)
						else:
							inputElem = child.bits[i]
							self._inputMap.append(inputElem)

		# Initialize elements
		self.columns = []
		for x in range(self.width):
			for y in range(self.height):
				column = Column()
				column.x = x
				column.y = y
				for z in range(self.numCellsPerColumn):
					cell = Cell()
					cell.z = z
					column.cells.append(cell)
				self.columns.append(column)

		# Create Spatial Pooler instance with appropriate parameters
		self.spatialPooler = SpatialPooler(
			inputDimensions = (sumDimension, 1),
			columnDimensions = (self.width, self.height),
			potentialRadius = self.potentialRadius,
			potentialPct = self.potentialPct,
			globalInhibition = self.globalInhibition,
			localAreaDensity = self.localAreaDensity,
			numActiveColumnsPerInhArea = self.numActiveColumnsPerInhArea,
			stimulusThreshold = self.stimulusThreshold,
			synPermInactiveDec = self.proximalSynPermDecrement,
			synPermActiveInc = self.proximalSynPermIncrement,
			synPermConnected = self.proximalSynConnectedPerm,
			minPctOverlapDutyCycle = self.minPctOverlapDutyCycle,
			minPctActiveDutyCycle = self.minPctActiveDutyCycle,
			dutyCyclePeriod = self.dutyCyclePeriod,
			maxBoost = self.maxBoost,
			seed = -1,
			spVerbosity = False)

		# Create Temporal Pooler instance with appropriate parameters
		self.temporalPooler = TemporalPooler(
			columnDimensions = (self.width, self.height),
			cellsPerColumn = self.numCellsPerColumn,
			learningRadius = self.learningRadius,
			initialPermanence = self.distalSynInitialPerm,
			connectedPermanence = self.distalSynConnectedPerm,
			minThreshold = self.minThreshold,
			maxNewSynapseCount = self.maxNumNewSynapses,
			permanenceIncrement = self.distalSynPermIncrement,
			permanenceDecrement = self.distalSynPermDecrement,
			activationThreshold = self.activationThreshold,
			seed = 42)
예제 #11
0
    def __init__(self, parentNode, name):
        """
		Initializes a new instance of this class.
		"""

        Node.__init__(self, parentNode, name, NodeType.region)

        #region Instance fields

        self.columns = []
        """List of columns that compose this region"""

        self.inputMapType = InputMapType.combined
        """Specify how the inputs are organized in the input map"""

        self._inputMap = []
        """An array representing the input map for this region."""

        #region Spatial Parameters

        self.enableSpatialPooling = True
        """Switch for spatial pooling"""

        self.potentialRadius = 0
        """This parameter determines the extent of the input that each column can potentially be connected to. This can be thought of as the input bits that are visible to each column, or a 'receptiveField' of the field of vision. A large enough value will result in 'global coverage', meaning that each column can potentially be connected to every input bit. This parameter defines a square (or hyper square) area: a column will have a max square potential pool with sides of length 2 * potentialRadius + 1."""

        self.potentialPct = 0.5
        """The percent of the inputs, within a column's potential radius, that a column can be connected to. If set to 1, the column will be connected to every input within its potential radius. This parameter is used to give each column a unique potential pool when a large potentialRadius causes overlap between the columns. At initialization time we choose ((2*potentialRadius + 1)^(# inputDimensions) * potentialPct) input bits to comprise the column's potential pool."""

        self.globalInhibition = False
        """If true, then during inhibition phase the winning columns are selected as the most active columns from the region as a whole. Otherwise, the winning columns are selected with respect to their local neighborhoods. Using global inhibition boosts performance x60."""

        self.localAreaDensity = -1.0
        """The desired density of active columns within a local inhibition area (the size of which is set by the internally calculated inhibitionRadius, which is in turn determined from the average size of the connected potential pools of all columns). The inhibition logic will insure that at most N columns remain ON within a local inhibition area, where N = localAreaDensity * (total number of columns in inhibition area)."""

        self.numActiveColumnsPerInhArea = int(0.02 *
                                              (self.width * self.height))
        """An alternate way to control the density of the active columns. If numActiveColumnsPerInhArea is specified then localAreaDensity must be less than 0, and vice versa. When using numActiveColumnsPerInhArea, the inhibition logic will insure that at most 'numActiveColumnsPerInhArea' columns remain ON within a local inhibition area (the size of which is set by the internally calculated inhibitionRadius, which is in turn determined from the average size of the connected receptive fields of all columns). When using this method, as columns learn and grow their effective receptive fields, the inhibitionRadius will grow, and hence the net density of the active columns will *decrease*. This is in contrast to the localAreaDensity method, which keeps the density of active columns the same regardless of the size of their receptive fields."""

        self.stimulusThreshold = 0
        """This is a number specifying the minimum number of synapses that must be on in order for a columns to turn ON. The purpose of this is to prevent noise input from activating columns. Specified as a percent of a fully grown synapse."""

        self.proximalSynConnectedPerm = 0.10
        """The default connected threshold. Any synapse whose permanence value is above the connected threshold is a "connected synapse", meaning it can contribute to the cell's firing."""

        self.proximalSynPermIncrement = 0.1
        """The amount by which an active synapse is incremented in each round. Specified as a percent of a fully grown synapse."""

        self.proximalSynPermDecrement = 0.01
        """The amount by which an inactive synapse is decremented in each round. Specified as a percent of a fully grown synapse."""

        self.minPctOverlapDutyCycle = 0.001
        """A number between 0 and 1.0, used to set a floor on how often a column should have at least stimulusThreshold active inputs. Periodically, each column looks at the overlap duty cycle of all other columns within its inhibition radius and sets its own internal minimal acceptable duty cycle to:
		  minPctDutyCycleBeforeInh * max(other columns' duty cycles).
		On each iteration, any column whose overlap duty cycle falls below this computed value will get all of its permanence values boosted up by synPermActiveInc. Raising all permanences in response to a sub-par duty cycle before inhibition allows a cell to search for new inputs when either its previously learned inputs are no longer ever active, or when the vast majority of them have been "hijacked" by other columns."""

        self.minPctActiveDutyCycle = 0.001
        """A number between 0 and 1.0, used to set a floor on how often a column should be activate. Periodically, each column looks at the activity duty cycle of all other columns within its inhibition radius and sets its own internal minimal acceptable duty cycle to:
		  minPctDutyCycleAfterInh * max(other columns' duty cycles).
		On each iteration, any column whose duty cycle after inhibition falls below this computed value will get its internal boost factor increased."""

        self.dutyCyclePeriod = 1000
        """The period used to calculate duty cycles. Higher values make it take longer to respond to changes in boost or synPerConnectedCell. Shorter values make it more unstable and likely to oscillate."""

        self.maxBoost = 10.0
        """The maximum overlap boost factor. Each column's overlap gets multiplied by a boost factor before it gets considered for inhibition. The actual boost factor for a column is number between 1.0 and maxBoost. A boost factor of 1.0 is used if the duty cycle is >= minOverlapDutyCycle, maxBoost is used if the duty cycle is 0, and any duty cycle in between is linearly extrapolated from these 2 endpoints."""

        #endregion

        #region Temporal Parameters

        self.enableTemporalPooling = True
        """Switch for temporal pooling"""

        self.numCellsPerColumn = 10
        """Number of cells per column. More cells, more contextual information"""

        self.learningRadius = min(self.width, self.height)
        """Radius around cell from which it can sample to form distal dendrite connections."""

        self.distalSynInitialPerm = 0.11
        """The initial permanence of an distal synapse."""

        self.distalSynConnectedPerm = 0.50
        """The default connected threshold. Any synapse whose permanence value is above the connected threshold is a "connected synapse", meaning it can contribute to the cell's firing."""

        self.distalSynPermIncrement = 0.10
        """The amount by which an active synapse is incremented in each round. Specified as a percent of a fully grown synapse."""

        self.distalSynPermDecrement = 0.10
        """The amount by which an inactive synapse is decremented in each round. Specified as a percent of a fully grown synapse."""

        self.minThreshold = 8
        """If the number of synapses active on a segment is at least this threshold, it is selected as the best matching cell in a bursing column."""

        self.activationThreshold = 12
        """If the number of active connected synapses on a segment is at least this threshold, the segment is said to be active."""

        self.maxNumNewSynapses = 15
        """The maximum number of synapses added to a segment during learning."""

        #endregion

        self.spatialPooler = None
        """Spatial Pooler instance"""

        self.temporalPooler = None
        """Temporal Pooler instance"""
예제 #12
0
    def initialize(self):
        """
		Initialize this node.
		"""

        if len(self.children) == 0:
            QtGui.QMessageBox.warning(
                None, "Warning",
                "Region '" + self.name + "' does not have any child!")
            return

        Node.initialize(self)
        for child in self.children:
            child.initialize()

        # Create the input map
        # An input map is a set of input elements (cells or sensor bits) that can be are grouped or combined
        # For example, if we have 2 children (#1 and #2) with dimensions 6 and 12 respectively,
        # a grouped input map would be something like:
        #   111111222222222222
        # while a combined one would be something like:
        #   122122122122122122
        self._inputMap = []
        sumDimension = 0
        if self.inputMapType == InputMapType.grouped:
            elemIdx = 0
            for child in self.children:
                dimension = child.width * child.height
                sumDimension += dimension

                # Arrange input from child into input map of this region
                if child.type == NodeType.region:
                    for column in child.columns:
                        inputElem = column.cells[0]
                        self._inputMap.append(inputElem)
                else:
                    for bit in child.bits:
                        inputElem = bit
                        self._inputMap.append(inputElem)
                elemIdx += 1

        elif self.inputMapType == InputMapType.combined:
            # Get the overall dimension and the minimum dimension among all children
            minDimension = self.children[0].width * self.children[0].height
            for child in self.children:
                dimension = child.width * child.height
                sumDimension += dimension
                if dimension < minDimension:
                    minDimension = dimension

            # Use the minimum dimension as a multiplication common factor to determine the frequency of each child element in a sequence
            frequencies = []
            nextIdx = []
            for child in self.children:
                dimension = child.width * child.height
                if dimension % minDimension == 0:
                    frequency = dimension / minDimension
                    frequencies.append(frequency)
                    nextIdx.append(0)
                else:
                    QtGui.QMessageBox.warning(
                        None, "Warning",
                        "Children dimensions should have a common multiple factor!"
                    )
                    return

            # Distribute alternatively child elements into input map according to their frequencies
            childIdx = 0
            for elemIdx in range(sumDimension):
                if childIdx == len(self.children):
                    childIdx = 0
                child = self.children[childIdx]

                # Start distribution taking in account the last inserted element
                i0 = nextIdx[childIdx]
                iN = i0 + frequencies[childIdx]
                nextIdx[childIdx] = iN
                for i in range(i0, iN):
                    if child.type == NodeType.region:
                        inputElem = child.columns[i].cells[0]
                        self._inputMap.append(inputElem)
                    else:
                        inputElem = child.bits[i]
                        self._inputMap.append(inputElem)

                # Alternate children
                childIdx += 1

        # Initialize elements
        self.columns = []
        colIdx = 0
        for x in range(self.width):
            for y in range(self.height):
                column = Column()
                column.x = x
                column.y = y
                for z in range(self.numCellsPerColumn):
                    cell = Cell()
                    cell.index = (colIdx * self.numCellsPerColumn) + z
                    cell.z = z
                    column.cells.append(cell)
                self.columns.append(column)
                colIdx += 1

        # Create Spatial Pooler instance with appropriate parameters
        self.spatialPooler = SpatialPooler(
            inputDimensions=(sumDimension, 1),
            columnDimensions=(self.width, self.height),
            potentialRadius=self.potentialRadius,
            potentialPct=self.potentialPct,
            globalInhibition=self.globalInhibition,
            localAreaDensity=self.localAreaDensity,
            numActiveColumnsPerInhArea=self.numActiveColumnsPerInhArea,
            stimulusThreshold=self.stimulusThreshold,
            synPermInactiveDec=self.proximalSynPermDecrement,
            synPermActiveInc=self.proximalSynPermIncrement,
            synPermConnected=self.proximalSynConnectedPerm,
            minPctOverlapDutyCycle=self.minPctOverlapDutyCycle,
            minPctActiveDutyCycle=self.minPctActiveDutyCycle,
            dutyCyclePeriod=self.dutyCyclePeriod,
            maxBoost=self.maxBoost,
            seed=-1,
            spVerbosity=False)

        # Create Temporal Pooler instance with appropriate parameters
        self.temporalPooler = TemporalPooler(
            columnDimensions=(self.width, self.height),
            cellsPerColumn=self.numCellsPerColumn,
            learningRadius=self.learningRadius,
            initialPermanence=self.distalSynInitialPerm,
            connectedPermanence=self.distalSynConnectedPerm,
            minThreshold=self.minThreshold,
            maxNewSynapseCount=self.maxNumNewSynapses,
            permanenceIncrement=self.distalSynPermIncrement,
            permanenceDecrement=self.distalSynPermDecrement,
            activationThreshold=self.activationThreshold,
            seed=42)

        return True
예제 #13
0
    def nextStep(self):
        """
		Performs actions related to time step progression.
		"""

        # Update states machine by remove the first element and add a new element in the end
        for encoding in self.encodings:
            encoding.currentValue.rotate()
            if encoding.enableInference:
                encoding.predictedValues.rotate()
                encoding.bestPredictedValue.rotate()

        Node.nextStep(self)
        for bit in self.bits:
            bit.nextStep()

        # Get record value from data source
        # If the last record was reached just rewind it
        data = self.dataSource.getNextRecordDict()
        if not data:
            self.dataSource.rewind()
            data = self.dataSource.getNextRecordDict()

        # Pass raw values to encoder and get a concatenated array
        outputArray = numpy.zeros(self.encoder.getWidth())
        self.encoder.encodeIntoArray(data, outputArray)

        # Get values obtained from the data source.
        outputValues = self.encoder.getScalars(data)

        # Get raw values and respective encoded bit array for each field
        prevOffset = 0
        for i in range(len(self.encodings)):
            encoding = self.encodings[i]

            # Convert the value to its respective data type
            currValue = outputValues[i]
            if encoding.encoderFieldDataType == FieldDataType.boolean:
                currValue = bool(currValue)
            elif encoding.encoderFieldDataType == FieldDataType.integer:
                currValue = int(currValue)
            elif encoding.encoderFieldDataType == FieldDataType.decimal:
                currValue = float(currValue)
            elif encoding.encoderFieldDataType == FieldDataType.dateTime:
                currValue = dateutil.parser.parse(str(currValue))
            elif encoding.encoderFieldDataType == FieldDataType.string:
                currValue = str(currValue)
            encoding.currentValue.setForCurrStep(currValue)

        # Update sensor bits
        for i in range(len(outputArray)):
            if outputArray[i] > 0.:
                self.bits[i].isActive.setForCurrStep(True)
            else:
                self.bits[i].isActive.setForCurrStep(False)

        # Mark falsely predicted bits
        for bit in self.bits:
            if bit.isPredicted.atPreviousStep(
            ) and not bit.isActive.atCurrStep():
                bit.isFalselyPredicted.setForCurrStep(True)

        self._output = outputArray
예제 #14
0
	def initialize(self):
		"""
		Initialize this node.
		"""

		Node.initialize(self)

		# Initialize input bits
		self.bits = []
		for x in range(self.width):
			for y in range(self.height):
				bit = Bit()
				bit.x = x
				bit.y = y
				self.bits.append(bit)

		if self.dataSourceType == DataSourceType.file:
			"""
			Initialize this node opening the file and place cursor on the first record.
			"""

			# If file name provided is a relative path, use project file path
			if self.fileName != '' and os.path.dirname(self.fileName) == '':
				fullFileName = os.path.dirname(Global.project.fileName) + '/' + self.fileName
			else:
				fullFileName = self.fileName

			# Open file
			if not os.path.isfile(fullFileName):
				QtGui.QMessageBox.warning(None, "Warning", "Input stream file '" + fullFileName + "' was not found or specified.", QtGui.QMessageBox.Ok)
				return

			if self.inputFormat == InputFormat.htm:
				self._file = open(fullFileName, "rb")

				# Get dimensions of the record
				width = 0
				height = 0
				character = 0
				while True:
					# Read next character
					character = self._file.read(1)

					# Check if character is 'return' and not a number, i.e. if the first record was read
					if character == '\r':
						character = self._file.read(1)
					if character == '\n':
						break

					# Pass over the line until find a 'return' character in order to get the width
					width = 0
					while character != '\n':
						width += 1
						character = self._file.read(1)
						if character == '\r':
							character = self._file.read(1)

					# Increments height
					height += 1

				# If current file record dimensions is not the same to sensor size then throws exception
				if self.width != width or self.height != height:
					QtGui.QMessageBox.warning(None, "Warning", "'" + self.name + "': File input size (" + width + " x " + height + ") is different from sensor size (" + self.width + " x " + self.height + ").", QtGui.QMessageBox.Ok)
					return

				# Put the pointer back to initial position
				self._file.seek(0)
			elif self.inputFormat == InputFormat.raw:
				self._file = open(fullFileName)

				# Create an instance class for an encoder given its module, class and constructor params
				self.encoder = getInstantiatedClass(self.encoderModule, self.encoderClass, self.encoderParams)

				# If encoder size is not the same to sensor size then throws exception
				encoderSize = self.encoder.getWidth()
				sensorSize = self.width * self.height
				if encoderSize > sensorSize:
					QtGui.QMessageBox.warning(None, "Warning", "'" + self.name + "': Encoder size (" + str(encoderSize) + ") is different from sensor size (" + str(self.width) + " x " + str(self.height) + " = " + str(sensorSize) + ").", QtGui.QMessageBox.Ok)
					return

		elif self.dataSourceType == DataSourceType.database:
			pass

		# Create Classifier instance with appropriate parameters
		self.minProbabilityThreshold = 0.0001
		self.steps = []
		for step in range(maxFutureSteps):
			self.steps.append(step+1)
		self.classifier = CLAClassifier(steps=self.steps)
예제 #15
0
	def __init__(self, parentNode, name):
		"""
		Initializes a new instance of the Node class.
		"""

		Node.__init__(self, parentNode, name, NodeType.region)

		#region Instance fields

		self.columns = []
		"""List of columns that compose this region"""

		self._inputMap = []
		"""An array representing the input map for this region."""

		#region Spatial Parameters

		self.enableSpatialPooling = True
		"""Switch for spatial pooling"""

		self.potentialRadius = 0
		"""This parameter determines the extent of the input that each column can potentially be connected to. This can be thought of as the input bits that are visible to each column, or a 'receptiveField' of the field of vision. A large enough value will result in 'global coverage', meaning that each column can potentially be connected to every input bit. This parameter defines a square (or hyper square) area: a column will have a max square potential pool with sides of length 2 * potentialRadius + 1."""

		self.potentialPct = 0.5
		"""The percent of the inputs, within a column's potential radius, that a column can be connected to. If set to 1, the column will be connected to every input within its potential radius. This parameter is used to give each column a unique potential pool when a large potentialRadius causes overlap between the columns. At initialization time we choose ((2*potentialRadius + 1)^(# inputDimensions) * potentialPct) input bits to comprise the column's potential pool."""

		self.globalInhibition = False
		"""If true, then during inhibition phase the winning columns are selected as the most active columns from the region as a whole. Otherwise, the winning columns are selected with respect to their local neighborhoods. Using global inhibition boosts performance x60."""

		self.localAreaDensity = -1.0
		"""The desired density of active columns within a local inhibition area (the size of which is set by the internally calculated inhibitionRadius, which is in turn determined from the average size of the connected potential pools of all columns). The inhibition logic will insure that at most N columns remain ON within a local inhibition area, where N = localAreaDensity * (total number of columns in inhibition area)."""

		self.numActiveColumnsPerInhArea = int(0.02 * (self.width * self.height))
		"""An alternate way to control the density of the active columns. If numActiveColumnsPerInhArea is specified then localAreaDensity must be less than 0, and vice versa. When using numActiveColumnsPerInhArea, the inhibition logic will insure that at most 'numActiveColumnsPerInhArea' columns remain ON within a local inhibition area (the size of which is set by the internally calculated inhibitionRadius, which is in turn determined from the average size of the connected receptive fields of all columns). When using this method, as columns learn and grow their effective receptive fields, the inhibitionRadius will grow, and hence the net density of the active columns will *decrease*. This is in contrast to the localAreaDensity method, which keeps the density of active columns the same regardless of the size of their receptive fields."""

		self.stimulusThreshold = 0
		"""This is a number specifying the minimum number of synapses that must be on in order for a columns to turn ON. The purpose of this is to prevent noise input from activating columns. Specified as a percent of a fully grown synapse."""

		self.proximalSynConnectedPerm = 0.10
		"""The default connected threshold. Any synapse whose permanence value is above the connected threshold is a "connected synapse", meaning it can contribute to the cell's firing."""

		self.proximalSynPermIncrement = 0.1
		"""The amount by which an active synapse is incremented in each round. Specified as a percent of a fully grown synapse."""

		self.proximalSynPermDecrement = 0.01
		"""The amount by which an inactive synapse is decremented in each round. Specified as a percent of a fully grown synapse."""

		self.minPctOverlapDutyCycle = 0.001
		"""A number between 0 and 1.0, used to set a floor on how often a column should have at least stimulusThreshold active inputs. Periodically, each column looks at the overlap duty cycle of all other columns within its inhibition radius and sets its own internal minimal acceptable duty cycle to:
		  minPctDutyCycleBeforeInh * max(other columns' duty cycles).
		On each iteration, any column whose overlap duty cycle falls below this computed value will get all of its permanence values boosted up by synPermActiveInc. Raising all permanences in response to a sub-par duty cycle before inhibition allows a cell to search for new inputs when either its previously learned inputs are no longer ever active, or when the vast majority of them have been "hijacked" by other columns."""

		self.minPctActiveDutyCycle = 0.001
		"""A number between 0 and 1.0, used to set a floor on how often a column should be activate. Periodically, each column looks at the activity duty cycle of all other columns within its inhibition radius and sets its own internal minimal acceptable duty cycle to:
		  minPctDutyCycleAfterInh * max(other columns' duty cycles).
		On each iteration, any column whose duty cycle after inhibition falls below this computed value will get its internal boost factor increased."""

		self.dutyCyclePeriod = 1000
		"""The period used to calculate duty cycles. Higher values make it take longer to respond to changes in boost or synPerConnectedCell. Shorter values make it more unstable and likely to oscillate."""

		self.maxBoost = 10.0
		"""The maximum overlap boost factor. Each column's overlap gets multiplied by a boost factor before it gets considered for inhibition. The actual boost factor for a column is number between 1.0 and maxBoost. A boost factor of 1.0 is used if the duty cycle is >= minOverlapDutyCycle, maxBoost is used if the duty cycle is 0, and any duty cycle in between is linearly extrapolated from these 2 endpoints."""

		#endregion

		#region Temporal Parameters

		self.enableTemporalPooling = True
		"""Switch for temporal pooling"""

		self.numCellsPerColumn = 10
		"""Number of cells per column. More cells, more contextual information"""

		self.learningRadius = min(self.width, self.height)
		"""Radius around cell from which it can sample to form distal dendrite connections."""

		self.distalSynInitialPerm = 0.11
		"""The initial permanence of an distal synapse."""

		self.distalSynConnectedPerm = 0.50
		"""The default connected threshold. Any synapse whose permanence value is above the connected threshold is a "connected synapse", meaning it can contribute to the cell's firing."""

		self.distalSynPermIncrement = 0.10
		"""The amount by which an active synapse is incremented in each round. Specified as a percent of a fully grown synapse."""

		self.distalSynPermDecrement = 0.10
		"""The amount by which an inactive synapse is decremented in each round. Specified as a percent of a fully grown synapse."""

		self.minThreshold = 8
		"""If the number of synapses active on a segment is at least this threshold, it is selected as the best matching cell in a bursing column."""

		self.activationThreshold = 12
		"""If the number of active connected synapses on a segment is at least this threshold, the segment is said to be active."""

		self.maxNumNewSynapses = 15
		"""The maximum number of synapses added to a segment during learning."""

		#endregion

		self.spatialPooler = None
		"""Spatial Pooler instance"""

		self.temporalPooler = None
		"""Temporal Pooler instance"""
예제 #16
0
	def initialize(self):
		"""
		Initialize this node.
		"""

		if len(self.children) == 0:
			QtGui.QMessageBox.warning(None, "Warning", "Region '" + self.name + "' does not have any child!")
			return

		Node.initialize(self)
		for child in self.children:
			child.initialize()

		# Create the input map
		# An input map is a set of input elements (cells or sensor bits) that should are grouped
		# For example, if we have 2 children (#1 and #2) with dimensions 6 and 12 respectively,
		# a input map would be something like:
		#   111111222222222222
		self._inputMap = []
		sumDimension = 0
		elemIdx = 0
		for child in self.children:
			dimension = child.width * child.height
			sumDimension += dimension

			# Arrange input from child into input map of this region
			if child.type == NodeType.region:
				for column in child.columns:
					inputElem = column.cells[0]
					self._inputMap.append(inputElem)
			else:
				for bit in child.bits:
					inputElem = bit
					self._inputMap.append(inputElem)
			elemIdx += 1

		# Initialize elements
		self.columns = []
		colIdx = 0
		for x in range(self.width):
			for y in range(self.height):
				column = Column()
				column.x = x
				column.y = y
				for z in range(self.numCellsPerColumn):
					cell = Cell()
					cell.index = (colIdx * self.numCellsPerColumn) + z
					cell.z = z
					column.cells.append(cell)
				self.columns.append(column)
				colIdx += 1

		# Create Spatial Pooler instance with appropriate parameters
		self.spatialPooler = SpatialPooler(
			inputDimensions = (sumDimension, 1),
			columnDimensions = (self.width, self.height),
			potentialRadius = self.potentialRadius,
			potentialPct = self.potentialPct,
			globalInhibition = self.globalInhibition,
			localAreaDensity = self.localAreaDensity,
			numActiveColumnsPerInhArea = self.numActiveColumnsPerInhArea,
			stimulusThreshold = self.stimulusThreshold,
			synPermInactiveDec = self.proximalSynPermDecrement,
			synPermActiveInc = self.proximalSynPermIncrement,
			synPermConnected = self.proximalSynConnectedPerm,
			minPctOverlapDutyCycle = self.minPctOverlapDutyCycle,
			minPctActiveDutyCycle = self.minPctActiveDutyCycle,
			dutyCyclePeriod = self.dutyCyclePeriod,
			maxBoost = self.maxBoost,
			seed = self.spSeed,
			spVerbosity = False)

		# Create Temporal Pooler instance with appropriate parameters
		self.temporalPooler = TemporalPooler(
			columnDimensions = (self.width, self.height),
			cellsPerColumn = self.numCellsPerColumn,
			learningRadius = self.learningRadius,
			initialPermanence = self.distalSynInitialPerm,
			connectedPermanence = self.distalSynConnectedPerm,
			minThreshold = self.minThreshold,
			maxNewSynapseCount = self.maxNumNewSynapses,
			permanenceIncrement = self.distalSynPermIncrement,
			permanenceDecrement = self.distalSynPermDecrement,
			activationThreshold = self.activationThreshold,
			seed = self.tpSeed)

		return True
예제 #17
0
	def __init__(self, parentNode, name):
		"""
		Initializes a new instance of this class.
		"""

		Node.__init__(self, parentNode, name, NodeType.sensor)

		#region Instance fields

		self.bits = []
		"""An array of the bit objects that compose the current output of this node."""

		self.dataSourceType = DataSourceType.file
		"""Type of the data source (File or Database)"""

		self.fileName = ''
		"""The input file name to be handled. Returns the input file name only if it is in the project directory, full path otherwise."""

		self._file = None
		"""File stream to handle the file."""

		self.databaseConnectionString = ""
		"""Connection string of the database."""

		self.databaseTable = ''
		"""Target table of the database."""

		self.databaseField = ''
		"""Target field of the database table."""

		self.inputFormat = InputFormat.htm
		"""Format of the node (HTM or raw data)"""

		self.inputRawDataType = InputRawDataType.string
		"""Data type of the raw input"""

		self.encoder = None
		"""Optional encoder to convert raw data to htm input and vice-versa."""

		self.encoderModule = ""
		"""Module name which encoder class is imported."""

		self.encoderClass = ""
		"""Class name which encode or decode values."""

		self.encoderParams = ""
		"""Parameters passed to the encoder class constructor."""

		self.predictionsMethod = PredictionsMethod.reconstruction
		"""Method used to get predicted values and their probabilities."""

		self.enableClassificationLearning = True
		"""Switch for classification learning"""

		self.enableClassificationInference = True
		"""Switch for classification inference"""

		self.currentValue = [None] * maxPreviousSteps
		"""Raw value encoded to network."""

		self.predictedValues = [None] * maxPreviousSteps
		"""Raw value decoded from network."""

		#endregion

		#region Statistics properties

		self.statsPrecisionRate = 0.
예제 #18
0
    def initialize(self):
        """
		Initialize this node.
		"""

        Node.initialize(self)

        # Initialize input bits
        self.bits = []
        for x in range(self.width):
            for y in range(self.height):
                bit = Bit()
                bit.x = x
                bit.y = y
                self.bits.append(bit)

        if self.dataSourceType == DataSourceType.file:
            """
			Initialize this node opening the file and place cursor on the first record.
			"""

            # If file name provided is a relative path, use project file path
            if self.fileName != '' and os.path.dirname(self.fileName) == '':
                fullFileName = os.path.dirname(
                    Global.project.fileName) + '/' + self.fileName
            else:
                fullFileName = self.fileName

            # Open file
            if not os.path.isfile(fullFileName):
                QtGui.QMessageBox.warning(
                    None, "Warning", "Input stream file '" + fullFileName +
                    "' was not found or specified.", QtGui.QMessageBox.Ok)
                return

            if self.inputFormat == InputFormat.htm:
                self._file = open(fullFileName, "rb")

                # Get dimensions of the record
                width = 0
                height = 0
                character = 0
                while True:
                    # Read next character
                    character = self._file.read(1)

                    # Check if character is 'return' and not a number, i.e. if the first record was read
                    if character == '\r':
                        character = self._file.read(1)
                    if character == '\n':
                        break

                    # Pass over the line until find a 'return' character in order to get the width
                    width = 0
                    while character != '\n':
                        width += 1
                        character = self._file.read(1)
                        if character == '\r':
                            character = self._file.read(1)

                    # Increments height
                    height += 1
            elif self.inputFormat == InputFormat.raw:
                pass

        elif self.dataSourceType == DataSourceType.database:
            pass

        # If current file record dimensions is not the same to sensor size then throws exception
        if self.width != width or self.height != height:
            self.width = width
            self.height = height
예제 #19
0
    def initialize(self):
        """
		Initialize this node.
		"""

        Node.initialize(self)

        # Initialize input bits
        self.bits = []
        for x in range(self.width):
            for y in range(self.height):
                bit = Bit()
                bit.x = x
                bit.y = y
                self.bits.append(bit)

        if self.dataSourceType == DataSourceType.file:
            """
			Initialize this node opening the file and place cursor on the first record.
			"""

            # If file name provided is a relative path, use project file path
            if self.fileName != '' and os.path.dirname(self.fileName) == '':
                fullFileName = os.path.dirname(
                    Global.project.fileName) + '/' + self.fileName
            else:
                fullFileName = self.fileName

            # Check if file really exists
            if not os.path.isfile(fullFileName):
                QtGui.QMessageBox.warning(
                    None, "Warning", "Input stream file '" + fullFileName +
                    "' was not found or specified.", QtGui.QMessageBox.Ok)
                return

            # Create a data source for read the file
            self.dataSource = FileRecordStream(fullFileName)

        elif self.dataSourceType == DataSourceType.database:
            pass

        self.encoder = MultiEncoder()
        for encoding in self.encodings:
            encoding.initialize()

            # Create an instance class for an encoder given its module, class and constructor params
            encoding.encoder = getInstantiatedClass(encoding.encoderModule,
                                                    encoding.encoderClass,
                                                    encoding.encoderParams)

            # Take the first part of encoder field name as encoder name
            # Ex: timestamp_weekend.weekend => timestamp_weekend
            encoding.encoder.name = encoding.encoderFieldName.split('.')[0]

            # Add sub-encoder to multi-encoder list
            self.encoder.addEncoder(encoding.dataSourceFieldName,
                                    encoding.encoder)

        # If encoder size is not the same to sensor size then throws exception
        encoderSize = self.encoder.getWidth()
        sensorSize = self.width * self.height
        if encoderSize > sensorSize:
            QtGui.QMessageBox.warning(
                None, "Warning",
                "'" + self.name + "': Encoder size (" + str(encoderSize) +
                ") is different from sensor size (" + str(self.width) + " x " +
                str(self.height) + " = " + str(sensorSize) + ").",
                QtGui.QMessageBox.Ok)
            return

        return True
예제 #20
0
	def initialize(self):
		"""
		Initialize this node.
		"""

		Node.initialize(self)

		# Initialize input bits
		self.bits = []
		for x in range(self.width):
			for y in range(self.height):
				bit = Bit()
				bit.x = x
				bit.y = y
				self.bits.append(bit)

		if self.dataSourceType == DataSourceType.file:
			"""
			Initialize this node opening the file and place cursor on the first record.
			"""

			# If file name provided is a relative path, use project file path
			if self.fileName != '' and os.path.dirname(self.fileName) == '':
				fullFileName = os.path.dirname(Global.project.fileName) + '/' + self.fileName
			else:
				fullFileName = self.fileName

			# Open file
			if not os.path.isfile(fullFileName):
				QtGui.QMessageBox.warning(None, "Warning", "Input stream file '" + fullFileName + "' was not found or specified.", QtGui.QMessageBox.Ok)
				return

			if self.inputFormat == InputFormat.htm:
				self._file = open(fullFileName, "rb")

				# Get dimensions of the record
				width = 0
				height = 0
				character = 0
				while True:
					# Read next character
					character = self._file.read(1)

					# Check if character is 'return' and not a number, i.e. if the first record was read
					if character == '\r':
						character = self._file.read(1)
					if character == '\n':
						break

					# Pass over the line until find a 'return' character in order to get the width
					width = 0
					while character != '\n':
						width += 1
						character = self._file.read(1)
						if character == '\r':
							character = self._file.read(1)

					# Increments height
					height += 1
			elif self.inputFormat == InputFormat.raw:
				pass

		elif self.dataSourceType == DataSourceType.database:
			pass

		# If current file record dimensions is not the same to sensor size then throws exception
		if self.width != width or self.height != height:
			self.width = width
			self.height = height
예제 #21
0
    def initialize(self):
        """
		Initialize this node.
		"""

        # Check if this region has nodes that feed it
        numFeeders = len(Global.project.network.getFeederNodes(self))
        if numFeeders == 0:
            QtGui.QMessageBox.warning(
                None, "Warning",
                "Region '" + self.name + "' does not have any child!")
            return

        # Initialize this node and the nodes that feed it
        Node.initialize(self)

        # Create the input map
        # An input map is a set of input elements (cells or sensor bits) that should are grouped
        # For example, if we have 2 nodes that feed this region (#1 and #2) with dimensions 6 and 12 respectively,
        # a input map would be something like:
        #   111111222222222222
        self._inputMap = []
        elemIdx = 0
        for feeder in Global.project.network.getFeederNodes(self):

            # Arrange input from feeder into input map of this region
            if feeder.type == NodeType.region:
                for column in feeder.columns:
                    inputElem = column.cells[0]
                    self._inputMap.append(inputElem)
            else:
                for bit in feeder.bits:
                    inputElem = bit
                    self._inputMap.append(inputElem)
            elemIdx += 1

        # Initialize elements
        self.columns = []
        colIdx = 0
        for x in range(self.width):
            for y in range(self.height):
                column = Column()
                column.x = x
                column.y = y
                for z in range(self.numCellsPerColumn):
                    cell = Cell()
                    cell.index = (colIdx * self.numCellsPerColumn) + z
                    cell.z = z
                    column.cells.append(cell)
                self.columns.append(column)
                colIdx += 1

        # Create Spatial Pooler instance with appropriate parameters
        self.spatialPooler = SpatialPooler(
            inputDimensions=(self.getInputSize(), 1),
            columnDimensions=(self.width, self.height),
            potentialRadius=self.potentialRadius,
            potentialPct=self.potentialPct,
            globalInhibition=self.globalInhibition,
            localAreaDensity=self.localAreaDensity,
            numActiveColumnsPerInhArea=self.numActiveColumnsPerInhArea,
            stimulusThreshold=self.stimulusThreshold,
            synPermInactiveDec=self.proximalSynPermDecrement,
            synPermActiveInc=self.proximalSynPermIncrement,
            synPermConnected=self.proximalSynConnectedPerm,
            minPctOverlapDutyCycle=self.minPctOverlapDutyCycle,
            minPctActiveDutyCycle=self.minPctActiveDutyCycle,
            dutyCyclePeriod=self.dutyCyclePeriod,
            maxBoost=self.maxBoost,
            seed=self.spSeed,
            spVerbosity=False)

        # Create Temporal Pooler instance with appropriate parameters
        self.temporalPooler = TemporalPooler(
            columnDimensions=(self.width, self.height),
            cellsPerColumn=self.numCellsPerColumn,
            learningRadius=self.learningRadius,
            initialPermanence=self.distalSynInitialPerm,
            connectedPermanence=self.distalSynConnectedPerm,
            minThreshold=self.minThreshold,
            maxNewSynapseCount=self.maxNumNewSynapses,
            permanenceIncrement=self.distalSynPermIncrement,
            permanenceDecrement=self.distalSynPermDecrement,
            activationThreshold=self.activationThreshold,
            seed=self.tpSeed)

        return True