Skip to content

Commit aea995d

Browse files
authored
Add whitebox test (#4)
Add ci scripts Update Examples Write fix for openml tasks with nan columns Add codecov
1 parent ca5e81b commit aea995d

File tree

12 files changed

+221
-10
lines changed

12 files changed

+221
-10
lines changed

.travis.yml

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
language: python
2+
dist: xenial
3+
os: linux
4+
5+
jobs:
6+
include:
7+
- python: "3.6"
8+
env: RUN_TESTS="true"
9+
- python: "3.7"
10+
env: RUN_TESTS="true"
11+
- python: "3.8"
12+
env:
13+
- RUN_TESTS="true"
14+
- USE_SINGULARITY="true"
15+
- python: "3.8"
16+
env: RUN_CODESTYLE="true"
17+
- python: "3.8"
18+
dist: bionic
19+
env:
20+
- RUN_EXAMPLES="true"
21+
- USE_SINGULARITY="true"
22+
- python: "3.8"
23+
dist: xenial
24+
env:
25+
- RUN_EXAMPLES="true"
26+
- USE_SINGULARITY="true"
27+
28+
before_cache:
29+
- rm -f $HOME/.cache/pip/log/debug.log
30+
31+
cache:
32+
pip
33+
34+
git:
35+
depth: 5
36+
37+
install:
38+
- chmod +x ci_scripts/install.sh && source ./ci_scripts/install.sh
39+
40+
script:
41+
- chmod +x ci_scripts/script.sh && source ./ci_scripts/script.sh

ci_scripts/codestyle.sh

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/usr/bin/env sh
2+
3+
if [[ "$RUN_CODESTYLE" == "true" ]]; then
4+
echo "Performing codestyle checking"
5+
pycodestyle --max-line-length=120 ./hpolib
6+
flake8 --max-line-length=120 ./hpolib
7+
else
8+
echo "Skip code style checking"
9+
fi

ci_scripts/examples.sh

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env sh
2+
3+
cd examples
4+
5+
for script in *.py
6+
do
7+
python $script
8+
rval=$?
9+
if [ "$rval" != 0 ]; then
10+
echo "Error running example $script"
11+
exit $rval
12+
fi
13+
done

ci_scripts/install.sh

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/usr/bin/env sh
2+
3+
install_packages=""
4+
5+
if [[ "$RUN_TESTS" == "true" ]]; then
6+
echo "Install tools for testing"
7+
install_packages="${install_packages}pytest,"
8+
pip install codecov
9+
else
10+
echo "Skip installing tools for testing"
11+
fi
12+
13+
if [[ "$RUN_CODESTYLE" == "true" ]]; then
14+
echo "Install tools for codestyle checking"
15+
install_packages="${install_packages}codestyle,"
16+
else
17+
echo "Skip installing tools for codestyle checking"
18+
fi
19+
20+
if [[ "$USE_SINGULARITY" == "true" ]]; then
21+
echo "Install Singularity"
22+
gimme force 1.14
23+
eval "$(gimme 1.14)"
24+
25+
sudo apt-get update && sudo apt-get install -y \
26+
build-essential \
27+
libssl-dev \
28+
uuid-dev \
29+
libgpgme11-dev \
30+
squashfs-tools \
31+
libseccomp-dev \
32+
wget \
33+
pkg-config \
34+
git \
35+
cryptsetup
36+
37+
export VERSION=3.5.2 && # adjust this as necessary \
38+
wget https://github.com/sylabs/singularity/releases/download/v${VERSION}/singularity-${VERSION}.tar.gz && \
39+
tar -xzf singularity-${VERSION}.tar.gz && \
40+
cd singularity
41+
42+
./mconfig && \
43+
make -C builddir && \
44+
sudo make -C builddir install
45+
46+
cd ..
47+
install_packages="${install_packages}singularity,"
48+
else
49+
echo "Skip installing Singularity"
50+
fi
51+
52+
install_packages="${install_packages}xgboost"
53+
echo "Install HPOlib3 with options: ${install_packages}"
54+
pip install .["${install_packages}"]

ci_scripts/script.sh

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/usr/bin/env sh
2+
3+
if [[ "$RUN_TESTS" == "true" ]]; then
4+
if [[ "$USE_SINGULARITY" == "true" ]]; then
5+
echo "Run tests with singularity support"
6+
# Create the coverage report for the singularity example, since it covers more tests.
7+
pytest -sv --cov=hpolib tests/
8+
codecov
9+
else
10+
echo "Run tests without singularity support"
11+
pytest -sv tests/
12+
fi
13+
fi
14+
15+
if [[ "$RUN_CODESTYLE" == "true" ]]; then
16+
echo "Run codestyle"
17+
chmod +x ci_scripts/codestyle.sh && source ./ci_scripts/codestyle.sh
18+
fi
19+
20+
if [[ "$RUN_EXAMPLES" == "true" ]]; then
21+
echo "Run all examples"
22+
chmod +x ci_scripts/examples.sh && source ./ci_scripts/examples.sh
23+
fi

examples/XGBoost_local.py

+9-5
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,27 @@
44

55
task_ids = get_openmlcc18_taskids()
66
for task_no, task_id in enumerate(task_ids):
7+
78
print(f'###################### TASK {task_no + 1} of {len(task_ids)}: Task-Id: {task_id} ######################')
9+
if task_id == 167204:
10+
continue # due to memory limits
11+
812
b = Benchmark(task_id=task_id)
913
cs = b.get_configuration_space()
1014
start = time()
11-
for i in range(5):
15+
num_configs = 1
16+
for i in range(num_configs):
1217
configuration = cs.sample_configuration()
1318
print(configuration)
14-
for n_estimator in [2, 4, 8, 16, 32]:
15-
for subsample in [0.1, 0.2, 0.4, 0.8, 1]:
19+
for n_estimator in [8, 64]:
20+
for subsample in [0.4, 1]:
1621
result_dict = b.objective_function(configuration, n_estimators=n_estimator, subsample=subsample)
1722
valid_loss = result_dict['function_value']
1823
train_loss = result_dict['train_loss']
1924

2025
result_dict = b.objective_function_test(configuration, n_estimators=n_estimator)
2126
test_loss = result_dict['function_value']
2227

23-
print(f'[{i+1}|5] No Estimator: {n_estimator:3d} - Subsample Rate: {subsample:.1f} - Test {test_loss:.4f} '
28+
print(f'[{i+1}|{num_configs}] No Estimator: {n_estimator:3d} - Subsample Rate: {subsample:.1f} - Test {test_loss:.4f} '
2429
f'- Valid {valid_loss:.4f} - Train {train_loss:.4f}')
25-
2630
print(f'Done, took totally {time()-start:.2f}')

examples/XGBoost_with_container.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ def run_benchmark(task_id):
4949
cs = b.get_configuration_space()
5050
configuration = cs.get_default_configuration()
5151

52-
n_estimators = [2, 4, 8, 16, 32, 64]
53-
subsample_ratios = [0.1, 0.2, 0.4, 0.8, 1]
52+
n_estimators = [8, 64]
53+
subsample_ratios = [0.4, 1]
5454

5555
result_per_data_set = []
5656
num_configs = 10
@@ -84,7 +84,7 @@ def run_benchmark(task_id):
8484

8585
if __name__ == "__main__":
8686
parser = argparse.ArgumentParser(prog='HPOlib CC Datasets', description='HPOlib3', usage='%(prog)s <task_id>')
87-
parser.add_argument('--array_id', type=int, help='Defines which data set to use. Values from 0 to 71')
87+
parser.add_argument('--array_id', default=0, type=int, help='Defines which data set to use. Values from 0 to 71')
8888

8989
args = parser.parse_args()
9090
task_ids = get_openmlcc18_taskids()

extra_requirements/tests.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"py": ["pycodestyle", "flake8"],
2+
"codestyle": ["pycodestyle","flake8"],
33
"pytest": ["pytest","pytest-cov"]
44
}

extra_requirements/xgboost.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
22
"xgboost": ["xgboost==0.90","json_tricks==3.14.0"]
3-
}
3+
}

