Skip to content

Commit 64b68b2

Browse files
committed
Merge pull request #1473 from longjon/pytest
Python testing
2 parents daa4c5b + 3f6a85c commit 64b68b2

7 files changed

Lines changed: 154 additions & 4 deletions

File tree

.travis.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ install:
2222
- sudo -E $SCRIPTS/travis_install.sh
2323

2424
before_script:
25-
- export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
25+
- export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib:/usr/local/cuda/lib64
26+
- export PATH=/home/travis/miniconda/bin:$PATH
2627
- if ! $WITH_CMAKE; then $SCRIPTS/travis_setup_makefile_config.sh; fi
2728

2829
script: $SCRIPTS/travis_build_and_test.sh

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,9 @@ runtest: $(TEST_ALL_BIN) $(TEST_ALL_DYNLINK_BIN)
441441
$(TEST_ALL_BIN) $(TEST_GPUID) --gtest_shuffle $(TEST_FILTER) && \
442442
$(TEST_ALL_DYNLINK_BIN) $(TEST_GPUID) --gtest_shuffle $(TEST_FILTER)
443443

444+
pytest: py
445+
cd python; python -m unittest discover -s caffe/test
446+
444447
warn: $(EMPTY_WARN_REPORT)
445448

446449
$(EMPTY_WARN_REPORT): $(ALL_WARNS) | $(BUILD_DIR)

python/caffe/test/test_net.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import unittest
2+
import tempfile
3+
import os
4+
import numpy as np
5+
6+
import caffe
7+
8+
def simple_net_file(num_output):
9+
"""Make a simple net prototxt, based on test_net.cpp, returning the name
10+
of the (temporary) file."""
11+
12+
f = tempfile.NamedTemporaryFile(delete=False)
13+
f.write("""name: 'testnet' force_backward: true
14+
layers { type: DUMMY_DATA name: 'data' top: 'data' top: 'label'
15+
dummy_data_param { num: 5 channels: 2 height: 3 width: 4
16+
num: 5 channels: 1 height: 1 width: 1
17+
data_filler { type: 'gaussian' std: 1 }
18+
data_filler { type: 'constant' } } }
19+
layers { type: CONVOLUTION name: 'conv' bottom: 'data' top: 'conv'
20+
convolution_param { num_output: 11 kernel_size: 2 pad: 3
21+
weight_filler { type: 'gaussian' std: 1 }
22+
bias_filler { type: 'constant' value: 2 } }
23+
weight_decay: 1 weight_decay: 0 }
24+
layers { type: INNER_PRODUCT name: 'ip' bottom: 'conv' top: 'ip'
25+
inner_product_param { num_output: """ + str(num_output) + """
26+
weight_filler { type: 'gaussian' std: 2.5 }
27+
bias_filler { type: 'constant' value: -3 } } }
28+
layers { type: SOFTMAX_LOSS name: 'loss' bottom: 'ip' bottom: 'label'
29+
top: 'loss' }""")
30+
f.close()
31+
return f.name
32+
33+
class TestNet(unittest.TestCase):
34+
def setUp(self):
35+
self.num_output = 13
36+
net_file = simple_net_file(self.num_output)
37+
self.net = caffe.Net(net_file)
38+
# fill in valid labels
39+
self.net.blobs['label'].data[...] = \
40+
np.random.randint(self.num_output,
41+
size=self.net.blobs['label'].data.shape)
42+
os.remove(net_file)
43+
44+
def test_memory(self):
45+
"""Check that holding onto blob data beyond the life of a Net is OK"""
46+
47+
params = sum(map(list, self.net.params.itervalues()), [])
48+
blobs = self.net.blobs.values()
49+
del self.net
50+
51+
# now sum everything (forcing all memory to be read)
52+
total = 0
53+
for p in params:
54+
total += p.data.sum() + p.diff.sum()
55+
for bl in blobs:
56+
total += bl.data.sum() + bl.diff.sum()
57+
58+
def test_forward_backward(self):
59+
self.net.forward()
60+
self.net.backward()
61+
62+
def test_inputs_outputs(self):
63+
self.assertEqual(self.net.inputs, [])
64+
self.assertEqual(self.net.outputs, ['loss'])
65+
66+
def test_save_and_read(self):
67+
f = tempfile.NamedTemporaryFile(delete=False)
68+
f.close()
69+
self.net.save(f.name)
70+
net_file = simple_net_file(self.num_output)
71+
net2 = caffe.Net(net_file, f.name)
72+
os.remove(net_file)
73+
os.remove(f.name)
74+
for name in self.net.params:
75+
for i in range(len(self.net.params[name])):
76+
self.assertEqual(abs(self.net.params[name][i].data
77+
- net2.params[name][i].data).sum(), 0)

