优化算法相关 实时绘制训练过程中损失和准确率的变化趋势

安装optproblems 和 fastprogress

1.pip install optproblems

https://ls11-www.cs.tu-dortmund.de/people/swessing/optproblems/doc/

该软件包包含一些用于黑盒优化的常见基准测试问题。 

包含的测试问题:

二进制问题OneMax,LeadingOnes和LeadingOnesTrailingZeros以及用于多模式问题的三个实例生成器
CEC 2005单目标问题集
CEC 2007多目标问题集
Dixon-Szegö系列进行全局优化
DTLZ问题1-7
多峰模型2
步行鱼小组(WFG)工具包
ZDT集合用于多目标优化

  • Binary problems OneMax, LeadingOnes, and LeadingOnesTrailingZeros and three instance generators for multimodal problems
  • CEC 2005 collection of single-objective problems
  • CEC 2007 collection of multiobjective problems
  • Dixon-Szegö collection for global optimization
  • DTLZ problems 1-7
  • Multiple-Peaks Model 2
  • Walking Fish Group (WFG) toolkit
  • ZDT collection for multiobjective optimization

此程序包的基础结构还可用于将您自己的(实际)优化问题包装在问题基类中。这样做的原因可能是以下功能:

支持单目标和多目标问题
通常,不对搜索空间做任何假设
评估自动计数
可以通过multiprocessing(.dummy)使用真正的并行性或并发性
提供用于检查绑定约束并修复连续优化中违反约束的功能
可选:检测并随后避免重复评估
还包括一些实际问题。(在测试问题上配置梯度法,超立方体中点的均匀性优化)
依存关系
此程序包的某些模块对第三方程序包具有其他依赖性。但是,在安装过程中不会强制执行这些操作,以免妨碍基本模块的使用,而基本模块将始终没有依赖性。

2. pip install liveloseplot

这款工具用于实时绘制训练时的损失和准确率,方便好用,不需要自己另外再写 plot 函数。Keras 和 PyTorch 中都可以使用

from livelossplot import PlotLossesKeras

model.fit(X_train, Y_train,
          epochs=10,
          validation_data=(X_test, Y_test),
          callbacks=[PlotLossesKeras()],
          verbose=0)

优化算法相关 实时绘制训练过程中损失和准确率的变化趋势

3. pip install fastprogress

from fastprogress import master_bar, progress_bar
from time import sleep
mb = master_bar(range(10))
for i in mb:
    for j in progress_bar(range(100), parent=mb):
        sleep(0.01)
        mb.child.comment = f'second bar stat'
    mb.first_bar.comment = f'first bar stat'
    mb.write(f'Finished loop {i}.')
    #mb.update_graph(graphs, x_bounds, y_bounds)

优化算法相关 实时绘制训练过程中损失和准确率的变化趋势

一个例子:

from optproblems import *
from optproblems import cec2005
import numpy as np
import random
import bisect
import matplotlib.pyplot as plt
from fastprogress import progress_bar

def get_best_possible_fitness(problem):
    optimal_solutions = problem.get_optimal_solutions()
    an_optimal_solution = optimal_solutions[0]
    problem.evaluate(an_optimal_solution)
    return an_optimal_solution.objective_values

