基于Python遗传算法的人工神经网络优化

人工神经网络(ANN)是一种简单的全连接神经网络,其通过前向传播来进行参数计算,使用后向传播进行参数权重更新。一般我们会采用随机梯度下降来更新权重,但今天我们换一个新的方法,通过遗传算法来进行参数寻优,遗传算法是一种经典的优化算法,其算法思想借鉴生物种群间“优胜劣汰”的机制。在本例程中我们通过使用遗传算法优化人工神经网络权重进行图像分类实验。

确定待优化参数

本例中,我们将要通过遗传算法优化神经网络各层的网络参数,因此我们首先定义人工神经网络的网络结构,这里我们使用的是4层网络,即一个输入、2个隐藏、1个输出。那么我们就得到要优化参数个数为102x150 + 150x60 + 60x4 = 24540个,如果我们设定遗传算法有8个群体,即整个参数数量将有24540x8 = 196320个。

由于网络的参数是矩阵形式,而在GA中是矢量形式,所以我们在优化的过程中需要转换以方便计算。下图是整个案例的流程图:

代码部分函数介绍

mat_to_vector函数和vector_to_mat函数:因为GA中参数为一维向量,而在ANN中是3个权重矩阵,所以通过这两个函数进行相互转换。

mat_to_vector函数代码如下

def mat_to_vector(mat_pop_weights):
     pop_weights_vector = []
     for sol_idx in range(mat_pop_weights.shape[0]):
         curr_vector = []
         for layer_idx in range(mat_pop_weights.shape[1]):
             vector_weights = numpy.reshape(mat_pop_weights[sol_idx, layer_idx], newshape=(mat_pop_weights[sol_idx, layer_idx].size))
             curr_vector.extend(vector_weights)
         pop_weights_vector.append(curr_vector)
     return numpy.array(pop_weights_vector)

vector_to_mat函数代码如下

def vector_to_mat(vector_pop_weights, mat_pop_weights):
    mat_weights = []
    for sol_idx in range(mat_pop_weights.shape[0]):
        start = 0
        end = 0
        for layer_idx in range(mat_pop_weights.shape[1]):
            end = end + mat_pop_weights[sol_idx, layer_idx].size
            curr_vector = vector_pop_weights[sol_idx, start:end]
            mat_layer_weights = numpy.reshape(curr_vector, newshape=(mat_pop_weights[sol_idx, layer_idx].shape))
            mat_weights.append(mat_layer_weights)
            start = end
    return numpy.reshape(mat_weights, newshape=mat_pop_weights.shape)

predict_outputs()函数:根据当前权重计算方案的准确度,而且在该函数中我们需要指定激活函数:relu或sigmod。

def predict_outputs(weights_mat, data_inputs, data_outputs, activation="relu"):
    predictions = numpy.zeros(shape=(data_inputs.shape[0]))
    for sample_idx in range(data_inputs.shape[0]):
        r1 = data_inputs[sample_idx, :]
        for curr_weights in weights_mat:
            r1 = numpy.matmul(a=r1, b=curr_weights)
            if activation == "relu":
                r1 = relu(r1)
            elif activation == "sigmoid":
                r1 = sigmoid(r1)
        predicted_label = numpy.where(r1 == numpy.max(r1))[0][0]
        predictions[sample_idx] = predicted_label
    correct_predictions = numpy.where(predictions == data_outputs)[0].size
    accuracy = (correct_predictions/data_outputs.size)*100
    return accuracy, predictions

fitness()函数:将每个方案解循环传给predict_outputs()函数计算结果,并将得到的准确度结果存储到数组中,

def fitness(weights_mat, data_inputs, data_outputs, activation="relu"):
    accuracy = numpy.empty(shape=(weights_mat.shape[0]))
    for sol_idx in range(weights_mat.shape[0]):
        curr_sol_mat = weights_mat[sol_idx, :]
        accuracy[sol_idx], _ = predict_outputs(curr_sol_mat, data_inputs, data_outputs, activation=activation)
    return accuracy

完整Python编程结构

本案例共三个Python脚本文件,其中GA.py实现遗传算法功能;ANN.py实现ANN相应结构功能;main.py为项目主程序,包括读取数据特征和类标签文件,根据标准偏差过滤特征,创建ANN架构,生成初始解决方案,通过计算所有解决方案的适合度值,选择最佳父母,应用交叉和突变,最后创造新的群体。main.py程序如下:

import numpy
import GA
import pickle
import ANN
import matplotlib.pyplot

f = open("dataset_features.pkl", "rb")
data_inputs2 = pickle.load(f)
f.close()
features_STDs = numpy.std(a=data_inputs2, axis=0)
data_inputs = data_inputs2[:, features_STDs>50]

f = open("outputs.pkl", "rb")
data_outputs = pickle.load(f)
f.close()
#Genetic algorithm parameters:
#    Mating Pool Size (Number of Parents)
#    Population Size
#    Number of Generations
#    Mutation Percent

sol_per_pop = 8
num_parents_mating = 4
num_generations = 1000
mutation_percent = 10

#Creating the initial population.
initial_pop_weights = []
for curr_sol in numpy.arange(0, sol_per_pop):
    HL1_neurons = 150
    input_HL1_weights = numpy.random.uniform(low=-0.1, high=0.1, 

                                             size=(data_inputs.shape[1], HL1_neurons))

    HL2_neurons = 60
    HL1_HL2_weights = numpy.random.uniform(low=-0.1, high=0.1, 

                                             size=(HL1_neurons, HL2_neurons))

    output_neurons = 4
    HL2_output_weights = numpy.random.uniform(low=-0.1, high=0.1, 

                                              size=(HL2_neurons, output_neurons))

    initial_pop_weights.append(numpy.array([input_HL1_weights, 

                                                HL1_HL2_weights, 

                                                HL2_output_weights]))

