遺傳算法探索
遺傳算法
適者生存。”適“的是什麼?是我們身邊的環境還是上帝的指引?
自然界的生物不管情願與否都被刻畫着。有一條無形的手指引着人類前進的方向。
遺傳算法,一個程序員自己刻畫世界的方式。遺傳算法通過模擬自然界的交叉變異,保證了問題的搜索空間。通過適應度函數刻畫程序員自己的世界。
遺傳算法本身是神經網絡的前身。遺傳算法的適應度函數和神經網絡的損失函數本質一樣。都是描述正解和現在得到解的差別。前期的神經網絡就是通過遺傳算法當作損失函數的。
關於遺傳算法的實現細節
一般的遺傳算法都有一個交配概率(又稱爲交叉概率),範圍一般是0.6~1,這個交配概率反映兩個被選中的個體進行交配的概率。例如,交配概率爲0.8,則80%的“夫妻”會生育後代。每兩個個體通過交配產生兩個新個體,代替原來的“老”個體,而不交配的個體則保持不變。–維基百科
c語言代碼
#include <stdio.h>
#include <stdlib.h>
struct Population{
int gene[11];//基因爲0,1組成
double x;//基因型轉化爲表現型
double y;
};
/*
求y=x*x的最小值,x取值範圍爲【-1,1】精度爲0.001,所以基因位爲11
*/
//初始種羣
void initPopulation(struct Population *population,int populationNum){
srand((unsigned)time(NULL));
for(int i=0;i<populationNum;i++){
population[i].x=-1;
for(int j=0;j<11;j++){
population[i].gene[j]=rand()%2;//隨機數
}
printf("init gene[%d]=",i);
for(int j=0;j<11;j++){
printf("%d",population[i].gene[j]);
}
printf("\n");
}
}
//基因型轉化爲表現型
void bitToNum(struct Population *population,int populationNum){
for(int i=0;i<populationNum;i++){
population[i].x=-1;
int count=1;//進位符
for(int j=10;j>=0;j--){
population[i].x+=population[i].gene[j]*count*0.001;
count*=2;
}
//printf("x=:%lf\n",population[i].x);
}
printf("\n");
}
//計算適應度函數
void fitness(struct Population *population,int populationNum){
for(int i=0;i<populationNum;i++){
population[i].y=population[i].x*population[i].x;//y=x*x
printf("y=:%lf\n",population[i].y);
}
}
//選擇
void selection(struct Population *population,struct Population *crossoverPopulation,int populationNum){
/*使用輪盤賭算法進行選擇,因爲該遺傳算法是求最小值,所以不能直接對fitness輪盤賭,通過一頓花裏胡哨的倒數歸一化操作,*/
double total=0,sum=0;
for(int i = 0;i<populationNum;i++){
total+=((double)population[i].y);
}
for(int i = 0;i<populationNum;i++){
sum+=(total/population[i].y);
}
double num,temp,rate;
for(int i=0;i<2*populationNum;i++){
num = 0;
temp = (rand()%100000)*0.00001;
for(int j=0;j<populationNum;j++){
num+=(total/population[j].y);
double rate = (double)num/sum;
if(temp <=rate){
for(int k=0;k<11;k++){
crossoverPopulation[i].gene[k]=population[j].gene[k];
}
break;
}
}
}
}
//交叉
void crossover(struct Population *population,struct Population *crossoverPopulation,int populationNum,double pc){
int probability,pos;
for(int i = 0;i<populationNum;i++){
probability = rand()%100;
if(probability<=pc*100){
pos == rand()%11;
for(int k=0;k<11;k++){
if(k<=pos){
population[i].gene[k]=crossoverPopulation[i].gene[k];
}else{
population[i].gene[k]=crossoverPopulation[i+populationNum].gene[k];
}
}
}
}
}
//變異
void mutation(struct Population *population,int populationNum,double pm){
int probability,pos;
for(int i=0;i<populationNum;i++){
probability = rand()%100;
if(probability<pm*100){
pos=rand()%10;
if(population[i].gene[pos]==1){
population[i].gene[pos]=0;
}else{
population[i].gene[pos]=1;
}
}
}
}
int main()
{
int populationNum=10;//初始種羣大小
double pc=0.8;//交叉概率
double pm=0.03;//變異概率
int generationNum=1000;//訓練代數
struct Population population[populationNum];
struct Population crossoverPopulation[2*populationNum];
initPopulation(population,populationNum);
for(int i=0;i<generationNum;i++){
bitToNum(population,populationNum);
fitness(population,populationNum);
selection(population,crossoverPopulation,populationNum);
crossover(population,crossoverPopulation,populationNum,pc);
mutation(population,populationNum,pm);
printf("\n");
}
printf("train finishing!!!");
return 0;
}