JINGPaC Tutorial - Elementi
In questo documento verranno presentati alcuni elementi interni di JINGPaC (operatori e funzioni di selezione) e le loro correnti implementazioni. Inoltre verrà accennato in quali classi avvengono i meccanismi evolutivi in modo da poterli ispezionare agevolmente.
Operatori
Gli operatori sono stati suddivisi in due tipologie logiche: gli operatori che possono essere applicati agli individui selezionati da una funzione (es: operatore Crossover, Riproduzione) e gli operatori a cui sono sottoposti tutti gli individui dopo essere passati dai precedenti (es: operatore Mutazione). Questi ultimi sono definiti "OperatorGeneral".
Perciò è possibile schematizzare nel seguente modo il processo a cui sono sottoposti gli individui delle popolazioni ad ogni ciclo evolutivo:
I tassi di applicazione e gli eventuali parametri dei vari operatori sono definiti in un oggetto OperatorPolicy associato ad ogni popolazione.
In particolar modo è possibile distinguere varie sezioni del file di configurazione: Operator, OperatorGeneral, OpertorPolicy.
- Operator
-
<operator id=2">
<className value="net.sourceforge.jingpac.evo.OperatorCrossoverMirror"/>
<selection>
<className value="net.sourceforge.jingpac.evo.SelectionTournament"/>
<param name="size" value="5"/>
</selection> </operator>Per ogni operatore che agisce nella prima fase è necessario indicare un attributo ID (visto che possono essere vari).
- className contiene la classe relativa a questo operatore
- selectionOgni operatore utilizza una sua funzione di selezione.
- className contiene la classe della funzione di selezione.
- param contiene i parametri relativi alla funzione di selezione, nel caso si vogliano creare nuove funzioni di selezione e queste necessitino di parametri è possibile passarli in questa posizione.
- OperatorGeneral
-
Questo operatore viene applicato a tutti gli individui in una seconda fase. Vi può essere un solo operatore per popolazione di questa tipologia.
<operatorGeneral>
<className value="net.sourceforge.jingpac.evo.OperatorGeneralMutationGARecursive"/>
</operatorGeneral>
Viene richiesto solo di specificare la classe di questo operatore. La probabilità di applicazione andrà specificata nella policy.
- OperatorPolicy
-
All'interno di questa sezione son presenti i parametri degli operatori e i loro tassi di applicazione.
<opPolicy>
<opRate opID="2" value="0.4"/>
<opRate opID="3" value="0.6"/>
<opRateInt opID="2" value="0.4"/>
<opRateGeneral value="0.02"/>
<elitism value="true"/>
</opPolicy>- opRate contiene un attributo ID e un value relativi all'operatore in questione. ATTENZIONE: la somma di tutti i "value" dei vari <opRate> deve essere uguale a 1.0. Ad esempio se nel sistema sono presenti gli operatori di Crossover e Riproduzione si avranno due tag <opRate> che specificano le probabilità di applicazione.
- opRateInt contiene un parametro utilizzabile dall'operatore a cui corrisponde il tag opID. In particolare viene utilizzato dalla factory quando viene richiesto un Hook su cui eseguire l'operatore. Ad esempio la GProgramFactory utilizza questo parametro per scegliere un nodo terminale o un nodo funzione. Perciò questo parametro è necessario in funzione della factory utilizzata.
- opRateGeneral indica il tasso di applicazione dell'operatore generale, in particolare nell'implementazione degli operatori corrente questo valore indica la probabilità del singolo cromosoma/peso della rete neurale di essere mutato, perciò dovrebbe essere un valore basso.
- elitism valore boolean che indica se attivare o meno l'elitismo. (il migliore (1) individuo viene copiato).
Operatori Implementati
Solitamente gli operatori sono indipendenti dal tipo di EvolvableObject utilizzato, nonostante ciò è stato necessario introdurre operatori specializzati per varie tipologie di EvolvableObject.
Classica implementazione dell'operatore di crossover per individui strutturalmente simili (es: nella corrente implementazione due individui GA sono strutturalmente simili mentre due individui GP non lo sono). Questo operatore funziona con individui GA poichè prende un punto di aggancio su un individuo e lo usa anche per l'altro e scambia i nodi. (un GAHook è costituito dagli indici dei cromosomi selezionati)
ind 2 = 1' 2' 3' 4' 5' 6'
ind 1' = 1 2' 3' 4' 5 6
ind 2' = 1' 2 3 4 5' 6'
Questa implementazione dell'operatore crossover può essere utilizzata per individui strutturalmente differenti poiché seleziona un punto di Hook, tramite la factory, per ogni individuo e li scambia.
Questo operatore è generico; acquisisce un Hook tramite la factory, crea un nuovo individuo e lo unisce all'EvolvableObject al posto dell'Hook.
Questo operatore è utilizzabile solamente con individui GA; seleziona un cromosoma e applica l'operatore OperatorMutationPlain su di esso.
Questo operatore è generico e clona semplicemente l'individuo selezionato.
Operatori Generali
Per ogni cromosoma, secondo la probabilità definita in <opRateGeneral>, crea un nuovo individuo grazie alla factory degli EvolvableObject presenti nei cromosomi. Utilizzabile solo con EvolvableObject di tipo GA.
Per ogni cromosoma, secondo la probabilità definita in <opRateGeneral>, applica l'operatore OperatorMutationPlain (perciò muta solo una parte dell'individuo). Utilizzabile solo con EvolvableObject di tipo GA.
Per ogni peso di ogni nodo, secondo la probabilità definita in <opRateGeneral>, viene modificato il valore. Utilizzabile solo con EvolvableObject di tipo Neural Network.
Implementazione di nuovi Operatori
Per creare un nuovo operatore è sufficiente estendere la classe astratta Operator anche se è consigliabile estendere OperatorMutation o OperatorCrossover poiché contengono già l'implementazione di qualche metodo comune per la tipologia di operatori.
Gli EvolvableObject in ingresso agli operatori provengono dalla popolazione ma sono clonati perciò l'operatore può modificarli come vuole.
Infine è necessario impostare la classe del nuovo operatore nel file XML.
<className value="net.sourceforge.jingpac.evo.OperatorGeneralMutationGARecursive"/>
</operatorGeneral>
Attenzione:
Tra gli operatori "normali" e quelli generali non vi sono differenze sostanziali; 'unica differenza è concettuale. In particolare rispetto all'utilizzo del parametro <opRateGeneral> che viene utilizzato dagli operatori generali per indicare NON una probabilità di scelta dell'operatore ma di applicazione. (vedere descrizione operatori generali implementati)
E' consigliabile dare uno sguardo al codice degli operatori già implementati come riferimento.
Funzioni di Selezione
Come precedentemente accennato sono state implementate varie funzioni per selezionare gli individui, la maggior parte di essi utilizza il metodo Population.sort(boolean).
Questo metodo riceve in ingresso un valore booleano, se il metodo viene invocato con true ordina la popolazione a fitness decrescente (l'individuo con la fitness maggiore è nella posizione 0).
Inoltre questo metodo utilizza una implementazione di un generico Comparator, FitnessComparator, perciò se è necessario modificare il metodo di ordinamento a basso livello è sufficiente creare una nuova implementazione di questa classe e istanziarla nel metodo Population.sort() che sarà utilizzata poi nel metodo Collections.sort() di Java.
La sintassi XML da inserire all'interno del tag <operator> è il seguente:
<className value="SelectionClassName"/>
<param name="size" value="5"/>
</selection>
I parametri sono necessari in base alla funzione selezionata.
Di seguito sono riportate le funzioni di selezione implementate:
Seleziona l'individuo con la Standardized Fitness più bassa.
Nessun parametro necessario.
Seleziona l'individuo con la Standardized Fitness più alta.
Nessun parametro necessario.
La probabilità per un EvolvableObject di essere selezionato è proporzionale alla sua fitness.
Nessun parametro necessario.
Ordina la popolazione con fitness decrescente, la suddivide in due parti secondo il valore di "cutoff"; successivamente selezionerà un individuo, tramite SelectionFitnessProportionate, dalla prima o seconda parte secondo la probabilità definita dal valore di "proportion".
<className value="net.sourceforge.jingpac.evo.SelectionFitnessOverselected"/>
<param name="cutoff" value="0.4"/>
<param name="proportion" value="0.6"/>
</selection>
Seleziona casualmente un numero corrispondente al valore del parametro "size" di individui, successivamente seleziona quello con la fitness maggiore.
Selezione casualmente un individuo dalla popolazione.
Nessun parametro necessario.
Per implementare nuove funzioni di selezione è sufficiente estendere la classe astratta SelectionFunction e impostare la classe nel file di configurazione XML.