pop_weights_mat = numpy.array(initial_pop_weights)
pop_weights_vector = GA.mat_to_vector(pop_weights_mat)

best_outputs = []
accuracies = numpy.empty(shape=(num_generations))

for generation in range(num_generations):
    print("Generation : ", generation)

    # converting the solutions from being vectors to matrices.
    pop_weights_mat = GA.vector_to_mat(pop_weights_vector, 
                                       pop_weights_mat)

    # Measuring the fitness of each chromosome in the population.
    fitness = ANN.fitness(pop_weights_mat, 
                          data_inputs, 
                          data_outputs, 
                          activation="sigmoid")

    accuracies[generation] = fitness[0]
    print("Fitness")
    print(fitness)

    # Selecting the best parents in the population for mating.
    parents = GA.select_mating_pool(pop_weights_vector, 

                                    fitness.copy(), 

                                    num_parents_mating)
    print("Parents")
    print(parents)

    # Generating next generation using crossover.
    offspring_crossover = GA.crossover(parents,

                                       offspring_size=(pop_weights_vector.shape[0]-parents.shape[0], pop_weights_vector.shape[1]))

    print("Crossover")
    print(offspring_crossover)

    # Adding some variations to the offsrping using mutation.
    offspring_mutation = GA.mutation(offspring_crossover, 

                                     mutation_percent=mutation_percent)
    print("Mutation")
    print(offspring_mutation)

    # Creating the new population based on the parents and offspring.
    pop_weights_vector[0:parents.shape[0], :] = parents
    pop_weights_vector[parents.shape[0]:, :] = offspring_mutation

pop_weights_mat = GA.vector_to_mat(pop_weights_vector, pop_weights_mat)
best_weights = pop_weights_mat [0, :]
acc, predictions = ANN.predict_outputs(best_weights, data_inputs, data_outputs, activation="sigmoid")
print("Accuracy of the best solution is : ", acc)

matplotlib.pyplot.plot(accuracies, linewidth=5, color="black")
matplotlib.pyplot.xlabel("Iteration", fontsize=20)
matplotlib.pyplot.ylabel("Fitness", fontsize=20)
matplotlib.pyplot.xticks(numpy.arange(0, num_generations+1, 100), fontsize=15)
matplotlib.pyplot.yticks(numpy.arange(0, 101, 5), fontsize=15)

f = open("weights_"+str(num_generations)+"_iterations_"+str(mutation_percent)+"%_mutation.pkl", "wb")
pickle.dump(pop_weights_mat, f)
f.close()

在进行迭代1000次训练之后,得到模型精度折线图如下,可以看到经过1,000次迭代后,精度超过97%,这个结果还是相当可以的。

本文分享自微信公众号 - 深度学习与python(PythonDC)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-03-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏机器学习与统计学

揭秘LinkedIn!全球最大的招聘推荐系统如何被机器学习驱动?

大数据文摘出品 来源:towardsdatascience 编译:夏雅薇、Stats熊

12430
来自专栏ATYUN订阅号

谷歌开发新模型EfficientNets,缩放CNN的精度与效率超越现有模型

卷积神经网络(CNN)通常以固定的资源成本开发,然后进行缩放,以便在获得更多资源时得到更好的精度。

12430
来自专栏小詹同学

Dropout的前世与今生

图 1:一些目前提出的 Dropout方法,以及 2012 到 2019 年间 Dropout 方法的理论进展。

11810
来自专栏深度学习和计算机视觉

CVPR2019 | 6D目标姿态估计,李飞飞夫妇等提出DenseFusion

6D 目标姿态估计对许多重要的现实应用都很关键,例如机器人抓取与操控、自动导航、增强现实等。理想情况下,该问题的解决方案要能够处理具有各种形状、纹理的物体,且面...

43030
来自专栏机器学习算法原理与实践

机器学习中的矩阵向量求导(五) 矩阵对矩阵的求导

    在矩阵向量求导前4篇文章中,我们主要讨论了标量对向量矩阵的求导,以及向量对向量的求导。本文我们就讨论下之前没有涉及到的矩阵对矩阵的求导,还有矩阵对向量,...

15420
来自专栏深度学习和计算机视觉

为什么不建议你入门计算机视觉

作者:Jackpop https://zhihu.com/p/question/317440183 本文已授权,未经允许,不得二次转载

37130
来自专栏深度学习和计算机视觉

SIGGRAPH提出的图像修复技术

图像修复技术是一种用可选内容填充目标区域的技术,它的主要用途是在对象删除任务中,从照片中删除一个对象,并用希望能保持图像上下文完整性的内容自动替换被删除的部分。...

14540
来自专栏ATYUN订阅号

纳米级无人机PULP Dronet仅重27克,具有强大的自主导航能力

苏黎世联邦理工学院和博洛尼亚大学的研究人员开发了一个纳米级无人机,名为PULP Dronet,仅有27克,具有深度学习的视觉导航引擎。论文显示无人机可以在一个端...

19630
来自专栏Jerry的SAP技术分享

机器学习在SAP Cloud for Customer中的应用

关于机器学习这个话题,我相信我这个公众号1500多位关注者里,一定有很多朋友的水平比Jerry高得多。如果您看过我以前两篇文章,您就会发现,我对机器学习仅仅停留...

8910
来自专栏灯塔大数据

学术大讲堂 | (三)智慧农业领域的关键AI技术

1) 从收入增长方面看:手机流量红利持续, 创新业务和宽带业务快速增长, 带动行业收入增长2.9%; 中电信、中联通收入增速超行业平均份额。

20630

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励