Skip to content

Commit

Permalink
Merge pull request BVLC#1473 from longjon/pytest
Browse files Browse the repository at this point in the history
Python testing
  • Loading branch information
longjon committed Dec 31, 2014
2 parents 5f8dcd1 + ff6a37d commit b1c13ab
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 4 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ install:
- sudo -E $SCRIPTS/travis_install.sh

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

script: $SCRIPTS/travis_build_and_test.sh
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,9 @@ runtest: $(TEST_ALL_BIN) $(TEST_ALL_DYNLINK_BIN)
$(TEST_ALL_BIN) $(TEST_GPUID) --gtest_shuffle $(TEST_FILTER) && \
$(TEST_ALL_DYNLINK_BIN) $(TEST_GPUID) --gtest_shuffle $(TEST_FILTER)

pytest: py
cd python; python -m unittest discover -s caffe/test

warn: $(EMPTY_WARN_REPORT)

$(EMPTY_WARN_REPORT): $(ALL_WARNS) | $(BUILD_DIR)
Expand Down
77 changes: 77 additions & 0 deletions python/caffe/test/test_net.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import unittest
import tempfile
import os
import numpy as np

import caffe

def simple_net_file(num_output):
"""Make a simple net prototxt, based on test_net.cpp, returning the name
of the (temporary) file."""

f = tempfile.NamedTemporaryFile(delete=False)
f.write("""name: 'testnet' force_backward: true
layers { type: DUMMY_DATA name: 'data' top: 'data' top: 'label'
dummy_data_param { num: 5 channels: 2 height: 3 width: 4
num: 5 channels: 1 height: 1 width: 1
data_filler { type: 'gaussian' std: 1 }
data_filler { type: 'constant' } } }
layers { type: CONVOLUTION name: 'conv' bottom: 'data' top: 'conv'
convolution_param { num_output: 11 kernel_size: 2 pad: 3
weight_filler { type: 'gaussian' std: 1 }
bias_filler { type: 'constant' value: 2 } }
weight_decay: 1 weight_decay: 0 }
layers { type: INNER_PRODUCT name: 'ip' bottom: 'conv' top: 'ip'
inner_product_param { num_output: """ + str(num_output) + """
weight_filler { type: 'gaussian' std: 2.5 }
bias_filler { type: 'constant' value: -3 } } }
layers { type: SOFTMAX_LOSS name: 'loss' bottom: 'ip' bottom: 'label'
top: 'loss' }""")
f.close()
return f.name

class TestNet(unittest.TestCase):
def setUp(self):
self.num_output = 13
net_file = simple_net_file(self.num_output)
self.net = caffe.Net(net_file)
# fill in valid labels
self.net.blobs['label'].data[...] = \
np.random.randint(self.num_output,
size=self.net.blobs['label'].data.shape)
os.remove(net_file)

def test_memory(self):
"""Check that holding onto blob data beyond the life of a Net is OK"""

params = sum(map(list, self.net.params.itervalues()), [])
blobs = self.net.blobs.values()
del self.net

# now sum everything (forcing all memory to be read)
total = 0
for p in params:
total += p.data.sum() + p.diff.sum()
for bl in blobs:
total += bl.data.sum() + bl.diff.sum()

def test_forward_backward(self):
self.net.forward()
self.net.backward()

def test_inputs_outputs(self):
self.assertEqual(self.net.inputs, [])
self.assertEqual(self.net.outputs, ['loss'])

def test_save_and_read(self):
f = tempfile.NamedTemporaryFile(delete=False)
f.close()
self.net.save(f.name)
net_file = simple_net_file(self.num_output)
net2 = caffe.Net(net_file, f.name)
os.remove(net_file)
os.remove(f.name)
for name in self.net.params:
for i in range(len(self.net.params[name])):
self.assertEqual(abs(self.net.params[name][i].data
- net2.params[name][i].data).sum(), 0)
49 changes: 49 additions & 0 deletions python/caffe/test/test_solver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import unittest
import tempfile
import os
import numpy as np

