|
from nets.envs import SCI |
|
|
|
import os |
|
import numpy as np |
|
import optuna |
|
from optuna.trial import TrialState |
|
import torch |
|
import torch.nn as nn |
|
import torch.nn.functional as F |
|
import torch.optim as optim |
|
import torch.utils.data |
|
from torchmetrics import R2Score |
|
import neptune.new as neptune |
|
import neptune.new.integrations.optuna as outils |
|
from optuna.visualization import plot_contour, plot_optimization_history,plot_parallel_coordinate |
|
|
|
DEVICE = torch.device("cpu") |
|
BATCHSIZE = 2 |
|
DIR = os.getcwd() |
|
EPOCHS = 10 |
|
N_TRAIN_EXAMPLES = BATCHSIZE * 10 |
|
N_VALID_EXAMPLES = BATCHSIZE * 10 |
|
|
|
class Hyper(SCI): |
|
""" Hyper parameter tunning class. Allows to generate best NN architecture for task. Inputs are column indexes. idx[-1] is targeted value. |
|
|
|
|
|
""" |
|
def __init__(self,idx:tuple=(1,3,7),*args, **kwargs): |
|
super(Hyper,self).__init__() |
|
self.loader = self.data_flow(idx=idx) |
|
|
|
|
|
def define_model(self,trial): |
|
|
|
n_layers = trial.suggest_int("n_layers", 2, 6) |
|
layers = [] |
|
|
|
in_features = self.input_dim |
|
|
|
for i in range(n_layers): |
|
out_features = trial.suggest_int("n_units_l{}".format(i), 4, 128) |
|
activations = trial.suggest_categorical('activation',['ReLU','Tanh','SiLU','SELU','RReLU']) |
|
|
|
layers.append(nn.Linear(in_features, out_features)) |
|
layers.append(getattr(nn,activations)()) |
|
p = trial.suggest_float("dropout_l{}".format(i), 0.0, 0.2) |
|
layers.append(nn.Dropout(p)) |
|
|
|
in_features = out_features |
|
layers.append(nn.Linear(in_features, 1)) |
|
|
|
return nn.Sequential(*layers) |
|
def objective(self,trial): |
|
|
|
model = self.define_model(trial).to(DEVICE) |
|
mape = R2Score() |
|
|
|
optimizer_name = trial.suggest_categorical("optimizer", ["Adam", "RMSprop", "SGD",'AdamW','Adamax','Adagrad']) |
|
lr = trial.suggest_float("lr", 1e-7, 1e-3, log=True) |
|
optimizer = getattr(optim, optimizer_name)(model.parameters(), lr=lr) |
|
|
|
train_loader, valid_loader = self.loader,self.loader |
|
|
|
|
|
for epoch in range(EPOCHS): |
|
model.train() |
|
for batch_idx, (data, target) in enumerate(train_loader): |
|
|
|
if batch_idx * BATCHSIZE >= N_TRAIN_EXAMPLES: |
|
break |
|
|
|
data, target = data.view(data.size(0), -1).to(DEVICE), target.to(DEVICE) |
|
|
|
optimizer.zero_grad() |
|
output = model(data) |
|
loss = F.mse_loss(output, target) |
|
loss.backward() |
|
optimizer.step() |
|
|
|
|
|
model.eval() |
|
correct = 0 |
|
pred=torch.tensor([]) |
|
targs=torch.tensor([]) |
|
with torch.no_grad(): |
|
for batch_idx, (data, target) in enumerate(valid_loader): |
|
|
|
if batch_idx * BATCHSIZE >= N_VALID_EXAMPLES: |
|
break |
|
data, target = data.view(data.size(0), -1).to(DEVICE), target.to(DEVICE) |
|
|
|
output = model(data) |
|
|
|
|
|
|
|
pred = torch.cat((pred,output.squeeze())) |
|
targs = torch.cat((targs,target)) |
|
|
|
|
|
accuracy = mape(pred,targs) |
|
|
|
trial.report(accuracy, epoch) |
|
|
|
|
|
if trial.should_prune(): |
|
raise optuna.exceptions.TrialPruned() |
|
|
|
return accuracy |
|
|
|
def start_study(self,n_trials:int=100,neptune_project:str=None,neptune_api:str=None): |
|
""" Starts study. Optionally provide your neptune repo and token for report generation. |
|
|
|
Args: |
|
n_trials (int, optional): Number of iterations. Defaults to 100. |
|
neptune_project (str, optional): . Defaults to None. |
|
neptune_api (str, optional):. Defaults to None. |
|
|
|
Returns: |
|
dict: quick report of results |
|
""" |
|
|
|
study = optuna.create_study(direction="maximize") |
|
if neptune_project and neptune_api: |
|
run = neptune.init_run( |
|
project=neptune_project, |
|
api_token=neptune_api, |
|
) |
|
neptune_callback = outils.NeptuneCallback(run) |
|
study.optimize(self.objective, n_trials=n_trials, timeout=600,callbacks=[neptune_callback]) |
|
else: |
|
study.optimize(self.objective, n_trials=n_trials, timeout=600) |
|
|
|
|
|
|
|
pruned_trials = study.get_trials(deepcopy=False, states=[TrialState.PRUNED]) |
|
complete_trials = study.get_trials(deepcopy=False, states=[TrialState.COMPLETE]) |
|
|
|
print("Study statistics: ") |
|
print(" Number of finished trials: ", len(study.trials)) |
|
print(" Number of pruned trials: ", len(pruned_trials)) |
|
print(" Number of complete trials: ", len(complete_trials)) |
|
|
|
print("Best trial:") |
|
self.trial = study.best_trial |
|
|
|
print(" Value: ", self.trial.value) |
|
|
|
print(" Params: ") |
|
for key, value in self.trial.params.items(): |
|
print(" {}: {}".format(key, value)) |
|
|
|
if neptune_api and neptune_project: |
|
run.stop() |
|
|
|
return {" Number of finished trials: ":len(study.trials), |
|
" Number of pruned trials: ": len(pruned_trials), |
|
" Number of complete trials: ": len(complete_trials), |
|
"Best trial score" : self.trial.value, |
|
" Params: ": self.trial.params |
|
},plot_contour(study, params=["lr", "n_layers"]),\ |
|
plot_optimization_history(study),\ |
|
plot_parallel_coordinate(study) |