神经网络训练与调试经验分享

训练神经网络通常是一种高风险高回报的策略。如果调整得当,可能会得到一个为特定任务工作的最先进的工作模型。以图像生成为例,这是神经网络的最新突破之一。只需几笔人工画笔,就可以创造出看起来非常真实的自然场景图像。然而,另一方面,训练一个生成性神经网络极其困难。必须经历一个严格的试错阶段才能把事情做对。几天前,当试图为年龄检测问题构建一个工作模型时,经历了类似的训练神经网络的经历。当为这个问题制作第一个模型时,它绝对拒绝训练。在这篇文章中,将分享如何调试神经网络的方法。请继续关注,因为有一个快乐的结局!

解决年龄检测问题与神经网络

在开始解决问题之前,让先概述一下这个问题是什么。印度演员年龄检测是一个最近发布的实践问题,涉及提取面部特征进行年龄分析。由于这是一个图像处理问题,自然选择了神经网络来解决这个问题。但正如之前所说,网络无法训练。即使让它训练超过一个小时200次迭代,准确率也没有变化。这里有一个证据!显然,这行不通!

检查神经网络架构

当构建神经网络时,首先要检查的是是否有正确定义架构。在这里,有一个三类问题,数据集中的图像大小不一。为了简化事情,将所有图像转换为32×32大小。根据这个,定义了如下架构:

# 定义变量 input_num_units = 32 * 32 * 3 # 图像是3D(RGB),因此乘以3 hidden_num_units = 500 output_num_units = 3 epochs = 50 batch_size = 128 model = Sequential([ InputLayer(input_shape=(input_num_units,)), Dense(units=hidden_num_units, activation='relu'), Dense(units=output_num_units, activation='softmax'), ])

看不出神经网络架构有任何问题。

检查神经网络的超参数

在看来,这是处理神经网络时最重要的步骤。这是因为有很多参数需要调整,有时尝试它们所有可能会令人沮丧。(附注:在这篇文章中调查了超参数以及如何调整它们)幸运的是,使用了一个非常简单的神经网络,只有一个隐藏层,使用经典的梯度下降算法(SGD)进行训练。

model.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy'])

需要注意的一点是,当使用SGD训练神经网络时,它可能会训练得很慢。为了克服这个问题,可以使用自适应梯度下降来更快地训练网络。

model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

但问题是,即使将训练算法从SGD更改为Adam(即自适应梯度下降),网络也没有训练。这意味着网络有根本性的问题。不得不使用Thor的锤子来打破这个问题!

TensorBoard概览

在理解神经网络的过程中,使用了许多构建和可视化神经网络的工具。在它们所有中,发现TensorBoard是一个重要的资产。它可以在训练神经网络时给有用的洞察。

除此之外,它还提供了一个漂亮的仪表板视图,这对于向利益相关者解释发现非常重要。在上面看到的证据图像本身就是TensorBoard的仪表板。

将介绍如何在系统中安装TensorBoard的步骤。建议自己尝试一下。

pip install Tensorboard

安装后,可以通过在终端输入以下命令来打开TensorBoard:

tensorboard --logdir=logs/

上面的“logs/”文件夹应该包含神经网络训练的历史。可以通过在Keras中包含一个TensorBoard回调来简单地获得这个历史。

model.fit(train_x, train_y, batch_size=batch_size, epochs=epochs, verbose=1, validation_split=0.2, callbacks=[keras.callbacks.TensorBoard(log_dir="logs/final/{}".format(time()), histogram_freq=1, write_graph=True, write_images=True)])

在这个例子中,传递了所有参数,以便保存所有内容。参数的含义如下:

  • write_graph:打印神经网络内部定义的图。
  • write_images:通过组合神经网络的权重创建图像。
  • histogram_freq:绘制神经网络中权重和偏差的分布。

检查网络复杂性

从短暂旅行回来后,接下来尝试的是检查构建的网络是否足以学习问题分布。为此,将架构从简单的神经网络更改为卷积神经网络。效果是准确率从一开始就急剧上升(从33%上升到54%)。但即使训练后,它仍然保持不变。

看来小实验失败了🙁

检查输入数据结构

在彻底检查了网络架构之后,是时候检查否有正确的数据集本身了。需要检查的一些事情是:

  • 所有记录是否都是相同大小?
  • 问题是否不平衡?
  • 是否进行了适当的预处理?

在这里,应该检查否有一个正确处理的输入。例如,在图像处理问题中,如果处理了图像,并且结果输入具有不规则的纵横比,神经网络显然会被它迷惑。

由于这是一个简单的网络,实际上没有进行任何预处理步骤。所以这不是问题。

在耗尽了可能遇到的大部分问题之后,开始感到有点沮丧,不知道真正的问题可能是什么。幸运的是,旅程结束了,因为发现了一个奇怪的错误,应该早就抓住了。

问题是发送给网络的输入数据范围是0到255。理想情况下,这个范围应该在0和1之间。输入数据的分布如下:

让向解释为什么归一化(将范围设置为0到1)很重要(因为亲自经历了找到它是什么麻烦😛)

temp = [] for img_name in train.ID: img_path = os.path.join(data_dir, 'Train', img_name) img = imread(img_path) img = imresize(img, (32, 32)) temp.append(img.astype('float32')) train_x = np.stack(temp) train_x = train_x / 255. # 归一化步骤
  1. 检查架构
  2. 检查神经网络的超参数
  3. 检查网络复杂性
  4. 检查输入数据结构
  5. 检查数据分布
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485