政安晨:【深度学习神经网络基础】(十四)—— 神经网络剪枝和模型选择

发布于:2024-04-27 ⋅ 阅读:(24) ⋅ 点赞:(0)

目录

简述

理解剪枝

剪枝连接

剪枝神经元

改善或降低表现

剪枝算法

模型选择

网格搜索模型选择

随机搜索模型选择

其他模型选择技术

总之


政安晨的个人主页:政安晨

欢迎 👍点赞✍评论⭐收藏

收录专栏: 政安晨的机器学习笔记

希望政安晨的博客能够对您有所裨益,如有不足之处,欢迎在评论区提出指正!

简述

人工智能神经网络剪枝是一种优化神经网络模型的方法,通过删除网络中的一些神经元或连接来减小网络的复杂度。剪枝的目的是提高模型的效率和性能,并减少其在计算和存储方面的需求。

神经网络剪枝的基本方法是根据一定的剪枝准则来选择要删除的神经元或连接。常见的剪枝准则包括权重剪枝、结构剪枝和一些启发式方法。权重剪枝通过将权重接近于零的连接删除,来减少模型的参数个数。结构剪枝则是通过删除整个神经元或神经元组来减小模型的大小。启发式方法是基于一些规则或经验,根据网络的特定性质进行剪枝。

模型选择是指在给定的数据集上选择最合适的神经网络模型。模型选择的目标是找到一个能够在训练集上拟合得很好,并且在测试集上泛化能力强的模型。常见的模型选择方法有交叉验证、正则化和自动调参等。

交叉验证是一种将数据集划分为训练集和验证集的方法,通过在不同的训练集和验证集组合上训练和评估模型,来选择最佳的模型。正则化是一种通过在损失函数中引入正则项来限制模型的复杂度,防止模型过拟合的方法。自动调参则是利用算法自动搜索最佳模型参数的过程,以提高模型的性能。

综上所述,人工智能神经网络剪枝和模型选择都是优化神经网络模型的方法剪枝通过删除神经元或连接来减小模型的复杂度,而模型选择则是在给定数据集上选择最合适的模型。两者都通过提高模型的效率和性能来改进神经网络模型。

在以前的文章中咱们知道,你可以利用各种训练算法,更好地调整神经网络的权重。实际上,这些算法调整神经网络的权重是为了降低神经网络的误差。我们通常将神经网络的权重称为神经网络模型的参数。一些机器学习模型可能具有权重以外的参数,如对数概率回归将系数作为参数。

当我们训练模型时,所有机器学习模型的参数都会改变,但是,这些模型还有一些在训练算法期间不变的超参数。对于神经网络,超参数指定了神经网络的架构。神经网络超参数的例子包括隐藏层和隐藏神经元的数量。

在本文中,我们将研究两种可以实际修改或为神经网络的结构提供建议的算法。

剪枝通过分析每个神经元对神经网络输出的贡献来进行。如果特定神经元与另一神经元的连接不会显著影响神经网络的输出,则删除该连接。通过这个过程,对输出仅产生少量影响的连接和神经元将被删除。

本文介绍的另一种算法是模型选择。

剪枝从已经训练好的神经网络开始,而模型选择会创建并训练许多具有不同超参数的神经网络。然后,程序选择产生神经网络的超参数,以达到最佳验证得分。

理解剪枝

剪枝是使神经网络更高效的过程。与咱们已经讨论过的训练算法不同,剪枝不会改善神经网络的训练误差。剪枝的主要目的是减少使用神经网络所需的处理量。另外,剪枝有时可以通过消除神经网络的复杂性,产生正则化效果。这种正则化有时可以减少神经网络中的过拟合。过拟合的减少可以帮助神经网络在训练集以外的数据上表现得更好。

剪枝通过分析神经网络的连接来进行。剪枝算法查找可以从神经网络中删除的单个连接和神经元,使它更有效地运行。通过删除不需要的连接,可以使神经网络执行得更快,并尽可能减少过拟合。在接下来,我们将研究如何剪枝连接和神经元。

