Random Search in hyperparam

This commit is contained in:
Petrônio Cândido 2019-12-25 22:11:08 -03:00
parent ed9c07deae
commit ad1205121d
5 changed files with 178 additions and 12 deletions

View File

@ -410,10 +410,6 @@ class FTS(object):
if save:
Util.persist_obj(self, file_path)
if 'statistics' in kw:
kwargs['statistics'] = kw['statistics']
print(kwargs['statistics'])
def clone_parameters(self, model):
"""

View File

@ -29,7 +29,7 @@ from pyFTS.common import Membership
from pyFTS.models import hofts, ifts, pwfts
from pyFTS.hyperparam import Util as hUtil
from pyFTS.distributed import dispy as dUtil
from pyFTS.hyperparam import Evolutionary
from pyFTS.hyperparam import Evolutionary, random_search as RS
from pyFTS.models.multivariate import mvfts, wmvfts, variable
from pyFTS.models.seasonal import partitioner as seasonal
from pyFTS.models.seasonal.common import DateTime
@ -315,6 +315,7 @@ def crossover_variable_params(best, worst, var):
param = {'partitioner': partitioner, 'npart': npart, 'alpha': alpha, 'mf': mf}
return param
def mutation(individual, **kwargs):
"""
Mutation operator
@ -356,6 +357,51 @@ def mutation(individual, **kwargs):
return individual
def mutation_random_search(individual, **kwargs):
"""
Mutation operator
:param individual: an individual genotype
:param pmut: individual probability o
:return:
"""
vars = kwargs.get('variables', None)
tvar = kwargs.get('target_variable', None)
l = len(vars)
il = len(individual['explanatory_variables'])
#
if il > 1:
for l in range(il):
il = len(individual['explanatory_variables'])
rnd = random.uniform(0, 1)
if rnd > .5:
rnd = random.randint(0, il-1)
val = individual['explanatory_variables'][rnd]
individual['explanatory_variables'].remove(val)
individual['explanatory_params'].pop(rnd)
else:
rnd = random.randint(0, l-1)
while rnd in individual['explanatory_variables']:
rnd = random.randint(0, l-1)
individual['explanatory_variables'].append(rnd)
individual['explanatory_params'].append(random_param(vars[rnd]))
for ct in np.arange(len(individual['explanatory_variables'])):
rnd = random.uniform(0, 1)
if rnd > .5:
mutate_variable_params(individual['explanatory_params'][ct], vars[ct])
rnd = random.uniform(0, 1)
if rnd > .5:
mutate_variable_params(individual['target_params'], tvar)
individual['f1'] = None
individual['f2'] = None
return individual
def mutate_variable_params(param, var):
if var['type']=='common':
@ -458,3 +504,31 @@ def log_result(datasetname, fts_method, result):
file.write(json.dumps(result))
print(result)
def random_search(datasetname, dataset, **kwargs):
experiments = kwargs.get('experiments', 30)
distributed = kwargs.get('distributed', False)
fts_method = kwargs.get('fts_method', hofts.WeightedHighOrderFTS)
shortname = str(fts_method.__module__).split('.')[-1]
kwargs['mutation_operator'] = mutation_random_search
kwargs['evaluation_operator'] = evaluate
kwargs['random_individual'] = random_genotype
ret = []
for i in np.arange(experiments):
print("Experiment {}".format(i))
start = time.time()
ret, statistics = RS.execute (dataset, **kwargs)
end = time.time()
ret['time'] = end - start
experiment = {'individual': ret, 'statistics': statistics}
ret = process_experiment(shortname, experiment, datasetname)
return ret

View File