import caffe
from test_net import simple_net_file

class TestSolver(unittest.TestCase):
def setUp(self):
self.num_output = 13
net_f = simple_net_file(self.num_output)
f = tempfile.NamedTemporaryFile(delete=False)
f.write("""net: '""" + net_f + """'
test_iter: 10 test_interval: 10 base_lr: 0.01 momentum: 0.9
weight_decay: 0.0005 lr_policy: 'inv' gamma: 0.0001 power: 0.75
display: 100 max_iter: 100 snapshot_after_train: false""")
f.close()
self.solver = caffe.SGDSolver(f.name)
self.solver.net.set_mode_cpu()
# fill in valid labels
self.solver.net.blobs['label'].data[...] = \
np.random.randint(self.num_output,
size=self.solver.net.blobs['label'].data.shape)
self.solver.test_nets[0].blobs['label'].data[...] = \
np.random.randint(self.num_output,
size=self.solver.test_nets[0].blobs['label'].data.shape)
os.remove(f.name)
os.remove(net_f)

def test_solve(self):
self.assertEqual(self.solver.iter, 0)
self.solver.solve()
self.assertEqual(self.solver.iter, 100)

def test_net_memory(self):
"""Check that nets survive after the solver is destroyed."""

nets = [self.solver.net] + list(self.solver.test_nets)
self.assertEqual(len(nets), 2)
del self.solver

total = 0
for net in nets:
for ps in net.params.itervalues():
for p in ps:
total += p.data.sum() + p.diff.sum()
for bl in net.blobs.itervalues():
total += bl.data.sum() + bl.diff.sum()
1 change: 1 addition & 0 deletions scripts/travis/travis_build_and_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ else
$MAKE all
$MAKE test
$MAKE pycaffe
$MAKE pytest
$MAKE warn
if ! $WITH_CUDA; then
$MAKE lint
Expand Down
11 changes: 11 additions & 0 deletions scripts/travis/travis_install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,14 @@ $MAKE
$MAKE install
popd
rm -f $LMDB_FILE

# Install the Python runtime dependencies via miniconda (this is much faster
# than using pip for everything).
wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh
chmod +x miniconda.sh
./miniconda.sh -b
export PATH=/home/travis/miniconda/bin:$PATH
conda update --yes conda
conda install --yes numpy scipy matplotlib scikit-image pip
pip install protobuf
rm /home/travis/miniconda/lib/libm.*
14 changes: 11 additions & 3 deletions scripts/travis/travis_setup_makefile_config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,18 @@ set -e
mv Makefile.config.example Makefile.config

if $WITH_CUDA; then
# Remove default gencode set; only generate compute_50.
sed -i 's/-gencode arch=.*\\//' Makefile.config
sed -i 's/CUDA_ARCH :=//' Makefile.config
# Only generate compute_50.
GENCODE="-gencode arch=compute_50,code=sm_50"
GENCODE="$GENCODE -gencode arch=compute_50,code=compute_50"
echo "CUDA_ARCH := $GENCODE" >> Makefile.config
fi

cat << 'EOF' >> Makefile.config
ANACONDA_HOME := $(HOME)/miniconda
PYTHON_INCLUDE := $(ANACONDA_HOME)/include \
$(ANACONDA_HOME)/include/python2.7 \
$(ANACONDA_HOME)/lib/python2.7/site-packages/numpy/core/include
PYTHON_LIB := $(ANACONDA_HOME)/lib
INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include
LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib
EOF
1 change: 1 addition & 0 deletions src/caffe/solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ void Solver<Dtype>::Init(const SolverParameter& param) {
LOG(INFO) << "Initializing solver from parameters: " << std::endl
<< param.DebugString();
param_ = param;
iter_ = 0;
if (param_.random_seed() >= 0) {
Caffe::set_random_seed(param_.random_seed());
}
Expand Down

0 comments on commit b1c13ab

Please sign in to comment.