239 lines
7.5 KiB
Python
239 lines
7.5 KiB
Python
import os
|
|
import unittest
|
|
|
|
import ray
|
|
from ray.tune import (
|
|
CheckpointConfig,
|
|
Trainable,
|
|
TuneError,
|
|
register_trainable,
|
|
run_experiments,
|
|
)
|
|
from ray.tune.experiment import Experiment
|
|
from ray.tune.experiment.trial import ExportFormat, Trial
|
|
from ray.tune.logger import LoggerCallback
|
|
from ray.tune.result import TIMESTEPS_TOTAL
|
|
|
|
|
|
def train_fn(config):
|
|
for i in range(100):
|
|
ray.tune.report(dict(timesteps_total=i))
|
|
|
|
|
|
class RunExperimentTest(unittest.TestCase):
|
|
def setUp(self):
|
|
os.environ["TUNE_STATE_REFRESH_PERIOD"] = "0.1"
|
|
register_trainable("f1", train_fn)
|
|
|
|
def tearDown(self):
|
|
ray.shutdown()
|
|
|
|
def testDict(self):
|
|
trials = run_experiments(
|
|
{
|
|
"foo": {
|
|
"run": "f1",
|
|
},
|
|
"bar": {
|
|
"run": "f1",
|
|
},
|
|
}
|
|
)
|
|
for trial in trials:
|
|
self.assertEqual(trial.status, Trial.TERMINATED)
|
|
self.assertEqual(trial.last_result[TIMESTEPS_TOTAL], 99)
|
|
|
|
def testExperiment(self):
|
|
exp1 = Experiment(
|
|
**{
|
|
"name": "foo",
|
|
"run": "f1",
|
|
}
|
|
)
|
|
[trial] = run_experiments(exp1)
|
|
self.assertEqual(trial.status, Trial.TERMINATED)
|
|
self.assertEqual(trial.last_result[TIMESTEPS_TOTAL], 99)
|
|
|
|
def testExperimentList(self):
|
|
exp1 = Experiment(
|
|
**{
|
|
"name": "foo",
|
|
"run": "f1",
|
|
}
|
|
)
|
|
exp2 = Experiment(
|
|
**{
|
|
"name": "bar",
|
|
"run": "f1",
|
|
}
|
|
)
|
|
trials = run_experiments([exp1, exp2])
|
|
for trial in trials:
|
|
self.assertEqual(trial.status, Trial.TERMINATED)
|
|
self.assertEqual(trial.last_result[TIMESTEPS_TOTAL], 99)
|
|
|
|
def testAutoregisterTrainable(self):
|
|
class B(Trainable):
|
|
def step(self):
|
|
return {"timesteps_this_iter": 1, "done": True}
|
|
|
|
trials = run_experiments(
|
|
{
|
|
"foo": {
|
|
"run": train_fn,
|
|
},
|
|
"bar": {"run": B},
|
|
}
|
|
)
|
|
for trial in trials:
|
|
self.assertEqual(trial.status, Trial.TERMINATED)
|
|
|
|
def testCheckpointAtEnd(self):
|
|
class MyTrainable(Trainable):
|
|
def step(self):
|
|
return {"timesteps_this_iter": 1, "done": True}
|
|
|
|
def save_checkpoint(self, path):
|
|
checkpoint = os.path.join(path, "checkpoint")
|
|
with open(checkpoint, "w") as f:
|
|
f.write("OK")
|
|
|
|
trials = run_experiments(
|
|
{
|
|
"foo": {
|
|
"run": MyTrainable,
|
|
"checkpoint_config": CheckpointConfig(checkpoint_at_end=True),
|
|
}
|
|
}
|
|
)
|
|
for trial in trials:
|
|
self.assertEqual(trial.status, Trial.TERMINATED)
|
|
self.assertTrue(trial.checkpoint)
|
|
|
|
def testExportFormats(self):
|
|
class train_fn(Trainable):
|
|
def step(self):
|
|
return {"timesteps_this_iter": 1, "done": True}
|
|
|
|
def _export_model(self, export_formats, export_dir):
|
|
path = os.path.join(export_dir, "exported")
|
|
with open(path, "w") as f:
|
|
f.write("OK")
|
|
return {export_formats[0]: path}
|
|
|
|
trials = run_experiments(
|
|
{"foo": {"run": train_fn, "export_formats": ["format"]}}
|
|
)
|
|
for trial in trials:
|
|
self.assertEqual(trial.status, Trial.TERMINATED)
|
|
self.assertTrue(
|
|
os.path.exists(
|
|
os.path.join(trial.storage.trial_working_directory, "exported")
|
|
)
|
|
)
|
|
|
|
def testInvalidExportFormats(self):
|
|
class MyTrainable(Trainable):
|
|
def step(self):
|
|
return {"timesteps_this_iter": 1, "done": True}
|
|
|
|
def _export_model(self, export_formats, export_dir):
|
|
ExportFormat.validate(export_formats)
|
|
return {}
|
|
|
|
def fail_trial():
|
|
run_experiments({"foo": {"run": MyTrainable, "export_formats": ["format"]}})
|
|
|
|
self.assertRaises(TuneError, fail_trial)
|
|
|
|
def testCustomResources(self):
|
|
ray.shutdown()
|
|
ray.init(resources={"hi": 3})
|
|
|
|
class MyTrainable(Trainable):
|
|
def step(self):
|
|
return {"timesteps_this_iter": 1, "done": True}
|
|
|
|
trials = run_experiments(
|
|
{
|
|
"foo": {
|
|
"run": MyTrainable,
|
|
"resources_per_trial": {"cpu": 1, "custom_resources": {"hi": 2}},
|
|
}
|
|
}
|
|
)
|
|
for trial in trials:
|
|
self.assertEqual(trial.status, Trial.TERMINATED)
|
|
|
|
def testCustomLoggerNoAutoLogging(self):
|
|
"""Does not create CSV/JSON logger callbacks automatically"""
|
|
os.environ["TUNE_DISABLE_AUTO_CALLBACK_LOGGERS"] = "1"
|
|
|
|
class CustomLoggerCallback(LoggerCallback):
|
|
def log_trial_result(self, iteration, trial, result):
|
|
with open(os.path.join(trial.local_path, "test.log"), "w") as f:
|
|
f.write("hi")
|
|
|
|
[trial] = run_experiments(
|
|
{"foo": {"run": "f1", "stop": {"training_iteration": 1}}},
|
|
callbacks=[CustomLoggerCallback()],
|
|
)
|
|
self.assertTrue(os.path.exists(os.path.join(trial.local_path, "test.log")))
|
|
self.assertFalse(os.path.exists(os.path.join(trial.local_path, "params.json")))
|
|
|
|
[trial] = run_experiments(
|
|
{"foo": {"run": "f1", "stop": {"training_iteration": 1}}}
|
|
)
|
|
self.assertFalse(os.path.exists(os.path.join(trial.local_path, "params.json")))
|
|
|
|
[trial] = run_experiments(
|
|
{"foo": {"run": "f1", "stop": {"training_iteration": 1}}},
|
|
)
|
|
self.assertFalse(os.path.exists(os.path.join(trial.local_path, "params.json")))
|
|
|
|
def testCustomLoggerWithAutoLogging(self):
|
|
"""Creates CSV/JSON logger callbacks automatically"""
|
|
if "TUNE_DISABLE_AUTO_CALLBACK_LOGGERS" in os.environ:
|
|
del os.environ["TUNE_DISABLE_AUTO_CALLBACK_LOGGERS"]
|
|
|
|
class CustomLoggerCallback(LoggerCallback):
|
|
def log_trial_result(self, iteration, trial, result):
|
|
with open(os.path.join(trial.local_path, "test.log"), "w") as f:
|
|
f.write("hi")
|
|
|
|
[trial] = run_experiments(
|
|
{"foo": {"run": "f1", "stop": {"training_iteration": 1}}},
|
|
callbacks=[CustomLoggerCallback()],
|
|
)
|
|
self.assertTrue(os.path.exists(os.path.join(trial.local_path, "test.log")))
|
|
self.assertTrue(os.path.exists(os.path.join(trial.local_path, "params.json")))
|
|
|
|
[trial] = run_experiments(
|
|
{"foo": {"run": "f1", "stop": {"training_iteration": 1}}}
|
|
)
|
|
self.assertTrue(os.path.exists(os.path.join(trial.local_path, "params.json")))
|
|
|
|
def testCustomTrialString(self):
|
|
[trial] = run_experiments(
|
|
{
|
|
"foo": {
|
|
"run": "f1",
|
|
"stop": {"training_iteration": 1},
|
|
"trial_name_creator": lambda t: "{}_{}_321".format(
|
|
t.trainable_name, t.trial_id
|
|
),
|
|
}
|
|
}
|
|
)
|
|
self.assertEqual(
|
|
str(trial), "{}_{}_321".format(trial.trainable_name, trial.trial_id)
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import sys
|
|
|
|
import pytest
|
|
|
|
sys.exit(pytest.main(["-v", __file__]))
|