提交 9a4fe7f8 authored 作者: Olivier Breuleux's avatar Olivier Breuleux

pulled macro and all references to it

上级 4549f839
...@@ -13,7 +13,6 @@ from elemwise import * ...@@ -13,7 +13,6 @@ from elemwise import *
def Env(i, o): def Env(i, o):
e = gof.Env(i, o) e = gof.Env(i, o)
gof.ExpandMacros().optimize(e)
return e return e
class _test_DimShuffle(unittest.TestCase): class _test_DimShuffle(unittest.TestCase):
......
...@@ -540,8 +540,8 @@ def verify_grad(testcase, op, pt, n_tests=1, rng=numpy.random, eps=0.0000001, to ...@@ -540,8 +540,8 @@ def verify_grad(testcase, op, pt, n_tests=1, rng=numpy.random, eps=0.0000001, to
num_grad = gradient.numeric_grad(cost_fn, pt) num_grad = gradient.numeric_grad(cost_fn, pt)
#symbolic_grad = exec_grad(cost, tensor_pt,as_tensor(1.0,name='g_cost')) symbolic_grad = grad(cost, tensor_pt,as_tensor(1.0,name='g_cost'))
symbolic_grad = grad.make_node(cost, tensor_pt).outputs
if 0: if 0:
print '-------' print '-------'
print '----------' print '----------'
...@@ -899,7 +899,7 @@ class T_subtensor(unittest.TestCase): ...@@ -899,7 +899,7 @@ class T_subtensor(unittest.TestCase):
n = as_tensor(numpy.random.rand(2,3)) n = as_tensor(numpy.random.rand(2,3))
z = scal.constant(0) z = scal.constant(0)
t = n[z:,z] t = n[z:,z]
gn = exec_grad(sum(exp(t)), n) gn = grad(sum(exp(t)), n)
gval = eval_outputs([gn]) gval = eval_outputs([gn])
s0 = 'array([ 2.05362099, 0. , 0. ])' s0 = 'array([ 2.05362099, 0. , 0. ])'
s1 = 'array([ 1.55009327, 0. , 0. ])' s1 = 'array([ 1.55009327, 0. , 0. ])'
...@@ -909,7 +909,7 @@ class T_subtensor(unittest.TestCase): ...@@ -909,7 +909,7 @@ class T_subtensor(unittest.TestCase):
def test_grad_0d(self): def test_grad_0d(self):
n = as_tensor(numpy.random.rand(2,3)) n = as_tensor(numpy.random.rand(2,3))
t = n[1,0] t = n[1,0]
gn = exec_grad(sum(exp(t)), n) gn = grad(sum(exp(t)), n)
gval = eval_outputs([gn]) gval = eval_outputs([gn])
g0 = repr(gval[0,:]) g0 = repr(gval[0,:])
g1 = repr(gval[1,:]) g1 = repr(gval[1,:])
...@@ -938,7 +938,7 @@ class T_Stack(unittest.TestCase): ...@@ -938,7 +938,7 @@ class T_Stack(unittest.TestCase):
a = as_tensor(numpy.array([[1, 2, 3], [4, 5, 6]])) a = as_tensor(numpy.array([[1, 2, 3], [4, 5, 6]]))
b = as_tensor(numpy.array([[7, 8, 9]])) b = as_tensor(numpy.array([[7, 8, 9]]))
s = vertical_stack(a, b) s = vertical_stack(a, b)
ga,gb = exec_grad(sum(vertical_stack(a,b)), [a,b]) ga,gb = grad(sum(vertical_stack(a,b)), [a,b])
gval = eval_outputs([ga, gb]) gval = eval_outputs([ga, gb])
self.failUnless(numpy.all(gval[0] == 1.0)) self.failUnless(numpy.all(gval[0] == 1.0))
...@@ -1672,13 +1672,13 @@ class _test_grad(unittest.TestCase): ...@@ -1672,13 +1672,13 @@ class _test_grad(unittest.TestCase):
"""grad: Test passing a single result param""" """grad: Test passing a single result param"""
o = _test_grad.O() o = _test_grad.O()
a1 = o.make_node() a1 = o.make_node()
self.failUnless(o.gval0 is exec_grad(a1.outputs[0], a1.inputs[0])) self.failUnless(o.gval0 is grad(a1.outputs[0], a1.inputs[0]))
def test_Nparam(self): def test_Nparam(self):
"""grad: Test passing multiple result params""" """grad: Test passing multiple result params"""
o = _test_grad.O() o = _test_grad.O()
a1 = o.make_node() a1 = o.make_node()
g0,g1 = exec_grad(a1.outputs[0], a1.inputs) g0,g1 = grad(a1.outputs[0], a1.inputs)
self.failUnless(o.gval0 is g0) self.failUnless(o.gval0 is g0)
self.failUnless(o.gval1 is g1) self.failUnless(o.gval1 is g1)
...@@ -1686,13 +1686,13 @@ class _test_grad(unittest.TestCase): ...@@ -1686,13 +1686,13 @@ class _test_grad(unittest.TestCase):
"""grad: Test returning a single None from grad""" """grad: Test returning a single None from grad"""
o = _test_grad.O() o = _test_grad.O()
a1 = o.make_node() a1 = o.make_node()
self.failUnless(None is exec_grad(a1.outputs[0], a1.outputs[1])) self.failUnless(None is grad(a1.outputs[0], a1.outputs[1]))
self.failUnless(None is exec_grad(a1.outputs[0], 'wtf')) self.failUnless(None is grad(a1.outputs[0], 'wtf'))
def test_NNone_rval(self): def test_NNone_rval(self):
"""grad: Test returning some Nones from grad""" """grad: Test returning some Nones from grad"""
o = _test_grad.O() o = _test_grad.O()
a1 = o.make_node() a1 = o.make_node()
g0,g1,g2 = exec_grad(a1.outputs[0], a1.inputs + ['wtf']) g0,g1,g2 = grad(a1.outputs[0], a1.inputs + ['wtf'])
self.failUnless(o.gval0 is g0) self.failUnless(o.gval0 is g0)
self.failUnless(o.gval1 is g1) self.failUnless(o.gval1 is g1)
self.failUnless(None is g2) self.failUnless(None is g2)
......
...@@ -91,10 +91,8 @@ class _test_dimshuffle_lift(unittest.TestCase): ...@@ -91,10 +91,8 @@ class _test_dimshuffle_lift(unittest.TestCase):
x, y, z = inputs([False]*1, [False]*2, [False]*3) x, y, z = inputs([False]*1, [False]*2, [False]*3)
e = x + y + z e = x + y + z
g = Env([x, y, z], [e]) g = Env([x, y, z], [e])
gof.ExpandMacros().optimize(g)
self.failUnless(str(g) == "[add(InplaceDimShuffle{x,0,1}(add(InplaceDimShuffle{x,0}(x), y)), z)]", str(g)) self.failUnless(str(g) == "[add(InplaceDimShuffle{x,0,1}(add(InplaceDimShuffle{x,0}(x), y)), z)]", str(g))
lift_dimshuffle.optimize(g) lift_dimshuffle.optimize(g)
gof.ExpandMacros().optimize(g)
self.failUnless(str(g) == "[add(add(InplaceDimShuffle{x,x,0}(x), InplaceDimShuffle{x,0,1}(y)), z)]", str(g)) self.failUnless(str(g) == "[add(add(InplaceDimShuffle{x,x,0}(x), InplaceDimShuffle{x,0,1}(y)), z)]", str(g))
......
...@@ -104,9 +104,6 @@ class FunctionFactory: ...@@ -104,9 +104,6 @@ class FunctionFactory:
if not isinstance(r, gof.Result): if not isinstance(r, gof.Result):
raise TypeError("All inputs and outputs to FunctionFactory should be Result instances. Received:", type(r), r) raise TypeError("All inputs and outputs to FunctionFactory should be Result instances. Received:", type(r), r)
env = std_env(inputs, outputs, disown_inputs = disown_inputs) env = std_env(inputs, outputs, disown_inputs = disown_inputs)
gof.ExpandMacros().optimize(env)
#gof.ExpandMacros(lambda node: getattr(node.op, 'level', 0) <= 1).optimize(env)
#gof.ExpandMacros(lambda node: node.op.level == 2).optimize(env)
if None is not optimizer: if None is not optimizer:
optimizer(env) optimizer(env)
env.validate() env.validate()
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import elemwise_cgen as cgen import elemwise_cgen as cgen
import numpy import numpy
from gof import Op, Macro, Apply from gof import Op, Apply
import scalar import scalar
from scalar import Scalar from scalar import Scalar
import gof import gof
......
...@@ -15,15 +15,14 @@ from link import \ ...@@ -15,15 +15,14 @@ from link import \
Linker, LocalLinker, PerformLinker, MetaLinker, Profiler Linker, LocalLinker, PerformLinker, MetaLinker, Profiler
from op import \ from op import \
Op, Macro, Dispatch Op
from opt import \ from opt import \
Optimizer, SeqOptimizer, \ Optimizer, SeqOptimizer, \
MergeOptimizer, MergeOptMerge, \ MergeOptimizer, MergeOptMerge, \
LocalOptimizer, LocalOptGroup, LocalOpKeyOptGroup, \ LocalOptimizer, LocalOptGroup, LocalOpKeyOptGroup, \
ExpandMacro, OpSub, OpRemove, PatternSub, \ OpSub, OpRemove, PatternSub, \
NavigatorOptimizer, TopoOptimizer, OpKeyOptimizer, \ NavigatorOptimizer, TopoOptimizer, OpKeyOptimizer
ExpandMacros
from toolbox import \ from toolbox import \
Bookkeeper, History, Validator, ReplaceValidate, NodeFinder, PrintListener Bookkeeper, History, Validator, ReplaceValidate, NodeFinder, PrintListener
......
...@@ -3,7 +3,7 @@ import unittest ...@@ -3,7 +3,7 @@ import unittest
from type import Type from type import Type
from graph import Result, Apply, Constant from graph import Result, Apply, Constant
from op import Op, Macro from op import Op
from opt import * from opt import *
from env import Env from env import Env
from toolbox import * from toolbox import *
...@@ -364,57 +364,6 @@ class _test_MergeOptimizer(unittest.TestCase): ...@@ -364,57 +364,6 @@ class _test_MergeOptimizer(unittest.TestCase):
reenter = Exception("Re-Entered")
class LoopyMacro(Macro):
def __init__(self):
self.counter = 0
def make_node(self, x, y):
return Apply(self, [x, y], [MyType()()])
def expand(self, node):
x, y = node.inputs
if self.counter > 0:
raise reenter
self.counter += 1
return [self(y, x)]
def __str__(self):
return "loopy_macro"
class _test_ExpandMacro(unittest.TestCase):
def test_straightforward(self):
class Macro1(Macro):
def make_node(self, x, y):
return Apply(self, [x, y], [MyType()()])
def expand(self, node):
return [op1(y, x)]
def __str__(self):
return "macro"
x, y, z = inputs()
e = Macro1()(x, y)
g = Env([x, y], [e])
ExpandMacros().optimize(g)
assert str(g) == "[Op1(y, x)]"
def test_loopy_1(self):
x, y, z = inputs()
e = LoopyMacro()(x, y)
g = Env([x, y], [e])
TopoOptimizer(ExpandMacro(), ignore_newtrees = True).optimize(g)
assert str(g) == "[loopy_macro(y, x)]"
def test_loopy_2(self):
x, y, z = inputs()
e = LoopyMacro()(x, y)
g = Env([x, y], [e])
try:
TopoOptimizer(ExpandMacro(), ignore_newtrees = False).optimize(g)
self.fail("should not arrive here")
except Exception, e:
if e is not reenter:
raise
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
......
...@@ -124,50 +124,3 @@ class Op(utils.object2): ...@@ -124,50 +124,3 @@ class Op(utils.object2):
""" """
raise utils.AbstractFunctionError() raise utils.AbstractFunctionError()
class Macro(Op):
"""
Abstract Op which does not have an implementation but can be expanded
into a computable graph with its expand() method.
"""
def expand(self, node):
"""
Returns a node representing the expansion of this macro.
"""
raise utils.AbstractFunctionError()
class Dispatch(Macro):
"""
Dispatches inputs to one of a list of candidate ops.
Tries each candidate in order.
"""
def __init__(self, name, candidates):
if not isinstance(name, str):
raise TypeError("name should be a string, not:", name, type(name))
self.candidates = candidates
self.name = name
def __node(self, *inputs):
for candidate in self.candidates:
try:
return candidate.make_node(*inputs)
except:
continue
raise TypeError("No suitable candidate found for %s(%s)" % (self, inputs))
def make_node(self, *inputs):
node = self.__node(*inputs)
node.op = self
return node
def expand(self, node):
return self.__node(*node.inputs)
def __str__(self):
return self.name
...@@ -214,20 +214,6 @@ class LocalOpKeyOptGroup(LocalOptGroup): ...@@ -214,20 +214,6 @@ class LocalOpKeyOptGroup(LocalOptGroup):
return [opt.op_key() for opt in self.opts] return [opt.op_key() for opt in self.opts]
class ExpandMacro(LocalOptimizer):
def __init__(self, filter = None):
if filter is None:
self.filter = lambda node: True
else:
self.filter = filter
def transform(self, node):
if not isinstance(node.op, op.Macro) or not self.filter(node):
return False
return node.op.expand(node)
class OpSub(LocalOptimizer): class OpSub(LocalOptimizer):
""" """
Replaces the application of a certain op by the application of Replaces the application of a certain op by the application of
...@@ -561,12 +547,3 @@ class OpKeyOptimizer(NavigatorOptimizer): ...@@ -561,12 +547,3 @@ class OpKeyOptimizer(NavigatorOptimizer):
def keep_going(exc, nav, repl_pairs): def keep_going(exc, nav, repl_pairs):
pass pass
##############################
### Pre-defined optimizers ###
##############################
def ExpandMacros(filter = None):
return TopoOptimizer(ExpandMacro(filter = filter),
order = 'in_to_out',
ignore_newtrees = False)
...@@ -169,7 +169,6 @@ def make_default_pp(): ...@@ -169,7 +169,6 @@ def make_default_pp():
pp.assign(T.pow, ppow) pp.assign(T.pow, ppow)
pp.assign(T.dot, pdot) pp.assign(T.dot, pdot)
pp.assign(T.Sum(), FunctionPrinter('sum')) pp.assign(T.Sum(), FunctionPrinter('sum'))
pp.assign(T.grad, FunctionPrinter('d'))
pp.assign(lambda pstate, r: r.owner and isinstance(r.owner.op, T.DimShuffle), DimShufflePrinter()) pp.assign(lambda pstate, r: r.owner and isinstance(r.owner.op, T.DimShuffle), DimShufflePrinter())
return pp return pp
......
...@@ -1142,19 +1142,7 @@ gemm = Gemm() ...@@ -1142,19 +1142,7 @@ gemm = Gemm()
# Gradient # Gradient
######################### #########################
class Grad(gof.Macro): def grad(cost, wrt, g_cost=None):
level = 2
def make_node(self, cost, wrt):
if not isinstance(wrt, list):
wrt = [wrt]
return Apply(self, [cost] + wrt, [_wrt.type() for _wrt in wrt])
def expand(self, node):
cost, wrt = node.inputs[0], node.inputs[1:]
g = exec_grad(cost, wrt)
return g
grad = Grad()
def exec_grad(cost, wrt, g_cost=None):
""" """
@type cost: L{Result} @type cost: L{Result}
@type wrt: L{Result} or list of L{Result}s. @type wrt: L{Result} or list of L{Result}s.
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论