剪枝连接

剪枝连接是大多数剪枝算法的核心。

该程序分析神经元之间的各个连接,以确定哪些连接对神经网络的有效性影响最小。连接不是程序剪枝的唯一目标。程序分析剪枝的连接后,还可以剪枝单个神经元。

剪枝神经元

剪枝主要集中在神经网络各个神经元之间的连接上。如果要剪枝单个神经元,我们必须检查每个神经元和其他神经元之间的连接。如果一个特定的神经元被弱连接完全包围,就没有理由保留该神经元。如果我们应用以前咱们讨论过的标准,就会得到没有连接的神经元,因为程序已剪掉了该神经元的所有连接。然后程序可以剪掉这种类型的神经元。

改善或降低表现

剪枝神经网络可能会改善其表现。对神经网络权重矩阵的任何修改,总会对神经网络识别的准确率产生某些影响。对神经网络影响很小或没有影响的连接,实际上可能会降低神经网络识别模式的准确率。消除这个弱连接可以改善神经网络的整体输出。

不幸的是,剪枝还可能降低神经网络的有效性。因此,必须坚持在剪枝前后分析神经网络的有效性。由于效率高是剪枝的主要好处,因此你必须谨慎评估处理时间上的改进与降低神经网络的有效性相比,是否值得。在本文的编程示例中,我们将在剪枝之前和之后评估神经网络的总体有效性。该分析将使我们了解剪枝过程对神经网络有效性的影响。

剪枝算法

现在,我们将仔细地查看剪枝的方式。

首先,剪枝检查先前训练过的神经网络的权重矩阵。

然后,剪枝算法将尝试删除神经元而不破坏神经网络的输出。

下图展示了用于选择性剪枝的算法流程。

如你所见,选择性剪枝算法采取了试错的方式。选择性剪枝算法尝试从神经网络中删除神经元,直到它无法删除其他神经元,而不降低神经网络的表现。

要进行此流程,选择性剪枝算法将循环遍历每个隐藏的神经元。对于遇到的每个隐藏神经元,程序都会评估带有或不带有指定神经元的神经网络的误差水平。如果错误率超过预定水平,程序将保留该神经元并评估下一个神经元。如果错误率没有明显提高,则程序将删除该神经元。

该程序评估完所有神经元后,将重复该流程。

这个循环一直持续到程序遍历隐藏神经元一次,而不删除任何神经元。这个流程完成后,便会获得一个新的神经网络,该神经网络的表现与原始神经网络相当,但具有更少的隐藏神经元。

模型选择

模型选择的过程,是程序员尝试寻找产生最佳神经网络或其他机器学习模型的一组超参数的过程。在本文中,我们提到了许多不同的超参数,它们是你必须提供给神经网络框架的参数。神经网络的部分超参数列举如下:

● 隐藏层数;

● 卷积层、池化层和Dropout层的顺序;

● 激活函数的类型;

● 隐藏的神经元数量;

● 池化层和卷积层的结构。

在阅读有关超参数的内容时,你可能一直想知道,如何才知道要设置哪些超参数。不幸的是,没有简单的答案。如果存在确定这些设置的简便方法,那么程序员将构建能够自动为你设置这些超参数的神经网络框架。

虽然我们将在以后的讨论中思考“构建神经网络”的更多超参数的信息,但你仍然需要使用本文中介绍的模型选择过程。不幸的是,模型选择非常耗时。在我们实际参加的上一次Kaggle比赛中,曾花费了90%的时间进行模型选择。通常,建模的成功与你花在模型选择上的时间密切相关。

网格搜索模型选择

网格搜索是一种反复试验的蛮力算法。对于这种算法,必须指定要使用的超参数的每个组合。你必须谨慎选择,因为为了实现搜索,迭代次数会迅速增加。通常,你必须指定要搜索的超参数。这种指定可能如下所示。

● 隐藏的神经元:2~10,步长2。

● 激活函数:tanh、S型和ReLU。

