# # Copyright (C) 2000 greg Landrum # """ Contains the class _NetNode_ which is used to represent nodes in neural nets **Network Architecture:** A tacit assumption in all of this stuff is that we're dealing with feedforward networks. The network itself is stored as a list of _NetNode_ objects. The list is ordered in the sense that nodes in earlier/later layers than a given node are guaranteed to come before/after that node in the list. This way we can easily generate the values of each node by moving sequentially through the list, we're guaranteed that every input for a node has already been filled in. Each node stores a list (_inputNodes_) of indices of its inputs in the main node list. """ from Numeric import * import ActFuncs # FIX: this class has not been updated to new-style classes # (RD Issue380) because that would break all of our legacy pickled # data. Until a solution is found for this breakage, an update is # impossible. class NetNode: """ a node in a neural network """ def Eval(self,valVect): """Given a set of inputs (valVect), returns the output of this node **Arguments** - valVect: a list of inputs **Returns** the result of running the values in valVect through this node """ if len(self.inputNodes) != 0: # grab our list of weighted inputs inputs = take(valVect,self.inputNodes) # weight them inputs = self.weights * inputs # run that through the activation function val = self.actFunc(sum(inputs)) else: val = 1 # put our value in the list and return it (just in case) valVect[self.nodeIndex] = val return val def SetInputs(self,inputNodes): """ Sets the input list **Arguments** - inputNodes: a list of _NetNode_s which are to be used as inputs **Note** If this _NetNode_ already has weights set and _inputNodes_ is a different length, this will bomb out with an assertion. """ self.inputNodes = inputNodes[:] if self.weights: assert (len(self.weights) == len(self.inputNodes)),\ 'lengths of weights and nodes do not match' def GetInputs(self): """ returns the input list """ return self.inputNodes def SetWeights(self,weights): """ Sets the weight list **Arguments** - weights: a list of values which are to be used as weights **Note** If this _NetNode_ already has _inputNodes_ and _weights_ is a different length, this will bomb out with an assertion. """ self.weights = array(weights) if self.inputNodes: assert (len(self.weights) == len(self.inputNodes)),\ 'lengths of weights and nodes do not match' def GetWeights(self): """ returns the weight list """ return self.weights def __init__(self,nodeIndex,nodeList,inputNodes=None,weights=None, actFunc=ActFuncs.Sigmoid,actFuncParms=()): """ Constructor **Arguments** - nodeIndex: the integer index of this node in _nodeList_ - nodeList: the list of other _NetNodes_ already in the network - inputNodes: a list of this node's inputs - weights: a list of this node's weights - actFunc: the activation function to be used here. Must support the API of _ActFuncs.ActFunc_. - actFuncParms: a tuple of extra arguments to be passed to the activation function constructor. **Note** There should be only one copy of _inputNodes_, every _NetNode_ just has a pointer to it so that changes made at one node propagate automatically to the others. """ if inputNodes and weights: assert (len(weights) == len(inputNodes)) if weights: self.weights = array(weights) else: self.weights = None if inputNodes: self.inputNodes = inputNodes[:] else: self.inputNodes = None self.nodeIndex = nodeIndex # there's only one of these, everybody has a pointer to it. self.nodeList = nodeList self.actFunc = apply(actFunc,actFuncParms)