class GA:
    """
    An implementation of Genetic Algorithm, pioneered by John Holland.
    
    
    The population consists of fixed length vectors of real numbers and is initialised
    using a uniform distribution of random numbers. It uses two point crossover, tournament
    selection and Gaussian convolution for mutation.
    
    Attributes
    ----------
    problem : obj
        The cec2005 problem to be attempted
    pop_size : int
        The size of the population
    vector_length : int
        The dimensions of the problem, should be the same used when creating the problem object 
    tournament_size: int, optional
        The number of individuals competing in each tournament
    mutation_rate: float, optional
        The likelyhood of mutation for each child
    mutation_scale: int, optional
        The size of the mutation used. i.e the standard deviation of the gaussian

    Public Methods
    -------
    evolve(num_iterations)
        Evoles the population for a number of given iterations
    """
    
    def __init__(self, problem, pop_size, vector_length, tournament_size=2, mutation_rate=0.3, mutation_scale=12):
        self.problem = problem
        self.vector_length = vector_length
        self.pop_size = pop_size
        self.tournament_size = tournament_size
        self.mutation_rate = mutation_rate
        self.mutation_scale = mutation_scale
        self.current_population = np.random.rand(self.pop_size, self.vector_length)
        
    def evolve(self, num_iterations=200):
        """Evolves the population for a given number of iterations

        Parameters
        ----------
        num_iterations : int, optional
            The number of generations before stopping evolving
        
        Returns
        -------
        results : list
            A list of the best fitness at each generation
        found_global_min_at : int
            The position at which the global min was found at, return -1 if not found
        """
        results = []
        found_global_min_at = -1
        best_possible_fitness = get_best_possible_fitness(self.problem)
        for i in range(num_iterations):
            best_index, fitnesses = self.find_current_best(self.current_population)
            results.append(fitnesses[best_index])
            if math.isclose(best_possible_fitness, fitnesses[best_index], rel_tol=1e-1):
                if found_global_min_at == -1:
                    found_global_min_at = i
            self.current_population = self.update_population(fitnesses)
        return results, found_global_min_at
        
    def update_population(self, fitnesses):
        """Performs one generational update of Genetic Algorithm"""
        next_population = np.empty((self.pop_size, self.vector_length))
        for i in range(int(self.pop_size / 2)):
            parent_a = self.tournament_select_with_replacement(self.current_population)
            parent_b = self.tournament_select_with_replacement(self.current_population)
            child_a, child_b = self.crossover(parent_a, parent_b)
            next_population[i] = self.mutate(child_a)
            position_child_b = i + (self.pop_size / 2)
            next_population[int(position_child_b)] = self.mutate(child_b)
            next_population = np.clip(next_population, self.problem.min_bounds, self.problem.max_bounds)
        return next_population

    def assess_fitness(self, individual):
        """Determines the fitness of an individual using the given problem"""
        solution = Individual(individual)
        self.problem.evaluate(solution)
        return solution.objective_values

    def find_current_best(self, population):
        """Evaluates a given population and returns the fittest individual"""
        fitnesses = [self.assess_fitness(x) for x in population]
        best_value = min(fitnesses)
        best_index = fitnesses.index(best_value)
        return best_index, fitnesses

    def tournament_select_with_replacement(self, population):
        """Competes a number of challengers and returns the fittest one"""
        challengers_indexes = np.random.choice(population.shape[0], self.tournament_size, replace=True)
        challengers = population[challengers_indexes]
        best_index, _ = self.find_current_best(challengers)
        return challengers[best_index]

    def crossover(self, parent_a, parent_b):
        """Performs two point crossover on two parents"""
        l = parent_a.shape[0]
        c, d = random.randint(0, l), random.randint(0, l)
        
        # Flip if c greater than d
        if (c > d): d, c = c, d 
        if (c == d): d += 1
        temp = np.copy(parent_a)
        child_a = np.concatenate([parent_a[0:c], parent_b[c:d], parent_a[d:]])
        child_b = np.concatenate([parent_b[0:c], temp[c:d], parent_b[d:]]) 
        return child_a, child_b

    def mutate(self, child):
        """May mutate a child using Gaussian convolution"""
        if self.mutation_rate >= random.uniform(0, 1):
            size = self.current_population.shape[1]
            mutation_value = np.random.normal(0, self.mutation_scale, size)
            child = child + mutation_value
        return child

def get_mean(tests):
    return np.mean(np.array(tests), axis=0)

##################################

def test():

size, num_iterations = 50, 200
vector_length = 10
problem = cec2005.F1(vector_length)
pso_fitnesses = []
pso_found_global_best_results = []
ga_fitnesses = []
ga_found_global_best_results = []
for j in progress_bar(range(10)):
    pso = PSO(problem, size, vector_length)
    fitness, pso_found_global_best = pso.improve(num_iterations)
    pso_found_global_best_results.append(pso_found_global_best)
    pso_fitnesses.append(fitness)
    
    ga = GA(problem, size, vector_length)
    fitness, ga_found_global_best = ga.evolve(num_iterations)
    ga_found_global_best_results.append(ga_found_global_best)
    ga_fitnesses.append(fitness)

pso_mean_fitnesses = get_mean(pso_fitnesses)
ga_mean_fitnesses = get_mean(ga_fitnesses)

best_possible_fitness = get_best_possible_fitness(problem)
best_fitnesses = np.full_like(pso_mean_fitnesses, best_possible_fitness)
fig, ax = plt.subplots()
ax.plot(best_fitnesses, label="Global best")
ax.plot(pso_mean_fitnesses,  label="PSO")
ax.plot(ga_mean_fitnesses, label="GA")
title = 'F1'
# ax.set_yscale('log')
plt.title(f'Mean fitness for CEC2005 Function {title}')
legend = ax.legend(loc='upper center', shadow=True)
# plt.ylim(0,1)
plt.ylabel('Fitness')
plt.xlabel('Iterations')
plt.show()

优化算法相关 实时绘制训练过程中损失和准确率的变化趋势

3 CEC2005问题

这套25个测试问题是为2005年9月2日至5日在英国爱丁堡举行的进化计算大会(CEC)上的实参优化特别会议而编写的。数学定义在[Suganthan2005]中给出。 此外,还为参与者提供了C,Java和Matlab的实现。 该代码是纯Python中Java代码的重新实现。

已用原始代码分发的测试数据验证了此实现的正确性。 根据特别会议的指南,对于此数据,对于参考目标值y和此处计算的值

优化算法相关 实时绘制训练过程中损失和准确率的变化趋势

[Suganthan2005] (12) P. N. Suganthan, N. Hansen, J. J. Liang, K. Deb, Y.-P. Chen, A. Auger, and S. Tiwari. Problem Definitions and Evaluation Criteria for the CEC 2005 Special Session on Real-Parameter Optimization. Technical Report, Nanyang Technological University, Singapore, May 2005 and KanGAL Report #2005005, IIT Kanpur, India. http://web.mysites.ntu.edu.sg/epnsugan/PublicSite/Shared%20Documents/CEC2005/Tech-Report-May-30-05.pdf