第一项指出,网格搜索应尝试搜索2~10的隐藏神经元计数,步长为2,从而得出以下结果:2、4、6、8和10(总共5种可能性)。

第二项指出,我们还应该针对每个神经元计数尝试采用激活函数tanh、S型和ReLU。5种可能性乘以3种可能性,因此该过程总共进行了15次迭代。

这些可能性在下面列出:

Iteration #1: [2][sigmoid]
Iteration #2: [4][sigmoid]
Iteration #3: [6][sigmoid]
Iteration #4: [8][sigmoid]
Iteration #5: [10][sigmoid]
Iteration #6: [2][ReLU]
Iteration #7: [4][ReLU]
Iteration #8: [6][ReLU]
Iteration #9: [8][ReLU]
Iteration #10: [10][ReLU]
Iteration #11: [2][tanh]
Iteration #12: [4][tanh]
Iteration #13: [6][tanh]
Iteration #14: [8][tanh]
Iteration #15: [10][tanh]

每种可能性称为一个轴(axis)。

这些轴会旋转着遍历所有可能的组合。

你可以想象汽车的里程表,来更加形象地想象这个过程。最左侧的转盘(即轴)旋转得最快。

它的计数范围是0~9。一旦达到9,并且需要转到下一个数字,它将转回0,并且左边的下一个位置向前转动一个数字。除非下一个位置也为9,否则左边的转盘将继续转。在某个时候,里程表上的所有数字都为9,整个设备将转回0。最后的转动发生时,将完成网格搜索。

大多数框架允许两种轴类型。

第一种类型是带有步长的数字范围;

第二种类型是值的列表,如上面的激活函数。

下面代码展示了转动几组值的所有迭代所需的伪代码:

网格搜索

# The variable axes contains a list of each axis
# Each axes (in axes) is a list of possible values 
# for that axis
# Current index of each axis is zero, create an array
# of zeros
indexes = zeros(len(axes))
done = false
while not done:
# Prepare vector of current iteration’s
# hyper-parameters
  iteration = []
  for i from 0 to len(axes)
    iteration.add(axes [i][indexes[i]] )
# Perform one iteration, passing in the hyper-parameters
# that are stored in the iteration list.  This function
# should train the neural network according to the 
# hyper-parameters and keep note of the best trained 
# network so far
  perform_iteration(iteration)
# Rotate the axes forward one unit, like a car's
# odometer
  indexes[0] = indexes[0] + 1;
  var counterIdx = 0;
# roll forward the other places, if needed
  while not done and  indexes[counterIdx]>=
        len(axes [counterIdx]):
    indexes[counterIdx] = 0
    counterIdx = counterIdx + 1
    if counterIdx>=len(axes):
      done = true
    else:
      indexes[counterIdx] = indexes[counterIdx] + 1

上面的代码使用两个循环来遍历每组可能的超参数。

当程序仍在生成超参数时,第一个循环就会继续。

每次循环,该循环都会将第一个超参数增加到下一个值。

第二个循环检测第一个超参数是否已翻转。

内部循环将继续前进到下一个超参数,直到不再发生翻转为止。

一旦所有超参数都翻转过来,该过程就完成了。

如你所见,网格搜索很快就会导致大量迭代。

考虑是否要在5个层上搜索隐藏神经元的最佳数量,每个层上最多允许200个神经元。

这个过程导致200的5次幂(即3200亿)次迭代。

因为每次迭代都涉及训练神经网络,所以迭代可能需要几分钟、几小时,甚至几天来执行。

在执行网格搜索时,多线程和网格处理可能是有益的。

通过线程池运行迭代可以大大加快搜索速度。线程池的大小应该等于计算机的核心数。

这种特征允许具有8个核心的计算机同时在8个神经网络上工作。

同时运行多个迭代时,单个模型的训练必须是单线程的。

许多框架将使用所有可用的核心来训练单个神经网络。

当你要训练大量的神经网络时,应该总是考虑并行训练多个神经网络,以便每个神经网络都使用多个计算机核心。

随机搜索模型选择

