神经网络和遗传算法(NN&GA)

在软计算课程上,老师让我们编程实现Hopfield网、联想记忆、BM、BP、SOFM、遗传算法。正在学习Ruby,就用ruby实现了上述内容。上述实现的内容比较简单,但没有对每个程序的输入和输出做说明。如果有任何疑问可以留言。希望和大家交流!


Hopfield

w = Array.new(4)
4.times do |i|
  w[i] = Array.new(4,0)
  4.times do |j|
    if j > i
      w[i][j] = (rand 101) / 100.0 * (-1) ** (rand 2)
    else
      w[i][j]=w[j][i]
    end
  end
end

u=Array.new(4)
4.times do |i|
  u[i] = (rand 101) / 100.0 * (-1) ** (rand 2)
end

target = Array.new(16)
16.times do |i|
  target[i] = Array.new(4)
  
  if i == 0
    target[0] = [-1,-1,-1,-1]
    next
  end
  if i > 0
    4.times do |k|
      t = target[i-1][k]
      target[i][k] = t
    end
    4.times do |j|
      ttt = target[i-1][3-j]
      if ttt == -1
        target[i][3-j] = 1
        break
      else
        target[i][3-j] = -1
      end
    end
  end
end

16.times do |k|
  energy = 0
  4.times do |i|
    4.times do |j|
      energy += -0.5*w[i][j]*target[k][i]*target[k][j]
    end
    energy+=u[i]*target[k][i]
  end
  puts target[k].join(" ") +"\t\t"+ energy.to_s
end

16.times do |i|
  tem = ""
   puts "\n"
  4.times do |k|
    tem += target[i][k].to_s + " "
  end
  puts tem
  tem = ""
  total = 0
 
  30.times do |j|
    total = 0
    4.times do |k|
      kk = target[i][k]
      if kk == 1
        total += 2 ** (3-k)
      end
    end
    if total/10 == 1
      tem += total.to_s + "  "
    else
      tem += " " + total.to_s + " "
    end
    
    total=0
    rRound = rand 4
    4.times do |k|
      total += w[rRound][k] * target[i][k]
    end
    if total-u[rRound] >= 0
    target[i][rRound] = 1
    else
      target[i][rRound] = -1
    end
  end
    
  total = 0
  4.times do |j|
    4.times do |k|
      total += -0.5 * w[j][k] * target[i][j] * target[i][k]
    end
    total += u[j] * target[i][j]
  end
  tem += "   " + total.to_s
  puts tem
end






BM算法

initial=[1,-1,1,-1]
t,n=1,1000

w = Array.new(4)
4.times do |i|
  w[i] = Array.new(4,0)
  4.times do |j|
    if j > i
      w[i][j] = (rand 101) / 100.0 * (-1) ** (rand 2)
    else
      w[i][j]=w[j][i]
    end
  end
end

u=Array.new(4)
4.times do |i|
  u[i] = (rand 101) / 100.0 * (-1) ** (rand 2)
end



def p(tt,mm)
  1.0/(1+Math.exp( -tt/mm ))
end

while n>0.01
select=rand 4
hi=0
  4.times do |j|
    hi+=w[select][j]*initial[j]
  end
hi-=u[select]
if hi>0
  initial[select]=1
else
  a=p(hi,n)
  
  if n>10
    b=(rand 700)/1000.0
  else
    b=0.5+(rand 200)/1000.0
  end

  if a > b
    initial[select]=1
  else
    initial[select]=-1
  end
end
n=1000/(1+t)
t+=1
end

total=0
4.times do |i|
  4.times do |j|
    total+=-0.5*w[i][j]*initial[i]*initial[j]
  end
  total+=u[i]*initial[i]
end
puts initial.join("\t")+"\t\t"+total.to_s
puts "\n"

target = Array.new(16)
16.times do |i|
  target[i] = Array.new(4)
  
  if i == 0
    target[0] = [-1,-1,-1,-1]
    next
  end
  if i > 0
    4.times do |k|
      t = target[i-1][k]
      target[i][k] = t
    end
    4.times do |j|
      ttt = target[i-1][3-j]
      if ttt == -1
        target[i][3-j] = 1
        break
      else
        target[i][3-j] = -1
      end
    end
  end
end

