def test_grad(self):
        place = core.CPUPlace()
        program = Program()

        with program_guard(program):
            x = layers.data(
                name='x', shape=[1], dtype='float32', stop_gradient=False)
            table = layers.lod_rank_table(x, level=0)
            array = layers.lod_tensor_to_array(x, table)
            result = layers.array_to_lod_tensor(array, table)

            mean = layers.mean(result)

            append_backward(mean)

        tensor = core.LoDTensor()
        tensor.set(numpy.arange(10).reshape(10, 1).astype('float32'), place)
        tensor.set_lod([[0, 3, 9, 10]])

        g_vars = program.global_block().var(x.name + "@GRAD")

        exe = Executor(place)
        g_out = [
            numpy.array(item).sum()
            for item in exe.run(program,
                                feed={'x': tensor},
                                fetch_list=[g_vars],
                                return_numpy=False)
        ]
        g_out_sum = numpy.array(g_out).sum()

        self.assertAlmostEqual(1.0, g_out_sum, delta=0.1)
Example #2
0
    def test_op_desc_creation(self):
        program = Program()
        block = program.current_block()
        mul_x = block.create_var(
            dtype="float32", shape=[5, 10], lod_level=0, name="mul.x")
        mul_y = block.create_var(
            dtype="float32", shape=[10, 8], lod_level=0, name="mul.y")
        mul_out = block.create_var(
            dtype="float32", shape=[5, 8], lod_level=0, name="mul.out")
        mul_op = block.append_op(
            type="mul",
            inputs={"X": [mul_x],
                    "Y": mul_y},
            outputs={"Out": [mul_out]},
            attrs={"x_num_col_dims": 1})

        self.assertNotEqual(str(mul_op), "")
        self.assertEqual(mul_op.type, "mul")
        self.assertEqual(mul_op.input_names, ["X", "Y"])
        self.assertEqual(mul_op.input("X"), ["mul.x"])
        self.assertEqual(mul_op.input("Y"), ["mul.y"])
        self.assertEqual(mul_op.output_names, ["Out"])
        self.assertEqual(mul_op.output("Out"), ["mul.out"])
        self.assertEqual(
            set(mul_op.attr_names),
            set(["x_num_col_dims", "y_num_col_dims", "op_role", "op_role_var"]))
        self.assertEqual(mul_op.has_attr("x_num_col_dims"), True)
        self.assertEqual(mul_op.attr_type("x_num_col_dims"), core.AttrType.INT)
        self.assertEqual(mul_op.attr("x_num_col_dims"), 1)
        self.assertEqual(mul_op.has_attr("y_num_col_dims"), True)
        self.assertEqual(mul_op.attr_type("y_num_col_dims"), core.AttrType.INT)
        self.assertEqual(mul_op.attr("y_num_col_dims"), 1)
        self.assertEqual(mul_op.idx, 0)
        self.assertEqual(mul_out.op, mul_op)
Example #3
0
    def test_debug_str(self):
        p = Program()
        b = p.current_block()

        #selected_rows
        b.create_var(
            name='selected_rows',
            dtype="float32",
            shape=[5, 10],
            type=core.VarDesc.VarType.SELECTED_ROWS)

        #tensor array
        b.create_var(
            name='tensor_array',
            shape=[5, 10],
            type=core.VarDesc.VarType.LOD_TENSOR_ARRAY)

        #operator
        mul_x = b.create_parameter(
            dtype="float32", shape=[5, 10], lod_level=0, name="mul.x")
        mul_y = b.create_var(
            dtype="float32", shape=[10, 8], lod_level=0, name="mul.y")
        mul_out = b.create_var(
            dtype="float32", shape=[5, 8], lod_level=0, name="mul.out")
        b.append_op(
            type="mul",
            inputs={"X": mul_x,
                    "Y": mul_y},
            outputs={"Out": mul_out},
            attrs={"x_num_col_dims": 1})

        print(debugger.pprint_program_codes(p))

        debugger.draw_block_graphviz(p.block(0), path="./test.dot")
