test_mnist.py 7.7 KB
Newer Older
Q
qiaolongfei 已提交
1 2 3
import paddle.v2.framework.core as core
from paddle.v2.framework.op import Operator
import numpy
Q
qiaolongfei 已提交
4
import paddle.v2 as paddle
Y
Yu Yang 已提交
5 6 7
exit(
    0
)  # FIXME(yuyang18): InferShape has been removed, this unittest should be changed until compile time is ready
Q
qiaolongfei 已提交
8

Q
qiaolongfei 已提交
9
BATCH_SIZE = 100
Q
qiaolongfei 已提交
10 11 12

scope = core.Scope()
place = core.CPUPlace()
Q
qiaolongfei 已提交
13 14
# if you want to test GPU training, you can use gpu place
# place = core.GPUPlace(0)
Q
qiaolongfei 已提交
15 16
dev_ctx = core.DeviceContext.create(place)

17 18
init_net = core.Net.create()
forward_net = core.Net.create()
Q
qiaolongfei 已提交
19 20 21 22
backward_net = None
optimize_net = core.Net.create()


Q
qiaolongfei 已提交
23
def atomic_id():
Q
qiaolongfei 已提交
24 25 26 27 28 29
    id = 0
    while True:
        yield id
        id += 1


Q
qiaolongfei 已提交
30
uniq_id = atomic_id().next
Q
qiaolongfei 已提交
31 32 33


def data_layer(name, dims):
D
dongzhihong 已提交
34
    var = scope.var(name)
Q
qiaolongfei 已提交
35 36 37 38 39 40
    tensor = var.get_tensor()
    tensor.set_dims(dims)  # 1 is batch size holder.
    return name


def feed_data(name, data):
Q
qiaolongfei 已提交
41
    assert isinstance(data, numpy.ndarray)
Q
qiaolongfei 已提交
42 43
    tensor = scope.find_var(name).get_tensor()
    tensor.set_dims(data.shape)
44
    if data.dtype == numpy.dtype("int32"):
Q
qiaolongfei 已提交
45
        tensor.alloc_int(place)
46
    elif data.dtype == numpy.dtype("float32"):
Q
qiaolongfei 已提交
47
        tensor.alloc_float(place)
Q
qiaolongfei 已提交
48 49
    else:
        raise ValueError("data type not supported")
Q
qiaolongfei 已提交
50 51 52 53 54 55 56
    tensor.set(data, place)


def grad_var_name(var_name):
    return var_name + "@GRAD"


Q
qiaolongfei 已提交
57
def sgd_optimizer(net, param_name, learning_rate=0.005):
Q
qiaolongfei 已提交
58 59
    grad_name = grad_var_name(param_name)
    optimize_op = Operator(
Q
qiaolongfei 已提交
60 61 62 63 64
        "sgd",
        param=param_name,
        grad=grad_name,
        param_out=param_name,
        learning_rate=learning_rate)
Q
qiaolongfei 已提交
65
    net.append_op(optimize_op)
Q
qiaolongfei 已提交
66 67 68


# should use operator and add these to the init_network
69
def init_param(net, param_name, dims):
D
dongzhihong 已提交
70
    scope.var(param_name)
71 72 73 74
    op = Operator(
        "uniform_random", Out=param_name, dims=dims, min=-0.5, max=0.5, seed=10)
    op.infer_shape(scope)
    net.append_op(op)
Q
qiaolongfei 已提交
75 76 77


# fc_layer
Q
qiaolongfei 已提交
78
def fc_layer(net, input, size, act="softmax", bias=True, param=None, name=None):
Q
qiaolongfei 已提交
79
    """
80
    The fully connected layer.
Q
qiaolongfei 已提交
81

82
    :param input: The name of input variable.
Q
qiaolongfei 已提交
83
    :type input: str
84 85 86 87 88 89 90 91 92
    :param size: The size of fully connected layer.
    :param act: The name of activation.
    :param param: The attribute of learnable parameter which can be used to
                  modify initialization mean and std of the parameter.
    :param bias: The attribute of bias. If set False, this layer does not have
                 a bias.
    :param name: The name of this layer. If it is not set explictly, a name
                 will be generated automatically.
    :return: The name of the output variable.
Q
qiaolongfei 已提交
93
    """
94

Q
qiaolongfei 已提交
95
    if name is None:
96
        name = "fc_%d" % uniq_id()
Q
qiaolongfei 已提交
97
    if not isinstance(name, str):
98
        raise ValueError("The name of a layer should be a string.")
Q
qiaolongfei 已提交
99 100 101 102

    input_dims = scope.find_var(input).get_tensor().get_dims()

    w_name = param or name + ".w"
