Merge branch 'plot_hyperopt_stats' into opt-ask-force-new-points

This commit is contained in:
Italo
2022-03-30 00:30:33 +01:00
committed by GitHub
15 changed files with 184 additions and 169 deletions

View File

@@ -32,20 +32,24 @@ from freqtrade.optimize.hyperopt_loss_interface import IHyperOptLoss # noqa: F4
from freqtrade.optimize.hyperopt_tools import HyperoptTools, hyperopt_serializer
from freqtrade.optimize.optimize_reports import generate_strategy_stats
from freqtrade.resolvers.hyperopt_resolver import HyperOptLossResolver
import matplotlib.pyplot as plt
import numpy as np
import random
# Suppress scikit-learn FutureWarnings from skopt
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=FutureWarning)
from skopt import Optimizer
from skopt.space import Dimension
from sklearn.model_selection import cross_val_score
from skopt.plots import plot_convergence, plot_regret, plot_evaluations, plot_objective
progressbar.streams.wrap_stderr()
progressbar.streams.wrap_stdout()
logger = logging.getLogger(__name__)
INITIAL_POINTS = 30
INITIAL_POINTS = 32
# Keep no more than SKOPT_MODEL_QUEUE_SIZE models
# in the skopt model queue, to optimize memory consumption
@@ -409,6 +413,35 @@ class Hyperopt:
f'({(self.max_date - self.min_date).days} days)..')
# Store non-trimmed data - will be trimmed after signal generation.
dump(preprocessed, self.data_pickle_file)
def get_asked_points(self, n_points: int) -> List[List[Any]]:
'''
Enforce points returned from `self.opt.ask` have not been already evaluated
Steps:
1. Try to get points using `self.opt.ask` first
2. Discard the points that have already been evaluated
3. Retry using `self.opt.ask` up to 3 times
4. If still some points are missing in respect to `n_points`, random sample some points
5. Repeat until at least `n_points` points in the `asked_non_tried` list
6. Return a list with length truncated at `n_points`
'''
i = 0
asked_non_tried: List[List[Any]] = []
while i < 100 and len(asked_non_tried) < n_points:
if i < 3:
self.opt.cache_ = {}
asked = self.opt.ask(n_points=n_points * 5)
else:
asked = self.opt.space.rvs(n_samples=n_points * 5)
asked_non_tried += [x for x in asked
if x not in self.opt.Xi
and x not in asked_non_tried]
i += 1
if asked_non_tried:
return asked_non_tried[:min(len(asked_non_tried), n_points)]
else:
return self.opt.ask(n_points=n_points)
def get_asked_points(self, n_points: int) -> Tuple[List[List[Any]], List[bool]]:
'''
@@ -515,7 +548,13 @@ class Hyperopt:
asked, is_random = self.get_asked_points(n_points=current_jobs)
f_val = self.run_optimizer_parallel(parallel, asked, i)
self.opt.tell(asked, [v['loss'] for v in f_val])
res = self.opt.tell(asked, [v['loss'] for v in f_val])
self.plot_optimizer(res, path='user_data/scripts', convergence=False, regret=False, r2=False, objective=True, jobs=jobs)
if res.models and hasattr(res.models[-1], "kernel_"):
print(f'kernel: {res.models[-1].kernel_}')
print(datetime.now())
# Calculate progressbar outputs
for j, val in enumerate(f_val):
@@ -561,3 +600,47 @@ class Hyperopt:
# This is printed when Ctrl+C is pressed quickly, before first epochs have
# a chance to be evaluated.
print("No epochs evaluated yet, no best result.")
def plot_r2(self, res, ax, jobs):
if len(res.x_iters) < 10:
return
if not hasattr(self, 'r2_list'):
self.r2_list = []
model = res.models[-1]
model.criterion = 'squared_error'
r2 = cross_val_score(model, X=res.x_iters, y=res.func_vals, scoring='r2', cv=5, n_jobs=jobs).mean()
r2 = r2 if r2 > -5 else -5
self.r2_list.append(r2)
ax.plot(range(INITIAL_POINTS, INITIAL_POINTS + jobs * len(self.r2_list), jobs), self.r2_list, label='R2', marker=".", markersize=12, lw=2)
def plot_optimizer(self, res, path, jobs, convergence=True, regret=True, evaluations=True, objective=True, r2=True):
path = Path(path)
if convergence:
ax = plot_convergence(res)
ax.flatten()[0].figure.savefig(path / 'convergence.png')
if regret:
ax = plot_regret(res)
ax.flatten()[0].figure.savefig(path / 'regret.png')
if evaluations:
# print('evaluations')
ax = plot_evaluations(res)
ax.flatten()[0].figure.savefig(path / 'evaluations.png')
if objective and res.models:
# print('objective')
ax = plot_objective(res, sample_source='result', n_samples=50, n_points=10)
ax.flatten()[0].figure.savefig(path / 'objective.png')
if r2 and res.models:
fig, ax = plt.subplots()
ax.set_ylabel('R2')
ax.set_xlabel('Epoch')
ax.set_title('R2')
ax = self.plot_r2(res, ax, jobs)
fig.savefig(path / 'r2.png')