Example #4
0
    def _calc_output(self, place):
        op_proto = OpProtoHolder.instance().get_op_proto(self.op_type)

        program = Program()
        block = program.global_block()

        inputs = append_input_output(block, op_proto, self.inputs, True)
        outputs = append_input_output(block, op_proto, self.outputs, False)
        op = block.append_op(
            type=self.op_type,
            inputs=inputs,
            outputs=outputs,
            attrs=self.attrs if hasattr(self, "attrs") else dict())
        # infer variable type and infer shape in compile-time
        op.desc.infer_var_type(block.desc)
        op.desc.infer_shape(block.desc)

        fetch_list = []
        for var_name, var in outputs.iteritems():
            if var_name in self.outputs:
                if isinstance(var, list):
                    for v in var:
                        fetch_list.append(v)
                else:
                    fetch_list.append(var)

        feed_map = self.feed_var(inputs, place)

        exe = Executor(place)
        outs = exe.run(program,
                       feed=feed_map,
                       fetch_list=fetch_list,
                       return_numpy=False)
        return outs, fetch_list
Example #5
0
    def test_program_clone_with_parameter(self):
        main_program = Program()
        startup_program = Program()
        with program_guard(main_program, startup_program):
            d = layers.data(name='x', shape=[784], dtype='float32')
            hidden = layers.fc(input=d, size=100)
            layers.fc(input=hidden, size=100)

        new_program = main_program.clone()
        self.assertNotEqual(0, len(new_program.blocks[0].all_parameters()))
Example #6
0
def get_parameter_value(para, executor):
    """
    Get the LoDTensor for the parameter

    :param executor: executor for retrieving the value
    :param para: the given parameter

    :return: the LoDTensor for the parameter
    """
    assert is_parameter(para)

    get_program = Program()
    block = get_program.global_block()
    new_var = _clone_var_in_block_(block, para)
    return executor.run(get_program, feed={}, fetch_list=[new_var])[0]
class TestShrinkRNNMemoryBase(unittest.TestCase):
    def setUp(self):
        self.main_program = Program()
        switch_main_program(self.main_program)
        x = layers.data('x', shape=[100], dtype='float32')
        x.stop_gradient = False
        rank_table_tensor = layers.data(
            'rank_table_tensor', shape=[1], dtype='float32', lod_level=1)
        table = layers.lod_rank_table(x=rank_table_tensor)
        i = layers.zeros(dtype='int64', shape=[1])
        self.mem1 = layers.shrink_memory(x=x, i=i, table=table)
        i = layers.increment(x=i)
        i.stop_gradient = True
        self.mem2 = layers.shrink_memory(x=self.mem1, i=i, table=table)
        i = layers.increment(x=i)
        i.stop_gradient = True
        self.mem3 = layers.shrink_memory(x=self.mem2, i=i, table=table)
        mem3_mean = layers.mean(self.mem3)
        append_backward(loss=mem3_mean)
        self.x_grad = self.main_program.global_block().var('x@GRAD')

    def sum_lodtensor(self, tensor):
        sum_res = 0.0
        for i in xrange(np.product(tensor.get_dims())):
            sum_res += tensor.get_float_element(i)
        return sum_res
Example #8
0
 def setup_program(self):
     self.main_program = Program()
     self.startup_program = Program()
     self.p_info = {
         "main_program": self.main_program,
         "startup_program": self.startup_program
     }
     self.place = core.CPUPlace()
Example #9
0
 def test_hsigmoid(self):
     program = Program()
     with program_guard(program):
         x = layers.data(name='x', shape=[2], dtype='float32')
         y = layers.data(name='y', shape=[2], dtype='int64')
         self.assertIsNotNone(
             layers.hsigmoid(
                 input=x, label=y, num_classes=2))
     print(str(program))
Example #10
0
 def test_sigmoid_cross_entropy(self):
     program = Program()
     with program_guard(program):
         dat = layers.data(name='data', shape=[10], dtype='float32')
         lbl = layers.data(name='label', shape=[10], dtype='float32')
         self.assertIsNotNone(
             layers.sigmoid_cross_entropy_with_logits(
                 x=dat, label=lbl))
     print(str(program))
Example #11
0
 def test_label_smooth(self):
     program = Program()
     with program_guard(program):
         label = layers.data(name="label", shape=[1], dtype="float32")
         one_hot_label = layers.one_hot(input=label, depth=10)
         smooth_label = layers.label_smooth(
             label=one_hot_label, epsilon=0.1, dtype="float32")
         self.assertIsNotNone(smooth_label)
     print(str(program))
