Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
8 changes: 8 additions & 0 deletions python/paddle/wrapper_demo/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import logging
import paddle.v2.framework.core as core

logger = logging.getLogger("paddle")
logger.setLevel(logging.INFO)

g_scope = core.Scope()
g_device = core.CPUPlace()
30 changes: 30 additions & 0 deletions python/paddle/wrapper_demo/demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# all the layer, op namespace are imported into pd for short
# the old absolute path should also work
# for example, pd.data -> paddle.layer.data
import paddle.v2 as pd

images = pd.data(name='pixe', type=pd.dense_vector(784))

label = pd.data(name='label', type=pd.integer_value(10))

prediction = pd.fc(input=images, size=10, act=...)
cost = pd.cross_entropy(prediction, label)

optimizer = pd.Momentum(...)

# following are different styles should supported

# v2 style, seems that hard to support multiple sub-model
parameters = pd.parameters.create(cost)
trainer = pd.SGD(cost=[cost], parameters=parameters, update_equation=optimizer)
trainer.train(reader=..., num_passes=5)

# style with new features borrowed from tf and pytorch
trainer = pd.SGD()
trainer.init_parameters()
# train a sub-model if there has more than one sub-models has different costs like gan
trainer.train(targets=[cost], update_equation=optimizer, reader=...)

# just forward run is supported
# borrowed from tf, forward run a sub-model whose end point is targets
#trainer.run(targets=[cost], reader=...)
28 changes: 28 additions & 0 deletions python/paddle/wrapper_demo/layer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from var import Var
from op import add_two, mul


class Layer(object):
def __init__(self):
self.name = 'layer'


class FC(layer):
def __init__(self, name=None):
self.type = "fc"

def __call__(self, input, size):
assert isinstance(input, Var)
self.input = input
mul_res = mul(input, self.W)
return mul_res

def _create_param(self):
self.W = Var(shape=self.input.shape)


class data(layer):
pass


fc = FC()
Empty file.
94 changes: 94 additions & 0 deletions python/paddle/wrapper_demo/op.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
'''
implementation of all the operators' python wrapper
'''
import paddle.v2.framework.core as core
from paddle.v2.framework.op import Operator
from session import g_session

from var import Var, PVar


class Op(object):
'''
NOTE both op's inputs and outputs are Var
usage:

out0, out1 = op(in0, in1, attr=attr0)
'''

def __init__(self, type):
self.type = type
# input vars
self.inputs = {}
# output vars
self.outputs = {}

def __call__(self, *args, **kwargs):
'''
get inputs and output outputs
'''
self._prepare_inputs(args, kwargs)
self._prepare_outputs()
str_arg = {}
# extract string name from Var
for k, v in self.inputs.items():
str_arg[k] = v.name if isinstance(v, Var) or isinstance(v,
PVar) else v
for k, v in self.outputs.items():
str_arg[k] = v.name

self.op = Operator(self.type, **str_arg)
self.hash_str = self._gen_hash(str_arg)

g_session.add_op(self)

def _prepare_outputs(self):
for out in Operator.get_op_output_names(self.type):
name = "%s-%d" % (out, Var.count)
var = Var(name)
self.outputs[name] = var

def _prepare_inputs(self, args, kwargs):
for idx, input_name in enumerate(
Operator.get_op_input_names(self.type)):
print 'input_name', input_name
if idx > len(args):
self.inputs[input_name] = kwargs[input_name]
continue
self.inputs[input_name] = args[idx]
for k, v in kwargs.items():
self.inputs[k] = v

def _gen_hash(self, str_arg):
'''
generate a hashkey for this op
'''
return hash("%s-%s" % (self.type, str_arg))

def __str__(self):
return "<Op {name}:\nInputs:{inputs}\nOutputs:{outputs}\n>".format(
name=self.hash_str,
inputs='\n -'.join(repr(v) for v in self.inputs),
outputs='\n -'.join(repr(v) for v in self.outputs), )

def __repr__(self):
return "<Op %s %d>" % (self.type, self.hash_str)


