ray/doc/source/tune/examples/nevergrad_example.ipynb

348 lines
9.2 KiB
Text
Raw Normal View History

{
"cells": [
{
"cell_type": "markdown",
"id": "5a1d28f3",
"metadata": {},
"source": [
"# Running Tune experiments with Nevergrad\n",
"\n",
"In this tutorial we introduce Nevergrad, while running a simple Ray Tune experiment. Tunes Search Algorithms integrate with Nevergrad and, as a result, allow you to seamlessly scale up a Nevergrad optimization process - without sacrificing performance.\n",
"\n",
"Nevergrad provides gradient/derivative-free optimization able to handle noise over the objective landscape, including evolutionary, bandit, and Bayesian optimization algorithms. Nevergrad internally supports search spaces which are continuous, discrete or a mixture of thereof. It also provides a library of functions on which to test the optimization algorithms and compare with other benchmarks.\n",
"\n",
"In this example we minimize a simple objective to briefly demonstrate the usage of Nevergrad with Ray Tune via `NevergradSearch`. It's useful to keep in mind that despite the emphasis on machine learning experiments, Ray Tune optimizes any implicit or explicit objective. Here we assume `nevergrad==0.4.3.post7` library is installed. To learn more, please refer to [Nevergrad website](https://github.com/facebookresearch/nevergrad)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5ab54f85",
"metadata": {
"tags": [
"remove-cell"
]
},
"outputs": [],
"source": [
"# !pip install ray[tune]\n",
"!pip install nevergrad==0.4.3.post7 "
]
},
{
"cell_type": "markdown",
"id": "66cb8206",
"metadata": {},
"source": [
"Click below to see all the imports we need for this example.\n",
"You can also launch directly into a Binder instance to run this notebook yourself.\n",
"Just click on the rocket symbol at the top of the navigation."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1f6d7a31",
"metadata": {
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"import time\n",
"\n",
"import ray\n",
"import nevergrad as ng\n",
"from ray import tune\n",
"from ray.tune.suggest import ConcurrencyLimiter\n",
"from ray.tune.suggest.nevergrad import NevergradSearch"
]
},
{
"cell_type": "markdown",
"id": "41f2c881",
"metadata": {},
"source": [
"Let's start by defining a simple evaluation function.\n",
"We artificially sleep for a bit (`0.1` seconds) to simulate a long-running ML experiment.\n",
"This setup assumes that we're running multiple `step`s of an experiment and try to tune two hyperparameters,\n",
"namely `width` and `height`, and `activation`."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "271bd5c5",
"metadata": {},
"outputs": [],
"source": [
"def evaluate(step, width, height, activation):\n",
" time.sleep(0.1)\n",
" activation_boost = 10 if activation==\"relu\" else 1\n",
" return (0.1 + width * step / 100) ** (-1) + height * 0.1 + activation_boost"
]
},
{
"cell_type": "markdown",
"id": "f060ea83",
"metadata": {},
"source": [
"Next, our `objective` function takes a Tune `config`, evaluates the `score` of your experiment in a training loop,\n",
"and uses `tune.report` to report the `score` back to Tune."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c71fc423",
"metadata": {},
"outputs": [],
"source": [
"def objective(config):\n",
" for step in range(config[\"steps\"]):\n",
" score = evaluate(step, config[\"width\"], config[\"height\"], config[\"activation\"])\n",
" tune.report(iterations=step, mean_loss=score)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "619263ee",
"metadata": {
"lines_to_next_cell": 0,
"tags": [
"remove-cell"
]
},
"outputs": [],
"source": [
"ray.init(configure_logging=False)"
]
},
{
"cell_type": "markdown",
"id": "5b7a4b94",
"metadata": {},
"source": [
"Now we construct the hyperparameter search space using `ConfigSpace`"
]
},
{
"cell_type": "markdown",
"id": "e2405373",
"metadata": {},
"source": [
"Next we define the search algorithm built from `NevergradSearch`, constrained to a maximum of `4` concurrent trials with a `ConcurrencyLimiter`. Here we use `ng.optimizers.OnePlusOne`, a simple evolutionary algorithm."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f099b674",
"metadata": {},
"outputs": [],
"source": [
"algo = NevergradSearch(\n",
" optimizer=ng.optimizers.OnePlusOne,\n",
")\n",
"algo = tune.suggest.ConcurrencyLimiter(algo, max_concurrent=4)"
]
},
{
"cell_type": "markdown",
"id": "4bddc4e5",
"metadata": {},
"source": [
"The number of samples is the number of hyperparameter combinations that will be tried out. This Tune run is set to `1000` samples.\n",
"(you can decrease this if it takes too long on your machine)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "adb807bc",
"metadata": {},
"outputs": [],
"source": [
"num_samples = 1000"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "191c7f89",
"metadata": {
"tags": [
"remove-cell"
]
},
"outputs": [],
"source": [
"# If 1000 samples take too long, you can reduce this number.\n",
"# We override this number here for our smoke tests.\n",
"num_samples = 10"
]
},
{
"cell_type": "markdown",
"id": "a3956381",
"metadata": {},
"source": [
"Finally, all that's left is to define a search space."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8829ffc5",
"metadata": {},
"outputs": [],
"source": [
"search_config = {\n",
" \"steps\": 100,\n",
" \"width\": tune.uniform(0, 20),\n",
" \"height\": tune.uniform(-100, 100),\n",
" \"activation\": tune.choice([\"relu, tanh\"])\n",
"}"
]
},
{
"cell_type": "markdown",
"id": "0b9d051f",
"metadata": {},
"source": [
"Finally, we run the experiment to `\"min\"`imize the \"mean_loss\" of the `objective` by searching `search_space` via `algo`, `num_samples` times. This previous sentence is fully characterizes the search problem we aim to solve. With this in mind, observe how efficient it is to execute `tune.run()`."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "769f4368",
"metadata": {},
"outputs": [],
"source": [
"analysis = tune.run(\n",
" objective,\n",
" search_alg=algo,\n",
" metric=\"mean_loss\",\n",
" mode=\"min\",\n",
" name=\"nevergrad_exp\",\n",
" num_samples=num_samples,\n",
" config=search_config,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "950003be",
"metadata": {},
"source": [
"Here are the hyperparamters found to minimize the mean loss of the defined objective."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0f021674",
"metadata": {
"lines_to_next_cell": 0
},
"outputs": [],
"source": [
"print(\"Best hyperparameters found were: \", analysis.best_config)"
]
},
{
"cell_type": "markdown",
"id": "0d3824ae",
"metadata": {},
"source": [
"## Optional: passing the (hyper)parameter space into the search algorithm\n",
"\n",
"We can also pass the search space into `NevergradSearch` using their designed format."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "89ae7455",
"metadata": {},
"outputs": [],
"source": [
"space = ng.p.Dict(\n",
" width=ng.p.Scalar(lower=0, upper=20),\n",
" height=ng.p.Scalar(lower=-100, upper=100),\n",
" activation=ng.p.Choice(choices=[\"relu\", \"tanh\"])\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e52eeab1",
"metadata": {},
"outputs": [],
"source": [
"algo = NevergradSearch(\n",
" optimizer=ng.optimizers.OnePlusOne,\n",
" space=space,\n",
" metric=\"mean_loss\",\n",
" mode=\"min\"\n",
")\n",
"algo = tune.suggest.ConcurrencyLimiter(algo, max_concurrent=4)"
]
},
{
"cell_type": "markdown",
"id": "f8926177",
"metadata": {},
"source": [
"Again we run the experiment, this time with a less passed via the `config` and instead passed through `search_alg`."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "64f39800",
"metadata": {},
"outputs": [],
"source": [
"analysis = tune.run(\n",
" objective,\n",
" search_alg=algo,\n",
"# metric=\"mean_loss\",\n",
"# mode=\"min\",\n",
" name=\"nevergrad_exp\",\n",
" num_samples=num_samples,\n",
" config={\"steps\": 100},\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0478c1ea",
"metadata": {
"tags": [
"remove-cell"
]
},
"outputs": [],
"source": [
"ray.shutdown()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"orphan": true
},
"nbformat": 4,
"nbformat_minor": 5
}