Example #12
0
def _save_lookup_tables_by_notify(executor, dirname, lookup_table,
                                  pserver_endpoints):
    """
    This function will send checkpoint notify message from Trainer 0
    to all the pservers.
    The checkpoint notify message contains lookup table name,
    the absolute path on pserver to save lookup_table.

    Args:
        executor(Executor): The executor to run for send checkpoint notify.
        dirname(str): The folder where to save.
        lookup_table(string): the lookup table name, when use distribute
            lookup table, we can get lookup table name by DistributeTranspiler.
            table_name
        ps_endpoint_list(list): the parameter server ip:port list.
            when use distribute lookup table, we can get ps_endpoint_list by
            distribute arguments.
    Return:
        None

    Examples:
        .. code-block:: python

            exe = fluid.Executor(fluid.CPUPlace())
            param_path = "./my_paddle_model"
            table_name = "share_w"
            ps_endpoints = ["127.0.0.1:6000","127.0.0.1:6001"]

            _save_pserver_vars_by_notify(executor=exe,
                    dirname=param_path, lookup_table=table_name,
                    pserver_endpoints=ps_endpoints)
    """

    pserver_notify_program = Program()
    pserver_notify_block = pserver_notify_program.global_block()

    attrs = {}
    attrs['epmap'] = pserver_endpoints
    attrs['dir'] = dirname
    attrs['lookup_table'] = lookup_table

    pserver_notify_block.append_op(
        type='checkpoint_notify', inputs={}, outputs={}, attrs=attrs)
    executor.run(pserver_notify_program)
 def setUp(self):
     self._delta = 0.005
     self._max_sequence_len = 3
     self._program = Program()
     switch_main_program(self._program)
     self.output_dim = 10
     self.place = core.CPUPlace()
     self.prepare_x_tensor()
     self.prepare_static_input_tensor()
     self.exe = fluid.Executor(self.place)
Example #14
0
    def test_remove_op(self):
        program = Program()
        program_desc = program.desc
        self.assertIsNotNone(program_desc)
        block = program_desc.block(0)
        self.assertIsNotNone(block)

        op0 = block.append_op()
        op1 = block.append_op()
        op2 = block.append_op()
        op0.set_type("test")
        op1.set_type("test")
        op2.set_type("test")

        block.remove_op(1, 2)
        program.sync_with_cpp()

        all_ops = []
        for idx in xrange(0, block.op_size()):
            all_ops.append(block.op(idx))
        self.assertEqual(all_ops, [op0, op2])
Example #15
0
 def test_mult_input(self):
     program = Program()
     block = program.current_block()
     sum_x1 = block.create_var(
         dtype="int", shape=[3, 4], lod_level=0, name="sum.x1")
     sum_x2 = block.create_var(
         dtype="int", shape=[3, 4], lod_level=0, name="sum.x2")
     sum_x3 = block.create_var(
         dtype="int", shape=[3, 4], lod_level=0, name="sum.x3")
     sum_out = block.create_var(
         dtype="int", shape=[3, 4], lod_level=0, name="sum.out")
     sum_op = block.append_op(
         type="sum",
         inputs={"X": [sum_x1, sum_x2, sum_x3]},
         outputs={"Out": sum_out})
     self.assertEqual(sum_op.type, "sum")
     self.assertEqual(sum_op.input_names, ["X"])
     self.assertEqual(sum_op.input("X"), ["sum.x1", "sum.x2", "sum.x3"])
     self.assertEqual(sum_op.output_names, ["Out"])
     self.assertEqual(sum_op.output("Out"), ["sum.out"])
     self.assertEqual(sum_op.idx, 0)
     self.assertEqual(sum_out.op, sum_op)
Example #16
0
    def test_check_output(self):
        program = Program()
        with program_guard(program):
            x = fluid.layers.data(
                name='x', shape=[self.dimension], dtype='float32', lod_level=1)
            block = program.current_block()
            one_hot_out = block.create_var(
                name="one_hot_out",
                type=core.VarDesc.VarType.LOD_TENSOR,
                dtype='float32')
            block.append_op(
                type='one_hot',
                inputs={'X': x},
                attrs={'depth': self.depth},
                outputs={'Out': one_hot_out})
            exe = fluid.Executor(self.place)

            def run():
                exe.run(feed={'x': self.x},
                        fetch_list=[one_hot_out],
                        return_numpy=False)

            self.assertRaises(core.EnforceNotMet, run)