16.times do |k|
  energy = 0
  4.times do |i|
    4.times do |j|
      energy += -0.5*w[i][j]*target[k][i]*target[k][j]
    end
    energy+=u[i]*target[k][i]
  end
  puts target[k].join(" ") +"\t\t"+ energy.to_s
end

16.times do |i|
  tem = ""
   puts "\n"
  4.times do |k|
    tem += target[i][k].to_s + " "
  end
  puts tem
  tem = ""
  total = 0
 
  30.times do |j|
    total = 0
    4.times do |k|
      kk = target[i][k]
      if kk == 1
        total += 2 ** (3-k)
      end
    end
    if total/10 == 1
      tem += total.to_s + "  "
    else
      tem += " " + total.to_s + " "
    end
    
    total=0
    rRound = rand 4
    4.times do |k|
      total += w[rRound][k] * target[i][k]
    end
    if total-u[rRound] >= 0
    target[i][rRound] = 1
    else
      target[i][rRound] = -1
    end
  end
    
  total = 0
  4.times do |j|
    4.times do |k|
      total += -0.5 * w[j][k] * target[i][j] * target[i][k]
    end
    total += u[j] * target[i][j]
  end
  tem += "   " + total.to_s
  puts tem
end






BP算法

#BP Algorithm endeavor
def f(t)
  m=1.0/(1.0+Math.exp(-t))
end

num_mode=8
num_input_nerve=3
num_middle_nerve=20
num_output_nerve=2
num_learntimes=200
affix=0.5

d=Array.new(num_mode)
num_mode.times do |i|
  d[i]=Array.new(num_output_nerve)
  num_output_nerve.times do |j|
    d[i][j]=(rand 101)/100.0
  end
end

input=Array.new(num_mode)
num_mode.times do |i|
  input[i]=Array.new(num_input_nerve)
  num_input_nerve.times do |j|
    input[i][j]=(rand 101)/100.0
  end
end

v=Array.new(num_input_nerve)
num_input_nerve.times do |i|
  v[i]=Array.new(num_middle_nerve)
  num_middle_nerve.times do |j|
    v[i][j]=(rand 101)/100.0*(-1)**(rand 2)
  end
end

r=Array.new(num_middle_nerve)
num_middle_nerve.times do |i|
  r[i]=(rand 101)/100.0*(-1)**(rand 2)
end

middle=Array.new()

w=Array.new(num_middle_nerve)
num_middle_nerve.times do |i|
  w[i]=Array.new(num_output_nerve)
  num_output_nerve.times do |j|
    w[i][j]=(rand 101)/100.0*(-1)**(rand 2)
  end
end

s=Array.new(num_middle_nerve)
num_middle_nerve.times do |i|
  s[i]=(rand 101)/100.0*(-1)**(rand 2)
end

output=Array.new()

#starts learning
num_learntimes.times do |g|
  num_mode.times do |k|
    
    middle=Array.new(num_middle_nerve,0)
    output=Array.new(num_output_nerve,0)
    help_w=Array.new(num_output_nerve,0)
    help_v=Array.new(num_middle_nerve,0)
    
    #figure out results
    num_middle_nerve.times do |i|
      num_input_nerve.times do |j|
        middle[i]+=input[k][j]*v[j][i]
      end
      middle[i]=f(middle[i]-r[i])
    end
    num_output_nerve.times do |i|
      num_middle_nerve.times do |j|
        output[i]+=middle[j]*w[j][i]
      end
      output[i]=f(output[i]-s[i])
    end
    
    #adjustment
    num_output_nerve.times do |i|
      help_w[i]=(d[k][i]-output[i])*output[i]*(1-output[i])
    end
    num_middle_nerve.times do |i|
      num_output_nerve.times do |j|
        help_v[i]+=help_w[j]*w[i][j]
      end
      help_v[i]*=middle[i]*(1-middle[i])
    end
    
    num_middle_nerve.times do |i|
      num_output_nerve.times do |j|
        w[i][j]+=affix*help_w[j]*middle[i]
      end
    end
    num_output_nerve.times do |i|
      s[i]-=affix*help_w[i]
    end
    
    num_input_nerve.times do |i|
      num_middle_nerve.times do |j|
        v[i][j]+=affix*help_v[j]*input[k][i]
      end
    end
    
    num_middle_nerve.times do |i|
      r[i]-=affix*help_v[i]
    end
      
  end
  #end learn 1 time
