Mercurial > pylearn
comparison doc/v2_planning/plugin_JB.py @ 1203:865936d8221b
v2planning plugin_JB - removed VM for clarity
author | James Bergstra <bergstrj@iro.umontreal.ca> |
---|---|
date | Mon, 20 Sep 2010 21:33:45 -0400 |
parents | acfd5e747a75 |
children | cbe1fb32686c |
comparison
equal
deleted
inserted
replaced
1202:7fff3d5c7694 | 1203:865936d8221b |
---|---|
15 train_pca = SEQ([ | 15 train_pca = SEQ([ |
16 BUFFER_REPEAT(pca_batchsize, CALL(dataset.next)), | 16 BUFFER_REPEAT(pca_batchsize, CALL(dataset.next)), |
17 FILT(pca.analyze)]) | 17 FILT(pca.analyze)]) |
18 | 18 |
19 # run the program | 19 # run the program |
20 VirtualMachine(train_pca).run() | 20 train_pca.run() |
21 | 21 |
22 The CALL, SEQ, FILT, and BUFFER_REPEAT are control-flow elements. The control-flow elements I | 22 The CALL, SEQ, FILT, and BUFFER_REPEAT are control-flow elements. The control-flow elements I |
23 defined so far are: | 23 defined so far are: |
24 | 24 |
25 - CALL - a basic statement, just calls a python function | 25 - CALL - a basic statement, just calls a python function |
36 and realizes all of them. | 36 and realizes all of them. |
37 The advantages of this approach are: | 37 The advantages of this approach are: |
38 | 38 |
39 - algorithms (including partially run ones) are COPYABLE, and SERIALIZABLE | 39 - algorithms (including partially run ones) are COPYABLE, and SERIALIZABLE |
40 | 40 |
41 - algorithms can be executed without seizing control of the python process (the VM is an | 41 - algorithms can be executed without seizing control of the python process (the run() |
42 iterator) so your main loop (aka alternate VM implementation) can be checking for network | 42 method does this, but if you look inside it you'll see it's a simple for loop) |
43 or filesystem events related to job management | 43 |
44 - it is easy to execute an algorithm step by step in a main loop that also checks for | |
45 network or filesystem events related to e.g. job management. | |
44 | 46 |
45 - the library can provide learning algorithms via control-flow templates, and the user can | 47 - the library can provide learning algorithms via control-flow templates, and the user can |
46 edit them (with search/replace calls) to include HOOKS, and DIAGNOSTIC plug-in | 48 edit them (with search/replace calls) to include HOOKS, and DIAGNOSTIC plug-in |
47 functionality | 49 functionality |
48 | 50 |
67 __copyright__ = 'TODO' | 69 __copyright__ = 'TODO' |
68 | 70 |
69 import copy, sys, cPickle | 71 import copy, sys, cPickle |
70 import numpy | 72 import numpy |
71 | 73 |
72 ################################################### | |
73 # Virtual Machine for executing programs | |
74 | |
75 class VirtualMachine(object): | |
76 def __init__(self, prog): | |
77 self.prog = prog | |
78 self.started = False | |
79 self.finished=False | |
80 def __iter__(self): | |
81 assert not self.started | |
82 self.prog.start(None) | |
83 self.started = True | |
84 return self | |
85 def next(self): | |
86 if self.finished: | |
87 raise StopIteration() | |
88 r = self.prog.step() | |
89 if r is INCOMPLETE: | |
90 return r | |
91 else: | |
92 self.finished=True | |
93 return r | |
94 def run(self,n_steps=float('inf')): | |
95 i = 0 | |
96 for r in self: | |
97 i += 1 | |
98 if i > n_steps: | |
99 break | |
100 return r | |
101 | |
102 | |
103 #################################################### | 74 #################################################### |
104 # CONTROL-FLOW CONSTRUCTS | 75 # CONTROL-FLOW CONSTRUCTS |
105 | 76 |
106 class INCOMPLETE: | 77 class INCOMPLETE: |
107 """Return value for Element.step""" | 78 """Return value for Element.step""" |
108 | 79 |
109 class ELEMENT(object): | 80 class ELEMENT(object): |
110 """ | 81 """ |
111 every execution block has a driver | 82 Base class for control flow elements (e.g. CALL, REPEAT, etc.) |
83 | |
84 The design is that every element has a driver, that is another element, or the iterator | |
85 implementation in the ELEMENT class. | |
112 | 86 |
113 the driver calls start when entering a new control element | 87 the driver calls start when entering a new control element |
114 - this would be called once per e.g. outer loop iteration | 88 - this would be called once per e.g. outer loop iteration |
115 | 89 |
116 the driver calls step to advance the control element | 90 the driver calls step to advance the control element |
117 - which returns INCOMPLETE | 91 - which returns INCOMPLETE |
118 - which returns any other object to indicate completion | 92 - which returns any other object to indicate completion |
119 """ | 93 """ |
120 | 94 |
95 # subclasses should override these methods: | |
121 def start(self, arg): | 96 def start(self, arg): |
122 pass | 97 pass |
123 def step(self): | 98 def step(self): |
124 pass | 99 pass |
100 | |
101 # subclasses should typically not override these: | |
102 def run(self, arg=None, n_steps=float('inf')): | |
103 self.start(arg) | |
104 i = 0 | |
105 r = self.step() | |
106 while r is INCOMPLETE: | |
107 i += 1 | |
108 #TODO make sure there is not an off-by-one error | |
109 if i > n_steps: | |
110 break | |
111 r = self.step() | |
112 return r | |
113 | |
125 | 114 |
126 class BUFFER_REPEAT(ELEMENT): | 115 class BUFFER_REPEAT(ELEMENT): |
127 """ | 116 """ |
128 Accumulate a number of return values into one list / array. | 117 Accumulate a number of return values into one list / array. |
129 | 118 |
221 class REPEAT(ELEMENT): | 210 class REPEAT(ELEMENT): |
222 def __init__(self, N, elements, pass_rvals=False): | 211 def __init__(self, N, elements, pass_rvals=False): |
223 self.N = N | 212 self.N = N |
224 self.elements = elements | 213 self.elements = elements |
225 self.pass_rvals = pass_rvals | 214 self.pass_rvals = pass_rvals |
215 | |
226 #TODO: check for N being callable | 216 #TODO: check for N being callable |
227 def start(self, arg): | 217 def start(self, arg): |
228 self.n = 0 #loop iteration | 218 self.n = 0 #loop iteration |
229 self.idx = 0 #element idx | 219 self.idx = 0 #element idx |
230 self.finished = False | 220 self.finished = False |
367 def f(a): | 357 def f(a): |
368 print l | 358 print l |
369 l[0] += a | 359 l[0] += a |
370 return l[0] | 360 return l[0] |
371 | 361 |
372 print VirtualMachine(WEAVE([ | 362 print WEAVE([ |
373 BUFFER_REPEAT(3,CALL(f,1)), | 363 BUFFER_REPEAT(3,CALL(f,1)), |
374 BUFFER_REPEAT(5,CALL(f,1)), | 364 BUFFER_REPEAT(5,CALL(f,1)), |
375 ])).run() | 365 ]).run() |
376 | 366 |
377 def main(): | 367 def main(): |
378 # create components | 368 # create components |
379 dataset = Dataset(numpy.random.RandomState(123).randn(13,1)) | 369 dataset = Dataset(numpy.random.RandomState(123).randn(13,1)) |
380 pca = PCA_Analysis() | 370 pca = PCA_Analysis() |
432 print >> sys.stderr, "pickling doesnt work, but it can be fixed I think" | 422 print >> sys.stderr, "pickling doesnt work, but it can be fixed I think" |
433 | 423 |
434 pkg = pkg2 | 424 pkg = pkg2 |
435 | 425 |
436 # running a program updates the variables in its package, but not the other package | 426 # running a program updates the variables in its package, but not the other package |
437 VirtualMachine(pkg['prog']).run() | 427 pkg['prog'].run() |
438 print pkg['kf'].scores | 428 print pkg['kf'].scores |
439 | 429 |
440 | 430 |
441 if __name__ == '__main__': | 431 if __name__ == '__main__': |
442 sys.exit(main()) | 432 sys.exit(main()) |