Skip to content

Commit 2c189dc

Browse files
authored
Merge pull request #7998 from reyoung/feature/make_image_classification_normal_unittest
Make image_classification as a normal python unittest
2 parents 3f61615 + 1b1f305 commit 2c189dc

File tree

2 files changed

+89
-58
lines changed

2 files changed

+89
-58
lines changed

python/paddle/v2/fluid/tests/book/CMakeLists.txt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
file(GLOB TEST_OPS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "test_*.py")
22
string(REPLACE ".py" "" TEST_OPS "${TEST_OPS}")
33

4-
list(REMOVE_ITEM TEST_OPS test_image_classification_train test_recognize_digits)
5-
py_test(test_image_classification_train_resnet SRCS test_image_classification_train.py ARGS resnet)
6-
py_test(test_image_classification_train_vgg SRCS test_image_classification_train.py ARGS vgg)
4+
list(REMOVE_ITEM TEST_OPS test_recognize_digits)
75
py_test(test_recognize_digits_mlp_cpu
86
SRCS test_recognize_digits.py
97
ARGS mlp)

python/paddle/v2/fluid/tests/book/test_image_classification_train.py

Lines changed: 88 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414

1515
from __future__ import print_function
1616

17-
import sys
18-
1917
import paddle.v2 as paddle
2018
import paddle.v2.fluid as fluid
19+
import unittest
20+
import contextlib
2121

2222

2323
def resnet_cifar10(input, depth=32):
@@ -89,56 +89,89 @@ def conv_block(input, num_filter, groups, dropouts):
8989
return fc2
9090

9191

92-
classdim = 10
93-
data_shape = [3, 32, 32]
94-
95-
images = fluid.layers.data(name='pixel', shape=data_shape, dtype='float32')
96-
label = fluid.layers.data(name='label', shape=[1], dtype='int64')
97-
98-
net_type = "vgg"
99-
if len(sys.argv) >= 2:
100-
net_type = sys.argv[1]
101-
102-
if net_type == "vgg":
103-
print("train vgg net")
104-
net = vgg16_bn_drop(images)
105-
elif net_type == "resnet":
106-
print("train resnet")
107-
net = resnet_cifar10(images, 32)
108-
else:
109-
raise ValueError("%s network is not supported" % net_type)
110-
111-
predict = fluid.layers.fc(input=net, size=classdim, act='softmax')
112-
cost = fluid.layers.cross_entropy(input=predict, label=label)
113-
avg_cost = fluid.layers.mean(x=cost)
114-
115-
optimizer = fluid.optimizer.Adam(learning_rate=0.001)
116-
opts = optimizer.minimize(avg_cost)
117-
118-
accuracy = fluid.evaluator.Accuracy(input=predict, label=label)
119-
120-
BATCH_SIZE = 128
121-
PASS_NUM = 1
122-
123-
train_reader = paddle.batch(
124-
paddle.reader.shuffle(
125-
paddle.dataset.cifar.train10(), buf_size=128 * 10),
126-
batch_size=BATCH_SIZE)
127-
128-
place = fluid.CPUPlace()
129-
exe = fluid.Executor(place)
130-
feeder = fluid.DataFeeder(place=place, feed_list=[images, label])
131-
exe.run(fluid.default_startup_program())
132-
133-
for pass_id in range(PASS_NUM):
134-
accuracy.reset(exe)
135-
for data in train_reader():
136-
loss, acc = exe.run(fluid.default_main_program(),
137-
feed=feeder.feed(data),
138-
fetch_list=[avg_cost] + accuracy.metrics)
139-
pass_acc = accuracy.eval(exe)
140-
print("loss:" + str(loss) + " acc:" + str(acc) + " pass_acc:" + str(
141-
pass_acc))
142-
# this model is slow, so if we can train two mini batch, we think it works properly.
143-
exit(0)
144-
exit(1)
92+
def main(net_type, use_cuda):
93+
if use_cuda and not fluid.core.is_compiled_with_cuda():
94+
return
95+
96+
classdim = 10
97+
data_shape = [3, 32, 32]
98+
99+
images = fluid.layers.data(name='pixel', shape=data_shape, dtype='float32')
100+
label = fluid.layers.data(name='label', shape=[1], dtype='int64')
101+
102+
if net_type == "vgg":
103+
print("train vgg net")
104+
net = vgg16_bn_drop(images)
105+
elif net_type == "resnet":
106+
print("train resnet")
107+
net = resnet_cifar10(images, 32)
108+
else:
109+
raise ValueError("%s network is not supported" % net_type)
110+
111+
predict = fluid.layers.fc(input=net, size=classdim, act='softmax')
112+
cost = fluid.layers.cross_entropy(input=predict, label=label)
113+
avg_cost = fluid.layers.mean(x=cost)
114+
115+
optimizer = fluid.optimizer.Adam(learning_rate=0.001)
116+
optimizer.minimize(avg_cost)
117+
118+
accuracy = fluid.evaluator.Accuracy(input=predict, label=label)
119+
120+
BATCH_SIZE = 128
121+
PASS_NUM = 1
122+
123+
train_reader = paddle.batch(
124+
paddle.reader.shuffle(
125+
paddle.dataset.cifar.train10(), buf_size=128 * 10),
126+
batch_size=BATCH_SIZE)
127+
128+
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
129+
exe = fluid.Executor(place)
130+
feeder = fluid.DataFeeder(place=place, feed_list=[images, label])
131+
exe.run(fluid.default_startup_program())
132+
133+
loss = 0.0
134+
for pass_id in range(PASS_NUM):
135+
accuracy.reset(exe)
136+
for data in train_reader():
137+
loss, acc = exe.run(fluid.default_main_program(),
138+
feed=feeder.feed(data),
139+
fetch_list=[avg_cost] + accuracy.metrics)
140+
pass_acc = accuracy.eval(exe)
141+
print("loss:" + str(loss) + " acc:" + str(acc) + " pass_acc:" + str(
142+
pass_acc))
143+
return
144+
145+
raise AssertionError(
146+
"Image classification loss is too large, {0:2.2}".format(loss))
147+
148+
149+
class TestImageClassification(unittest.TestCase):
150+
def test_vgg_cuda(self):
151+
with self.scope_prog_guard():
152+
main('vgg', use_cuda=True)
153+
154+
def test_resnet_cuda(self):
155+
with self.scope_prog_guard():
156+
main('resnet', use_cuda=True)
157+
158+
def test_vgg_cpu(self):
159+
with self.scope_prog_guard():
160+
main('vgg', use_cuda=False)
161+
162+
def test_resnet_cpu(self):
163+
with self.scope_prog_guard():
164+
main('resnet', use_cuda=False)
165+
166+
@contextlib.contextmanager
167+
def scope_prog_guard(self):
168+
prog = fluid.Program()
169+
startup_prog = fluid.Program()
170+
scope = fluid.core.Scope()
171+
with fluid.scope_guard(scope):
172+
with fluid.program_guard(prog, startup_prog):
173+
yield
174+
175+
176+
if __name__ == '__main__':
177+
unittest.main()

0 commit comments

Comments
 (0)