Evolutive hyperparam
This commit is contained in:
parent
4029b4223d
commit
cf24e88b8a
338
pyFTS/hyperparam/Evolutionary.py
Normal file
338
pyFTS/hyperparam/Evolutionary.py
Normal file
@ -0,0 +1,338 @@
|
|||||||
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
import math
|
||||||
|
import time
|
||||||
|
from functools import reduce
|
||||||
|
from operator import itemgetter
|
||||||
|
import dispy
|
||||||
|
|
||||||
|
import random
|
||||||
|
from pyFTS.common import Util
|
||||||
|
from pyFTS.benchmarks import Measures
|
||||||
|
from pyFTS.partitioners import Grid, Entropy # , Huarng
|
||||||
|
from pyFTS.models import hofts
|
||||||
|
from pyFTS.common import Membership
|
||||||
|
from pyFTS.hyperparam import Util as hUtil
|
||||||
|
|
||||||
|
|
||||||
|
# Gera indivíduos após operadores
|
||||||
|
def genotype(mf, npart, partitioner, order, alpha, lags, len_lags, rmse):
|
||||||
|
ind = dict(mf=mf, npart=npart, partitioner=partitioner, order=order, alpha=alpha, lags=lags, len_lags=len_lags,
|
||||||
|
rmse=rmse)
|
||||||
|
return ind
|
||||||
|
|
||||||
|
|
||||||
|
# Gera indivíduos
|
||||||
|
def random_genotype():
|
||||||
|
order = random.randint(1, 3)
|
||||||
|
return genotype(
|
||||||
|
random.randint(1, 4),
|
||||||
|
random.randint(10, 100),
|
||||||
|
random.randint(1, 2),
|
||||||
|
order,
|
||||||
|
random.uniform(0, .5),
|
||||||
|
sorted(random.sample(range(1, 50), order)),
|
||||||
|
[],
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Gera uma população de tamanho n
|
||||||
|
def initial_population(n):
|
||||||
|
pop = []
|
||||||
|
for i in range(n):
|
||||||
|
pop.append(random_genotype())
|
||||||
|
return pop
|
||||||
|
|
||||||
|
|
||||||
|
# Função de avaliação
|
||||||
|
def phenotype(individual, train):
|
||||||
|
try:
|
||||||
|
if individual['mf'] == 1:
|
||||||
|
mf = Membership.trimf
|
||||||
|
elif individual['mf'] == 2:
|
||||||
|
mf = Membership.trapmf
|
||||||
|
elif individual['mf'] == 3 and individual['partitioner'] != 2:
|
||||||
|
mf = Membership.gaussmf
|
||||||
|
else:
|
||||||
|
mf = Membership.trimf
|
||||||
|
|
||||||
|
if individual['partitioner'] == 1:
|
||||||
|
partitioner = Grid.GridPartitioner(data=train, npart=individual['npart'], func=mf)
|
||||||
|
elif individual['partitioner'] == 2:
|
||||||
|
partitioner = Entropy.EntropyPartitioner(data=train, npart=individual['npart'], func=mf)
|
||||||
|
|
||||||
|
model = hofts.WeightedHighOrderFTS(partitioner=partitioner,
|
||||||
|
lags=individual['lags'],
|
||||||
|
alpha_cut=individual['alpha'],
|
||||||
|
order=individual['order'])
|
||||||
|
|
||||||
|
model.fit(train)
|
||||||
|
|
||||||
|
return model
|
||||||
|
|
||||||
|
except Exception as ex:
|
||||||
|
print("EXCEPTION!", str(ex), str(individual))
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def evaluation1(dataset, individual):
|
||||||
|
from pyFTS.common import Util
|
||||||
|
from pyFTS.benchmarks import Measures
|
||||||
|
|
||||||
|
try:
|
||||||
|
results = []
|
||||||
|
lengths = []
|
||||||
|
|
||||||
|
for count, train, test in Util.sliding_window(dataset, 800, train=.8, inc=.25):
|
||||||
|
model = phenotype(individual, train)
|
||||||
|
|
||||||
|
if model is None:
|
||||||
|
return (None)
|
||||||
|
|
||||||
|
rmse, _, _ = Measures.get_point_statistics(test, model)
|
||||||
|
lengths.append(len(model))
|
||||||
|
|
||||||
|
results.append(rmse)
|
||||||
|
|
||||||
|
_lags = sum(model.lags) * 100
|
||||||
|
|
||||||
|
rmse = np.nansum([.6 * np.nanmean(results), .4 * np.nanstd(results)])
|
||||||
|
len_lags = np.nansum([.4 * np.nanmean(lengths), .6 * _lags])
|
||||||
|
|
||||||
|
return len_lags, rmse
|
||||||
|
|
||||||
|
except Exception as ex:
|
||||||
|
print("EXCEPTION!", str(ex), str(individual))
|
||||||
|
return np.inf
|
||||||
|
|
||||||
|
|
||||||
|
def tournament(population, objective):
|
||||||
|
n = len(population) - 1
|
||||||
|
|
||||||
|
r1 = random.randint(0, n) if n > 2 else 0
|
||||||
|
r2 = random.randint(0, n) if n > 2 else 1
|
||||||
|
ix = r1 if population[r1][objective] < population[r2][objective] else r2
|
||||||
|
return population[ix]
|
||||||
|
|
||||||
|
|
||||||
|
def selection1(population):
|
||||||
|
pais = []
|
||||||
|
prob = .8
|
||||||
|
|
||||||
|
# for i in range(len(population)):
|
||||||
|
pai1 = tournament(population, 'rmse')
|
||||||
|
pai2 = tournament(population, 'rmse')
|
||||||
|
|
||||||
|
finalista = tournament([pai1, pai2], 'len_lags')
|
||||||
|
|
||||||
|
return finalista
|
||||||
|
|
||||||
|
|
||||||
|
def lag_crossover2(best, worst):
|
||||||
|
order = int(round(.7 * best['order'] + .3 * worst['order']))
|
||||||
|
lags = []
|
||||||
|
|
||||||
|
min_order = min(best['order'], worst['order'])
|
||||||
|
|
||||||
|
max_order = best if best['order'] > min_order else worst
|
||||||
|
|
||||||
|
for k in np.arange(0, order):
|
||||||
|
if k < min_order:
|
||||||
|
lags.append(int(round(.7 * best['lags'][k] + .3 * worst['lags'][k])))
|
||||||
|
else:
|
||||||
|
lags.append(max_order['lags'][k])
|
||||||
|
|
||||||
|
for k in range(1, order):
|
||||||
|
while lags[k - 1] >= lags[k]:
|
||||||
|
lags[k] += random.randint(1, 10)
|
||||||
|
|
||||||
|
return order, lags
|
||||||
|
|
||||||
|
|
||||||
|
# Cruzamento
|
||||||
|
def crossover(pais):
|
||||||
|
import random
|
||||||
|
|
||||||
|
if pais[0]['rmse'] < pais[1]['rmse']:
|
||||||
|
best = pais[0]
|
||||||
|
worst = pais[1]
|
||||||
|
else:
|
||||||
|
best = pais[1]
|
||||||
|
worst = pais[0]
|
||||||
|
|
||||||
|
npart = int(round(.7 * best['npart'] + .3 * worst['npart']))
|
||||||
|
alpha = float(.7 * best['alpha'] + .3 * worst['alpha'])
|
||||||
|
|
||||||
|
rnd = random.uniform(0, 1)
|
||||||
|
mf = best['mf'] if rnd < .7 else worst['mf']
|
||||||
|
|
||||||
|
rnd = random.uniform(0, 1)
|
||||||
|
partitioner = best['partitioner'] if rnd < .7 else worst['partitioner']
|
||||||
|
|
||||||
|
order, lags = lag_crossover2(best, worst)
|
||||||
|
|
||||||
|
rmse = []
|
||||||
|
len_lags = []
|
||||||
|
|
||||||
|
filho = genotype(mf, npart, partitioner, order, alpha, lags, len_lags, rmse)
|
||||||
|
|
||||||
|
return filho
|
||||||
|
|
||||||
|
|
||||||
|
# Mutação | p é a probabilidade de mutação
|
||||||
|
|
||||||
|
def mutation_lags(lags, order):
|
||||||
|
new = sorted(random.sample(range(1, 50), order))
|
||||||
|
for lag in np.arange(len(lags) - 1):
|
||||||
|
new[lag] = min(50, max(1, int(lags[lag] + np.random.normal(0, 0.5))))
|
||||||
|
|
||||||
|
if order > 1:
|
||||||
|
for k in np.arange(1, order):
|
||||||
|
while new[k] <= new[k - 1]:
|
||||||
|
new[k] = int(new[k] + np.random.randint(1, 5))
|
||||||
|
|
||||||
|
return new
|
||||||
|
|
||||||
|
|
||||||
|
def mutation(individual):
|
||||||
|
import numpy.random
|
||||||
|
individual['npart'] = min(50, max(3, int(individual['npart'] + np.random.normal(0, 2))))
|
||||||
|
individual['alpha'] = min(.5, max(0, individual['alpha'] + np.random.normal(0, .1)))
|
||||||
|
individual['mf'] = random.randint(1, 2)
|
||||||
|
individual['partitioner'] = random.randint(1, 2)
|
||||||
|
individual['order'] = min(5, max(1, int(individual['order'] + np.random.normal(0, 0.5))))
|
||||||
|
# Chama a função mutation_lags
|
||||||
|
individual['lags'] = mutation_lags( individual['lags'], individual['order'])
|
||||||
|
#individual['lags'] = sorted(random.sample(range(1, 50), individual['order']))
|
||||||
|
|
||||||
|
return individual
|
||||||
|
|
||||||
|
|
||||||
|
# Elitismo
|
||||||
|
def elitism(population, new_population):
|
||||||
|
# Pega melhor indivíduo da população corrente
|
||||||
|
population = sorted(population, key=itemgetter('rmse'))
|
||||||
|
best = population[0]
|
||||||
|
|
||||||
|
# Ordena a nova população e insere o melhor1 no lugar do pior
|
||||||
|
new_population = sorted(new_population, key=itemgetter('rmse'))
|
||||||
|
new_population[-1] = best
|
||||||
|
|
||||||
|
# Ordena novamente e pega o melhor
|
||||||
|
new_population = sorted(new_population, key=itemgetter('rmse'))
|
||||||
|
|
||||||
|
return new_population
|
||||||
|
|
||||||
|
|
||||||
|
def genetico(dataset, ngen, npop, pcruz, pmut, option=1):
|
||||||
|
new_populacao = populacao_nova = []
|
||||||
|
# Gerar população inicial
|
||||||
|
populacao = initial_population(npop)
|
||||||
|
|
||||||
|
# Avaliar população inicial
|
||||||
|
result = [evaluation1(dataset, k) for k in populacao]
|
||||||
|
|
||||||
|
for i in range(npop):
|
||||||
|
if option == 1:
|
||||||
|
populacao[i]['len_lags'], populacao[i]['rmse'] = result[i]
|
||||||
|
else:
|
||||||
|
populacao[i]['rmse'] = result[i]
|
||||||
|
|
||||||
|
# Gerações
|
||||||
|
for i in range(ngen):
|
||||||
|
# Iteração para gerar a nova população
|
||||||
|
for j in range(int(npop / 2)):
|
||||||
|
# Selecao de pais
|
||||||
|
pais = []
|
||||||
|
pais.append(selection1(populacao))
|
||||||
|
pais.append(selection1(populacao))
|
||||||
|
|
||||||
|
# Cruzamento com probabilidade pcruz
|
||||||
|
rnd = random.uniform(0, 1)
|
||||||
|
filho1 = crossover(pais) if pcruz > rnd else pais[0]
|
||||||
|
rnd = random.uniform(0, 1)
|
||||||
|
filho2 = crossover(pais) if pcruz > rnd else pais[1]
|
||||||
|
|
||||||
|
# Mutação com probabilidade pmut
|
||||||
|
rnd = random.uniform(0, 1)
|
||||||
|
filho11 = mutation(filho1) if pmut > rnd else filho1
|
||||||
|
rnd = random.uniform(0, 1)
|
||||||
|
filho22 = mutation(filho2) if pmut > rnd else filho2
|
||||||
|
|
||||||
|
# Insere filhos na nova população
|
||||||
|
new_populacao.append(filho11)
|
||||||
|
new_populacao.append(filho22)
|
||||||
|
|
||||||
|
result = [evaluation1(dataset, k) for k in new_populacao]
|
||||||
|
|
||||||
|
for i in range(len(new_populacao)):
|
||||||
|
new_populacao[i]['len_lags'], new_populacao[i]['rmse'] = result[i]
|
||||||
|
|
||||||
|
populacao = elitism(populacao, new_populacao)
|
||||||
|
|
||||||
|
new_populacao = []
|
||||||
|
|
||||||
|
melhorT = sorted(populacao, key=lambda item: item['rmse'])[0]
|
||||||
|
|
||||||
|
return melhorT
|
||||||
|
|
||||||
|
|
||||||
|
def cluster_method(dataset, ngen, npop, pcruz, pmut, option=1):
|
||||||
|
print(ngen, npop, pcruz, pmut, option)
|
||||||
|
|
||||||
|
from pyFTS.hyperparam.Evolutionary import genetico
|
||||||
|
|
||||||
|
inicio = time.time()
|
||||||
|
ret = genetico(dataset, ngen, npop, pcruz, pmut, option)
|
||||||
|
fim = time.time()
|
||||||
|
ret['time'] = fim - inicio
|
||||||
|
ret['size'] = ret['len_lags']
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def process_jobs(jobs, datasetname, conn):
|
||||||
|
for job in jobs:
|
||||||
|
result = job()
|
||||||
|
if job.status == dispy.DispyJob.Finished and result is not None:
|
||||||
|
print("Processing result of {}".format(result))
|
||||||
|
|
||||||
|
metrics = ['rmse', 'size', 'time']
|
||||||
|
|
||||||
|
for metric in metrics:
|
||||||
|
record = (datasetname, 'Evolutive', 'WHOFTS', None, result['mf'],
|
||||||
|
result['order'], result['partitioner'], result['npart'],
|
||||||
|
result['alpha'], str(result['lags']), metric, result[metric])
|
||||||
|
|
||||||
|
print(record)
|
||||||
|
|
||||||
|
hUtil.insert_hyperparam(record, conn)
|
||||||
|
|
||||||
|
|
||||||
|
else:
|
||||||
|
print(job.exception)
|
||||||
|
print(job.stdout)
|
||||||
|
|
||||||
|
|
||||||
|
def execute(datasetname, dataset, **kwargs):
|
||||||
|
nodes = kwargs.get('nodes', ['127.0.0.1'])
|
||||||
|
|
||||||
|
cluster, http_server = Util.start_dispy_cluster(cluster_method, nodes=nodes)
|
||||||
|
conn = hUtil.open_hyperparam_db('hyperparam.db')
|
||||||
|
|
||||||
|
ngen = kwargs.get('ngen', 70)
|
||||||
|
npop = kwargs.get('npop', 20)
|
||||||
|
pcruz = kwargs.get('pcruz', .8)
|
||||||
|
pmut = kwargs.get('pmut', .2)
|
||||||
|
option = kwargs.get('option', 1)
|
||||||
|
|
||||||
|
jobs = []
|
||||||
|
|
||||||
|
for i in range(kwargs.get('experiments', 30)):
|
||||||
|
print("Experiment {}".format(i))
|
||||||
|
job = cluster.submit(dataset, ngen, npop, pcruz, pmut, option)
|
||||||
|
jobs.append(job)
|
||||||
|
|
||||||
|
process_jobs(jobs, datasetname, conn)
|
||||||
|
|
||||||
|
Util.stop_dispy_cluster(cluster, http_server)
|
@ -54,7 +54,8 @@ def cluster_method(individual, train, test):
|
|||||||
size = len(model)
|
size = len(model)
|
||||||
|
|
||||||
return individual, rmse, size, mape, u
|
return individual, rmse, size, mape, u
|
||||||
|
|
||||||
|
|
||||||
def process_jobs(jobs, datasetname, conn):
|
def process_jobs(jobs, datasetname, conn):
|
||||||
for job in jobs:
|
for job in jobs:
|
||||||
result, rmse, size, mape, u = job()
|
result, rmse, size, mape, u = job()
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from pyFTS.hyperparam import GridSearch
|
from pyFTS.hyperparam import GridSearch, Evolutionary
|
||||||
|
|
||||||
def get_train_test():
|
def get_dataset():
|
||||||
from pyFTS.data import Malaysia
|
from pyFTS.data import Malaysia
|
||||||
|
|
||||||
ds = Malaysia.get_data('temperature')[:1000]
|
ds = Malaysia.get_data('temperature')[:1000]
|
||||||
# ds = pd.read_csv('Malaysia.csv',delimiter=',' )[['temperature']].values[:2000].flatten().tolist()
|
# ds = pd.read_csv('Malaysia.csv',delimiter=',' )[['temperature']].values[:2000].flatten().tolist()
|
||||||
train = ds[:800]
|
#train = ds[:800]
|
||||||
test = ds[800:]
|
#test = ds[800:]
|
||||||
|
|
||||||
return 'Malaysia.temperature', train, test
|
return 'Malaysia.temperature', ds #train, test
|
||||||
|
|
||||||
"""
|
"""
|
||||||
hyperparams = {
|
hyperparams = {
|
||||||
@ -20,7 +20,7 @@ hyperparams = {
|
|||||||
'lags': np.arange(1,35,2),
|
'lags': np.arange(1,35,2),
|
||||||
'alpha': np.arange(.0, .5, .05)
|
'alpha': np.arange(.0, .5, .05)
|
||||||
}
|
}
|
||||||
"""
|
|
||||||
|
|
||||||
hyperparams = {
|
hyperparams = {
|
||||||
'order':[3], #[1, 2],
|
'order':[3], #[1, 2],
|
||||||
@ -30,9 +30,13 @@ hyperparams = {
|
|||||||
'lags': np.arange(1, 10),
|
'lags': np.arange(1, 10),
|
||||||
'alpha': [.0, .3, .5]
|
'alpha': [.0, .3, .5]
|
||||||
}
|
}
|
||||||
|
"""
|
||||||
nodes = ['192.168.0.106', '192.168.0.110', '192.168.0.107']
|
nodes = ['192.168.0.106', '192.168.0.110', '192.168.0.107']
|
||||||
|
|
||||||
ds, train, test = get_train_test()
|
datsetname, dataset = get_dataset()
|
||||||
|
|
||||||
GridSearch.execute(hyperparams, ds, train, test, nodes=nodes)
|
#GridSearch.execute(hyperparams, ds, train, test, nodes=nodes)
|
||||||
|
|
||||||
|
#Evolutionary.cluster_method(dataset, 70, 20, .8, .3, 1)
|
||||||
|
|
||||||
|
Evolutionary.execute(datsetname, dataset, nodes=nodes, ngen=50, npop=30, )
|
||||||
|
@ -17,8 +17,30 @@ from pyFTS.models.multivariate import common, variable, mvfts, cmvfts
|
|||||||
from pyFTS.models.seasonal import partitioner as seasonal
|
from pyFTS.models.seasonal import partitioner as seasonal
|
||||||
from pyFTS.models.seasonal.common import DateTime
|
from pyFTS.models.seasonal.common import DateTime
|
||||||
|
|
||||||
|
|
||||||
|
model = Util.load_obj('/home/petronio/Downloads/ClusteredMVFTS1solarorder2knn3')
|
||||||
|
|
||||||
|
data = [[12, 100], [13, 200]]
|
||||||
|
|
||||||
|
for k in data:
|
||||||
|
k[0] = pd.to_datetime('2018-01-01 {}:00:00'.format(k[0]), format='%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
df = pd.DataFrame(data, columns=['data', 'glo_avg'])
|
||||||
|
|
||||||
|
#forecasts = model.predict(df, steps_ahead=24, generators={'Hour': lambda x: x + pd.to_timedelta(1, unit='h')})
|
||||||
|
|
||||||
|
#print(forecasts)
|
||||||
|
|
||||||
|
f = lambda x: x + pd.to_timedelta(1, unit='h')
|
||||||
|
|
||||||
|
for ix, row in df.iterrows():
|
||||||
|
print(row['data'])
|
||||||
|
print(f(row['data']))
|
||||||
|
|
||||||
|
|
||||||
# Multivariate time series
|
# Multivariate time series
|
||||||
|
|
||||||
|
'''
|
||||||
train_mv = {}
|
train_mv = {}
|
||||||
test_mv = {}
|
test_mv = {}
|
||||||
|
|
||||||
@ -131,3 +153,4 @@ for ct, key in enumerate(models.keys()):
|
|||||||
Util.persist_obj(model, model.shortname)
|
Util.persist_obj(model, model.shortname)
|
||||||
|
|
||||||
del(model)
|
del(model)
|
||||||
|
'''
|
Loading…
Reference in New Issue
Block a user