[Tune] Pbt Function API (#9958)

* adding function convnet example

* add unit test

* update test

* update example

* wip

* move error from experiment to tune

* wip

* Fix checkpoint deletion

* updating code

* adding smoke test

* updating pbt guide

* formatting

* fix build

* add best checkpoint analysis util

* update test

* add comments

* remove class api

* fix example

* add setup and teardown to tests

* formatting

* Update python/ray/tune/tests/test_trial_scheduler_pbt.py

Co-authored-by: Kai Fricke <kai@anyscale.com>
Co-authored-by: Richard Liaw <rliaw@berkeley.edu>
This commit is contained in:
Amog Kamsetty
2020-08-14 17:52:30 -07:00
committed by GitHub
co-authored by Kai Fricke Richard Liaw
parent fba5906ce3
commit f87a4aa45d
9 changed files with 274 additions and 32 deletions
@@ -1,6 +1,8 @@
# coding: utf-8
import os
import random
import sys
import tempfile
import unittest
from unittest.mock import patch
@@ -128,6 +130,35 @@ class CheckpointManagerTest(unittest.TestCase):
self.assertEqual(newest, checkpoints[1])
self.assertEqual(checkpoint_manager.best_checkpoints(), [])
def testSameCheckpoint(self):
checkpoint_manager = CheckpointManager(
1, "i", delete_fn=lambda c: os.remove(c.value))
tmpfiles = []
for i in range(3):
tmpfile = tempfile.mktemp()
with open(tmpfile, "wt") as fp:
fp.write("")
tmpfiles.append(tmpfile)
checkpoints = [
Checkpoint(Checkpoint.PERSISTENT, tmpfiles[0],
self.mock_result(5)),
Checkpoint(Checkpoint.PERSISTENT, tmpfiles[1],
self.mock_result(10)),
Checkpoint(Checkpoint.PERSISTENT, tmpfiles[2],
self.mock_result(0)),
Checkpoint(Checkpoint.PERSISTENT, tmpfiles[1],
self.mock_result(20))
]
for checkpoint in checkpoints:
checkpoint_manager.on_checkpoint(checkpoint)
self.assertTrue(os.path.exists(checkpoint.value))
for tmpfile in tmpfiles:
if os.path.exists(tmpfile):
os.remove(tmpfile)
if __name__ == "__main__":
import pytest
@@ -126,6 +126,13 @@ class ExperimentAnalysisSuite(unittest.TestCase):
assert paths[0][0] == expected_path
assert paths[0][1] == best_trial.metric_analysis[self.metric]["last"]
def testGetBestCheckpoint(self):
best_trial = self.ea.get_best_trial(self.metric)
checkpoints_metrics = self.ea.get_trial_checkpoints_paths(best_trial)
expected_path = max(checkpoints_metrics, key=lambda x: x[1])[0]
best_checkpoint = self.ea.get_best_checkpoint(best_trial, self.metric)
assert expected_path == best_checkpoint
def testAllDataframes(self):
dataframes = self.ea.trial_dataframes
self.assertTrue(len(dataframes) == self.num_samples)
@@ -5,6 +5,7 @@ import random
import unittest
import sys
import ray
from ray import tune
from ray.tune.schedulers import PopulationBasedTraining
@@ -23,13 +24,32 @@ class MockTrainable(tune.Trainable):
def save_checkpoint(self, tmp_checkpoint_dir):
checkpoint_path = os.path.join(tmp_checkpoint_dir, "model.mock")
with open(checkpoint_path, "wb") as fp:
pickle.dump((self.a, self.b), fp)
pickle.dump((self.a, self.b, self.iter), fp)
return tmp_checkpoint_dir
def load_checkpoint(self, tmp_checkpoint_dir):
checkpoint_path = os.path.join(tmp_checkpoint_dir, "model.mock")
with open(checkpoint_path, "rb") as fp:
self.a, self.b = pickle.load(fp)
self.a, self.b, self.iter = pickle.load(fp)
def MockTrainingFunc(config, checkpoint_dir=None):
iter = 0
a = config["a"]
b = config["b"]
if checkpoint_dir:
checkpoint_path = os.path.join(checkpoint_dir, "model.mock")
with open(checkpoint_path, "rb") as fp:
a, b, iter = pickle.load(fp)
while True:
iter += 1
with tune.checkpoint_dir(step=iter) as checkpoint_dir:
checkpoint_path = os.path.join(checkpoint_dir, "model.mock")
with open(checkpoint_path, "wb") as fp:
pickle.dump((a, b, iter), fp)
tune.report(mean_accuracy=(a - iter) * b)
class MockParam(object):
@@ -44,6 +64,12 @@ class MockParam(object):
class PopulationBasedTrainingResumeTest(unittest.TestCase):
def setUp(self):
ray.init()
def tearDown(self):
ray.shutdown()
def testPermutationContinuation(self):
"""
Tests continuation of runs after permutation.
@@ -74,7 +100,6 @@ class PopulationBasedTrainingResumeTest(unittest.TestCase):
},
fail_fast=True,
num_samples=20,
global_checkpoint_period=1,
checkpoint_freq=1,
checkpoint_at_end=True,
keep_checkpoints_num=1,
@@ -83,6 +108,33 @@ class PopulationBasedTrainingResumeTest(unittest.TestCase):
name="testPermutationContinuation",
stop={"training_iteration": 5})
def testPermutationContinuationFunc(self):
scheduler = PopulationBasedTraining(
time_attr="training_iteration",
metric="mean_accuracy",
mode="max",
perturbation_interval=1,
log_config=True,
hyperparam_mutations={"c": lambda: 1})
param_a = MockParam([10, 20, 30, 40])
param_b = MockParam([1.2, 0.9, 1.1, 0.8])
random.seed(100)
np.random.seed(1000)
tune.run(
MockTrainingFunc,
config={
"a": tune.sample_from(lambda _: param_a()),
"b": tune.sample_from(lambda _: param_b()),
"c": 1
},
fail_fast=True,
num_samples=4,
keep_checkpoints_num=1,
checkpoint_score_attr="min-training_iteration",
scheduler=scheduler,
name="testPermutationContinuationFunc",
stop={"training_iteration": 3})
if __name__ == "__main__":
import pytest