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

Source Code for Module ML.Neural.Network

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