Package rdkit :: Package ML :: Package Neural :: Module Network
[hide private]
[frames] | no frames]

Source Code for Module rdkit.ML.Neural.Network

  1  ## Automatically adapted for numpy.oldnumeric Jun 27, 2008 by -c 
  2   
  3  # 
  4  #  Copyright (C) 2000-2008  greg Landrum 
  5  # 
  6  """ Contains the class _Network_ which is used to represent neural nets 
  7   
  8  **Network Architecture:** 
  9   
 10    A tacit assumption in all of this stuff is that we're dealing with 
 11    feedforward networks. 
 12   
 13    The network itself is stored as a list of _NetNode_ objects.  The list 
 14    is ordered in the sense that nodes in earlier/later layers than a 
 15    given node are guaranteed to come before/after that node in the list. 
 16    This way we can easily generate the values of each node by moving 
 17    sequentially through the list, we're guaranteed that every input for a 
 18    node has already been filled in. 
 19   
 20    Each node stores a list (_inputNodes_) of indices of its inputs in the 
 21    main node list. 
 22   
 23  """ 
 24  import numpy 
 25  import random 
 26   
 27  from rdkit.ML.Neural import NetNode, ActFuncs 
 28   
 29  # FIX: this class has not been updated to new-style classes 
 30  # (RD Issue380) because that would break all of our legacy pickled 
 31  # data. Until a solution is found for this breakage, an update is 
 32  # impossible. 
