加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

遗传算法的神经网络python实现代码

发布时间:2020-12-17 17:08:38 所属栏目:Python 来源:网络整理
导读:今天PHP站长网 52php.cn把收集自互联网的代码分享给大家,仅供参考。 ## {{{ http://code.activestate.com/recipes/578241/ (r1)from operator import itemgetter,attrgetterimport mathimport randomimport stringimport

以下代码由PHP站长网 52php.cn收集自互联网

现在PHP站长网小编把它分享给大家,仅供参考

## {{{ http://code.activestate.com/recipes/578241/ (r1)
from operator import itemgetter,attrgetter
import math
import random
import string
import timeit
from timeit import Timer as t
import matplotlib.pyplot as plt
import numpy as np
 
def sigmoid (x):
  return math.tanh(x)
 
def makeMatrix ( I,J,fill=0.0):
  m = []
  for i in range(I):
    m.append([fill]*J)
  return m
   
def randomizeMatrix ( matrix,a,b):
  for i in range ( len (matrix) ):
    for j in range ( len (matrix[0]) ):
      matrix[i][j] = random.uniform(a,b)
 
class NN:
  def __init__(self,NI,NH,NO):
    self.ni = NI
    self.nh = NH
    self.no = NO
    self.ai = [1.0]*self.ni
    self.ah = [1.0]*self.nh
    self.ao = [1.0]*self.no
    self.wi = [ [0.0]*self.nh for i in range(self.ni) ]
    self.wo = [ [0.0]*self.no for j in range(self.nh) ]
    randomizeMatrix ( self.wi,-0.2,0.2 )
    randomizeMatrix ( self.wo,-2.0,2.0 )
 
  def runNN (self,inputs):
    if len(inputs) != self.ni:
      print 'incorrect number of inputs'
    for i in range(self.ni):
      self.ai[i] = inputs[i]
    for j in range(self.nh):
      self.ah[j] = sigmoid(sum([ self.ai[i]*self.wi[i][j] for i in range(self.ni) ]))
    for k in range(self.no):
      self.ao[k] = sigmoid(sum([ self.ah[j]*self.wo[j][k] for j in range(self.nh) ]))
    return self.ao
 
  def weights(self):
    print 'Input weights:'
    for i in range(self.ni):
      print self.wi[i]
    print
    print 'Output weights:'
    for j in range(self.nh):
      print self.wo[j]
    print ''
 
  def test(self,patterns):
    results,targets = [],[]
    for p in patterns:
      inputs = p[0]
      rounded = [ round(i) for i in self.runNN(inputs) ]
      if rounded == p[1]: result = '+++++'
      else: result = '-----'
      print '%s %s %s %s %s %s %s' %( 'Inputs:',p[0],'-->',str(self.runNN(inputs)).rjust(65),'Target',p[1],result)
      results+= self.runNN(inputs)
      targets += p[1]
    return results,targets
 
  def sumErrors (self):
    error = 0.0
    for p in pat:
      inputs = p[0]
      targets = p[1]
      self.runNN(inputs)
      error += self.calcError(targets)
    inverr = 1.0/error
    return inverr
 
  def calcError (self,targets):
    error = 0.0
    for k in range(len(targets)):
      error += 0.5 * (targets[k]-self.ao[k])**2
    return error
 
  def assignWeights (self,weights,I):
    io = 0
    for i in range(self.ni):
      for j in range(self.nh):
        self.wi[i][j] = weights[I][io][i][j]
    io = 1
    for j in range(self.nh):
      for k in range(self.no):
        self.wo[j][k] = weights[I][io][j][k]
 
  def testWeights (self,I):
    same = []
    io = 0
    for i in range(self.ni):
      for j in range(self.nh):
        if self.wi[i][j] != weights[I][io][i][j]:
          same.append(('I',i,j,round(self.wi[i][j],2),round(weights[I][io][i][j],round(self.wi[i][j] - weights[I][io][i][j],2)))
 
    io = 1
    for j in range(self.nh):
      for k in range(self.no):
        if self.wo[j][k] !=  weights[I][io][j][k]:
          same.append((('O',k),round(self.wo[j][k],round(weights[I][io][j][k],round(self.wo[j][k] - weights[I][io][j][k],2)))
    if same != []:
      print same
 
def roulette (fitnessScores):
  cumalativeFitness = 0.0
  r = random.random()
  for i in range(len(fitnessScores)):
    cumalativeFitness += fitnessScores[i]
    if cumalativeFitness > r:
      return i
       
def calcFit (numbers):  # each fitness is a fraction of the total error
  total,fitnesses = sum(numbers),[]
  for i in range(len(numbers)):          
    fitnesses.append(numbers[i]/total)
  return fitnesses
 
# takes a population of NN objects
def pairPop (pop):
  weights,errors = [],[]
  for i in range(len(pop)):                 # for each individual
    weights.append([pop[i].wi,pop[i].wo])   # append input & output weights of individual to list of all pop weights
    errors.append(pop[i].sumErrors())       # append 1/sum(MSEs) of individual to list of pop errors
  fitnesses = calcFit(errors)               # fitnesses are a fraction of the total error
  for i in range(int(pop_size*0.15)):
    print str(i).zfill(2),'1/sum(MSEs)',str(errors[i]).rjust(15),str(int(errors[i]*graphical_error_scale)*'-').rjust(20),'fitness'.rjust(12),str(fitnesses[i]).rjust(17),str(int(fitnesses[i]*1000)*'-').rjust(20)
  del pop
  return zip(weights,errors,fitnesses)            # weights become item[0] and fitnesses[1] in this way fitness is paired with its weight in a tuple
   
def rankPop (newpopW,pop):
  errors,copy = [],[]           # a fresh pop of NN's are assigned to a list of len pop_size
  #pop = [NN(ni,nh,no)]*pop_size # this does not work as they are all copies of eachother
  pop = [NN(ni,no) for i in range(pop_size) ]
  for i in range(pop_size): copy.append(newpopW[i])
  for i in range(pop_size): 
    pop[i].assignWeights(newpopW,i)                                    # each individual is assigned the weights generated from previous iteration
    pop[i].testWeights(newpopW,i)
  for i in range(pop_size): 
    pop[i].testWeights(newpopW,i)
  pairedPop = pairPop(pop)                                              # the fitness of these weights is calculated and tupled with the weights
  rankedPop = sorted(pairedPop,key = itemgetter(-1),reverse = True)   # weights are sorted in descending order of fitness (fittest first)
  errors = [ eval(repr(x[1])) for x in rankedPop ]
  return rankedPop,eval(repr(rankedPop[0][1])),float(sum(errors))/float(len(errors))
 
def iteratePop (rankedPop):
  rankedWeights = [ item[0] for item in rankedPop]
  fitnessScores = [ item[-1] for item in rankedPop]
  newpopW = [ eval(repr(x)) for x in rankedWeights[:int(pop_size*0.15)] ]
  while len(newpopW) <= pop_size:                                       # Breed two randomly selected but different chromos until pop_size reached
    ch1,ch2 = [],[]
    index1 = roulette(fitnessScores)                                   
    index2 = roulette(fitnessScores)
    while index1 == index2:                                             # ensures different chromos are used for breeeding
      index2 = roulette(fitnessScores)
    #index1,index2 = 3,4
    ch1.extend(eval(repr(rankedWeights[index1])))
    ch2.extend(eval(repr(rankedWeights[index2])))
    if random.random() < crossover_rate:
      ch1,ch2 = crossover(ch1,ch2)
    mutate(ch1)
    mutate(ch2)
    newpopW.append(ch1)
    newpopW.append(ch2)
  return newpopW
 
graphical_error_scale = 100
max_iterations = 4000
pop_size = 100
mutation_rate = 0.1
crossover_rate = 0.8
ni,no = 4,6,1
 
def main ():
  # Rank first random population
  pop = [ NN(ni,no) for i in range(pop_size) ] # fresh pop
  pairedPop = pairPop(pop)
  rankedPop = sorted(pairedPop,reverse = True) # THIS IS CORRECT
  # Keep iterating new pops until max_iterations
  iters = 0
  tops,avgs = [],[]
  while iters != max_iterations:
    if iters%1 == 0:
      print 'Iteration'.rjust(150),iters
    newpopW = iteratePop(rankedPop)
    rankedPop,toperr,avgerr = rankPop(newpopW,pop)
    tops.append(toperr)
    avgs.append(avgerr)
    iters+=1
   
  # test a NN with the fittest weights
  tester = NN (ni,no)
  fittestWeights = [ x[0] for x in rankedPop ]
  tester.assignWeights(fittestWeights,0)
  results,targets = tester.test(testpat)
  x = np.arange(0,150)
  title2 = 'Test after '+str(iters)+' iterations'
  plt.title(title2)
  plt.ylabel('Node output')
  plt.xlabel('Instances')
  plt.plot( results,'xr',linewidth = 0.5)
  plt.plot( targets,'s',color = 'black',linewidth = 3)
  #lines = plt.plot( results,'sg')
  plt.annotate(s='Target Values',xy = (110,0),family = 'sans-serif',size  ='small')
  plt.annotate(s='Test Values',0.5),color = 'red',size  ='small',weight = 'bold')
  plt.figure(2)
  plt.subplot(121)
  plt.title('Top individual error evolution')
  plt.ylabel('Inverse error')
  plt.xlabel('Iterations')
  plt.plot( tops,'-g',linewidth = 1)
  plt.subplot(122)
  plt.plot( avgs,linewidth = 1)
  plt.title('Population average error evolution')
  plt.ylabel('Inverse error')
  plt.xlabel('Iterations')
   
  plt.show()
   
  print 'max_iterations',max_iterations,'tpop_size',pop_size,'pop_size*0.15',int(pop_size*0.15),'tmutation_rate',mutation_rate,'crossover_rate',crossover_rate,'ni,no',ni,no
 
def crossover (m1,m2):
  r = random.randint(0,(ni*nh)+(nh*no) ) # ni*nh+nh*no  = total weights
  output1 = [ [[0.0]*nh]*ni,[[0.0]*no]*nh ]
  output2 = [ [[0.0]*nh]*ni,[[0.0]*no]*nh ]
  for i in range(len(m1)):
    for j in range(len(m1[i])):
      for k in range(len(m1[i][j])):
        if r >= 0:
          output1[i][j][k] = m1[i][j][k]
          output2[i][j][k] = m2[i][j][k]
        elif r < 0:
          output1[i][j][k] = m2[i][j][k]
          output2[i][j][k] = m1[i][j][k]
        r -=1
  return output1,output2
 
def mutate (m):
  # could include a constant to control
  # how much the weight is mutated by
  for i in range(len(m)):
    for j in range(len(m[i])):
      for k in range(len(m[i][j])):
        if random.random() < mutation_rate:
            m[i][j][k] = random.uniform(-2.0,2.0)
   
if __name__ == "__main__":
    main()
pat = [
  [[5.1,3.5,1.4,0.2],[-1],['Iris-setosa']],[[4.9,3.0,[[4.7,3.2,1.3,[[5.4,3.9,1.7,0.4],[[4.6,3.4,0.3],[[5.0,1.5,[[4.4,2.9,3.1,0.1],3.7,[[4.8,1.6,[[4.3,1.1,[[5.8,4.0,1.2,[[5.7,4.4,[[5.1,3.8,3.6,1.0,3.3,0.5],1.9,[[5.2,4.1,[[5.5,4.2,[[4.5,2.3,0.6],[[5.3,[[7.0,4.7,1.4],[0],['Iris-versicolor']],[[6.4,4.5,1.5],[[6.9,4.9,1.3],[[6.5,2.8,4.6,[[6.3,1.6],2.4,1.0],[[6.6,2.7,2.0,[[5.9,[[6.0,2.2,[[6.1,[[5.6,[[6.7,[[6.2,2.5,1.1],4.8,1.8],1.2],4.3,[[6.8,5.0,1.7],2.6,5.1,6.0,2.5],[1],['Iris-virginica']],1.9],[[7.1,5.9,2.1],5.6,5.8,2.2],[[7.6,6.6,[[7.3,6.3,[[7.2,6.1,2.0],5.3,5.5,2.4],[[7.7,6.7,6.9,2.3],5.7,[[7.4,[[7.9,6.4,5.4,5.2,['Iris-virginica']]
]
 
testpat = [
  [[5.1,['Iris-virginica']]
]

以上内容由PHP站长网【52php.cn】收集整理供大家参考研究

如果以上内容对您有帮助,欢迎收藏、点赞、推荐、分享。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读