Mon 21 Jul 22:43:21 CEST 2025
This commit is contained in:
parent
9493e0954b
commit
8ab16efe48
169
js/ml/opt.js
Normal file
169
js/ml/opt.js
Normal file
|
@ -0,0 +1,169 @@
|
|||
/**
|
||||
* Created by joonkukang on 2014. 1. 16..
|
||||
*/
|
||||
var math = require('./utils').math;
|
||||
let optimize = module.exports;
|
||||
|
||||
optimize.hillclimb = function(options){
|
||||
var domain = options['domain'];
|
||||
var costf = options['costf'];
|
||||
|
||||
var i;
|
||||
var vec = [];
|
||||
for(i=0 ; i<domain.length ; i++)
|
||||
vec.push(math.randInt(domain[i][0],domain[i][1]));
|
||||
|
||||
var current, best;
|
||||
|
||||
while(true) {
|
||||
var neighbors = [];
|
||||
var i,j;
|
||||
|
||||
for(i=0 ; i<domain.length ; i++) {
|
||||
if(vec[i] > domain[i][0]) {
|
||||
var newVec = [];
|
||||
for(j=0 ; j<domain.length ; j++)
|
||||
newVec.push(vec[j]);
|
||||
newVec[i]-=1;
|
||||
neighbors.push(newVec);
|
||||
} else if (vec[i] < domain[i][1]) {
|
||||
var newVec = [];
|
||||
for(j=0 ; j<domain.length ; j++)
|
||||
newVec.push(vec[j]);
|
||||
newVec[i]+=1;
|
||||
neighbors.push(newVec);
|
||||
}
|
||||
}
|
||||
|
||||
current = costf(vec);
|
||||
best = current;
|
||||
for(i=0 ; i<neighbors.length ; i++) {
|
||||
var cost = costf(neighbors[i]);
|
||||
if(cost < best) {
|
||||
best = cost;
|
||||
vec = neighbors[i];
|
||||
}
|
||||
}
|
||||
if(best === current)
|
||||
break;
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
optimize.anneal = function(options){
|
||||
var domain = options['domain'];
|
||||
var costf = options['costf'];
|
||||
var temperature = options['temperature'];
|
||||
var cool = options['cool'];
|
||||
var step = options['step'];
|
||||
var callback
|
||||
|
||||
var i;
|
||||
var vec = [];
|
||||
for(i=0 ; i<domain.length ; i++)
|
||||
vec.push(math.randInt(domain[i][0],domain[i][1]));
|
||||
|
||||
while(temperature > 0.1) {
|
||||
var idx = math.randInt(0,domain.length - 1);
|
||||
var dir = math.randInt(-step,step);
|
||||
var newVec = [];
|
||||
for(i=0; i<vec.length ; i++)
|
||||
newVec.push(vec[i]);
|
||||
newVec[idx]+=dir;
|
||||
if(newVec[idx] < domain[idx][0]) newVec[idx] = domain[idx][0];
|
||||
if(newVec[idx] > domain[idx][1]) newVec[idx] = domain[idx][1];
|
||||
|
||||
var ea = costf(vec);
|
||||
var eb = costf(newVec);
|
||||
var p = Math.exp(-1.*(eb-ea)/temperature);
|
||||
if(eb < ea || Math.random() < p)
|
||||
vec = newVec;
|
||||
|
||||
temperature *= cool;
|
||||
}
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
optimize.genetic = function(options){
|
||||
var domain = options['domain'];
|
||||
var costf = options['costf'];
|
||||
var population = options['population'];
|
||||
var q = options['q'] || 0.3;
|
||||
var elite = options['elite'] || population * 0.04;
|
||||
var epochs = options['epochs'] || 100;
|
||||
|
||||
var i,j;
|
||||
// Initialize population array
|
||||
var pop =[];
|
||||
for(i=0; i<population; i++) {
|
||||
var vec = [];
|
||||
for(j=0; j<domain.length; j++)
|
||||
vec.push(math.randInt(domain[j][0],domain[j][1]));
|
||||
pop.push(vec);
|
||||
}
|
||||
pop.sort(function(a,b){return costf(a) - costf(b);});
|
||||
|
||||
for(i=0 ; i<epochs ; i++) {
|
||||
// elitism
|
||||
var newPop = [];
|
||||
for(j=0;j<elite;j++)
|
||||
newPop.push(pop[j]);
|
||||
|
||||
// compute fitnesses
|
||||
var fitnesses = [];
|
||||
for(j=0; j<pop.length; j++)
|
||||
fitnesses[j] = q * Math.pow(1-q,j);
|
||||
fitnesses = math.normalizeVec(fitnesses);
|
||||
|
||||
// crossover, mutate
|
||||
for(j=0; j<pop.length - elite;j++) {
|
||||
var idx1 = rouletteWheel(fitnesses);
|
||||
var idx2 = rouletteWheel(fitnesses);
|
||||
var crossovered = crossover(pop[idx1],pop[idx2]);
|
||||
var mutated = mutate(crossovered);
|
||||
newPop.push(mutated);
|
||||
}
|
||||
|
||||
// replacement
|
||||
pop = newPop;
|
||||
pop.sort(function(a,b){return costf(a) - costf(b);});
|
||||
//console.log("Current Cost : ",costf(pop[0]));
|
||||
}
|
||||
return pop[0];
|
||||
|
||||
function mutate(vec) {
|
||||
var idx = math.randInt(0,domain.length - 1);
|
||||
var newVec = [];
|
||||
var i;
|
||||
for(i=0; i<domain.length ; i++)
|
||||
newVec.push(vec[i]);
|
||||
newVec[idx] += (Math.random() < 0.5) ? 1 : -1;
|
||||
if(newVec[idx] < domain[idx][0]) newVec[idx] = domain[idx][0];
|
||||
if(newVec[idx] > domain[idx][1]) newVec[idx] = domain[idx][1];
|
||||
return newVec;
|
||||
}
|
||||
function crossover(vec1,vec2) {
|
||||
var idx = math.randInt(0,domain.length - 2);
|
||||
var newVec = [];
|
||||
var i;
|
||||
for(i=0; i<idx ; i++)
|
||||
newVec.push(vec1[i]);
|
||||
for(i=idx; i<domain.length; i++)
|
||||
newVec.push(vec2[i]);
|
||||
return newVec;
|
||||
}
|
||||
function rouletteWheel(vec) {
|
||||
var a = [0.0];
|
||||
var i;
|
||||
for(i=0;i<vec.length;i++) {
|
||||
a.push(a[i] + vec[i]);
|
||||
}
|
||||
var rand = Math.random();
|
||||
for(i=0;i< a.length;i++) {
|
||||
if(rand > a[i] && rand <= a[i+1])
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user