Example #17
0
def load_inference_model(dirname,
                         executor,
                         model_filename=None,
                         params_filename=None):
    """
    Load inference model from a directory

    :param dirname: directory path
    :param executor: executor that load inference model
    :param model_filename: The name of file to load inference program.
        If not specified, default filename `__model__` will be used.
    :param params_filename: The name of file to load parameters.
        It is used for the case that all parameters are saved in a single binary file.
        If not specified, parameters are considered saved in separate files.

    :return: [program, feed_target_names, fetch_targets]
             program: program especially for inference.
             feed_target_names: Names of variables that need to feed data
             fetch_targets: Variables from which we can get inference results.
    """
    if not os.path.isdir(dirname):
        raise ValueError("There is no directory named '%s'", dirname)

    if model_filename is not None:
        model_filename = os.path.basename(model_filename)
    else:
        model_filename = "__model__"
    model_filename = os.path.join(dirname, model_filename)

    if params_filename is not None:
        params_filename = os.path.basename(params_filename)

    with open(model_filename, "rb") as f:
        program_desc_str = f.read()

    program = Program.parse_from_string(program_desc_str)
    load_persistables(executor, dirname, program, params_filename)

    feed_target_names = program.desc.get_feed_target_names()
    fetch_target_names = program.desc.get_fetch_target_names()
    fetch_targets = [
        program.global_block().var(name) for name in fetch_target_names
    ]

    return [program, feed_target_names, fetch_targets]
Example #18
0
    def test_program_clone(self):
        prog = Program()

        x = prog.global_block().create_var(
            name='X', shape=[1000, 784], dtype='float32')

        y = prog.global_block().create_var(
            name='Y', shape=[784, 100], dtype='float32')
        out = prog.global_block().create_var(name='Out', dtype='float32')
        prog.global_block().append_op(
            type="mul", inputs={'X': [x],
                                'Y': [y]}, outputs={'Out': [out]})

        # FIXME(yuyang18): We manual compare the output string, since the order
        # of variable could be changed.
        print(prog)
        print(prog.clone())
 def setUp(self):
     self.main_program = Program()
     switch_main_program(self.main_program)
     x = layers.data('x', shape=[100], dtype='float32')
     x.stop_gradient = False
     rank_table_tensor = layers.data(
         'rank_table_tensor', shape=[1], dtype='float32', lod_level=1)
     table = layers.lod_rank_table(x=rank_table_tensor)
     i = layers.zeros(dtype='int64', shape=[1])
     self.mem1 = layers.shrink_memory(x=x, i=i, table=table)
     i = layers.increment(x=i)
     i.stop_gradient = True
     self.mem2 = layers.shrink_memory(x=self.mem1, i=i, table=table)
     i = layers.increment(x=i)
     i.stop_gradient = True
     self.mem3 = layers.shrink_memory(x=self.mem2, i=i, table=table)
     mem3_mean = layers.mean(self.mem3)
     append_backward(loss=mem3_mean)
     self.x_grad = self.main_program.global_block().var('x@GRAD')
Example #20
0
    def test_parse_program_from_string(self):
        prog = Program()

        x = prog.global_block().create_var(
            name='X', shape=[1000, 784], dtype='float32')

        y = prog.global_block().create_var(
            name='Y', shape=[784, 100], dtype='float32')
        out = prog.global_block().create_var(name='Out', dtype='float32')
        prog.global_block().append_op(
            type="mul", inputs={'X': [x],
                                'Y': [y]}, outputs={'Out': [out]})

        binary_str = prog.desc.serialize_to_string()
        prog_restored = Program.parse_from_string(binary_str)

        print(prog)
        print(prog_restored)
