1
2
3
4
5
6 """ Training algorithms for feed-forward neural nets
7
8 Unless noted otherwise, algorithms and notation are taken from:
9 "Artificial Neural Networks: Theory and Applications",
10 Dan W. Patterson, Prentice Hall, 1996
11
12 """
13 from __future__ import print_function
14 import numpy
15
16 from rdkit.six.moves import xrange
17
19 """ "virtual base class" for network trainers
20
21 """
22 pass
23
25 """implement back propagation (algorithm on pp 153-154 of Patterson)
26
27 I don't *think* that I've made any assumptions about the connectivity of
28 the net (i.e. full connectivity between layers is not required).
29
30 **NOTE:** this code is currently making the assumption that the activation
31 functions on the nodes in the network are capable of calculating their
32 derivatives using only their values (i.e. a DerivFromVal method should
33 exist). This shouldn't be too hard to change.
34
35 """
37 """ does a BackProp step based upon the example
38
39 **Arguments**
40
41 - example: a 2-tuple:
42 1) a list of variable values values
43 2) a list of result values (targets)
44
45 - net: a _Network_ (or something supporting the same API)
46
47 - resVect: if this is nonzero, then the network is not required to
48 classify the _example_
49
50 **Returns**
51
52 the backprop error from _network_ **before the update**
53
54 **Note**
55
56 In case it wasn't blindingly obvious, the weights in _network_ are modified
57 in the course of taking a backprop step.
58
59 """
60 totNumNodes = net.GetNumNodes()
61 if self.oldDeltaW is None:
62 self.oldDeltaW = numpy.zeros(totNumNodes,numpy.float64)
63 outputNodeList = net.GetOutputNodeList()
64 nOutput = len(outputNodeList)
65 targetVect = numpy.array(example[-nOutput:],numpy.float64)
66 trainVect = example[:-nOutput]
67 if resVect is None:
68
69 net.ClassifyExample(trainVect)
70 resVect = net.GetLastOutputs()
71 outputs = numpy.take(resVect,outputNodeList)
72 errVect = targetVect - outputs
73
74 delta = numpy.zeros(totNumNodes,numpy.float64)
75
76 for i in xrange(len(outputNodeList)):
77 idx = outputNodeList[i]
78 node = net.GetNode(idx)
79
80 delta[idx] = errVect[i]*node.actFunc.DerivFromVal(resVect[idx])
81
82 inputs = node.GetInputs()
83 weights = delta[idx]*node.GetWeights()
84 for j in xrange(len(inputs)):
85 idx2 = inputs[j]
86 delta[idx2] = delta[idx2] + weights[j]
87
88
89 for layer in xrange(net.GetNumHidden()-1,-1,-1):
90 nodesInLayer = net.GetHiddenLayerNodeList(layer)
91 for idx in nodesInLayer:
92 node = net.GetNode(idx)
93
94 delta[idx] = delta[idx]*node.actFunc.DerivFromVal(resVect[idx])
95
96
97 if layer != 0:
98 inputs = node.GetInputs()
99 weights = delta[idx]*node.GetWeights()
100 for i in xrange(len(inputs)):
101 idx2 = inputs[i]
102 delta[idx2] = delta[idx2] + weights[i]
103
104
105
106 nHidden = net.GetNumHidden()
107 for layer in xrange(0,nHidden+1):
108 if layer == nHidden:
109 idxList = net.GetOutputNodeList()
110 else:
111 idxList = net.GetHiddenLayerNodeList(layer)
112 for idx in idxList:
113 node = net.GetNode(idx)
114 dW = self.speed * delta[idx] * numpy.take(resVect,node.GetInputs())
115 newWeights = node.GetWeights() + dW
116 node.SetWeights(newWeights)
117
118
119 return numpy.sqrt(errVect*errVect)[0]
120
121
122 - def TrainOnLine(self,examples,net,maxIts=5000,errTol=0.1,useAvgErr=1,
123 silent=0):
124 """ carries out online training of a neural net
125
126 The definition of online training is that the network is updated after
127 each example is presented.
128
129 **Arguments**
130
131 - examples: a list of 2-tuple:
132 1) a list of variable values values
133 2) a list of result values (targets)
134
135 - net: a _Network_ (or something supporting the same API)
136
137 - maxIts: the maximum number of *training epochs* (see below for definition) to be
138 run
139
140 - errTol: the tolerance for convergence
141
142 - useAvgErr: if this toggle is nonzero, then the error at each step will be
143 divided by the number of training examples for the purposes of checking
144 convergence.
145
146 - silent: controls the amount of visual noise produced as this runs.
147
148
149 **Note**
150
151 a *training epoch* is one complete pass through all the training examples
152
153 """
154 nExamples = len(examples)
155 converged = 0
156 cycle = 0
157
158 while (not converged) and (cycle < maxIts):
159 maxErr = 0
160 newErr = 0
161
162 for example in examples:
163 localErr = self.StepUpdate(example,net)
164 newErr += localErr
165 if localErr > maxErr:
166 maxErr = localErr
167 if useAvgErr == 1:
168 newErr = newErr / nExamples
169 else:
170 newErr = maxErr
171
172
173 if newErr <= errTol:
174 converged = 1
175
176
177 if not silent:
178 print('epoch %d, error: % 6.4f'%(cycle,newErr))
179
180 cycle = cycle + 1
181 if not silent:
182 if converged:
183 print('Converged after %d epochs.'%cycle)
184 else:
185 print('NOT Converged after %d epochs.'%cycle)
186 print('final error: % 6.4f'%newErr)
187
188 - def __init__(self,speed=0.5,momentum=0.7):
189 """ Constructor
190
191 **Arguments**
192
193 - speed: the speed parameter for back prop training
194
195 - momentum: the momentum term for back prop training
196 *Not currently used*
197
198 """
199 self.speed = speed
200 self.momentum = momentum
201 self.oldDeltaW = None
202
203
204
205 if __name__ == '__main__':
206 from rdkit.ML.Neural import Network
207
209 examples = [
210 [[0,0,1], [0.1]],
211 [[0,1,1], [.1]],
212 [[1,0,1], [.1]],
213 [[1,1,1], [.9]]
214 ]
215 net = Network.Network([3,1])
216 t = BackProp()
217 t.TrainOnLine(examples,net)
218 return net
219
221 examples = [
222 [[0,0,1], [0.1]],
223 [[0,1,1], [.9]],
224 [[1,0,1], [.9]],
225 [[1,1,1], [.9]]
226 ]
227 net = Network.Network([3,1])
228 t = BackProp()
229 t.TrainOnLine(examples,net,maxIts=1000,useAvgErr=0)
230 print('classifications:')
231 for example in examples:
232 res = net.ClassifyExample(example[0])
233 print('%f -> %f'%(example[1][0],res))
234
235 return net
236
238 examples = [
239 [[0,0,1], [.1]],
240 [[0,1,1], [.9]],
241 [[1,0,1], [.9]],
242 [[1,1,1], [.1]]
243 ]
244 net = Network.Network([3,3,1])
245
246 t = BackProp(speed=.8)
247 t.TrainOnLine(examples,net,errTol=0.2)
248 return net
249
250
252 examples = [
253 [.1,.1],
254 [.2,.2],
255 [.3,.3],
256 [.4,.4],
257 [.8,.8],
258 ]
259 net = Network.Network([1,2,1])
260 t = BackProp(speed=.8)
261 t.TrainOnLine(examples,net,errTol=0.1,useAvgErr=0)
262 print('classifications:')
263 for example in examples:
264 res = net.ClassifyExample(example[:-1])
265 print('%f -> %f'%(example[-1],res))
266
267 return net
268
270 import random
271 random.seed(23)
272 import profile,pstats
273 datFile = '%s.prof.dat'%(command)
274 profile.run('%s()'%command,datFile)
275 stats = pstats.Stats(datFile)
276 stats.strip_dirs()
277 stats.sort_stats('time').print_stats()
278
279 if 0:
280 net = testXor()
281 print('Xor:', net)
282 from rdkit.six.moves import cPickle
283 outF = open('xornet.pkl','wb+')
284 cPickle.dump(net,outF)
285 outF.close()
286 else:
287
288 net = testLinear()
289
290