1. 在所有其他参数保持不变的情况下,更改超参数 num_hiddens
的值,并查看此超参数的变化对结果有何影响。确定此超参数的最佳值。
py
num_inputs, num_outputs, num_hiddens_list = 784, 10, [128, 256, 512, 1024, 2048, 4096]
for num_hiddens in num_hiddens_list:
W1 = nn.Parameter(torch.randn(num_inputs, num_hiddens, requires_grad=True) * 0.01)
b1 = nn.Parameter(torch.zeros(num_hiddens, requires_grad=True))
W2 = nn.Parameter(torch.randn(num_hiddens, num_outputs, requires_grad=True) * 0.01)
b2 = nn.Parameter(torch.zeros(num_outputs, requires_grad=True))
params = [W1, b1, W2, b2]
loss = nn.CrossEntropyLoss(reduction='none')
num_epochs, lr = 10, 0.1
updater = torch.optim.SGD(params, lr=lr)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)
print(f'num_hiddens {num_hiddens}')
从 test acc 来说,256 最佳
2. 尝试添加更多的隐藏层,并查看它对结果有何影响。
py
num_inputs, num_outputs, num_hiddens = 784, 10, 256
num_layers_list = [0, 128, 256, 512, 1024]
for num_layers in num_layers_list:
W1 = nn.Parameter(torch.randn(num_inputs, num_hiddens, requires_grad=True) * 0.01)
b1 = nn.Parameter(torch.zeros(num_hiddens, requires_grad=True))
WS, BS = [], []
for layer in range(num_layers):
WS.append(nn.Parameter(torch.randn(num_hiddens, num_hiddens, requires_grad=True) * 0.01))
BS.append(nn.Parameter(torch.zeros(num_hiddens, requires_grad=True)))
W2 = nn.Parameter(torch.randn(num_hiddens, num_outputs, requires_grad=True) * 0.01)
b2 = nn.Parameter(torch.zeros(num_outputs, requires_grad=True))
params = [W1, b1] + [x for pair in zip(WS, BS) for x in pair] + [W2, b2]
loss = nn.CrossEntropyLoss(reduction='none')
num_epochs, lr = 10, 0.1
updater = torch.optim.SGD(params, lr=lr)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)
5. 描述为什么涉及多个超参数更具挑战性。
涉及多个超参数的优化更具挑战性,原因如下:
-
高维搜索空间:每个超参数都增加了搜索空间的一个维度。随着超参数数量的增加,可能的组合呈指数增长,使得搜索变得更加复杂。
-
计算成本:对于每个超参数组合,通常需要训练整个模型并评估其性能,这在计算上可能非常昂贵,尤其是对于大型模型或数据集。
-
超参数交互:不同的超参数之间可能存在复杂的相互作用,这意味着一个超参数的最优值可能依赖于另一个超参数的设置。
-
局部最优:在高维空间中,存在许多局部最优解,这可能导致搜索算法陷入局部最优而无法找到全局最优解。
-
评估成本:对于每个超参数组合,评估模型性能可能需要大量的时间和资源,特别是如果使用交叉验证等方法。
-
超参数敏感性:某些超参数可能对模型性能非常敏感,而其他超参数的影响可能相对较小,这使得确定哪些超参数需要精细调整变得困难。
-
搜索策略的选择:确定合适的搜索策略(如网格搜索、随机搜索、贝叶斯优化等)对于多个超参数来说更加困难。
-
资源限制:在有限的资源下,需要在超参数的数量和每个超参数的候选值之间做出权衡。
-
超参数范围:确定每个超参数的合理搜索范围是一个挑战,尤其是当缺乏领域知识时。
-
模型泛化能力:超参数的最优组合不仅取决于模型在训练集上的性能,还需要考虑模型在未见过的测试数据上的泛化能力。
-
时间限制:在实际应用中,可能存在严格的时间限制,这限制了可以探索的超参数组合的数量。
-
调试难度:当模型表现不佳时,很难确定是由于超参数设置不当还是模型结构或数据本身的问题。
-
模型稳定性:某些模型可能对超参数的变化非常敏感,导致结果的高方差。
-
搜索算法的效率:大多数超参数搜索算法在多个超参数的情况下效率会降低,需要更多的迭代才能找到好的解。
-
并行化难度:并行化超参数搜索可以加快搜索过程,但并行化本身可能很复杂,尤其是在超参数空间很大时。
由于这些挑战,超参数优化通常需要仔细的规划和执行,以及对模型、数据和领域知识的深入理解。在实践中,可能需要采用多种策略和工具来有效地处理多个超参数的优化问题。
6. 如果想要构建多个超参数的搜索方法,请想出一个聪明的策略。
构建多个超参数的搜索方法,通常称为超参数优化(Hyperparameter Optimization, HPO),是一个在机器学习中非常重要的过程。这个过程的目标是找到一组超参数,使得模型在验证集上的性能最优。以下是一些有效的超参数搜索策略:
-
网格搜索(Grid Search):
- 定义每个超参数的可能值的范围。
- 通过遍历所有可能的超参数组合来进行搜索。
- 对于每一组超参数,训练模型并评估其性能。
-
随机搜索(Random Search):
- 从超参数的分布中随机选择值。
- 训练模型并评估性能。
- 重复一定次数或直到找到满意的结果。
-
贝叶斯优化(Bayesian Optimization):
- 使用概率模型来预测超参数的性能。
- 根据模型预测来选择最有潜力的超参数组合进行评估。
-
梯度基搜索(Gradient-based Search):
- 如果超参数可以通过模型的梯度来优化,可以使用这种方法。
- 适用于那些可以微分的超参数。
-
遗传算法(Genetic Algorithms):
- 模拟自然选择的过程。
- 使用选择、交叉(杂交)、变异等操作来迭代地改进超参数组合。
-
网格搜索与随机搜索的结合:
- 先用网格搜索来缩小超参数的范围。
- 然后在较小的范围内使用随机搜索进行更细致的搜索。
-
自动化机器学习(AutoML)工具:
- 使用专门的库或框架,如Hyperopt、Optuna、Keras Tuner等,它们提供了自动化的超参数搜索功能。
-
多任务学习(Multi-task Learning):
- 如果同时训练多个相关任务,可以共享一些超参数,以减少搜索空间。
-
元学习(Meta-learning):
- 利用历史优化经验来指导新的超参数搜索。
-
分层搜索(Hierarchical Search):
- 对于一些超参数,先进行粗略的搜索,找到大致范围后再进行更细致的搜索。
-
超参数空间的降维:
- 使用降维技术,如主成分分析(PCA),来减少超参数的数量。
-
超参数嵌套搜索:
- 某些超参数的最优值可能依赖于其他超参数的值,可以嵌套地进行搜索。
选择哪种策略取决于多个因素,包括模型的复杂性、超参数的数量、搜索资源(时间和计算能力)、以及对模型性能的要求。在实践中,通常需要结合多种策略来达到最佳的优化效果。