103
    init_param(net=init_net, param_name=w_name, dims=[input_dims[1], size])
Q
qiaolongfei 已提交
104 105 106
    sgd_optimizer(net=optimize_net, param_name=w_name, learning_rate=0.01)

    pre_activation = name + ".mul.out"
D
dongzhihong 已提交
107
    scope.var(pre_activation)
Q
qiaolongfei 已提交
108
    mul_op = Operator("mul", X=input, Y=w_name, Out=pre_activation)
Q
qiaolongfei 已提交
109
    net.append_op(mul_op)
Q
qiaolongfei 已提交
110 111 112 113

    # create bias variable if needed
    if bias:
        bias_name = name + ".b"
114
        init_param(net=init_net, param_name=bias_name, dims=[size])
Q
qiaolongfei 已提交
115
        sgd_optimizer(
Q
qiaolongfei 已提交
116
            net=optimize_net, param_name=bias_name, learning_rate=0.001)
Q
qiaolongfei 已提交
117
        bias_out = name + ".rowwise_add.out"
D
dongzhihong 已提交
118
        scope.var(bias_out)
Q
qiaolongfei 已提交
119
        rowwise_append_op = Operator(
Q
qiaolongfei 已提交
120
            "rowwise_add", X=pre_activation, b=bias_name, Out=bias_out)
Q
qiaolongfei 已提交
121
        net.append_op(rowwise_append_op)
Q
qiaolongfei 已提交
122 123 124
        pre_activation = bias_out

    activation_op = Operator(act, X=pre_activation, Y=name)
Q
qiaolongfei 已提交
125
    net.append_op(activation_op)
D
dongzhihong 已提交
126
    scope.var(name)
Q
qiaolongfei 已提交
127 128 129 130 131
    net.infer_shape(scope)
    return name


def cross_entropy_layer(net, input, label):
132
    cost_name = "cross_entropy_%d" % uniq_id()
Q
qiaolongfei 已提交
133
    cross_entropy_op = Operator(
X
Xinghai Sun 已提交
134
        "cross_entropy", X=input, Label=label, Y=cost_name)
Q
qiaolongfei 已提交
135
    net.append_op(cross_entropy_op)
D
dongzhihong 已提交
136
    scope.var(cost_name)
Q
qiaolongfei 已提交
137 138 139 140
    net.infer_shape(scope)
    return cost_name


Q
qiaolongfei 已提交
141
def create_backward_net(forward_net):
Q
qiaolongfei 已提交
142 143
    net = core.Operator.backward(forward_net, set())
    for input in net.inputs()["all"]:
D
dongzhihong 已提交
144
        var = scope.var(input)
Q
qiaolongfei 已提交
145 146
        var.get_tensor()
    for output in net.outputs()["all"]:
D
dongzhihong 已提交
147
        var = scope.var(output)
Q
qiaolongfei 已提交
148 149 150 151
        var.get_tensor()
    return net


Q
qiaolongfei 已提交
152
def debug_print_op(op):
Q
qiaolongfei 已提交
153 154 155 156
    print("===============" + op.type() + "==============")
    print("***inputs:***")
    for input in op.inputs()["all"]:
        print input, scope.find_var(input).get_tensor().get_dims()
Q
qiaolongfei 已提交
157
    print("\n***outputs:***")
Q
qiaolongfei 已提交
158 159 160 161 162 163
    for output in op.outputs()["all"]:
        print output, scope.find_var(output).get_tensor().get_dims()
    print("")
    print("")


Q
qiaolongfei 已提交
164 165 166 167
def set_cost(cost):
    cost_shape = numpy.array(scope.find_var(cost).get_tensor()).shape
    cost_grad = \
        scope.find_var(grad_var_name(cost)).get_tensor()
Q
qiaolongfei 已提交
168 169 170 171 172
    cost_grad.set_dims(cost_shape)
    cost_grad.alloc_float(place)
    cost_grad.set(numpy.ones(cost_shape).astype("float32"), place)


Q
qiaolongfei 已提交
173
def get_cost_mean(cost):
Q
qiaolongfei 已提交
174
    cost_data = numpy.array(scope.find_var(cost).get_tensor())
Q
qiaolongfei 已提交
175
    return cost_data.sum() / len(cost_data)
Q
qiaolongfei 已提交
176

Q
qiaolongfei 已提交
177

Q
qiaolongfei 已提交
178 179 180 181 182
def error_rate(predict, label):
    predict_var = numpy.array(scope.find_var(predict).get_tensor()).argmax(
        axis=1)
    label = numpy.array(scope.find_var(label).get_tensor())
    error_num = numpy.sum(predict_var != label)
