save ddpg model in database
This commit is contained in:
committed by
Dana Van Aken
parent
c8fbaf6e4b
commit
a3fcf59f07
@@ -185,6 +185,9 @@ class Migration(migrations.Migration):
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=64, verbose_name=b'session name')),
|
||||
('description', models.TextField(blank=True, null=True)),
|
||||
('ddpg_actor_model', models.BinaryField(null=True, blank=True)),
|
||||
('ddpg_critic_model', models.BinaryField(null=True, blank=True)),
|
||||
('ddpg_reply_memory', models.BinaryField(null=True, blank=True)),
|
||||
('creation_time', models.DateTimeField()),
|
||||
('last_update', models.DateTimeField()),
|
||||
('upload_code', models.CharField(max_length=30, unique=True)),
|
||||
|
||||
@@ -187,6 +187,9 @@ class Session(BaseModel):
|
||||
hardware = models.ForeignKey(Hardware)
|
||||
algorithm = models.IntegerField(choices=AlgorithmType.choices(),
|
||||
default=AlgorithmType.OTTERTUNE)
|
||||
ddpg_actor_model = models.BinaryField(null=True, blank=True)
|
||||
ddpg_critic_model = models.BinaryField(null=True, blank=True)
|
||||
ddpg_reply_memory = models.BinaryField(null=True, blank=True)
|
||||
|
||||
project = models.ForeignKey(Project)
|
||||
creation_time = models.DateTimeField()
|
||||
|
||||
@@ -353,7 +353,7 @@ class BaseParser(object, metaclass=ABCMeta):
|
||||
|
||||
def format_enum(self, enum_value, metadata):
|
||||
enumvals = metadata.enumvals.split(',')
|
||||
return enumvals[enum_value]
|
||||
return enumvals[int(round(enum_value))]
|
||||
|
||||
def format_integer(self, int_value, metadata):
|
||||
return int(round(int_value))
|
||||
|
||||
@@ -35,7 +35,7 @@ MAX_TRAIN_SIZE = 7000
|
||||
# Batch size in GPR model
|
||||
BATCH_SIZE = 3000
|
||||
|
||||
# Threads for TensorFlow config
|
||||
# Threads for TensorFlow config
|
||||
NUM_THREADS = 4
|
||||
|
||||
# ---GRADIENT DESCENT CONSTANTS---
|
||||
@@ -54,3 +54,19 @@ DEFAULT_EPSILON = 1e-6
|
||||
DEFAULT_SIGMA_MULTIPLIER = 3.0
|
||||
|
||||
DEFAULT_MU_MULTIPLIER = 1.0
|
||||
|
||||
# ---CONSTRAINTS CONSTANTS---
|
||||
# Batch size in DDPG model
|
||||
DDPG_BATCH_SIZE = 32
|
||||
|
||||
# Learning rate of actor network
|
||||
ACTOR_LEARNING_RATE = 0.001
|
||||
|
||||
# Learning rate of critic network
|
||||
CRITIC_LEARNING_RATE = 0.001
|
||||
|
||||
# The impact of future reward on the decision
|
||||
GAMMA = 0.1
|
||||
|
||||
# The changing rate of the target network
|
||||
TAU = 0.002
|
||||
|
||||
@@ -7,7 +7,7 @@ from .async_tasks import (aggregate_target_results,
|
||||
configuration_recommendation,
|
||||
map_workload,
|
||||
train_ddpg,
|
||||
run_ddpg)
|
||||
configuration_recommendation_ddpg)
|
||||
|
||||
|
||||
from .periodic_tasks import (run_background_tasks)
|
||||
|
||||
@@ -5,14 +5,12 @@
|
||||
#
|
||||
import random
|
||||
import queue
|
||||
from os.path import dirname, abspath, join
|
||||
import os
|
||||
import numpy as np
|
||||
|
||||
from celery.task import task, Task
|
||||
from celery.utils.log import get_task_logger
|
||||
from djcelery.models import TaskMeta
|
||||
from sklearn.preprocessing import StandardScaler
|
||||
from sklearn.preprocessing import StandardScaler, MinMaxScaler
|
||||
|
||||
from analysis.ddpg.ddpg import DDPG
|
||||
from analysis.gp import GPRNP
|
||||
@@ -29,7 +27,10 @@ from website.settings import (DEFAULT_LENGTH_SCALE, DEFAULT_MAGNITUDE,
|
||||
MAX_TRAIN_SIZE, BATCH_SIZE, NUM_THREADS,
|
||||
DEFAULT_RIDGE, DEFAULT_LEARNING_RATE,
|
||||
DEFAULT_EPSILON, MAX_ITER, GPR_EPS,
|
||||
DEFAULT_SIGMA_MULTIPLIER, DEFAULT_MU_MULTIPLIER)
|
||||
DEFAULT_SIGMA_MULTIPLIER, DEFAULT_MU_MULTIPLIER,
|
||||
DDPG_BATCH_SIZE, ACTOR_LEARNING_RATE,
|
||||
CRITIC_LEARNING_RATE, GAMMA, TAU)
|
||||
|
||||
from website.settings import INIT_FLIP_PROB, FLIP_PROB_DECAY
|
||||
from website.types import VarType
|
||||
|
||||
@@ -235,10 +236,10 @@ def train_ddpg(result_id):
|
||||
|
||||
# Clean knob data
|
||||
cleaned_agg_data = clean_knob_data(agg_data['X_matrix'], agg_data['X_columnlabels'], session)
|
||||
agg_data['X_matrix'] = np.array(cleaned_agg_data[0]).flatten()
|
||||
agg_data['X_columnlabels'] = np.array(cleaned_agg_data[1]).flatten()
|
||||
knob_data = DataUtil.normalize_knob_data(agg_data['X_matrix'],
|
||||
agg_data['X_columnlabels'], session)
|
||||
knob_data = np.array(cleaned_agg_data[0])
|
||||
knob_labels = np.array(cleaned_agg_data[1])
|
||||
knob_bounds = np.vstack(DataUtil.get_knob_bounds(knob_labels.flatten(), session))
|
||||
knob_data = MinMaxScaler().fit(knob_bounds).transform(knob_data)[0]
|
||||
knob_num = len(knob_data)
|
||||
metric_num = len(metric_data)
|
||||
LOG.info('knob_num: %d, metric_num: %d', knob_num, metric_num)
|
||||
@@ -276,26 +277,23 @@ def train_ddpg(result_id):
|
||||
* (2 * prev_objective - objective) / prev_objective
|
||||
|
||||
# Update ddpg
|
||||
project_root = dirname(dirname(dirname(abspath(__file__))))
|
||||
saved_memory = join(project_root, 'checkpoint/reply_memory_' + session.project.name)
|
||||
saved_model = join(project_root, 'checkpoint/ddpg_' + session.project.name)
|
||||
ddpg = DDPG(n_actions=knob_num, n_states=metric_num)
|
||||
if os.path.exists(saved_memory):
|
||||
ddpg.replay_memory.load_memory(saved_memory)
|
||||
ddpg.load_model(saved_model)
|
||||
ddpg = DDPG(n_actions=knob_num, n_states=metric_num, alr=ACTOR_LEARNING_RATE,
|
||||
clr=CRITIC_LEARNING_RATE, gamma=GAMMA, batch_size=DDPG_BATCH_SIZE, tau=TAU)
|
||||
if session.ddpg_actor_model and session.ddpg_critic_model:
|
||||
ddpg.set_model(session.ddpg_actor_model, session.ddpg_critic_model)
|
||||
if session.ddpg_reply_memory:
|
||||
ddpg.replay_memory.set(session.ddpg_reply_memory)
|
||||
ddpg.add_sample(prev_metric_data, knob_data, reward, metric_data, False)
|
||||
if len(ddpg.replay_memory) > 32:
|
||||
ddpg.update()
|
||||
checkpoint_dir = join(project_root, 'checkpoint')
|
||||
if not os.path.exists(checkpoint_dir):
|
||||
os.makedirs(checkpoint_dir)
|
||||
ddpg.replay_memory.save(saved_memory)
|
||||
ddpg.save_model(saved_model)
|
||||
session.ddpg_actor_model, session.ddpg_critic_model = ddpg.get_model()
|
||||
session.ddpg_reply_memory = ddpg.replay_memory.get()
|
||||
session.save()
|
||||
return result_info
|
||||
|
||||
|
||||
@task(base=ConfigurationRecommendation, name='run_ddpg')
|
||||
def run_ddpg(result_info):
|
||||
@task(base=ConfigurationRecommendation, name='configuration_recommendation_ddpg')
|
||||
def configuration_recommendation_ddpg(result_info): # pylint: disable=invalid-name
|
||||
LOG.info('Use ddpg to recommend configuration')
|
||||
result_id = result_info['newest_result_id']
|
||||
result = Result.objects.filter(pk=result_id)
|
||||
@@ -305,20 +303,20 @@ def run_ddpg(result_info):
|
||||
cleaned_agg_data = clean_knob_data(agg_data['X_matrix'], agg_data['X_columnlabels'],
|
||||
session)
|
||||
knob_labels = np.array(cleaned_agg_data[1]).flatten()
|
||||
knob_data = np.array(cleaned_agg_data[0]).flatten()
|
||||
knob_num = len(knob_data)
|
||||
knob_num = len(knob_labels)
|
||||
metric_num = len(metric_data)
|
||||
|
||||
project_root = dirname(dirname(dirname(abspath(__file__))))
|
||||
saved_memory = join(project_root, 'checkpoint/reply_memory_' + session.project.name)
|
||||
saved_model = join(project_root, 'checkpoint/ddpg_' + session.project.name)
|
||||
ddpg = DDPG(n_actions=knob_num, n_states=metric_num)
|
||||
if os.path.exists(saved_memory):
|
||||
ddpg.replay_memory.load_memory(saved_memory)
|
||||
ddpg.load_model(saved_model)
|
||||
ddpg = DDPG(n_actions=knob_num, n_states=metric_num, alr=ACTOR_LEARNING_RATE,
|
||||
clr=CRITIC_LEARNING_RATE, gamma=GAMMA, batch_size=DDPG_BATCH_SIZE, tau=TAU)
|
||||
if session.ddpg_actor_model is not None and session.ddpg_critic_model is not None:
|
||||
ddpg.set_model(session.ddpg_actor_model, session.ddpg_critic_model)
|
||||
if session.ddpg_reply_memory is not None:
|
||||
ddpg.replay_memory.set(session.ddpg_reply_memory)
|
||||
knob_data = ddpg.choose_action(metric_data)
|
||||
LOG.info('recommended knob: %s', knob_data)
|
||||
knob_data = DataUtil.denormalize_knob_data(knob_data, knob_labels, session)
|
||||
|
||||
knob_bounds = np.vstack(DataUtil.get_knob_bounds(knob_labels, session))
|
||||
knob_data = MinMaxScaler().fit(knob_bounds).inverse_transform(knob_data.reshape(1, -1))[0]
|
||||
conf_map = {k: knob_data[i] for i, k in enumerate(knob_labels)}
|
||||
conf_map_res = {}
|
||||
conf_map_res['status'] = 'good'
|
||||
|
||||
@@ -93,30 +93,35 @@ class TaskUtil(object):
|
||||
class DataUtil(object):
|
||||
|
||||
@staticmethod
|
||||
def normalize_knob_data(knob_values, knob_labels, session):
|
||||
for i, knob in enumerate(knob_labels):
|
||||
def get_knob_bounds(knob_labels, session):
|
||||
minvals = []
|
||||
maxvals = []
|
||||
for _, knob in enumerate(knob_labels):
|
||||
knob_object = KnobCatalog.objects.get(dbms=session.dbms, name=knob, tunable=True)
|
||||
minval = float(knob_object.minval)
|
||||
maxval = float(knob_object.maxval)
|
||||
knob_new = SessionKnob.objects.filter(knob=knob_object, session=session, tunable=True)
|
||||
if knob_new.exists():
|
||||
minval = float(knob_new[0].minval)
|
||||
maxval = float(knob_new[0].maxval)
|
||||
knob_values[i] = (knob_values[i] - minval) / (maxval - minval)
|
||||
knob_values[i] = max(0, min(knob_values[i], 1))
|
||||
return knob_values
|
||||
|
||||
@staticmethod
|
||||
def denormalize_knob_data(knob_values, knob_labels, session):
|
||||
for i, knob in enumerate(knob_labels):
|
||||
knob_object = KnobCatalog.objects.get(dbms=session.dbms, name=knob, tunable=True)
|
||||
minval = float(knob_object.minval)
|
||||
maxval = float(knob_object.maxval)
|
||||
knob_session_object = SessionKnob.objects.filter(knob=knob_object, session=session,
|
||||
tunable=True)
|
||||
if knob_session_object.exists():
|
||||
minval = float(knob_session_object[0].minval)
|
||||
maxval = float(knob_session_object[0].maxval)
|
||||
else:
|
||||
minval = float(knob_object.minval)
|
||||
maxval = float(knob_object.maxval)
|
||||
minvals.append(minval)
|
||||
maxvals.append(maxval)
|
||||
return np.array(minvals), np.array(maxvals)
|
||||
|
||||
@staticmethod
|
||||
def denormalize_knob_data(knob_values, knob_labels, session):
|
||||
for i, knob in enumerate(knob_labels):
|
||||
knob_object = KnobCatalog.objects.get(dbms=session.dbms, name=knob, tunable=True)
|
||||
knob_session_object = SessionKnob.objects.filter(knob=knob_object, session=session,
|
||||
tunable=True)
|
||||
if knob_session_object.exists():
|
||||
minval = float(knob_session_object[0].minval)
|
||||
maxval = float(knob_session_object[0].maxval)
|
||||
else:
|
||||
minval = float(knob_object.minval)
|
||||
maxval = float(knob_object.maxval)
|
||||
knob_values[i] = knob_values[i] * (maxval - minval) + minval
|
||||
return knob_values
|
||||
|
||||
|
||||
@@ -30,8 +30,8 @@ from .models import (BackupData, DBMSCatalog, KnobCatalog, KnobData, MetricCatal
|
||||
MetricData, MetricManager, Project, Result, Session, Workload,
|
||||
SessionKnob)
|
||||
from .parser import Parser
|
||||
from .tasks import (aggregate_target_results, map_workload, train_ddpg, run_ddpg,
|
||||
configuration_recommendation)
|
||||
from .tasks import (aggregate_target_results, map_workload, train_ddpg,
|
||||
configuration_recommendation, configuration_recommendation_ddpg)
|
||||
from .types import (DBMSType, KnobUnitType, MetricType,
|
||||
TaskType, VarType, WorkloadStatusType, AlgorithmType)
|
||||
from .utils import JSONUtil, LabelUtil, MediaUtil, TaskUtil
|
||||
|
||||
Reference in New Issue
Block a user