python/caffe/test/test_solver.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import unittest
2+
import tempfile
3+
import os
4+
import numpy as np
5+
6+
import caffe
7+
from test_net import simple_net_file
8+
9+
class TestSolver(unittest.TestCase):
10+
def setUp(self):
11+
self.num_output = 13
12+
net_f = simple_net_file(self.num_output)
13+
f = tempfile.NamedTemporaryFile(delete=False)
14+
f.write("""net: '""" + net_f + """'
15+
test_iter: 10 test_interval: 10 base_lr: 0.01 momentum: 0.9
16+
weight_decay: 0.0005 lr_policy: 'inv' gamma: 0.0001 power: 0.75
17+
display: 100 max_iter: 100 snapshot_after_train: false""")
18+
f.close()
19+
self.solver = caffe.SGDSolver(f.name)
20+
self.solver.net.set_mode_cpu()
21+
# fill in valid labels
22+
self.solver.net.blobs['label'].data[...] = \
23+
np.random.randint(self.num_output,
24+
size=self.solver.net.blobs['label'].data.shape)
25+
self.solver.test_nets[0].blobs['label'].data[...] = \
26+
np.random.randint(self.num_output,
27+
size=self.solver.test_nets[0].blobs['label'].data.shape)
28+
os.remove(f.name)
29+
os.remove(net_f)
30+
31+
def test_solve(self):
32+
self.assertEqual(self.solver.iter, 0)
33+
self.solver.solve()
34+
self.assertEqual(self.solver.iter, 100)
35+
36+
def test_net_memory(self):
37+
"""Check that nets survive after the solver is destroyed."""
38+
39+
nets = [self.solver.net] + list(self.solver.test_nets)
40+
self.assertEqual(len(nets), 2)
41+
del self.solver
42+
43+
total = 0
44+
for net in nets:
45+
for ps in net.params.itervalues():
46+
for p in ps:
47+
total += p.data.sum() + p.diff.sum()
48+
for bl in net.blobs.itervalues():
49+
total += bl.data.sum() + bl.diff.sum()

scripts/travis/travis_build_and_test.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ else
2626
$MAKE all
2727
$MAKE test
2828
$MAKE pycaffe
29+
$MAKE pytest
2930
$MAKE warn
3031
if ! $WITH_CUDA; then
3132
$MAKE lint

scripts/travis/travis_install.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,14 @@ $MAKE
5757
$MAKE install
5858
popd
5959
rm -f $LMDB_FILE
60+
61+
# Install the Python runtime dependencies via miniconda (this is much faster
62+
# than using pip for everything).
63+
wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh
64+
chmod +x miniconda.sh
65+
./miniconda.sh -b
66+
export PATH=/home/travis/miniconda/bin:$PATH
67+
conda update --yes conda
68+
conda install --yes numpy scipy matplotlib scikit-image pip
69+
pip install protobuf
70+
rm /home/travis/miniconda/lib/libm.*

scripts/travis/travis_setup_makefile_config.sh

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,18 @@ set -e
55
mv Makefile.config.example Makefile.config
66

77
if $WITH_CUDA; then
8-
# Remove default gencode set; only generate compute_50.
9-
sed -i 's/-gencode arch=.*\\//' Makefile.config
10-
sed -i 's/CUDA_ARCH :=//' Makefile.config
8+
# Only generate compute_50.
119
GENCODE="-gencode arch=compute_50,code=sm_50"
1210
GENCODE="$GENCODE -gencode arch=compute_50,code=compute_50"
1311
echo "CUDA_ARCH := $GENCODE" >> Makefile.config
1412
fi
13+
14+
cat << 'EOF' >> Makefile.config
15+
ANACONDA_HOME := $(HOME)/miniconda
16+
PYTHON_INCLUDE := $(ANACONDA_HOME)/include \
17+
$(ANACONDA_HOME)/include/python2.7 \
18+
$(ANACONDA_HOME)/lib/python2.7/site-packages/numpy/core/include
19+
PYTHON_LIB := $(ANACONDA_HOME)/lib
20+
INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include
21+
LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib
22+
EOF

0 commit comments

Comments
 (0)