end

#test on learning times
errorsum=0
puts "results:"
num_mode.times do |k|
  middle=Array.new(num_middle_nerve,0)
  output=Array.new(num_output_nerve,0)
  num_middle_nerve.times do |i|
    num_input_nerve.times do |j|
      middle[i]+=input[k][j]*v[j][i]
    end
    middle[i]=f(middle[i]-r[i])
  end
  num_output_nerve.times do |i|
    num_middle_nerve.times do |j|
      output[i]+=middle[j]*w[j][i]
    end
    output[i]=f(output[i]-s[i])
    errorsum+=(d[k][i]-output[i])**2
  end
  puts "%.2f" %output[0]+"  "+"%.2f" %output[1]
end

errorsum/=2
puts "total deviation:"+errorsum.to_s

num_learntimes=100
#starts learning
num_learntimes.times do |g|
  num_mode.times do |k|
    
    middle=Array.new(num_middle_nerve,0)
    output=Array.new(num_output_nerve,0)
    help_w=Array.new(num_output_nerve,0)
    help_v=Array.new(num_middle_nerve,0)
    
    #figure out results
    num_middle_nerve.times do |i|
      num_input_nerve.times do |j|
        middle[i]+=input[k][j]*v[j][i]
      end
      middle[i]=f(middle[i]-r[i])
    end
    num_output_nerve.times do |i|
      num_middle_nerve.times do |j|
        output[i]+=middle[j]*w[j][i]
      end
      output[i]=f(output[i]-s[i])
    end
    
    #adjustment
    num_output_nerve.times do |i|
      help_w[i]=(d[k][i]-output[i])*output[i]*(1-output[i])
    end
    num_middle_nerve.times do |i|
      num_output_nerve.times do |j|
        help_v[i]+=help_w[j]*w[i][j]
      end
      help_v[i]*=middle[i]*(1-middle[i])
    end
    
    num_middle_nerve.times do |i|
      num_output_nerve.times do |j|
        w[i][j]+=affix*help_w[j]*middle[i]
      end
    end
    num_output_nerve.times do |i|
      s[i]-=affix*help_w[i]
    end
    
    num_input_nerve.times do |i|
      num_middle_nerve.times do |j|
        v[i][j]+=affix*help_v[j]*input[k][i]
      end
    end
    
    num_middle_nerve.times do |i|
      r[i]-=affix*help_v[i]
    end
      
  end
  #end learn 1 time
end

#test on learning times
errorsum=0
puts "results:"
num_mode.times do |k|
  middle=Array.new(num_middle_nerve,0)
  output=Array.new(num_output_nerve,0)
  num_middle_nerve.times do |i|
    num_input_nerve.times do |j|
      middle[i]+=input[k][j]*v[j][i]
    end
    middle[i]=f(middle[i]-r[i])
  end
  num_output_nerve.times do |i|
    num_middle_nerve.times do |j|
      output[i]+=middle[j]*w[j][i]
    end
    output[i]=f(output[i]-s[i])
    errorsum+=(d[k][i]-output[i])**2
  end
  puts "%.2f" %output[0]+"  "+"%.2f" %output[1]
end

errorsum/=2
puts "total deviation:"+errorsum.to_s

num_learntimes=100
#starts learning
num_learntimes.times do |g|
  num_mode.times do |k|
    
    middle=Array.new(num_middle_nerve,0)
    output=Array.new(num_output_nerve,0)
    help_w=Array.new(num_output_nerve,0)
    help_v=Array.new(num_middle_nerve,0)
    
    #figure out results
    num_middle_nerve.times do |i|
      num_input_nerve.times do |j|
        middle[i]+=input[k][j]*v[j][i]
      end
      middle[i]=f(middle[i]-r[i])
    end
    num_output_nerve.times do |i|
      num_middle_nerve.times do |j|
        output[i]+=middle[j]*w[j][i]
      end
      output[i]=f(output[i]-s[i])
    end
    
    #adjustment
    num_output_nerve.times do |i|
      help_w[i]=(d[k][i]-output[i])*output[i]*(1-output[i])
    end
    num_middle_nerve.times do |i|
      num_output_nerve.times do |j|
        help_v[i]+=help_w[j]*w[i][j]
      end
      help_v[i]*=middle[i]*(1-middle[i])
    end
    
    num_middle_nerve.times do |i|
      num_output_nerve.times do |j|
        w[i][j]+=affix*help_w[j]*middle[i]
      end
    end
    num_output_nerve.times do |i|
      s[i]-=affix*help_w[i]
    end
    
    num_input_nerve.times do |i|
      num_middle_nerve.times do |j|
        v[i][j]+=affix*help_v[j]*input[k][i]
      end
    end
    
    num_middle_nerve.times do |i|
      r[i]-=affix*help_v[i]
    end
      
  end
  #end learn 1 time