sgd = Op("sgd")
add_two = Op("add_two")
mul = Op("mul")
mean = Op("mean")
mul = Op("mul")
rowwise_add = Op("rowwise_add")
sigmoid = Op("sigmoid")
softmax = Op("softmax")
gaussian = Op("gaussian")
cross_entropy = Op("cross_entropy")
fill_zeros_like = Op("fill_zeros_like")
uniform_random = Op("uniform_random")

if __name__ == '__main__':
in0 = Var(shape=[10, 20])
in1 = Var(shape=[10, 20])
out = add_two(in0, in1)
71 changes: 71 additions & 0 deletions python/paddle/wrapper_demo/session.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
'''
session stores all the vars, ops for topology alalysis.
'''
from common import logger, g_scope, g_device
from topology import Topology
import paddle.v2.framework.core as core


class Session(object):
'''
NOTE this maybe renamed to Context, but it acts like tf.Session
only one Session is needed, so it maybe hiddened from user.
'''

def __init__(self, scope=g_scope, device=g_device):
self.ops = {}
self.vars = {}

self.scope = scope
self.device = device
self.topology = Topology(self)

def add_var(self, var):
'''
register a var in the context
'''
logger.info('register a var %s' % repr(var))
assert repr(var) not in self.vars
self.vars[repr(var)] = var

def add_op(self, op):
'''
register a op in the context
'''
logger.info('register an op %s' % repr(op))
assert repr(op) not in self.ops
self.ops[repr(op)] = op

def run(self, targets=[], need_backward=False):
'''
just run a sub-graph, compatible with paddle.infer
'''
self.topology.build()
visited_nodes = self.topology.DFS_to_targets(targets)
ops = filter(lambda _: _.startswith('<Op'), visited_nodes)

# create a core.Net
net = core.Net.create()
for op in ops:
core_op = op.op
net.add(core_op)
net.complete_add_op(True)

ctx = core.DeviceContext.create(self.device)
net.infer_shape(self.scope)
net.run(self.scope, ctx)

def deserialize(self, str):
'''
to load
'''
pass

def serialize(self):
pass

def __str__(self):
pass


g_session = Session()
70 changes: 70 additions & 0 deletions python/paddle/wrapper_demo/topology.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
class Graph(object):
def __init__(self):
# node : str
# targets: list
self.edges = {}

def add(self, op, reverse=False):
'''
add edges according to op's inputs and outputs
'''
sources = op.inputs if not reverse else op.outputs
targets = op.outputs if not reverse else op.inputs
for var in sources:
key = repr(var)
if key not in self.edges:
self.edges[key] = []
self.edges[key] += [repr(op)]
for var in targets:
key = repr(op)
if key not in self.edges:
self.edges[key] = []
self.edges[key] += [repr(var) for var in op.outputs]

def __str__(self):
pass


class Topology(object):
'''
graph generator
'''

def __init__(self, session):
self.session = session
self.graph = Graph()
self.reverse_graph = Graph()

def build(self):
self._create_graph()
self._create_reverse_graph()

def _create_graph(self):
for op in self.session.ops:
self.graph.add(op)

def _create_reverse_graph(self, graph):
for op in self.session.ops:
self.graph.add(op, reverse=True)

def DFS_to_targets(self, targets=[]):
'''
@targets: list of Val
return: reprs of vars and ops
'''
visited_set = set()
visited_nodes = []

# use reverse graph, the targets as the start points
# get the sequence visited, reverse it and return

stack = targets
cur = None
for target in targets:
while stack:
cur = stack.pop()
if cur not in visited_set:
visited_set.add(cur)
visited_nodes.append(cur)
stack.extend(self.graph.edges[cur])
return list(reversed(visited_nodes))
24 changes: 24 additions & 0 deletions python/paddle/wrapper_demo/trainer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from session import g_session


class SGD(object):
def __init__(self, cost, parameters, update_equatio, session=g_session):
self.session = session
self.cost = cost

def init_parameters(self):
'''
# borrowed from tf, no need to expose parameters.create outside
'''
pass

def train(self, reader, event_hander, num_passes, targets=None):
if not targets:
targets = [cost]
self.session.run(targets, need_backward=True)

def run(self, reader, targets):
'''
run a sub-graph
'''
self.session.run(targets)
3 changes: 3 additions & 0 deletions python/paddle/wrapper_demo/v2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from op import *
from var import *
from session import *
Loading