神经网络训练:从评估到优化
1. 评估多层感知机(MLP)
在Python中,一旦实现了评估方法,评估大型神经网络和小型神经网络的难度是一样的,因为Python会帮我们完成所有工作。
MLP类的评估方法应接收一个64维向量作为输入,并返回一个10维向量作为输出。从输入到输出的过程是基于逐层计算激活值,从输入层一直到输出层。为了便于后续的反向传播,我们需要记录所有层的激活值。因此,我们将评估函数分为两步构建:
-
前馈(feedforward)方法
:用于计算所有层的激活值。输入层的激活值就是输入向量,要得到下一层的激活值,需要将当前层的激活值向量与权重矩阵相乘,加上下一层的偏置,然后将结果的每个坐标通过sigmoid函数。重复这个过程直到输出层。以下是代码实现:
class MLP():
...
def feedforward(self,v):
activations = []
a = v
activations.append(a)
for w,b in zip(self.weights, self.biases):
z = w @ a + b
a = [sigmoid(x) for x in z]
activations.append(a)
return activations
- 评估(evaluate)方法 :运行前馈方法并提取最后一层的激活向量作为结果。代码如下:
class MLP():
...
def evaluate(self,v):
return np.array(self.feedforward(v)[-1])
2. 测试MLP的分类性能
使用合适大小的MLP,它现在可以接受一个数字图像的向量并输出结果。例如:
nn = MLP([64,16,10])
v = np.matrix.flatten(digits.images[0]) / 15.
nn.evaluate(v)
由于权重和偏置是随机初始化的,这些数字并不能很好地预测图像代表的数字。实际上,随机初始化的MLP只有10%的预测准确率,我们可以使用
test_digit_classify
函数来验证这一点:
test_digit_classify(nn.evaluate)
3. 使用梯度下降训练神经网络
训练神经网络意味着找到最佳的权重和偏置,使神经网络尽可能好地完成手头的任务。我们可以将训练过程看作一个最小化问题。
3.1 将训练构建为最小化问题
对于线性函数
ax + b
或逻辑函数
σ(ax + by + c)
,我们创建了一个成本函数来衡量这些函数与数据的匹配程度。对于MLP,它的行为可能取决于数百或数千个常量,包括所有层的权重和偏置。我们的神经网络有64、16和10个神经元的三层结构,总共有1210个常量需要调整。
我们可以将成本函数看作这些1210个值的函数,并使用梯度下降来最小化它。为了衡量神经网络输出向量与理想输出向量之间的误差,我们可以使用它们在10维空间中的距离的平方。
3.2 使用反向传播计算梯度
如果直接计算成本函数的1210个偏导数,计算量会非常大,因为每个偏导数都需要对成本函数进行两次评估。更好的方法是使用反向传播算法,它可以递归地计算所有偏导数,从输出层的权重和偏置开始,一直到第一层。
3.3 使用scikit-learn自动训练
我们可以使用scikit-learn库来自动完成成本计算、反向传播和梯度下降。具体步骤如下:
1.
准备数据
:将训练数据(数字图像的64维向量)放入一个NumPy数组中,并将对应的答案放入一个输出列表中。
x = np.array([np.matrix.flatten(img) for img in digits.images[:1000]]) / 15.0
y = digits.target[:1000]
-
初始化MLP
:使用
MLPClassifier类初始化一个MLP,并指定隐藏层的大小、激活函数、最大迭代次数等参数。
from sklearn.neural_network import MLPClassifier
mlp = MLPClassifier(hidden_layer_sizes=(16,),
activation='logistic',
max_iter=100,
verbose=10,
random_state=1,
learning_rate_init=.1)
-
训练神经网络
:使用
fit方法将输入数据和输出数据传递给MLP进行训练。
mlp.fit(x,y)
-
测试性能
:训练完成后,我们可以使用
_predict方法对图像向量进行预测,并使用test_digit_classify函数测试其分类准确率。
def sklearn_trained_classify(v):
return mlp._predict([v])[0]
test_digit_classify(sklearn_trained_classify)
4. 相关练习
- 练习16.10 :使用显式循环重写前馈方法,而不是使用NumPy矩阵乘法,并确认结果与之前的实现完全匹配。
-
练习16.11
:修改
test_digit_classify函数,使其可以在测试集的自定义范围内工作,并测试训练后的MLP在训练集之后的500个示例上的表现。
def test_digit_classify(classifier,start=0,test_count=1000):
correct = 0
end = start + test_count
for img, target in zip(digits.images[start:end],
digits.target[start:end]):
v = np.matrix.flatten(img) / 15
output = classifier(v)
answer = list(output).index(max(output))
if answer == target:
correct += 1
return (correct/test_count)
- 练习16.12 :使用平方距离成本函数,计算随机生成的MLP和scikit-learn训练的MLP在1000个训练示例上的成本。
def y_vec(digit):
return np.array([1 if i == digit else 0 for i in range(0,10)])
def cost_one(classifier,x,i):
return sum([(classifier(x)[j] - y_vec(i)[j])**2 for j in range(10)])
def total_cost(classifier):
return sum([cost_one(classifier,x[j],y[j]) for j in range(1000)])/1000.
-
练习16.13
:从
MLPClassifier中提取权重和偏置,将它们插入到我们自己构建的MLP类中,并测试其在数字分类任务上的性能。
nn = MLP([64,16,10])
nn.weights = [w.T for w in mlp.coefs_]
nn.biases = mlp.intercepts_
test_digit_classify(nn.evaluate,
start=1000,
test_count=500)
5. 总结
通过以上步骤,我们学习了如何评估MLP的性能,如何将训练过程构建为最小化问题,以及如何使用scikit-learn库自动训练神经网络。通过练习,我们可以进一步巩固所学知识,并深入理解神经网络的工作原理。
以下是一个简单的流程图,展示了神经网络训练的主要步骤:
graph TD;
A[准备数据] --> B[初始化MLP];
B --> C[训练神经网络];
C --> D[测试性能];
通过这些步骤,我们可以不断优化神经网络的性能,使其在数字分类等任务上取得更好的效果。
神经网络训练:从评估到优化
6. 深入理解反向传播
虽然我们可以使用scikit - learn库自动完成训练,但了解反向传播的原理对于深入理解神经网络非常有帮助。反向传播的核心是递归地计算成本函数关于权重和偏置的偏导数。
在神经网络中,每个神经元的输出取决于前一层神经元的输出、权重和偏置。通过链式法则,我们可以从输出层开始,逐步计算每一层的偏导数。以下是反向传播的大致步骤:
1.
前向传播
:计算所有层的激活值,就像我们在
feedforward
方法中所做的那样。
2.
计算输出层的误差
:将神经网络的输出与理想输出进行比较,计算误差。
3.
反向传播误差
:从输出层开始,逐层计算误差的传播,更新每一层的权重和偏置。
下面是一个简化的反向传播过程的表格说明:
|步骤|操作|
| ---- | ---- |
|前向传播|计算各层激活值,记录中间结果|
|输出层误差计算|计算输出与理想输出的差异|
|反向传播误差|从输出层向输入层传播误差,更新权重和偏置|
7. 优化训练过程
在训练神经网络时,有几个关键因素会影响训练的效果和效率:
-
学习率
:学习率决定了在每次梯度下降步骤中权重和偏置更新的幅度。如果学习率过大,可能会导致训练过程不稳定,甚至无法收敛;如果学习率过小,训练速度会非常缓慢。
-
迭代次数
:迭代次数是指梯度下降算法执行的次数。如果迭代次数太少,神经网络可能无法充分学习数据的特征;如果迭代次数太多,可能会导致过拟合。
-
激活函数
:激活函数引入了非线性因素,使得神经网络能够学习复杂的模式。不同的激活函数具有不同的特性,例如sigmoid函数将输入映射到(0, 1)区间,ReLU函数则在输入大于0时直接输出输入值。
以下是一个不同学习率和迭代次数对训练效果影响的示例表格:
|学习率|迭代次数|训练准确率|
| ---- | ---- | ---- |
|0.01|50|80%|
|0.1|100|90%|
|1|20|不稳定|
8. 过拟合与欠拟合问题
在训练神经网络时,过拟合和欠拟合是两个常见的问题。
-
欠拟合
:当神经网络无法学习到数据的基本特征时,就会出现欠拟合。这可能是由于模型过于简单,或者训练数据不足导致的。解决欠拟合的方法包括增加模型的复杂度、增加训练数据等。
-
过拟合
:当神经网络在训练数据上表现良好,但在测试数据上表现不佳时,就会出现过拟合。这是因为模型过于复杂,学习了训练数据中的噪声和细节,而没有学习到数据的一般规律。解决过拟合的方法包括正则化、早停法等。
下面是一个简单的流程图,展示了过拟合和欠拟合的判断和解决方法:
graph TD;
A[训练模型] --> B{训练集和测试集表现};
B -->|训练集和测试集准确率都低| C[欠拟合];
B -->|训练集准确率高,测试集准确率低| D[过拟合];
C --> E[增加模型复杂度];
C --> F[增加训练数据];
D --> G[正则化];
D --> H[早停法];
9. 拓展应用
神经网络在许多领域都有广泛的应用,除了数字分类,还包括图像识别、语音识别、自然语言处理等。在不同的应用场景中,需要根据具体的需求调整神经网络的结构和参数。
例如,在图像识别中,通常会使用卷积神经网络(CNN),它可以自动提取图像的特征。在自然语言处理中,循环神经网络(RNN)及其变体(如LSTM、GRU)可以处理序列数据。
10. 总结与展望
通过对多层感知机(MLP)的评估、训练和优化,我们深入了解了神经网络的工作原理和训练方法。从最初随机初始化的低准确率,到使用scikit - learn库训练后的高准确率,我们见证了神经网络的强大能力。
在未来的研究和应用中,我们可以进一步探索更复杂的神经网络结构,如深度卷积神经网络、生成对抗网络等。同时,我们也可以关注如何处理大规模数据、提高训练效率和模型的可解释性等问题。
通过不断地学习和实践,我们可以更好地利用神经网络解决各种实际问题,推动人工智能技术的发展。
超级会员免费看

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