end

#test on learning times
errorsum=0
puts "results:"
num_mode.times do |k|
  middle=Array.new(num_middle_nerve,0)
  output=Array.new(num_output_nerve,0)
  num_middle_nerve.times do |i|
    num_input_nerve.times do |j|
      middle[i]+=input[k][j]*v[j][i]
    end
    middle[i]=f(middle[i]-r[i])
  end
  num_output_nerve.times do |i|
    num_middle_nerve.times do |j|
      output[i]+=middle[j]*w[j][i]
    end
    output[i]=f(output[i]-s[i])
    errorsum+=(d[k][i]-output[i])**2
  end
  puts "%.2f" %output[0]+"  "+"%.2f" %output[1]
end
puts "want to be:"
num_mode.times do |k|
  puts "%.2f" %d[k][0]+"  "+"%.2f" %d[k][1]
end
errorsum/=2
puts "total deviation:"+errorsum.to_s


联想记忆(Hopfield)
def ppp( aa )
  note = ""
  15.times do |i|
    if aa[i] == 1
      note += " 1\t"
    else
      note += "-1\t"
    end
  end
  note
end

def change( bb, cc )
  15.times do |i|
    if bb[i] == 1
      if ((rand 2) + (rand 2)) / 2 == 0
        cc[i] = 1
      else
        next
      end
    else
      next
    end
  end
  cc
end

u=Array.new(15)
15.times do |i|
  u[i]=(rand 101)/100.0*(-1)**(rand 2)
end

w = Array.new(15,0)
15.times do |i|
  w[i] = Array.new(15,0)
  15.times do |j|
    if j > i
      w[i][j]=(rand 101)/100.0*(-1)**(rand 2)
    else
      w[i][j]=w[j][i]
    end
  end
end

# inital status
ini_status = Array.new(15,0)
15.times do |i|
  if (rand 2) == 0
    ini_status[i] = -1
  else
    ini_status[i] = 1
  end
end
puts "Forehead status",ppp(ini_status)

120.times do |i|
  now = rand 15
  tt = 0
  15.times do |j|
    tt += w[now][j] * ini_status[j]
  end
  if tt-u[now] >= 0
    ini_status[now] = 1
  else
    ini_status[now] = -1
  end
end
puts "\nMemory status(->forehead status)",ppp(ini_status)

temp = 0
15.times do |i|
  15.times do |j|
    temp += -0.5 * w[i][j] * ini_status[i] * ini_status[j]
  end
end
puts "Engergy is" + temp.to_s

target = [-1,1,-1,1,-1,1,1,1,1,1,-1,1,1,-1,1]
puts "\nA letter target(what we want to become)",ppp(target)

test = Array.new(15,-1)
test = [-1,-1,-1,1,-1,1,-1,-1,-1,1,-1,-1,-1,-1,-1]
puts "\nTest object(we want it to become A letter)",ppp(test)
simulate = Array.new(15,0)

15.times do |i|
  if test[i] != target[i]
    simulate[i] = -1 * ini_status[i]
  else
    simulate[i] = ini_status[i]
  end
end
puts "\n#Hopfield new initial status(->memory status(generated by above 3))",ppp(simulate)

120.times do |i|
  now = rand 15
  tt = 0
  15.times do |j|
    tt += w[now][j] * simulate[j]
  end
  if tt-u[now] >= 0
    simulate[now] = 1
  else
    simulate[now] = -1
  end
end
puts "\nFinal status(->hopfield new initial status(by the same w[]))",ppp(simulate)

temp = 0
15.times do |i|
  15.times do |j|
    temp += -0.5 * w[i][j] * simulate[i] * simulate[j]
  end