Example #21
0
def save_vars(executor,
              dirname,
              main_program=None,
              vars=None,
              predicate=None,
              filename=None):
    """
    Save variables to directory by executor.

    :param executor: executor that save variable
    :param dirname: directory path
    :param main_program: program. If vars is None, then filter all variables in this
    program which fit `predicate`. Default default_main_program.
    :param predicate: The Predicate describes a callable that returns a variable
    as a bool. If it returns true, the corresponding input variable will be saved.
    :param vars: variables need to be saved. If vars is specified, program & predicate
    will be ignored
    :param filename: The name of a single file that all vars are saved to.
        If it is None, save variables to separate files.

    :return: None
    """
    if vars is None:
        if main_program is None:
            main_program = default_main_program()
        if not isinstance(main_program, Program):
            raise TypeError("program should be as Program type or None")

        save_vars(
            executor,
            dirname=dirname,
            vars=filter(predicate, main_program.list_vars()),
            filename=filename)
    else:
        save_program = Program()
        save_block = save_program.global_block()

        save_var_map = {}
        for each_var in vars:
            # NOTE: don't save the variable which type is RAW
            if each_var.type == core.VarDesc.VarType.RAW:
                continue
            new_var = _clone_var_in_block_(save_block, each_var)
            if filename is None:
                save_block.append_op(
                    type='save',
                    inputs={'X': [new_var]},
                    outputs={},
                    attrs={'file_path': os.path.join(dirname, new_var.name)})
            else:
                save_var_map[new_var.name] = new_var

        if filename is not None:
            save_var_list = []
            for name in sorted(save_var_map.keys()):
                save_var_list.append(save_var_map[name])

            save_block.append_op(
                type='save_combine',
                inputs={'X': save_var_list},
                outputs={},
                attrs={'file_path': os.path.join(dirname, filename)})

        executor.run(save_program)
Example #22
0
 def test_step_scopes(self):
     prog = Program()
     b = prog.current_block()
     var = b.create_var(
         name='step_scopes', type=core.VarDesc.VarType.STEP_SCOPES)
     self.assertEqual(core.VarDesc.VarType.STEP_SCOPES, var.type)
Example #23
0
def load_vars(executor,
              dirname,
              main_program=None,
              vars=None,
              predicate=None,
              filename=None):
    """
    Load variables from directory by executor.

    :param executor: executor that load variable
    :param dirname: directory path
    :param main_program: program. If vars is None, then filter all variables in this
    program which fit `predicate`. Default default_main_program().
    :param predicate: The Predicate describes a callable that returns a variable
    as a bool. If it returns true, the corresponding input variable will be loaded.
    :param vars: variables need to be loaded. If vars is specified, program &
    predicate will be ignored
    :param filename: The name of the single file that all vars are loaded from.
        If it is None, load variables from separate files.

    :return: None
    """
    if vars is None:
        if main_program is None:
            main_program = default_main_program()
        if not isinstance(main_program, Program):
            raise TypeError("program's type should be Program")

        load_vars(
            executor,
            dirname=dirname,
            vars=filter(predicate, main_program.list_vars()),
            filename=filename)
    else:
        load_prog = Program()
        load_block = load_prog.global_block()

        load_var_map = {}
        for each_var in vars:
            assert isinstance(each_var, Variable)
            if each_var.type == core.VarDesc.VarType.RAW:
                continue
            new_var = _clone_var_in_block_(load_block, each_var)
            if filename is None:
                load_block.append_op(
                    type='load',
                    inputs={},
                    outputs={'Out': [new_var]},
                    attrs={'file_path': os.path.join(dirname, new_var.name)})
            else:
                load_var_map[new_var.name] = new_var

        if filename is not None:
            load_var_list = []
            for name in sorted(load_var_map.keys()):
                load_var_list.append(load_var_map[name])

            load_block.append_op(
                type='load_combine',
                inputs={},
                outputs={"Out": load_var_list},
                attrs={'file_path': os.path.join(dirname, filename)})

        executor.run(load_prog)
