DEAP1.2.2(四) 计算统计

(四) 计算统计

  1. Computing Statistics
    通常情况下,我们想要在优化过程中编辑数据。Statistic模块可以在任何设计好的目标上改变一些本不可改变的数据。为了达到这个目的,需要使用与工具箱中完全相同的语法在静态数据中注册统计函数。
states = tools.Statistics(key = lambda ind : ind.fitness.values)

使用key的第一个参数作为统计对象。这个key必须支持一个可以在之后被应用到数据上的函数从而得到统计结果。之前的例子使用了fitness.values()中每一个元素的属性。

states.register('avg', numpy.mean)
states.register('std', numpy.std)
states.register('min', numpy.min)
states.register('max', numpy.max)

这些统计函数现在被注册了。register函数希望alias(‘名字’)作为第一个属性以及一个在向量上操作的函数(numpy.mean)作为第二个属性。在调用时,任何在后面的元素都会传到函数上。统计目标的创建已经完成。

  1. Predefined Algorithms
    当使用一个预定义的算法时,例如esSimple()/eaMuPlusLambada()/eaMuCommaLambda()/eaGenerateUpdata(),之前创建的统计目标可以作为算法的属性。
pop, logbook = algorithms.esSimple(pop, toolbox, cxpb = 0.5, mutpb = 0.2, ngen = 0, stats = stats, verbose = True)

统计将会在每一次迭代中自动的进行计算。详细参数在优化过程中会打印在屏幕上。一旦算法返回,最终的种群和一个logbook将会返回。在下一节可以看到更详细的信息。

  1. Writing Your Own Algorithm
    当编写自己的算法时,包含统计时十分简单的。只需要去在需要的目标上编写统计。例如,在一个给定种群上编写统计需要调用compile()方法完成。
record = stats.compile(pop)

这些用于编辑函数的属性必须在一个迭代元素中,这样这些key才会被调用。这里,我们的种群(pop)包含了许多个体。统计目标将会在每一个个体上调用key函数获取fitness.values属性的值。这个结果数组的值最终会给到每一个统计函数并且将结果输入到record字典中,每一个key都会与相应的函数相关联。

在你的main函数中把这个命令放在更新种群之后就可以得到一系列的统计值:标准差-最大值-平均值-最小值。

  1. Multi-objective Statistics
    正如统计可以通过numpy函数直接进行计算,所有的目标将会通过默认numpy的属性联合在一起。接下来,一个需要明确的事情是每一个axis的操作。这会通过给予axis一个额外的属性作为注册函数达成。
stats = tools.Statistics(key=lambda ind: ind.fitness.values)
stats.register("avg", numpy.mean, axis=0)
stats.register("std", numpy.std, axis=0)
stats.register("min", numpy.min, axis=0)
stats.register("max", numpy.max, axis=0)
  1. Multiple Statistics
    计算种群个体的不同属性也是可以的。例如,在遗传程序设计(GP)中除了对适应度统计之外,对表达式树的高度统计也是常见的。一个可以使用多元Statistics目标的函数是MultiStatistics。
stats_fit = tools.Statistics(ket= lambda ind: ind.fitness.values)
stats_size = tools.Statistics(key = len)
mstats = tools.MultiStatistics(fitness = stats_fit, size = stats_size)

两个统计目标使用与之前相同的方式被创建。第二个目标将会通过调用len()获取每一个个体的长度。一旦创建完成,统计目标将会被给到MultiStatistics函数中,这里地元素都是使用keywords来定义的。这些keywords将会提供不同统计量的定义。这些统计函数仅仅可以在multi-statistics被注册一次

mstats.register("avg", numpy.mean)
mstats.register("std", numpy.std)
mstats.register("min", numpy.min)
mstats.register("max", numpy.max)

多元统计目标可以给到一个算法当中,或者他们可以以相似的形式运用到单一统计中

record = mstats.compile(pop)

在这种情况下,record就是一个字典的字典类型(嵌套)。第一个等级包括一些统计信息的关键字,第二个等级包括一些预制件相似的简单统计目标

>>> print(record)
{'fitness': {'std': 1.64, 'max': 6.86, 'avg': 1.71, 'min': 0.166},
'size': {'std': 1.89, 'max': 7, 'avg': 4.54, 'min': 3}}
  1. Logging Data
    一旦数据通过统计产生,我们可以使用Logbook对它进行存储。Logbook是用来
    按时间顺序排列的条目(如字典)。它会直接兼容数据类型并且返回统计目标,但是不会被数据限制。实际上,任何东西都可以包含在日志的条目中。