@ -0,0 +1,84 @@
"""
Simple Random Search Hyperparameter Optimization
"""
from pyFTS.hyperparam import Evolutionary
import time
__measures = ['f1', 'f2', 'rmse', 'size']
def execute( dataset, **kwargs):
"""
Batch execution of Random Search Hyperparameter Optimization
:param datasetname:
:param dataset: The time series to optimize the FTS
:keyword ngen: An integer value with the maximum number of generations, default value: 30
:keyword mgen: An integer value with the maximum number of generations without improvement to stop, default value 7
:keyword fts_method: The FTS method to optimize
:keyword parameters: dict with model specific arguments for fts_method
:keyword random_individual: create an random genotype
:keyword evalutation_operator: a function that receives a dataset and an individual and return its fitness
:keyword mutation_operator: a function that receives one individual and return a changed individual
:keyword window_size: An integer value with the the length of scrolling window for train/test on dataset
:keyword train_rate: A float value between 0 and 1 with the train/test split ([0,1])
:keyword increment_rate: A float value between 0 and 1 with the the increment of the scrolling window,
relative to the window_size ([0,1])
:keyword collect_statistics: A boolean value indicating to collect statistics for each generation
:keyword distributed: A value indicating it the execution will be local and sequential (distributed=False),
or parallel and distributed (distributed='dispy' or distributed='spark')
:keyword cluster: If distributed='dispy' the list of cluster nodes, else if distributed='spark' it is the master node
:return: the best genotype
"""
ngen = kwargs.get('ngen',30)
mgen = kwargs.get('mgen', 7)
kwargs['pmut'] = 1.0
random_individual = kwargs.get('random_individual', Evolutionary.random_genotype)
evaluation_operator = kwargs.get('evaluation_operator', Evolutionary.evaluate)
mutation_operator = kwargs.get('mutation_operator', Evolutionary.mutation)
no_improvement_count = 0
individual = random_individual(**kwargs)
stat = {}
stat[0] = {}
ret = evaluation_operator(dataset, individual, **kwargs)
for key in __measures:
individual[key] = ret[key]
stat[0][key] = ret[key]
print(individual)
for i in range(1,ngen+1):
print("GENERATION {} {}".format(i, time.time()))
new = mutation_operator(individual, **kwargs)
ret = evaluation_operator(dataset, new, **kwargs)
new_stat = {}
for key in __measures:
new[key] = ret[key]
new_stat[key] = ret[key]
print(new)
if new['f1'] <= individual['f1'] and new['f2'] <= individual['f2']:
individual = new
no_improvement_count = 0
stat[i] = new_stat
print(individual)
else:
stat[i] = stat[i-1]
no_improvement_count += 1
print("WITHOUT IMPROVEMENT {}".format(no_improvement_count))
if no_improvement_count == mgen:
break
return individual, stat

View File

@ -162,12 +162,10 @@ class Partitioner(object):
nearest = self.search(data, type='index')
mv = np.zeros(self.partitions)
try:
for ix in nearest:
tmp = self[ix].membership(data)
mv[ix] = tmp if tmp >= alpha_cut else 0.
except:
print(ix)
ix = np.ravel(np.argwhere(mv > 0.))

View File

@ -56,6 +56,20 @@ explanatory_variables =[
target_variable = {'name': 'Load', 'data_label': 'load', 'type': 'common'}
nodes=['192.168.28.38']
deho_mv.random_search(datsetname, dataset,
ngen=200, mgen=200,
window_size=2000, train_rate=.9, increment_rate=1,
experiments=1,
fts_method=wmvfts.WeightedMVFTS,
variables=explanatory_variables,
target_variable=target_variable,
#distributed='dispy', nodes=nodes,
parameters=dict(num_batches=5)
#parameters=dict(distributed='dispy', nodes=nodes, num_batches=5)
)
'''
deho_mv.execute(datsetname, dataset,
ngen=20, npop=15,psel=0.6, pcross=.5, pmut=.3,
window_size=2000, train_rate=.9, increment_rate=1,
@ -67,7 +81,7 @@ deho_mv.execute(datsetname, dataset,
parameters=dict(num_batches=5)
#parameters=dict(distributed='dispy', nodes=nodes, num_batches=5)
)
'''
'''
ret = Evolutionary.execute(datsetname, dataset,
ngen=30, npop=20,psel=0.6, pcross=.5, pmut=.3,