如何使用Python+遗传算法玩转人工神经网络?

Darfie 2019-03-07

点击上方关注,All in AI中国

作者——Ahmed Gad

在之前的教程"使用NumPy和Fruits360图像数据集分类的人工神经网络"中(https://www.linkedin.com/pulse/artificial-neural-network-implementation-using-numpy-fruits360-gad),我创建了一个人工神经网络(ANN),用于对4类Fruits360图像数据集进行分类。另外,我的GitHub页面中提供了本教程中使用的源代码。(https://github.com/ahmedfgad/NumPyANN)

如何使用Python+遗传算法玩转人工神经网络?

本教程也可在TowardsDataScience获得。(https://towardsdatascience.com/artificial-neural-network-implementation-using-numpy-and-classification-of-the-fruits360-image-3c56affa4491)

本教程简单来说,就是提取特征向量(360个色调色调通道直方图),并使用基于滤波器的技术使用标准偏差将其减少到102个元素。之后,我们的使用NumPy从头开始构建ANN。

人工神经网络并没有完全创建起来,只是准备好了前向传递,但并没有用于更新网络权重的后向传递。这就是为什么准确率非常低,不超过45%的原因。该问题的解决方案是使用优化技术来更新网络权重。本教程使用遗传算法(GA)来优化网络权重。

本教程中使用的源代码可以在我的GitHub页面中找到。(https://github.com/ahmedfgad/NeuralGenetic)

关于遗传算法

在开始本教程之前,我建议你阅读本教程末尾参考资料部分列出的教程。

在了解了基于数值示例的遗传算法的工作原理以及使用Python实现之后,我们可以通过更新其权重(参数)进而使用遗传算法来优化ANN。

GA和ANN的结合

GA为特定问题创建了多种解决方案,并不断对这些解决方案进行改进。每个解决方案都包含可能有助于增强结果的所有参数。对于ANN来说,所有层中的权重都有助于实现高准确率。因此,GA中的单个解决方案将包含ANN中的所有权重。根据前面教程中讨论并结合在下图中给出的网络结构,我们可以发现ANN具有4层(1个输入,2个隐藏和1个输出)。任何层中的任何权重都将是同一解决方案的一部分。这种网络的单一解决方案将包含:102x150 + 150x60 + 60x4 = 24,540的总权重。如果总体有8个解决方案,每个解决方案有24,540个参数,则整个群体中的参数总数为24,540x8 = 196,320。

如何使用Python+遗传算法玩转人工神经网络?

看上图,网络的参数是矩阵形式的,因为这使得ANN的计算更加容易。对于每个层,都存在一个相关联的权重矩阵。只需将输入矩阵乘以给定图层的参数矩阵,即可返回此层中的输出。GA中的染色体是一维向量,因此我们必须将权重矩阵转换成一维向量。

因为矩阵乘法对于ANN来说是一个很好的选择,所以在使用ANN的时候我们仍然会以矩阵形式来表示ANN参数。因此,在使用ANN时使用矩阵形式,在使用GA时使用向量形式。这使得我们需要将矩阵转换为向量,反之亦然。下图总结了使用GA和ANN的步骤。

如何使用Python+遗传算法玩转人工神经网络?

权重矩阵到一维向量

总体中的每个解决方案都有两种表示形式。第一个是用于GA的一维向量,第二个是与ANN一起工作的矩阵。因为3层有3个权重矩阵(2个隐藏+ 1个输出),所以将有3个向量。因为GA中的解决方案被表示为单个一维向量,所以这样的3个单独的一维向量将被连接成单个一维向量。每个解决方案将表示为长度为24,540的向量。下面的Python代码创建了一个名为mat_to_vector()的函数,该函数将总体内所有解决方案的参数从矩阵转换为向量。

如何使用Python+遗传算法玩转人工神经网络?

该函数可以使用一个表示所有解的总体的参数,以便遍历它们并返回它们的向量表示。在函数的开头,创建一个名为pop_weights_vector的空列表变量来保存结果(所有解决方案的向量)。对于矩阵形式的每个解,有一个内部循环通过它的三个矩阵。对于每个矩阵,使用numpy.reshape()函数将其转换为向量,该函数支持输入矩阵和矩阵将被重新调整的输出大小。 variablecurr_vector接受单个解决方案的所有向量。生成所有向量后,它们将被附加到pop_weights_vector变量中。

请注意,我们对属于同一解决方案的向量使用numpy.extend()函数,对属于不同解决方案的向量使用numpy.append()函数。原因是numpy.extend()获取属于同一解决方案的3个向量中的数字并将它们连接在一起。换句话说,为两个列表调用此函数会返回一个新的单个列表,其中包含两个列表中的数字。这适用于仅创建一维染色体。但是numpy.append()将为每个解决方案返回三个列表。将其调用为两个列表,它返回一个新列表,该列表被拆分为两个子列表。很明显,这不是我们的目标。所以最后,functionmat_to_vector()将填充解决方案作为NumPy数组返回,以便以后进行轻松操作。

实施GA步骤

在将所有解决方案从矩阵转换为向量并连接在一起之后,我们已准备好完成标题为"遗传算法优化简介"的教程中讨论的GA步骤了。这些步骤在主图中给出,并在下图中进行了总结。

如何使用Python+遗传算法玩转人工神经网络?

请记住,GA使用适应度函数来返回每个解决方案的适应值。适应值越高,解决方案越好。

诸如ANN之类的分类器的常见适应度函数之一是准确率。它是正确分类的样本与样本总数之间的比率。它是根据下一个等式计算的。根据主图中的步骤计算每种解决方案的分类准确率。

如何使用Python+遗传算法玩转人工神经网络?

每个解的单个一维向量被转换回3个矩阵,其中每个层一个矩阵(2个隐藏和1个输出)。转换使用名为vector_to_mat()的函数进行。它在下一个代码中定义。

如何使用Python+遗传算法玩转人工神经网络?

它反转了之前完成的工作。但是有一个重要的问题。如果给定解的向量是一端,我们如何分成三个不同的部分,每个部分代表一个矩阵?输入层和隐藏层之间的第一个参数矩阵的大小为102x150。转换为向量时,其长度为15,300。因为它是根据themat_to_vector()函数插入curr_vector变量的第一个向量,所以它的索引从索引0开始并在索引15,299结束。 mat_pop_weights用作thevector_to_mat()函数的参数,以便了解每个矩阵的大小。我们对使用mat_pop_weights变量中的权重不感兴趣,只使用了矩阵大小。

对于同一解决方案中的第二个向量,它将是一个大小为150x60的矩阵的转换结果。因此,向量长度为9,000。将这样的向量插入到前一个长度为15,300的向量之前的curr_vector变量中。因此,它将从指数15,300开始,到指数15,300 + 9,000-1 = 24,299结束。使用-1是因为Python从0开始索引。对于大小为60x4的参数矩阵创建的最后一个向量,其长度为240。因为它是在前一个长度为9,000的向量之后恰好添加到curr_vector变量中的,所以它的索引将在它之后开始。它的起始指数是24,300,它的结束指数是24,300 + 240-1 = 24,539。因此,我们可以成功地将向量还原到原始的3个矩阵中。

为每个解决方案返回的矩阵用于预测所用数据集中1,962个样本中每个样本的类别标签,以计算准确度。这是使用2个函数完成的,函数分别是predict_outputs()和fitness()。

如何使用Python+遗传算法玩转人工神经网络?

如何使用Python+遗传算法玩转人工神经网络?

predict_outputs()函数接受训练数据的单个解决方案/输入和输出的权重,以及指定要使用的激活函数的可选参数。它只返回一个解决方案的准确率,而不是总体中的所有解决方案。它命令返回总体内所有解的适应值(即准确率),fitness()函数循环遍历每个解,将其传递给predict_outputs()函数,将所有解的准确率存储到准确率数组中,最后返回这样一个数组。

在计算所有解的适合度值(即准确率)之后,应用主图中的GA的剩余步骤与前面的步骤相同。

完整的Python实现

这个项目的Python实现有三个Python文件:

1.GA.py用于实现GA功能。

2.ANN.py用于实现ANN功能。

3.通过多代调用此类函数的第三个文件。这是该项目的主要文件。

主要项目文件实施

第三个文件是主文件,因为它连接所有函数。它读取特征和类标签文件,根据标准偏差过滤特征,创建ANN架构,生成初始解决方案,通过计算所有解决方案的适合度值,选择最佳"父母",应用交叉和突变,最后创造新的"人口"。其实施如下。

如何使用Python+遗传算法玩转人工神经网络?

如何使用Python+遗传算法玩转人工神经网络?

如何使用Python+遗传算法玩转人工神经网络?

如何使用Python+遗传算法玩转人工神经网络?

如何使用Python+遗传算法玩转人工神经网络?

如何使用Python+遗传算法玩转人工神经网络?

如何使用Python+遗传算法玩转人工神经网络?

如何使用Python+遗传算法玩转人工神经网络?

如何使用Python+遗传算法玩转人工神经网络?

如何使用Python+遗传算法玩转人工神经网络?

基于1,000次迭代数据,使用Matplotlib可视化库在此文件的

末尾创建一个图,该库显示每一代的准确率如何变化。如下图所示。

如何使用Python+遗传算法玩转人工神经网络?

经过1,000次迭代后,准确率超过97%。相比之下,如果不使用上一个教程中的优化技术,这个比例为45%。这是为什么结果可能不好的证据,不是因为模型或数据中存在错误,而是因为没有使用优化技术。当然,对诸如10,000代之类的参数使用不同的值可能会提高准确率。在此文件的末尾,它将矩阵形式的参数保存到磁盘以供以后使用。

GA.py实施

GA.py文件实现如下所示。请注意,mutation()函数接受mutation_percent参数,该参数定义随机更改其值的基因数。它在主文件中设置为10%。这样的文件包含2个新函数mat_to_vector()和vector_to_mat()。

如何使用Python+遗传算法玩转人工神经网络?

如何使用Python+遗传算法玩转人工神经网络?

如何使用Python+遗传算法玩转人工神经网络?

如何使用Python+遗传算法玩转人工神经网络?

如何使用Python+遗传算法玩转人工神经网络?

ANN.py实施

最后,ANN.py根据下面列出的代码实现。除了fitness()和predict_outputs()函数之外,它还包含激活函数sigmoid和ReLU的实现,以计算准确率。

如何使用Python+遗传算法玩转人工神经网络?

如何使用Python+遗传算法玩转人工神经网络?

如何使用Python+遗传算法玩转人工神经网络?

如何使用Python+遗传算法玩转人工神经网络?

编译出品

相关推荐