hpolib/benchmarks/ml/xgboost_benchmark.py

+3
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ def __init__(self, task_id: Union[int, None] = None, n_threads: int = 1,
4949
self.X_valid = self.X_valid[:, sorting]
5050
self.X_test = self.X_test[:, sorting]
5151

52+
nan_columns = np.all(np.isnan(self.X_train), axis=0)
53+
self.categorical_data = self.categorical_data[~nan_columns]
54+
5255
mean_imputer = SimpleImputer(strategy='mean')
5356
self.X_train = mean_imputer.fit_transform(self.X_train)
5457
self.X_valid = mean_imputer.transform(self.X_valid)

tests/__init__.py

Whitespace-only changes.

tests/test_whitebox.py

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import numpy as np
2+
import pytest
3+
from time import time
4+
5+
import logging
6+
logging.basicConfig(level=logging.DEBUG)
7+
8+
try:
9+
import Pyro4
10+
skip_container_test = False
11+
except ImportError:
12+
skip_container_test = True
13+
14+
15+
def test_whitebox_without_container():
16+
from hpolib.benchmarks.ml.xgboost_benchmark import XGBoostBenchmark as Benchmark
17+
b = Benchmark(task_id=167199, rng=0)
18+
cs = b.get_configuration_space(seed=0)
19+
20+
start = time()
21+
configuration = cs.get_default_configuration()
22+
assert configuration['colsample_bylevel'] == 1.0
23+
assert len(configuration.keys()) == 6
24+
25+
n_estimator = 32
26+
subsample = 1
27+
result_dict = b.objective_function(configuration, n_estimators=n_estimator, subsample=subsample, rng=0)
28+
valid_loss = result_dict['function_value']
29+
train_loss = result_dict['train_loss']
30+
31+
result_dict = b.objective_function_test(configuration, n_estimators=n_estimator, rng=0)
32+
test_loss = result_dict['function_value']
33+
34+
assert np.isclose(train_loss, 0.1071, atol=0.001)
35+
assert np.isclose(valid_loss, 0.3873, atol=0.001)
36+
assert np.isclose(test_loss, 0.38181, atol=0.001)
37+
38+
39+
@pytest.mark.skipif(skip_container_test, reason="Requires singularity and flask")
40+
def test_whitebox_with_container():
41+
from hpolib.container.benchmarks.ml.xgboost_benchmark import XGBoostBenchmark as Benchmark
42+
b = Benchmark(container_source='library://keggensperger/automl/',
43+
container_name='xgboost_benchmark',
44+
task_id=167199,
45+
rng=0)
46+
47+
cs = b.get_configuration_space()
48+
configuration = cs.get_default_configuration()
49+
assert configuration['colsample_bylevel'] == 1.0
50+
assert len(configuration.keys()) == 6
51+
52+
n_estimator = 32
53+
subsample = 1
54+
result_dict = b.objective_function(configuration, n_estimators=n_estimator, subsample=subsample)
55+
valid_loss = result_dict['function_value']
56+
train_loss = result_dict['train_loss']
57+
result_dict = b.objective_function_test(configuration, n_estimators=n_estimator)
58+
test_loss = result_dict['function_value']
59+
60+
print(train_loss, valid_loss, test_loss)
61+
assert np.isclose(train_loss, 0.1071, atol=0.001)
62+
assert np.isclose(valid_loss, 0.3873, atol=0.001)
63+
assert np.isclose(test_loss, 0.38181, atol=0.001)
64+

0 commit comments

Comments
 (0)