logbook = tools.Logbook()
logbook.record(gen=0, evals=30, **record)

record()方法采用可变数字作为参数,每一个参数作为数据都会被记录。在最后一个例子中,我们保存了一代,结果的数量和任何包含在record()中的东西都会通过这个方法产生统计学目标。所有的记录都会被保存在Logicbook中,直到它被销毁。在一些列的记录之后,我们可能会想去调用logbook中的信息

gen, avg = logbook.select("gen", "avg")

select()方法提供了一种方法去调用所有的与record中keyword相关的信息。这个方法采取了可变数量的字符串元素,就是在record或者statistics中的keywords。这里,我们调用代数和平均适应度,使用一个单独的select进行调用。一个logbook是一个可选择的目标(只要插入数据是可选择的),它可以提供一种很好的方法去存储演化过程中的统计参数。

import pickle
    pickle.dump(logbook, lb_file)

注意:每一个算法返回的logbook包含着每一代的信息和适应度在整个进化过程中的数目。

  1. Printing to Screen
    一个logbook可以打印在屏幕或者文档中。它的str()方法在第一个key中返回每一个key的头,同时使用这些keys完成logbook。按照行插入的时间顺序排列,而列将处于未定义的顺序。指定顺序的最简单方法是将header属性设置为指定列顺序的字符串列表。
logbook.header = 'gen', 'avg', 'spam'

结果为

>>>print(logbook)
gen avg spam
0     [ 50, 2 ]

每一个列名包含了没有明确记录的列名,它将会被空着,就像spam一样。

一个logbook同样包含尚未打印的条目的流属性。

>>> print(logbook.stream)
gen   avg      spam
0     [ 50.2]
>>> logbook.record(gen=1, evals=15, **record)
>>> print(logbook.stream)
1     [ 50.2]
  1. Dealing with Multi-statistics
    Logbook可以与字典类型合作,返回MultiStatistics目标。事实上,它将在chapters中为每一个包含在字典中的子字典记录数据,接下来,一个multi record可以被看做一个record
logbook = tools.Logbook()
logbook.record(gen=0, evals=30, **record)

与列排序不同的一点是,当我们明确chapters的顺序时,它们的内容如下

logbook.header = "gen", "evals", "fitness", "size"
logbook.chapters["fitness"].header = "min", "avg", "max"
logbook.chapters["size"].header = "min", "avg", "max"

(看起来就是fitness包含min、avg、max;size也包含这些,然后它们的输出就都分别包含这些)

>>> print(logbook)
                     fitness                 size
            -------------------------  ---------------
gen   evals min      avg      max      min   avg   max
0     30    0.165572 1.71136  6.85956  3     4.54  7

这些数据的调用同样也可以通过chapter进行调用

gen = logbook.select("gen")
fit_mins = logbook.chapters["fitness"].select("min")
size_avgs = logbook.chapters["size"].select("avg")

迭代次数、最小适应度和平均尺寸就可以按照时间顺序获得了。如果一些数据不可用,一个None会出现在向量中。

  1. Some Plotting Sugar
    在优化过程中最常用的操作就是在图中显示进化过程。Logbook可以有效地执行这一操作。使用选择方法,我们可以调用需要的数据并且使用matplotlib去绘制图形。
gen = logbook.select("gen")
fit_mins = logbook.chapters["fitness"].select("min")
size_avgs = logbook.chapters["size"].select("avg")

import matplotlib.pyplot as plt

fig, ax1 = plt.subplots()
line1 = ax1.plot(gen, fit_mins, "b-", label="Minimum Fitness")
ax1.set_xlabel("Generation")
ax1.set_ylabel("Fitness", color="b")
for tl in ax1.get_yticklabels():
    tl.set_color("b")

ax2 = ax1.twinx()
line2 = ax2.plot(gen, size_avgs, "r-", label="Average Size")
ax2.set_ylabel("Size", color="r")
for tl in ax2.get_yticklabels():
    tl.set_color("r")

lns = line1 + line2
labs = [l.get_label() for l in lns]
ax1.legend(lns, labs, loc="center right")

plt.show()

当添加到符号回归实例时,它将会给出下面图像:


DEAP1.2.2(四) 计算统计_第1张图片
pic.png

10 总结
这一节主要讲的是
1、在迭代过程中输出统计学信息的方法,包括适应度值、种群平均数、方差等等。针对不同的目标可以设置多组统计数据并行输出。
2、在迭代过程中输出种群信息,将他们保存在文件或者输出到屏幕上。以及绘制它们在演化过程中的适应度图像等。

你可能感兴趣的:(DEAP1.2.2(四) 计算统计)