深度学习神经网络的参数调优与性能优化
1. 神经网络权重计算与影响
在神经网络中,权重数量对训练速度有着重要影响。例如,考虑一个 100x100 的网络,当有 10 个数值输入并分类为 3 个状态时,权重数量为 (10 * 100) + (100 * 100) + (100 * 3) = 11,300。若将输入改为 5 个数值输入和 5 个枚举输入(如性别、喜爱颜色、迈尔斯 - 布里格斯性格类型、星座和中国生肖),每个枚举级别成为一个输入神经元(每个类别还额外有一个输入神经元处理缺失或未见过的值),此时输入神经元变为 5 + 3 + 11 + 17 + 13 + 13 = 62 个,总权重数量变为 (62 * 100) + (100 * 100) + (100 * 3) = 16,500,比之前增加了 50%。
这表明,权重越多,训练速度越慢。如果天真地使用一个有 50,000 个级别的因子(如邮政编码),且第一层隐藏层有 1000 个神经元,可能会比预期多出 5000 万个权重。
2. 激活函数
神经元有多个加权输入和一个输出,输入求和后,激活函数决定输出值。H2O 支持三种激活函数:
-
Rectifier
:最常用的激活函数,也是默认值。它输出加权输入的总和,但将所有负值裁剪为零。这意味着会产生很多零值(零值对训练更深的网络有好处),但正值无界。
-
Tanh
:双曲正切的缩写。它将输入范围从负无穷到正无穷转换为输出范围 -1 到 +1,在输入总和接近零时变化最快。
-
Maxout
:直接输出输入中的最大值,即加权输入直接使用,不进行求和。
每种激活函数都有“最佳”的说法,但实际上取决于数据。尽可能使用网格搜索尝试所有三种选项。通常 Rectifier 更快,若有疑问可选择它。若 Rectifier 或 Maxout 出现数值不稳定问题,可切换到 Tanh。
此外,H2O 支持的激活参数有六个可能值,因为每个激活函数都有“WithDropout”变体,可使用
hidden_dropout_ratios
控制输出随机置零的速率,作为正则化技术避免过拟合。
3. 深度学习参数
3.1 隐藏层设置
hidden
参数用于设置隐藏层的大小,默认是 200,200,表示有两个隐藏层,每层 200 个神经元。若设置为 60,40,20,则有三个隐藏层,分别有 60、40 和 20 个神经元。
3.2 自动编码器设置
auto-encoder
参数默认值为 false,表示进行监督学习。若设置为 true,则进行自动编码,通常此时应将
activation
设置为 Tanh。
3.3 深度学习正则化
深度学习的正则化主要有两种方法:
-
丢弃连接
:在连接一层到下一层时丢弃部分连接。
-
正则化
:通过设置相关参数实现。
激活函数选择
activation
参数有六个可能值,先选择三种激活函数之一,再选择是否使用丢弃。若要使用
hidden_dropout_ratios
,必须指定 “TanhWithDropout”、“RectifierWithDropout” 或 “MaxoutWithDropout” 之一。在使用检查点时,激活函数的选择不能更改,且不能在网格中部分模型使用隐藏比率,部分不使用。在这些情况下,建议始终使用 “WithDropout” 激活函数,并在不需要丢弃时将
hidden_dropout_ratios
设置为 0.0。
隐藏层丢弃比率
hidden_dropout_ratios
为每个隐藏层指定一个比率,默认值为 0.5,表示每个训练行通过网络时,神经元有 50% 的概率将其值传递到下一个隐藏层,50% 的概率传递零。若不使用支持丢弃的激活函数,则该参数被忽略。此参数难以直观选择,最好在网格中进行实验,在层数较多的网络中尝试更高的丢弃率。
输入丢弃比率
input_dropout_ratio
表示输入神经元输入到第一个隐藏层的百分比,默认值为 0.0(无输入丢弃)。若为 0.5,则每个训练数据行中的每个特征有 50% 的概率被使用,即每次训练样本和每个 epoch 中会将一半的列置零。如果数据中有很多噪声,此参数可能有效,但 0.5 是比较高的值。可在网格中使用此参数,初始时使用较宽的范围,如 0.0、0.1、0.2、0.3、0.4 和 0.5。
L1 正则化
l1
即 L1 正则化,也称为套索正则化,默认值为 0,典型尝试值为 0.0001 或更小。
L2 正则化
l2
即 L2 正则化,也称为岭正则化,默认值为 0,典型尝试值为 0.0001 或更小。
最大权重平方和
max_w2
为神经元输入权重的平方和设置上限,默认无限制,这是一种直接防止权重增长过大的方法。
3.4 深度学习评分参数
有大量参数可控制评分频率,它们用于平衡以下几个概念:
- 需要准确的分数来判断模型和进行早停。
- 评分花费的时间不能用于训练。
- 定期评分可更精细地选择最佳模型。
- 考虑集群因素。
- 考虑训练数据大小。
以下是一些重要的评分参数:
-
train_samples_per_iteration
:控制每次迭代使用的训练行数,通常使用 -2(默认,让 H2O 决定)、0 和 -1 这三个特殊值。0 和 -1 在单节点上含义相同,即每个 epoch 评分一次。在多节点使用时,它们的含义不同。
-
score_interval
:评分模型的最小时间间隔(秒),默认值为 5。若
stopping_rounds
也为 5,则模型至少构建 50 秒。若其他参数(如低
score_duty_cycle
、高
train_samples_per_iteration
)导致评分间隔已经较长,更改此参数可能无效。
-
score_duty_cycle
:评分与训练花费时间的比例,范围从 0.0 到 1.0,较低值表示更多时间用于训练,较高值表示更多时间用于评分。默认值为 0.1(10% 的时间用于评分,90% 用于训练)。
-
target_ratio_comm_to_comp
:通信开销与计算的目标比率,默认值为 0.05,即 5% 的时间用于节点间通信,95% 的时间用于每个节点的训练。此参数仅对多节点集群有意义,且仅在
train_samples_per_iteration = -2
时使用。降低此值可能使评分间隔变长或无效果。
-
replicate_training_data
:默认值为 true,表示将整个训练数据集复制到集群的每个节点。对于小数据集,这可以加快训练速度。
-
shuffle_training_data
:默认值为 false,若设置为 true,则训练数据随机排序。例如,若设置了
balance_classes
,建议使用此参数。
-
score_validation_samples
:评分时使用的验证数据集行数,默认值为 0,表示使用所有验证数据。若验证数据较大或评分更频繁,可选择较低值以加快评分速度(但会牺牲准确性)。
-
score_training_samples
:与
score_validation_samples
类似,但用于训练数据评分。默认值为 10,000,以确保非常大的数据集不会使评分过慢。若评分频繁,可将此值设置得更低。
-
score_validation_sampling
:仅在
score_validation_samples
从默认值 0 更改时使用,默认值为 “Uniform”,也可以是 “Stratified”(在进行分类且目标类不平衡时可能有更好的结果)。
如果觉得评分过于频繁,降低
score_duty_cycle
或增加
score_interval
通常是好的选择,显式设置
train_samples_per_iteration
也可以达到同样的效果。如果觉得早停触发过早,也可以采取这些措施,但最好的解决方法通常是增加
stopping_rounds
。
4. 建筑能源效率案例:默认深度学习模型
建筑能源效率问题是一个回归问题。使用 10 折交叉验证,而不是验证集。运行相应代码设置 H2O、加载数据并定义训练集、测试集、特征和目标变量:
m <- h2o.deeplearning(x, y, train, nfolds = 10, model_id = "DL_defaults")
m = h2o.estimators.H2ODeepLearningEstimator(model_id="DL_defaults")
m.train(x, y, train, nfolds=10)
该模型运行时间略超过 10 秒,使用了所有 8 个核心。10 折交叉验证的平均均方误差(MSE)为 8.15(标准差为 1.40),测试数据的 MSE 为 6.60。与随机森林、GBM 相比,默认模型的结果较差,仅略好于 GLM。
5. 建筑能源效率案例:调优深度学习模型
5.1 早停设置
为了给每个模型更多的 epoch 并避免担忧,使用早停技术。对于前几个网格,采用更严格的早停标准:如果在最后三次评分中没有至少提高 0.5%,则停止训练。相关参数设置如下:
stopping_metric = "MSE",
stopping_tolerance = 0.005,
stopping_rounds = 3,
epochs = 1000,
train_samples_per_iteration = 0,
score_interval = 3
5.2 增加 epoch 的效果
仅增加 epoch 数量(其他设置保持默认),结果显示模型在所有三个数据集上都有显著改善:
| | Default | Early#1 | Early#2 |
| — | — | — | — |
| Train - MSE | 5.587 | 0.223 | 0.092 |
| CV - MSE | 17.510 | 4.854 | 4.908 |
| Test - MSE | 7.089 | 0.580 | 0.437 |
| Epochs | 11.519 | 194.000 | 192.000 |
5.3 网络布局实验
由于问题是非线性的,认为需要两个隐藏层,但不认为需要超过三个层。尝试不同的隐藏层大小组合,共得到 14 种组合。为了加快速度,将交叉验证折数从 10 折减少到 6 折。实验结果如下:
| hidden | train.mse | xval.mse | sd | epochs | time |
| — | — | — | — | — | — |
| 324,324,324 | 0.347 | 4.368 | 0.494 | 177 | 23.4 |
| 54,54 | 0.087 | 4.712 | 0.556 | 982 | 5.2 |
| 162,162 | 0.059 | 4.744 | 0.446 | 525 | 10.4 |
| 324,162 | 0.096 | 4.788 | 0.503 | 236 | 7.0 |
| 324,162,162 | 0.162 | 4.946 | 0.479 | 171 | 9.9 |
| 162,81,81 | 0.270 | 4.978 | 0.457 | 418 | 8.0 |
| 54,108,108 | 0.022 | 5.005 | 0.581 | 518 | 7.4 |
| 162,324,324 | 0.135 | 5.026 | 0.322 | 158 | 17.5 |
| 162,162,162 | 0.152 | 5.065 | 0.629 | 243 | 10.0 |
| 162,81 | 0.035 | 5.077 | 0.649 | 623 | 7.9 |
| 162,324 | 0.087 | 5.147 | 0.520 | 244 | 9.3 |
| 54,108 | 0.015 | 5.242 | 0.573 | 836 | 6.3 |
| 324,324 | 0.131 | 5.456 | 0.627 | 205 | 8.4 |
| 54,54,54 | 0.049 | 5.983 | 1.173 | 720 | 6.5 |
从这些结果来看,没有强烈的需求增加更多的神经元或层,但更多的 epoch 可能会有更好的效果。
5.4 激活函数、丢弃和正则化实验
考虑激活函数的最佳值以及丢弃和正则化是否有帮助。有两种丢弃类型:输入层与第一个隐藏层之间的丢弃(
input_dropout_ratio
)和隐藏层输出的丢弃(
hidden_dropout_ratios
)。由于只有 8 个输入列(18 个输入神经元),较高的
input_dropout_ratio
值可能效果不佳。
使用以下超参数进行网格搜索:
- 若为 3 层网络,使用 324,162,162;若为 2 层网络,尝试 54,54 和 162,162。
- 激活函数选择 RectifierWithDropout、TanhWithDropout 或 MaxoutWithDropout。
- 隐藏层丢弃比率为 0(无丢弃)、0.1(每次少量丢弃)、0.2(丢弃 20%)和 0.5(丢弃 50%,默认值)。
- 输入丢弃比率为 0(无丢弃)或 0.1(忽略 10% 的输入)。
- L1 正则化为 0(无正则化)或 0.00001(1e - 05)。
- L2 正则化为 0(无正则化)、0.00001(1e - 05)或 0.0001(1e - 04)。
结果表明,最佳模型完全不使用丢弃。激活函数的选择影响较小,Rectifier 比 Tanh 或 Maxout 更快。对于 L2 正则化,约一半的顶级模型使用 0.00001,一半使用 0。对于 L1 正则化,0 和 0.00001 各占约 50%,但 0.0001 似乎会使结果变差。
5.5 最佳模型训练
选择最佳模型并进行重新训练,使用 10 折交叉验证,较宽松的早停标准,并允许最多 2000 个 epoch:
m <- h2o.deeplearning(
x, y, train,
nfolds = 10,
model_id = "DL_best",
activation = "Tanh",
l2 = 0.00001, #1e-05
hidden = c(162,162),
stopping_metric = "MSE",
stopping_tolerance = 0.0005,
stopping_rounds = 5,
epochs = 2000,
train_samples_per_iteration = 0,
score_interval = 3
)
该模型最终使用了 479 个 epoch,训练数据的 MSE 为 0.148,测试数据的 MSE 为 0.434,是目前最好的结果。但实际上,大部分改进来自于增加 epoch 数量。
5.6 交叉验证指标之谜
交叉验证结果与测试数据结果差异较大。例如,10 折交叉验证模型的 MSE 平均值为 4.661(标准差为 0.63),而模型信息中显示的另一个 MSE 指标为 4.724274,基于所有训练数据的模型在训练数据上的 MSE 为 0.128,优于测试数据的 0.425。
这可能是因为该数据集没有噪声和重复,包含每种建筑类型的一个样本。训练数据量 562 可能不足以代表整体,但当使用全部 625 个训练行时,模型性能有了显著提升。深度学习是唯一表现出这种行为的算法,其他算法的交叉验证 MSE 与测试数据 MSE 相近。
综上所述,通过合理调整神经网络的参数,如激活函数、隐藏层大小、丢弃率和正则化参数,并结合早停技术和增加 epoch 数量,可以显著提高模型性能。但在实际应用中,需要根据具体数据集和问题进行细致的调优。
6. 总结与建议
6.1 权重与训练速度
权重数量对训练速度影响显著。在设计神经网络时,要谨慎考虑输入特征的类型和数量,尤其是枚举类型特征,避免因过多的输入神经元导致权重数量大幅增加,从而降低训练效率。例如,对于具有大量级别的因子(如邮政编码),可参考相关视频中使用 H2O 和额外数据集降低维度的方法。
6.2 激活函数选择
- 一般情况下,Rectifier 激活函数速度较快,可作为首选。若遇到数值不稳定问题,可切换到 Tanh。
- 利用网格搜索尝试不同的激活函数及其 “WithDropout” 变体,根据数据特点选择最适合的激活函数。
6.3 参数调优
- 隐藏层设置 :根据问题的复杂程度合理设置隐藏层的数量和大小。可通过实验不同的组合,找到性能和训练时间的平衡点。
- 正则化 :L1 和 L2 正则化可用于防止过拟合,但具体效果因数据集而异。在建筑能源效率案例中,L2 正则化的效果不明显,L1 正则化使用较小值(如 0.00001)时表现较好。
- 丢弃率 :在大多数情况下,不使用丢弃或使用较小的丢弃率效果更好。对于输入丢弃比率,由于输入特征较少,较高的值可能会导致性能下降。
-
早停设置
:合理设置早停参数可以避免过度训练,节省计算资源。在建筑能源效率案例中,增加
stopping_rounds可以解决早停触发过早的问题。
6.4 交叉验证
交叉验证结果与测试数据结果可能存在差异,这可能与数据集的特点有关。在评估模型性能时,要综合考虑多种指标,并结合实际情况进行分析。
6.5 整体流程建议
以下是一个深度学习模型调优的基本流程:
graph LR
A[数据准备] --> B[默认模型训练]
B --> C[早停设置]
C --> D[增加 epoch 实验]
D --> E[网络布局实验]
E --> F[激活函数、丢弃和正则化实验]
F --> G[选择最佳模型重新训练]
G --> H[模型评估]
7. 未来研究方向
虽然在建筑能源效率案例中通过参数调优取得了较好的结果,但仍有一些方面值得进一步研究:
-
更复杂的网络结构
:尝试使用更复杂的神经网络结构,如卷积神经网络(CNN)或循环神经网络(RNN),看是否能进一步提高模型性能。
-
集成学习
:将深度学习模型与其他机器学习算法进行集成,如随机森林、GBM 等,可能会获得更好的预测效果。
-
自动化调优
:开发自动化的参数调优工具,减少人工调优的时间和工作量。
8. 结论
深度学习在解决复杂问题方面具有强大的能力,但模型的性能高度依赖于参数的调优。通过本文的介绍和建筑能源效率案例的分析,我们了解了神经网络中权重计算、激活函数、参数设置等关键知识,并掌握了一套有效的参数调优方法。在实际应用中,要根据具体问题和数据集的特点,灵活运用这些方法,不断尝试和优化,以获得最佳的模型性能。同时,持续关注深度学习领域的新发展和新技术,将有助于我们更好地应对各种挑战。
希望本文能为读者在深度学习模型调优方面提供有价值的参考,帮助大家在实际项目中取得更好的成果。
超级会员免费看
2023

被折叠的 条评论
为什么被折叠?