33 -class Network:
34 """ a neural network 35 36 """
37 - def ConstructRandomWeights(self,minWeight=-1,maxWeight=1):
38 """initialize all the weights in the network to random numbers 39 40 **Arguments** 41 42 - minWeight: the minimum value a weight can take 43 44 - maxWeight: the maximum value a weight can take 45 46 """ 47 for node in self.nodeList: 48 inputs = node.GetInputs() 49 if inputs: 50 weights = [random.uniform(minWeight,maxWeight) for x in range(len(inputs))] 51 node.SetWeights(weights)
52 53
54 - def FullyConnectNodes(self):
55 """ Fully connects each layer in the network to the one above it 56 57 58 **Note** 59 this sets the connections, but does not assign weights 60 61 """ 62 nodeList = range(self.numInputNodes) 63 nConnections = 0 64 for layer in xrange(self.numHiddenLayers): 65 for i in self.layerIndices[layer+1]: 66 self.nodeList[i].SetInputs(nodeList) 67 nConnections = nConnections + len(nodeList) 68 nodeList = self.layerIndices[layer+1] 69 70 for i in self.layerIndices[-1]: 71 self.nodeList[i].SetInputs(nodeList) 72 nConnections = nConnections + len(nodeList) 73 self.nConnections = nConnections
74
75 - def ConstructNodes(self,nodeCounts,actFunc,actFuncParms):
76 """ build an unconnected network and set node counts 77 78 **Arguments** 79 80 - nodeCounts: a list containing the number of nodes to be in each layer. 81 the ordering is: 82 (nInput,nHidden1,nHidden2, ... , nHiddenN, nOutput) 83 84 """ 85 self.nodeCounts = nodeCounts 86 self.numInputNodes = nodeCounts[0] 87 self.numOutputNodes = nodeCounts[-1] 88 self.numHiddenLayers = len(nodeCounts)-2 89 self.numInHidden = [None]*self.numHiddenLayers 90 for i in xrange(self.numHiddenLayers): 91 self.numInHidden[i] = nodeCounts[i+1] 92 93 numNodes = sum(self.nodeCounts) 94 self.nodeList = [None]*(numNodes) 95 for i in xrange(numNodes): 96 self.nodeList[i] = NetNode.NetNode(i,self.nodeList, 97 actFunc=actFunc, 98 actFuncParms=actFuncParms) 99 100 self.layerIndices = [None]*len(nodeCounts) 101 start = 0 102 for i in xrange(len(nodeCounts)): 103 end = start + nodeCounts[i] 104 self.layerIndices[i] = range(start,end) 105 start = end
106
107 - def GetInputNodeList(self):
108 """ returns a list of input node indices 109 """ 110 return self.layerIndices[0]
111 - def GetOutputNodeList(self):
112 """ returns a list of output node indices 113 """ 114 return self.layerIndices[-1]
115 - def GetHiddenLayerNodeList(self,which):
116 """ returns a list of hidden nodes in the specified layer 117 """ 118 return self.layerIndices[which+1]
119
120 - def GetNumNodes(self):
121 """ returns the total number of nodes 122 """ 123 return sum(self.nodeCounts)
124
125 - def GetNumHidden(self):
126 """ returns the number of hidden layers 127 """ 128 return self.numHiddenLayers
129
130 - def GetNode(self,which):
131 """ returns a particular node 132 """ 133 return self.nodeList[which]
134 - def GetAllNodes(self):
135 """ returns a list of all nodes 136 """ 137 return self.nodeList
138
139 - def ClassifyExample(self,example,appendExamples=0):
140 """ classifies a given example and returns the results of the output layer. 141 142 **Arguments** 143 144 - example: the example to be classified 145 146 **NOTE:** 147 148 if the output layer is only one element long, 149 a scalar (not a list) will be returned. This is why a lot of the other 150 network code claims to only support single valued outputs. 151 152 """ 153 if len(example) > self.numInputNodes: 154 if len(example)-self.numInputNodes > self.numOutputNodes: 155 example = example[1:-self.numOutputNodes] 156 else: 157 example = example[:-self.numOutputNodes] 158 assert len(example) == self.numInputNodes 159 totNumNodes = sum(self.nodeCounts) 160 results = numpy.zeros(totNumNodes,numpy.float64) 161 for i in xrange(self.numInputNodes): 162 results[i] = example[i] 163 for i in xrange(self.numInputNodes,totNumNodes): 164 self.nodeList[i].Eval(results) 165 self.lastResults = results[:] 166 if self.numOutputNodes == 1: 167 return results[-1] 168 else: 169 return results
170
171 - def GetLastOutputs(self):
172 """ returns the complete list of output layer values from the last time this node classified anything""" 173 return self.lastResults
174
175 - def __str__(self):
176 """ provides a string representation of the network """ 177 outStr = 'Network:\n' 178 for i in xrange(len(self.nodeList)): 179 outStr = outStr + '\tnode(% 3d):\n'%i 180 outStr = outStr + '\t\tinputs: %s\n'%(str(self.nodeList[i].GetInputs())) 181 outStr = outStr + '\t\tweights: %s\n'%(str(self.nodeList[i].GetWeights())) 182 183 outStr = outStr + 'Total Number of Connections: % 4d'%self.nConnections 184 return outStr
185
186 - def __init__(self,nodeCounts,nodeConnections=None, 187 actFunc=ActFuncs.Sigmoid,actFuncParms=(), 188 weightBounds=1):
189 """ Constructor 190 191 This constructs and initializes the network based upon the specified 192 node counts. 193 194 A fully connected network with random weights is constructed. 195 196 **Arguments** 197 198 - nodeCounts: a list containing the number of nodes to be in each layer. 199 the ordering is: 200 (nInput,nHidden1,nHidden2, ... , nHiddenN, nOutput) 201 202 - nodeConnections: I don't know why this is here, but it's optional. ;-) 203 204 - actFunc: the activation function to be used here. Must support the API 205 of _ActFuncs.ActFunc_. 206 207 - actFuncParms: a tuple of extra arguments to be passed to the activation function 208 constructor. 209 210 - weightBounds: a float which provides the boundary on the random initial weights 211 212 213 214 """ 215 self.ConstructNodes(nodeCounts,actFunc,actFuncParms) 216 self.FullyConnectNodes() 217 self.ConstructRandomWeights(minWeight=-weightBounds,maxWeight=weightBounds) 218 self.lastResults = []
219 220 if __name__ == '__main__': 221 222 print '[2,2,2]' 223 net = Network([2,2,2]) 224 print net 225 226 print '[2,4,1]' 227 net = Network([2,4,1]) 228 print net 229 230 print '[2,2]' 231 net = Network([2,2]) 232 print net 233 input = [1,0] 234 res = net.ClassifyExample(input) 235 print input,'->',res 236 input = [0,1] 237 res = net.ClassifyExample(input) 238 print input,'->',res 239 input = [.5,.5] 240 res = net.ClassifyExample(input) 241 print input,'->',res 242