end
puts "Engergy is" + temp.to_s

judge = "Y"
15.times do |i|
  if ini_status[i] != simulate[i]
    judge = "N"
    puts "\nMemory lost!!!"
    break
  end
end
if judge == "Y"
  puts "\nWe learnt it!! "
end


SOFM网(输入为sin曲线。实现了点的文件生成,再用C语言画图,ruby是在不容易实现画图,除非在Mac系统里)
#SOM another try!
#by Brinado on Apr. 17th, 2008

#initialization
num_mode=80
num_matrix=10
num_learn=60
ita=0.5
sigma=1

#input -- Math.sin
input=Array.new(num_mode)
num_mode.times do |i|
  input[i]=Array.new(2)
  2.times do |j|
    input[i][0]=1.0*i/num_mode
    input[i][1]=Math.sin(Math::PI*2.0*i/num_mode)/2+0.5
  end
end

#w
w=Array.new(100)
100.times do |i|
  w[i]=Array.new(2)
  2.times do |j|
    w[i][j]=0.5+(rand 100)/1000*(-1)**(rand 2)
  end
end

#output
output=Array.new(num_mode)
num_mode.times do |i|
  output[i]=Array.new(2)
  2.times do |j|
    output[i][j]=1.0*i/num_mode
    output[i][j]=Math.sin(Math::PI*2.0*i/num_mode)
  end
end

num_learn.times do |g|
  num_mode.times do |k|
    distance=Array.new(100)
    a,b,tt3=0,0,999
    100.times do |i|
        tt=Math.sqrt((input[k][0]-w[i][0])**2+(input[k][1]-w[i][1])**2)
        #puts tt
        distance[i]=tt
      if tt<tt3
        a,tt3=i,tt
      end
    end
    
    100.times do |i|
      2.times do |j|
        tta1,tta2=(a/9-i/9)**2+(a%9-i%9)**2,sigma**2
        w[i][j]+=ita*Math.exp(-1.0*tta1/sigma)*(input[k][j]-w[i][j])
      end
    end
    
    #insertion here...
  end
  if sigma<0.005
     sigma==0.005
  else
     sigma-=0.005
  end
end


txt = ""
f = File.open("db.txt", "w")
100.times do |i|
    txt = "%.15f" %w[i][0] + " " + "%.15f" %w[i][1] + " "
    f.write(txt)
end
f.close


SOFM网C语言画图实现
#include<stdio.h>
#include<stdlib.h>
#include<graphics.h>
#define MM 19

main()
{
 char ch[MM];
 int i=0,j=0;
 int object[200];
 int graphdriver=VGA;
 int graphmode=VGAHI;

 FILE *f;
 if((f=fopen("[b]c:/turboc2/brinado/db2.txt[/b]","r"))==NULL)
 {
  printf("db.txt open error.\n");
  exit(0);
 }
 while(i<200)
 {
  fgets(ch,MM,f);
  object[i]=(int)((ch[2]-'0')*10+ch[3]-'0'+(ch[4]-'0')*0.1)*4;
  i++;
 }
 fclose(f);


 initgraph(&graphdriver,&graphmode," ");
 cleardevice();
 /*
 setcolor(RED);
 for(j=0;j<200;j+=2)
 {
  if(j==18||j==38||j==58||j==78||j==98||j==118||j==138||j==158||j==178||j==198)
  {
   if(j!=198){line(object[j],object[j+1],object[j+20],object[j+21]);}
   continue;
  }
  line(object[j],object[j+1],object[j+2],object[j+3]);
  if(j<180)
  {
   line(object[j],object[j+1],object[j+20],object[j+21]);
  }
 }
 */
 for(j=0;j<200;j+=2)
 {
  putpixel(object[j],object[j+1],2);
  putpixel(object[j]+1,object[j+1],1);
  putpixel(object[j],object[j+1]+1,1);
  putpixel(object[j],object[j+1]-1,1);
  putpixel(object[j]-1,object[j+1],1);
 }
 setcolor(WHITE);
 rectangle(0,0,639,479);
 getch();
 closegraph();
}


GA-遗传算法
#target:[0 0 0 0 0] [1 1 1 1 1]

