python遗传算法实现数据拟合

python据说功能强大,触角伸到各个领域,网上搜了一下其科学计算和工程计算能力也相当强,具备各种第三方包,除了性能软肋外,其他无可指摘,甚至可以同matlab等专业工具一较高下。

从网上找了一个使用遗传算法实现数据拟合的例子学习了一下,确实Python相当贴合自然语言,终于编程语言也能说人话了,代码整体简洁、优雅。。

代码功能:给出一个隐藏函数 例如 z=x^2+y^2,生成200个数据,利用这200个数据,使用遗传算法猜测这些数据是什么公式生成的。 (说的太直白,一点都不高大上)

代码如下:

  1  #  coding=utf-8
  2  from random  import random, randint, choice,uniform
  3  from copy  import deepcopy
  4  import numpy as np
  5  import matplotlib.pyplot as plt
  6 
  7  from random  import random, randint, choice
  8  from copy  import deepcopy
  9  import numpy as np
 10 
 11  #  运算类
 12  class fwrapper:
 13      def  __init__(self, function, childcount, name):
 14         self.function = function
 15         self.childcount = childcount
 16         self.name = name
 17 
 18  #  节点类
 19  class node:
 20      def  __init__(self, fw, children):
 21         self.function = fw.function
 22         self.name = fw.name
 23         self.children = children
 24  # 将inp指定的运算符作用到子节点上
 25       def evaluate(self, inp):
 26          #  循环调用子节点的子节点的子节点....的evaluate方法
 27          results = [n.evaluate(inp)  for n  in self.children]
 28          #  返回运算结果
 29           return self.function(results)
 30  # 打印本节点及所属节点的操作运算符
 31       def display(self, indent=0):
 32          print( '   ' * indent) + self.name
 33          for c  in self.children:
 34             c.display(indent + 1)
 35 
 36  # 参数节点类,x+y 其中x,y都是参数节点
 37  class paramnode:
 38      def  __init__(self, idx):
 39         self.idx = idx
 40  #  evaluate方法返回paramnode节点值本身
 41       def evaluate(self, inp):
 42          return inp[self.idx]
 43 
 44      def display(self, indent=0):
 45          print  ' %sp%d ' % ( '   ' * indent, self.idx)
 46 
 47  #  常数节点
 48  class constnode:
 49      def  __init__(self, v):
 50         self.v = v
 51 
 52      def evaluate(self, inp):
 53          return self.v
 54 
 55      def display(self, indent=0):
 56          print  ' %s%d ' % ( '   ' * indent, self.v)
 57 
 58  #  操作运算符类
 59  class opera:
 60      #  使用前面定义的fwrapper类生产常用的加减乘除运算,第一个参数是本运算执行方式,第二个参数是本运算接受的参数个数,第三个参数是本运算名称
 61      addw = fwrapper( lambda l: l[0] + l[1], 2,  ' add ')
 62     subw = fwrapper( lambda l: l[0] - l[1], 2,  ' subtract ')
 63     mulw = fwrapper( lambda l: l[0] * l[1], 2,  ' multiply ')
 64 
 65      def iffunc(l):
 66          if l[0] > 0:
 67              return l[1]
 68          else:
 69              return l[2]
 70      # 定义if运算
 71      ifw = fwrapper(iffunc, 3,  ' if ')
 72 
 73      def isgreater(l):
 74          if l[0] > l[1]:
 75              return 1
 76          else:
 77              return 0
 78      # 定义greater运算
 79      gtw = fwrapper(isgreater, 2,  ' isgreater ')
 80      # 构建运算符集合
 81      flist = [addw, mulw, ifw, gtw, subw]
 82 
 83      # 使用node,paramnode,fwrapper构建一个example
 84       def exampletree(self):
 85          return node(self.ifw, [node(self.gtw, [paramnode(0), constnode(3)]), node(self.addw, [paramnode(1), constnode(5)]),
 86                           node(self.subw, [paramnode(1), constnode(2)]), ])
 87 
 88 
 89      #  构建一颗随机运算数,pc为参数(分叉)个数,maxdepth为树的深度,fpr为运算符个数在运算符加节点总数中所占比例,ppr为参数个数在参数加常数个数总数中所占的比例
 90       def makerandomtree(self,pc, maxdepth=4, fpr=0.5, ppr=0.6):
 91          if random() < fpr  and maxdepth > 0:
 92             f = choice(self.flist)
 93              #  递归调用makerandomtree实现子节点的创建
 94              children = [self.makerandomtree(pc, maxdepth - 1, fpr, ppr)  for i  in range(f.childcount)]
 95              return node(f, children)
 96          elif random() < ppr:
 97              return paramnode(randint(0, pc - 1))
 98          else:
 99              return constnode(randint(0, 10))