也可以使用随机搜索进行模型选择。随机搜索方法不是系统地尝试每个超参数组合,而是为超参数选择随机值。

对于数字范围,你不再需要指定步长,随机模型选择将在指定的起点和终点之间选择连续范围的浮点数。

对于随机搜索,程序员通常指定时间或迭代限制。

下面展示了使用上面同样的轴进行的随机搜索,但仅限于10次迭代:

Iteration #1: [3.298266736790538][sigmoid]
Iteration #2: [9.569985574809834][ReLU]
Iteration #3: [1.241154231596738][sigmoid]
Iteration #4: [9.140498645836487][sigmoid]
Iteration #5: [8.041758658131585][tanh]
Iteration #6: [2.363519841339439][ReLU]
Iteration #7: [9.72388393455185][tanh]
Iteration #8: [3.411276006139815][tanh]
Iteration #9: [3.1166220877785236][sigmoid]
Iteration #10: [8.559433702612296][sigmoid]

如你所见,第一个轴(即隐藏的神经元计数)采用浮点值。

你可以通过将神经元计数四舍五入到最接近的整数来解决这个问题。

我们还建议避免重复测试相同的超参数。

因此,该程序应保留以前尝试过的超参数的列表,以便不会重复使用先前尝试过的超参数,这些尝试过的超参数属于一个较小的范围。

其他模型选择技术

模型选择是一个非常活跃的研究领域,因此,有许多创新的方法来实现它。

你可以将超参数视为值的向量,并将为这些超参数找到最佳神经网络得分的过程视为目标函数,从而将搜索超参数视为优化问题。

我们在前面的一些文章中研究了许多优化算法。这些算法如下:

● 蚁群优化(Ant Colony Optimization,ACO);

● 遗传算法;

● 基因编程;

● 爬山;

● Nelder-Mead;

● 粒子群优化;

● 模拟退火。

尽管算法列表很长,但现实是这些算法中的大多数都不适合模型选择,因为模型选择的目标函数计算起来很耗时。

训练一个神经网络,并确定给定的一组超参数对神经网络的训练有多好,可能需要几分钟、几小时,甚至几天的时间。

如果你希望将优化功能应用于模型选择,则Nelder-Mead(有时是爬山)是最好的选择。这些算法试图最小化对目标函数的调用。对于超参数搜索,调用目标函数非常昂贵,因为必须训练神经网络。一种优化的好方法是生成一组超参数,用作Nelder-Mead的起点,并让Nelder-Mead来改善这些超参数。Nelder-Mead是超参数搜索的不错选择,因为它对目标函数的调用相对较少。

模型选择是Kaggle数据科学竞赛中很常见的部分。根据比赛的讨论和报告,大多数参与者使用网格和随机搜索进行模型选择,Nelder-Mead也很受欢迎。另一种日益流行的技术是贝叶斯优化,如Snoek、Larochelle和Adams(2012)所述。用Python实现的这个算法称为Spearmint,你可以在GitHub搜索来找到它。

总之

咱们可以对神经网络进行剪枝。

剪枝神经网络会删除连接和神经元,使神经网络更有效率。执行速度、连接数和错误率都是效率的衡量标准。尽管神经网络必须有效识别模式,但提高效率是剪枝的主要目标。有几种不同的算法可以剪枝神经网络。

在本文中,我们研究了其中两种算法。

如果你的神经网络已经运行得足够快,那么必须评估剪枝是否合理。即使效率很重要,你也必须权衡提高效率与权衡神经网络有效性。

模型选择在神经网络开发中起着重要作用。超参数用来对隐藏的神经元数、层数和激活函数等进行设置。

模型选择被用来找到将产生最佳训练神经网络的超参数集。

各种算法可以搜索超参数的可能设置,并找到最佳设置。剪枝有时会减少神经网络的过拟合。这种过拟合的减少通常只是剪枝过程的副产品。减少过拟合的算法称为正则化算法。剪枝有时会产生正则化效果,此外还有一整套算法可以减少过拟合,它们被称为正则化算法。

以后咱们有机会再详细讨论。