#evaluate fitness
def godbenchmark(god)
  result=0
  10.times do |i|
    if i<5
      if god[i]==0
        result+=1
      end
    else
      if god[i]==1
        result+=1
      end
    end
  end
  result #return fitness value
end

#crossover using single point method
#change from 0~10 points totally. When set position===10, operation equals to completely change 2 chrommosomes
def crossover(a,b,position)
  10.times do |j|
    if j>=position
      tt=a[j]
      a[j]=b[j]
      b[j]=tt
    end
  end
end

#initialize chromosome
chromosome=Array.new(6)
6.times do |i|
  chromosome[i]=Array.new(10,0)
  10.times do |j|
    if (rand 2)==1
      chromosome[i][j]=1
    end
  end
end

#parameters
#p_crossover=0.4
#p_mutation=3/60
#num_chromosome=6
#num_gene=10
iterates=50
step=0
record=Array.new(50)

init=Array.new(6,0)
6.times do |i|
  init[i]=Array.new(2)
  init[i][0]=i
  init[i][1]=godbenchmark(chromosome[i])
end
#pop ranking
ttt,t1=init[0][1],0
6.times do |i|
  for j in 0..(5-i)
    if j==0
      ttt,t1=init[0][1],0
    end
    if init[j][1] > ttt
      mm1,mm2=init[j][0],init[j][1]
      init[j][0],init[j][1]=init[t1][0],init[t1][1]
      init[t1][0],init[t1][1]=mm1,mm2
      ttt,t1=init[j][1],j
    else
      ttt,t1=init[j][1],j
    end
  end
end

#select using tournament method
middle=Array.new(6)
6.times do |i|
  middle[i]=Array.new(10)
  if i==0
    10.times do |j|
      middle[i][j]=chromosome[init[i][0]][j]
    end
  else
    10.times do |j|
      middle[i][j]=chromosome[init[i-1][0]][j]
    end
  end
end
chromosome=middle

#iteration begins...
iterates.times do |k|
  #crossover begin
  3.times do |i|
    if (rand 10)/10.0 >= 0.6
      case i
        when 0
          crossover chromosome[0],chromosome[5],(rand 10) #must change anyway!!!
        when 1
          crossover chromosome[1],chromosome[4],(rand 10)
        when 2
          crossover chromosome[2],chromosome[3],(rand 10)
      end
    end
  end
  #crossover end
  
  #mutation begin
  6.times do |i|
    percentage=0.85
    if (rand 100)/100.0 >= percentage
      tt=rand 10
      if chromosome[i][tt]==0
        chromosome[i][tt]=1
      else
        chromosome[i][tt]=0
      end
    end
  end
  #mutation end
  
  #selection begin
  init=Array.new(6,0)
  6.times do |i|
    init[i]=Array.new(2)
    init[i][0]=i
    init[i][1]=godbenchmark(chromosome[i])
  end
  #pop ranking
  ttt,t1=init[0][1],0
  6.times do |i|
    for j in 0..(5-i)
      if j==0
        ttt,t1=init[0][1],0
      end
      if init[j][1] > ttt
        mm1,mm2=init[j][0],init[j][1]
        init[j][0],init[j][1]=init[t1][0],init[t1][1]
        init[t1][0],init[t1][1]=mm1,mm2
        ttt,t1=init[j][1],j
      else
        ttt,t1=init[j][1],j
      end
    end
  end
  #select using tournament method
  middle=Array.new(6)
  6.times do |i|
    middle[i]=Array.new(10)
    if i==0
      10.times do |j|
        middle[i][j]=chromosome[init[i][0]][j]
      end
    else
      10.times do |j|
        middle[i][j]=chromosome[init[i-1][0]][j]
      end
    end
  end
  chromosome=middle
  #select end

  record[step]=godbenchmark(chromosome[0])
  step+=1
  #exit condition
  if godbenchmark(chromosome[0])==10
    break
  end
end

#print initial chromosome
print="--Final Result--\n"
6.times do |i|
  10.times do |j|
    print+=chromosome[i][j].to_s+"\t"
  end
  print+="\n"
end
puts print
puts "\n*Note:this result is the No.#{step} generation's reproduction!","\n*Step change(fitness result) in detail:\n","\n"
step.times do |i|
  puts "No.#{i} step best: "+record[i].to_s
end

你可能感兴趣的:(算法,F#,db2,J#,Ruby)