100 
101 
102      # 变异,变异概率probchange=0.1
103       def mutate(self,t, pc, probchange=0.1):
104          #  变异后返回一颗随机树
105           if random() < probchange:
106              return self.makerandomtree(pc)
107          else:
108             result = deepcopy(t)
109              #  递归调用,给其子节点变异的机会
110               if isinstance(t, node):
111                 result.children = [self.mutate(c, pc, probchange)  for c  in t.children]
112              return result
113 
114      # 交叉
115       def crossover(self,t1, t2, probswap=0.7, top=1):
116          #  如果符合交叉概率,就将t2的值返回,实现交叉;
117           if random() < probswap  and  not top:
118              return deepcopy(t2)
119          else:
120              # 如果本层节点未实现交配,递归询问子节点是否符合交配条件
121               # 首先使用deepcopy保存本节点
122              result = deepcopy(t1)
123              if isinstance(t1, node)  and isinstance(t2, node):
124                  # 依次递归询问t1下的各子孙节点交配情况,交配对象为t2的各子孙;t1,t2家族同辈交配
125                  result.children = [self.crossover(c, choice(t2.children), probswap, 0)  for c  in t1.children]
126              return result
127 
128      #  random2.display()
129       #  muttree=mutate(random2,2)
130       #  muttree.display()
131       #  cross=crossover(random1,random2)
132       #  cross.display()
133 
134      # 设置一个隐藏函数,也就是原始函数
135       def hiddenfunction(self,x, y):
136          return x ** 2+ y**2
137 
138      # 依照隐藏函数,生成坐标数据
139       def buildhiddenset(self):
140             rows = []
141              for i  in range(200):
142                 x = randint(0, 10)
143                 x=uniform(-1,1)
144                 y = randint(0, 10)
145                 y=uniform(-1,1)
146                 rows.append([x, y, self.hiddenfunction(x, y)])
147              print( " rows: ",rows)
148              return rows
149 
150      # 拟合成绩函数,判定拟合函数(实际是一颗图灵树)贴近原始函数的程度
151       def scorefunction(self,tree, s):
152         dif = 0
153          #  print("tree:",tree)
154           #  print("s:",s)
155           for data  in s:
156              #  print("data[0]:",data[0])
157               #  print("data[1]:",data[1])
158              v = tree.evaluate([data[0],data[1]])
159              # 累加每个数据的绝对值偏差
160              dif += abs(v - data[2])
161          return dif
162 
163      # 返回一个成绩判定函数rankfunction的句柄
164       def getrankfunction(self,dataset):
165          # 此函数调用拟合成绩函数,并对成绩排序,返回各个种群的成绩
166           def rankfunction(population):
167             scores = [(self.scorefunction(t, dataset), t)  for t  in population]
168             scores.sort()
169              return scores
170          return rankfunction
171 
172      #  hiddenset=buildhiddenset()
173       #  scorefunction(random2,hiddenset)
174       #  scorefunction(random1,hiddenset)
175 
176      def evolve(self,pc, popsize, rankfunction, maxgen=500, mutationrate=0.1, breedingrate=0.4, pexp=0.7, pnew=0.05):
177          # 轮盘算法
178           def selectindex():
179              return int(np.log(random()) / np.log(pexp))
180          # 使用随机树生成第一代各种群
181          population = [self.makerandomtree(pc)  for i  in range(popsize)]
182          # 计算每一代各种群的成绩,
183           for i  in range(maxgen):
184             scores = rankfunction(population)
185              # 打印历代最好成绩
186               print( ' the best score in genneration  ',i, ' : ',scores[0][0])
187              # 成绩完全吻合原函数的话,退出函数
188               if scores[0][0] == 0:
189                  break
190              # 创建新一代各种群,成绩前两名的直接进入下一代
191              newpop = [scores[0][1], scores[1][1]]
192              while len(newpop) < popsize:
193                  # pnew为引进随机种群概率,未达此概率的,使用原种群的交配、变异生成新种群
194                   if random() > pnew:
195                     newpop.append(
196                         self.mutate(self.crossover(scores[selectindex()][1], scores[selectindex()][1], probswap=breedingrate), pc,
197                                probchange=mutationrate))
198                  # 引入随机种群
199                   else:
200                     newpop.append(self.makerandomtree(pc))
201             population = newpop
202              # 打印历代最好种群
203               #  scores[0][1].display()
204           return scores[0][1]
205 
206 
207 
208  def main(argv):
209     e=opera()
210      def exampletree():
211          return node(e.ifw,[node(e.gtw,[paramnode(0),constnode(3)]),node(e.addw,[paramnode(1),constnode(5)]),node(e.subw,[paramnode(1),constnode(2)])])
212 
213 
214      #  random1=e.makerandomtree(2)
215       #  random1.evaluate([7,1])
216       #  random1.evaluate([2,4])
217       #  random2=e.makerandomtree(2)
218       #  random2.evaluate([5,3])
219       #  random2.evaluate([5,20])
220       #  random1.display()
221       #  random2.display()
222 
223      #  exampletree = e.exampletree()
224       #  exampletree.display()
225       #  print(exampletree.evaluate([6, 1]))
226       #  print('after evaluate:')
227       #  exampletree.display()
228       #  exampletree.evaluate([2, 3])
229       #  exampletree.evaluate([5, 3])
230       #  exampletree.display()
231 
232     a=opera()
233     row2=a.buildhiddenset()
234      #  fig=plt.figure()
235       #  ax=fig.add_subplot(1,1,1)
236       #  plt.plot(np.random.randn(1000).cumsum())
237       #  plt.show()
238 
239 
240 
241      from mpl_toolkits.mplot3d  import Axes3D
242     fig = plt.figure()
243     ax = fig.add_subplot(111, projection= ' 3d ')
244     X = [1, 1, 2, 2]
245     Y = [3, 4, 4, 3]
246     Z = [1, 2, 1, 1]
247     rx=[]
248     ry=[]
249     rz=[]
250      for i  in row2:
251         rx.append(i[0])
252         ry.append(i[1])
253         rz.append(i[2])
254 
255     ax.plot_trisurf(rx, ry, rz)
256     rz2=[]
257     rf = a.getrankfunction(row2)
258     final = a.evolve(2, 100, rf, mutationrate=0.2, breedingrate=0.1, pexp=0.7, pnew=0.1,maxgen=500)
259      print( ' __________________is it?_________________________ ')
260     final.display()
261      for j  in range(0,len(rx)):
262         rz2.append(final.evaluate([rx[j],ry[j]]))
263     fig2 = plt.figure()
264     ax2 = fig2.add_subplot(111, projection= ' 3d ')
265     ax2.plot_trisurf(rx, ry, rz2)
266 
267     plt.show()
268 
269 
270      #  print(rf)
271       #  final = a.evolve(2, 500, rf, mutationrate=0.2, breedingrate=0.1, pexp=0.7, pnew=0.1)
272       #  print("final:",final)
273       #  print(final.evaluate([1,8]))
274       #  print(final.evaluate([2,9]))
275 
276 
277 
278 
279 
280  if  __name__== " __main__ ":

281     main(0) 

 

看懂不一定写的出来,这是这次写这个程序最大的体会, 得定时拿出来复习复习。

转载于:https://www.cnblogs.com/javajava/p/4988706.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值