Um dos pacotes mais interessantes para realizar otimização é o pacote DEoptim. Essa abordagem permite a otimização de funções dos mais diversos tipos de uma maneira fácil.
Entretanto, por usar Otimização Evolucionária o processo de otimização pode ser lento, caso utilize-se muitas populações, iterações ou níveis tolerância extremos.
Aqui mostrarei como usar a opção parallelType da função DEoptim para que esse processo seja acelerado por meio da programação em paralelo.
Considere a seguinte função com múltiplos máximos e mínimos locais:
f<-function(x,y){ res<-(268/((3*x+18)^2+(3*y+7)^2+(18+7)))-(2*(268)/((3*x-21)^2+(3*y+21)^2+(21+21)))-(3*(268)/((3*x+18)^2+(3*y-21)^2+(18+21)))+(4*(268)/((3*x-21)^2+(3*y-7)^2+(21+7))) return(res) }Podemos fazer o gráfico dessa função através do seguinte bloco de comandos:
#Chama a biblioteca library(plot3D) #Cria a grade de valores na função z<-f(M[,"x"], M[,"y"]) #Faz o gráfico persp3D(z = z, x = M[,"x"], y = M[,"y"], expand = 0.3, main = "Função complicada", facets = FALSE, scale = FALSE, clab = "Valor da função",zlab="Valor", colkey = list(side = 1, length = 0.5))O próximo passo para realizar a otimização é escrever a função no formato adequado para o uso do método DEoptim. Para isso, basta trocar o argumento da função que ao invés de serem dois parâmetros, será agora um vetor contendo esses dois argumentos, em outras palavras:
fEval<-function(parms){ x<-parms[1] y<-parms[2] res<-(268/((3*x+18)^2+(3*y+7)^2+(18+7)))-(2*(268)/((3*x-21)^2+(3*y+21)^2+(21+21)))-(3*(268)/((3*x+18)^2+(3*y-21)^2+(18+21)))+(4*(268)/((3*x-21)^2+(3*y-7)^2+(21+7))) return(res) }Note que só as três primeiras linhas foram alteradas. A seguir, precisamos configurar os nossos clusters para que a função possa ser otimizada em paralelo, a função busca pelo menor valor da função:
#Chama o pacote DEoptim e doSNOW library(DEoptim) library(doSNOW) #Guarda o número de clusters disponíveis numSlaves<- detectCores() #Cria os clusters cl <− makeCluster(numSlaves) #Passa todas as bibliotecas que são usadas para o cálculo da função #clusterEvalQ(cl , library(pracma, ... )) #Passa todos os objetos necessários para o cômputo da função #clusterExport(cl , ... ) #Registra os clusters registerDoSNOW (cl) #Realiza a otimização outDEoptim <− DEoptim (fEval, c(-15,-15), c(15,15), DEoptim.control(list(trace=FALSE, NP=50, itermax=50, parallelType = 2))) #Fecha os clusters stopCluster(cl) #Guarda os melhores resultados. fim <- outDEoptim $ optim $ bestmem fimAlguns comentários são importantes: as linhas 8 e 10 são utilizadas para se passar bibliotecas e objetos do R que são utilizados no cômputo da função que deve ser otimizada. Nesse caso, como não usamos nenhum pacote especial para o cômputo da função e nem bibliotecas esses comandos estão comentados. Caso deseje-se passar esses valores, basta atribuí-los na forma de lista em cada comando. Na função DEoptim o primeiro argumento é a função a ser minimizada, seguido pelos limites inferiores e superiores para os argumentos. O último argumento é uma lista que controla as condições da função de otimização: NP é o número de populações a serem geradas no algoritmo de Otimização Evolucionária, itermax é o número total de iterações e parallelType = 2 define a forma de paralelismo a ser considerada. Observe ainda que se o valor de NP e/ou itermax e o paralelismo não for adotado, esse processo pode ser muito lento computacionalmente, daí a vantagem de se utilizar o processamento em paralelo que pode reduzir esse tempo computacional significativamente. Mote ainda que o comando trace=FALSE é para suprimir os resultados em cada iteração, e caso deseje-se maximizar a função ao invés de minimizar, basta trabalhar com o valor do negativo da função, ou ainda com seu recíproco.
Nenhum comentário:
Postar um comentário