Files
rdkit/Python/ML/Neural/NetNode.py
Greg Landrum 75a79b6327 initial import
2006-05-06 22:20:08 +00:00

150 lines
4.1 KiB
Python
Executable File

#
# 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)