Example #24
0
class RecurrentOpTest1(unittest.TestCase):
    '''
    Test RNNOp
    equation:
        h_t = ( x_t + h_{t-1} ) / scale
    vars:
        - x
    memories:
        - h
    outputs:
        - h
    '''

    input_dim = 2
    batch_size = 1
    sent_len = 1

    def setup_program(self):
        self.main_program = Program()
        self.startup_program = Program()
        self.p_info = {
            "main_program": self.main_program,
            "startup_program": self.startup_program
        }
        self.place = core.CPUPlace()

    def setUp(self):
        self.setup_program()
        self.data_field = {"x", "h_boot"}

        self.input_shape = (self.sent_len, self.batch_size, self.input_dim)
        self.output_shape = (self.sent_len, self.batch_size, self.input_dim)
        self.py_rnn = PySimpleRNN1(self.input_shape, self.output_shape)

        self.output = layers.mean(self.create_rnn_op(), **self.p_info)

    def create_rnn_op(self):
        x = layers.data(
            shape=[self.sent_len, self.batch_size, self.input_dim],
            dtype='float32',
            name='x',
            append_batch_size=False,
            **self.p_info)
        x.stop_gradient = False
        h_boot = layers.data(
            shape=[self.input_dim],
            dtype='float32',
            name='h_boot',
            **self.p_info)
        h_boot.stop_gradient = False

        rnn = layers.StaticRNN(main_program=self.main_program)
        with rnn.step():
            h_pre = rnn.memory(init=h_boot)
            x_t = rnn.step_input(x)

            h = layers.scale(
                x=layers.elementwise_add(
                    x=h_pre, y=x_t, **self.p_info),
                scale=self.py_rnn.scale,
                **self.p_info)

            rnn.update_memory(h_pre, h)
            rnn.output(h)

        return rnn()

    def forward(self):
        self.feed_map = {
            x: create_tensor(getattr(self.py_rnn, x), self.place)
            for x in self.data_field
        }
        exe = Executor(self.place)
        out = exe.run(self.main_program,
                      feed=self.feed_map,
                      fetch_list=[self.output])

        return out[0]

    def backward(self):
        self.feed_map = {
            x: create_tensor(getattr(self.py_rnn, x), self.place)
            for x in self.data_field
        }
        fetch_list = [
            self.main_program.global_block().var(grad_var_name(x))
            for x in self.data_field
        ]

        exe = Executor(self.place)
        return exe.run(self.main_program,
                       feed=self.feed_map,
                       fetch_list=fetch_list,
                       return_numpy=False)

    def test_backward(self):
        self.check_forward()

        append_backward(self.output)

        ana_grad = [np.array(x) for x in self.backward()]

        num_grad = self.get_numerical_gradient()
        for idx, name in enumerate(self.data_field):
            self.assertEqual(num_grad[idx].shape, ana_grad[idx].shape)
            self.assertTrue(
                np.isclose(
                    num_grad[idx], ana_grad[idx], rtol=0.1).all())

    def check_forward(self):
        print 'test recurrent op forward'
        pd_output = self.forward()
        py_output = self.py_rnn.forward()
        print 'pd_output', pd_output
        print
        print 'py_output', py_output
        self.assertEqual(pd_output.shape, py_output.shape)
        self.assertTrue(np.isclose(pd_output, py_output, rtol=0.1).all())

    def get_numerical_gradient(self, delta=0.005):
        dloss_dout = 1.0
        feed_list = [getattr(self.py_rnn, x) for x in self.data_field]
        grad_list = [np.zeros_like(x) for x in feed_list]
        for feed, grad in zip(feed_list, grad_list):
            for f, g in np.nditer([feed, grad], op_flags=['readwrite']):
                o = float(f)
                f[...] = o + delta
                y_pos = self.forward()

                f[...] = o - delta
                y_neg = self.forward()

                f[...] = o
                dout_dfeed = (y_pos - y_neg) / (delta * 2)
                g[...] = dout_dfeed[0]

        return grad_list