Q
qiaolongfei 已提交
183
    return error_num / float(len(label))
Q
qiaolongfei 已提交
184 185


186
images = data_layer(name="pixel", dims=[BATCH_SIZE, 784])
X
Xinghai Sun 已提交
187
labels = data_layer(name="label", dims=[BATCH_SIZE, 1])
188 189
fc1 = fc_layer(net=forward_net, input=images, size=100, act="sigmoid")
fc2 = fc_layer(net=forward_net, input=fc1, size=100, act="sigmoid")
190
predict = fc_layer(net=forward_net, input=fc2, size=10, act="softmax")
191 192 193 194 195
cost = cross_entropy_layer(net=forward_net, input=predict, label=labels)

init_net.complete_add_op(True)
forward_net.complete_add_op(True)
backward_net = create_backward_net(forward_net)
Q
qiaolongfei 已提交
196
optimize_net.complete_add_op(True)
Q
qiaolongfei 已提交
197

198 199
print(init_net)
print(forward_net)
Q
qiaolongfei 已提交
200
print(backward_net)
Q
qiaolongfei 已提交
201
print(optimize_net)
Q
qiaolongfei 已提交
202

203
debug_print_op(forward_net)
Q
qiaolongfei 已提交
204 205
debug_print_op(backward_net)
debug_print_op(optimize_net)
Q
qiaolongfei 已提交
206

Q
qiaolongfei 已提交
207
train_reader = paddle.batch(
Q
qiaolongfei 已提交
208 209 210 211
    paddle.reader.shuffle(
        paddle.dataset.mnist.train(), buf_size=8192),
    batch_size=BATCH_SIZE)

Q
qiaolongfei 已提交
212

Q
qiaolongfei 已提交
213
def test(cost_name):
Q
qiaolongfei 已提交
214 215
    test_reader = paddle.batch(
        paddle.dataset.mnist.test(), batch_size=BATCH_SIZE)
Q
qiaolongfei 已提交
216 217 218
    cost = []
    error = []
    for data in test_reader():
Q
qiaolongfei 已提交
219 220
        image_data = numpy.array(map(lambda x: x[0], data)).astype("float32")
        label_data = numpy.array(map(lambda x: x[1], data)).astype("int32")
X
Xinghai Sun 已提交
221
        label_data = numpy.expand_dims(label_data, axis=1)
Q
qiaolongfei 已提交
222 223
        feed_data(images, image_data)
        feed_data(labels, label_data)
Q
qiaolongfei 已提交
224

225 226
        forward_net.infer_shape(scope)
        forward_net.run(scope, dev_ctx)
Q
qiaolongfei 已提交
227
        cost.append(get_cost_mean(cost_name))
Q
qiaolongfei 已提交
228 229 230 231 232
        error.append(error_rate(predict, "label"))
    print("cost=" + str(sum(cost) / float(len(cost))) + " error_rate=" + str(
        sum(error) / float(len(error))))


Q
qiaolongfei 已提交
233
PASS_NUM = 1
234 235

init_net.run(scope, dev_ctx)
Q
qiaolongfei 已提交
236
for pass_id in range(PASS_NUM):
Q
qiaolongfei 已提交
237
    batch_id = 0
Q
qiaolongfei 已提交
238

Q
qiaolongfei 已提交
239
    for data in train_reader():
Q
qiaolongfei 已提交
240 241
        image_data = numpy.array(map(lambda x: x[0], data)).astype("float32")
        label_data = numpy.array(map(lambda x: x[1], data)).astype("int32")
X
Xinghai Sun 已提交
242
        label_data = numpy.expand_dims(label_data, axis=1)
Q
qiaolongfei 已提交
243 244
        feed_data(images, image_data)
        feed_data(labels, label_data)
Q
qiaolongfei 已提交
245

246 247
        forward_net.infer_shape(scope)
        forward_net.run(scope, dev_ctx)
Q
qiaolongfei 已提交
248
        set_cost(cost)
Q
qiaolongfei 已提交
249 250
        backward_net.infer_shape(scope)
        backward_net.run(scope, dev_ctx)
Q
qiaolongfei 已提交
251

Q
qiaolongfei 已提交
252
        optimize_net.run(scope, dev_ctx)
Q
qiaolongfei 已提交
253 254
        if batch_id % 100 == 0:
            print("pass[" + str(pass_id) + "] batch_id[" + str(batch_id) + "]")
Q
qiaolongfei 已提交
255
            test(cost)
Q
qiaolongfei 已提交
256 257

        batch_id = batch_id + 1