class TestDyRnnStaticInput(unittest.TestCase):
    def setUp(self):
        self._delta = 0.005
        self._max_sequence_len = 3
        self._program = Program()
        switch_main_program(self._program)
        self.output_dim = 10
        self.place = core.CPUPlace()
        self.prepare_x_tensor()
        self.prepare_static_input_tensor()
        self.exe = fluid.Executor(self.place)

    def prepare_x_tensor(self):
        self.x_tensor_dim = 10
        lod = [[0, 2, 3, 6]]
        shape = [lod[0][-1], self.x_tensor_dim]
        self.x_tensor_data = np.random.random(shape).astype('float32')
        self.x_tensor = core.LoDTensor()
        self.x_tensor.set_lod(lod)
        self.x_tensor.set(self.x_tensor_data, self.place)

    def prepare_static_input_tensor(self):
        self.static_input_tensor_dim = 4
        lod = [[0, 1, 3, 6]]
        shape = [lod[0][-1], self.static_input_tensor_dim]
        self.static_input_data = np.random.random(shape).astype('float32')
        self.static_input_tensor = core.LoDTensor()
        self.static_input_tensor.set_lod(lod)
        self.static_input_tensor.set(self.static_input_data, self.place)

    def fetch_value(self, var):
        fetch_outs = self.exe.run(feed={
            'x_tensor': self.x_tensor,
            'static_input_tensor': self.static_input_tensor
        },
                                  fetch_list=[var],
                                  return_numpy=False)
        return self._lodtensor_to_ndarray(fetch_outs[0])

    def _lodtensor_to_ndarray(self, lod_tensor):
        dims = lod_tensor.get_dims()
        ndarray = np.zeros(shape=dims).astype('float32')
        for i in xrange(np.product(dims)):
            ndarray.ravel()[i] = lod_tensor.get_float_element(i)
        return ndarray, lod_tensor.lod()

    def build_graph(self, only_forward=False):
        x_tensor = fluid.layers.data(
            name='x_tensor',
            shape=[self.x_tensor_dim],
            dtype='float32',
            lod_level=1)
        x_tensor.stop_gradient = False

        static_input_tensor = fluid.layers.data(
            name='static_input_tensor',
            shape=[self.static_input_tensor_dim],
            dtype='float32',
            lod_level=1)
        static_input_tensor.stop_gradient = False

        if only_forward:
            static_input_out_array = self._program.global_block().create_var(
                name='static_input_out_array',
                type=core.VarDesc.VarType.LOD_TENSOR_ARRAY,
                dtype='float32')
            static_input_out_array.stop_gradient = True

        rnn = fluid.layers.DynamicRNN()
        with rnn.block():
            step_x = rnn.step_input(x_tensor)
            step_static_input = rnn.static_input(static_input_tensor)
            if only_forward:
                fluid.layers.array_write(
                    x=step_static_input,
                    i=rnn.step_idx,
                    array=static_input_out_array)
            last = fluid.layers.sequence_pool(
                input=step_static_input, pool_type='last')
            projected = fluid.layers.fc(input=[step_x, last],
                                        size=self.output_dim)
            rnn.output(projected)

        if only_forward:
            static_input_step_outs = []
            step_idx = fluid.layers.fill_constant(
                shape=[1], dtype='int64', value=0)
            step_idx.stop_gradient = True

            for i in xrange(self._max_sequence_len):
                step_out = fluid.layers.array_read(static_input_out_array,
                                                   step_idx)
                step_out.stop_gradient = True
                static_input_step_outs.append(step_out)
                fluid.layers.increment(x=step_idx, value=1.0, in_place=True)

        if only_forward:
            return static_input_step_outs

        last = fluid.layers.sequence_pool(input=rnn(), pool_type='last')
        loss = fluid.layers.mean(last)
        append_backward(loss)
        static_input_grad = self._program.global_block().var(
            framework.grad_var_name('static_input_tensor'))
        return static_input_grad, loss

    def get_seq_len_from_lod(self, lod):
        return [lod[0][i + 1] - lod[0][i] for i in xrange(len(lod[0]) - 1)]

    def get_expected_static_step_outs(self):
        x_lod = self.x_tensor.lod()
        x_seq_len = self.get_seq_len_from_lod(x_lod)
        x_seq_len_sorted = sorted(x_seq_len)
        x_sorted_indices = np.argsort(x_seq_len)[::-1]

        static_lod = self.static_input_tensor.lod()
        static_sliced = [
            self.static_input_data[static_lod[0][i]:static_lod[0][i + 1]]
            for i in xrange(len(static_lod[0]) - 1)
        ]
        static_seq_len = self.get_seq_len_from_lod(static_lod)
        static_reordered = []
        for i in xrange(len(x_sorted_indices)):
            static_reordered.extend(static_sliced[x_sorted_indices[i]].tolist())
        static_seq_len_reordered = [
            static_seq_len[x_sorted_indices[i]]
            for i in xrange(len(x_sorted_indices))
        ]

        static_step_outs = []
        static_step_lods = []

        for i in xrange(self._max_sequence_len):
            end = len(x_seq_len) - bisect.bisect_left(x_seq_len_sorted, i + 1)
            lod = [0]
            for i in xrange(end):
                lod.append(static_seq_len_reordered[i] + lod[-1])
            static_step_lods.append([lod])
            end = lod[-1]
            static_step_outs.append(
                np.array(static_reordered[:end]).astype('float32'))

        return static_step_outs, static_step_lods

    def test_step_out(self):
        static_step_outs = self.build_graph(only_forward=True)
        self.exe.run(framework.default_startup_program())
        expected_outs, expected_lods = self.get_expected_static_step_outs()
        for i in xrange(self._max_sequence_len):
            step_out, lod = self.fetch_value(static_step_outs[i])
            self.assertTrue(np.allclose(step_out, expected_outs[i]))
            self.assertTrue(np.allclose(lod, expected_lods[i]))

    def test_network_gradient(self):
        static_input_grad, loss = self.build_graph()
        self.exe.run(framework.default_startup_program())

        actual_gradients, actual_lod = self.fetch_value(static_input_grad)

        static_input_shape = self.static_input_tensor.get_dims()
        numeric_gradients = np.zeros(shape=static_input_shape).astype('float32')
        # calculate numeric gradients
        tensor_size = np.product(static_input_shape)
        for i in xrange(tensor_size):
            origin = self.static_input_tensor.get_float_element(i)
            x_pos = origin + self._delta
            self.static_input_tensor.set_float_element(i, x_pos)
            y_pos = self.fetch_value(loss)[0][0]
            x_neg = origin - self._delta
            self.static_input_tensor.set_float_element(i, x_neg)
            y_neg = self.fetch_value(loss)[0][0]
            self.static_input_tensor.set_float_element(i, origin)
            numeric_gradients.ravel()[i] = (y_pos - y_neg) / self._delta / 2
        self.assertTrue(np.allclose(actual_gradients, numeric_gradients, 0.001))
        self.assertTrue(np.allclose(actual_lod, self.static_input_tensor.lod()))
 def test_debug_str(self):
     p = Program()
     p.current_block().create_var(name='t', shape=[0, 1])
     self.assertRaises(ValueError, callableObj=p.__str__)
Example #27
0
    def _get_gradient(self, input_to_check, place, output_names, no_grad_set):
        prog = Program()
        block = prog.global_block()
        inputs_with_np = {
            key: value
            for (key, value) in OpTest._create_var_descs_(
                block, getattr(self, 'inputs', {}))
        }
        outputs_with_np = {
            key: val
            for (key, val) in OpTest._create_var_descs_(
                block, getattr(self, 'outputs', {}))
        }
        inputs = {
            k: [item[0] for item in inputs_with_np[k]]
            for k in inputs_with_np
        }
        outputs = {
            k: [item[0] for item in outputs_with_np[k]]
            for k in outputs_with_np
        }

        op = block.append_op(
            type=self.op_type,
            inputs=inputs,
            outputs=outputs,
            attrs=getattr(self, 'attrs', {}))

        # infer variable type and infer shape in compile-time
        op.desc.infer_var_type(block.desc)
        op.desc.infer_shape(block.desc)

        mean_inputs = map(block.var, output_names)

        if len(mean_inputs) == 1:
            loss = block.create_var(dtype=mean_inputs[0].dtype, shape=[1])
            op = block.append_op(
                inputs={"X": mean_inputs}, outputs={"Out": loss}, type='mean')
            op.desc.infer_var_type(block.desc)
            op.desc.infer_shape(block.desc)
        else:
            avg_sum = []
            for cur_loss in mean_inputs:
                cur_avg_loss = block.create_var(dtype=cur_loss.dtype, shape=[1])
                op = block.append_op(
                    inputs={"X": [cur_loss]},
                    outputs={"Out": [cur_avg_loss]},
                    type="mean")
                op.desc.infer_var_type(block.desc)
                op.desc.infer_shape(block.desc)
                avg_sum.append(cur_avg_loss)

            loss_sum = block.create_var(dtype=avg_sum[0].dtype, shape=[1])
            op_sum = block.append_op(
                inputs={"X": avg_sum}, outputs={"Out": loss_sum}, type='sum')
            op_sum.desc.infer_var_type(block.desc)
            op_sum.desc.infer_shape(block.desc)

            loss = block.create_var(dtype=loss_sum.dtype, shape=[1])
            op_loss = block.append_op(
                inputs={"X": loss_sum},
                outputs={"Out": loss},
                type='scale',
                attrs={'scale': 1.0 / float(len(avg_sum))})
            op_loss.desc.infer_var_type(block.desc)
            op_loss.desc.infer_shape(block.desc)

        param_grad_list = append_backward(
            loss=loss, parameter_list=input_to_check, no_grad_set=no_grad_set)

        feed_dict = {
            item[0].name: OpTest._numpy_to_lod_tensor(item[1], item[2], place)
            for p_name in inputs_with_np for item in inputs_with_np[p_name]
        }

        fetch_list = [g for p, g in param_grad_list]
        executor = Executor(place)
        return map(np.array,
                   executor.run(prog, feed_dict, fetch_list,
                                return_numpy=False))