吴恩达机器学习ex4 Neural Networks Learning (python)
发布日期:2021-05-11 00:18:02 浏览次数:23 分类:精选文章

本文共 3337 字,大约阅读时间需要 11 分钟。

反向传播算法:训练神经网络识别手写数字

反向传播算法是机器学习中训练神经网络的核心技术,用于通过误差信息调整网络参数,使其能够更好地拟合数据。以下是详细的实现步骤和解释。

1. 数据预处理

首先,我们需要加载训练数据和标签。数据集包含5000个手写数字,每个数字由20x20像素组成,转换为400维向量。标签是0-9的数字,使用one-hot编码转换为10维向量。

import numpy as np
import pandas as pd
from scipy.io import loadmat
from sklearn.preprocessing import OneHotEncoder
def load_data(path):
data = loadmat(path)
X = data['X']
y = data['y']
return X, y
X, y = load_data('../data_files/data/ex4data1.mat')
y = y.reshape(-1, 1)
encoder = OneHotEncoder(sparse=False)
y_onehot = encoder.fit_transform(y)

2. 神经网络结构

神经网络由输入层、隐藏层和输出层组成。输入层有400个神经元(每个样本20x20像素),隐藏层有25个神经元,输出层有10个神经元(对应0-9的数字)。

3. 前向传播

实现前向传播函数,将输入数据通过网络计算输出。加入偏置单元,激活函数使用sigmoid。

def sigmoid(z):
return np.clip(np.squeeze(1 / (1 + np.exp(-z))), 1e-7, 1 - 1e-7)
def forward_propagate(theta, X):
t1, t2 = deserialize(theta)
a1 = X
z2 = a1 @ t1.T
a2 = np.insert(sigmoid(z2), 0, 1, axis=1)
z3 = a2 @ t2.T
h = sigmoid(z3)
return a1, z2, a2, z3, h
def deserialize(seq):
return seq[:25*401].reshape(25, 401), seq[25*401:].reshape(10, 26)
a1, z2, a2, z3, h = forward_propagate(theta, X)

4. 误差函数

计算交叉熵损失。

def cost(theta, X, y):
a1, z2, a2, z3, h = forward_propagate(theta, X)
J = 0
for i in range(len(X)):
first = -y[i] * np.log(h[i])
second = (1 - y[i]) * np.log(1 - h[i])
J = J + np.sum(first - second)
return J / len(X)

5. 反向传播

实现反向传播算法,计算每一层的梯度。

def sigmoid_derivative(z):
sig = sigmoid(z)
return sig * (1 - sig)
def backpropagation(theta, X, y):
a1, z2, a2, z3, h = forward_propagate(theta, X)
d3 = h - y
d2 = d3 @ t2[:, 1:] * sigmoid_derivative(z2)
D2 = d3.T @ a2
D1 = d2.T @ a1
D = (1 / len(X)) * serialize(D1, D2)
return D
def serialize(a, b):
return np.r_[a.flatten(), b.flatten()]
def deserialize(seq):
return seq[:25*401].reshape(25, 401), seq[25*401:].reshape(10, 26)

6. 梯度下降优化

使用随机初始化和梯度下降优化训练网络。

def random_init(size):
return np.random.uniform(-0.12, 0.12, size)
def nn_training(X, y):
init_theta = random_init(10285)
res = opt.minimize(fun=costReg, x0=init_theta, args=(X, y, 1),
method='TNC', jac=regularized_gradient, options={'maxiter': 400})
return res
def regularized_gradient(theta, X, y, learning_rate=1):
a1, z2, a2, z3, h = forward_propagate(theta, X)
D = backpropagation(theta, X, y)
theta1, theta2 = deserialize(theta)
D1, D2 = deserialize(D)
theta1[:0] = 0
theta2[:0] = 0
reg_D1 = D1 + (learning_rate / len(X)) * theta1
reg_D2 = D2 + (learning_rate / len(X)) * theta2
return serialize(reg_D1, reg_D2)

7. 训练并验证

训练网络并验证准确率。

def accuracy(theta, X, y):
_, _, _, _, h = forward_propagate(theta, X)
y_pred = np.argmax(h, axis=1) + 1
print(classification_report(y, y_pred))
res = nn_training(X, y_onehot)
accuracy(res.x, X, y)

8. 可视化隐藏层

可视化隐藏层中的权重矩阵,观察网络学习的特征。

def plot_hidden(theta):
t1, _ = deserialize(theta)
t1 = t1[:, 1:]
fig, ax_array = plt.subplots(5, 5, sharex=True, sharey=True, figsize=(6, 6))
for r in range(5):
for c in range(5):
ax_array[r, c].matshow(t1[r * 5 + c].reshape(20, 20), cmap='gray_r')
plt.xticks([])
plt.yticks([])
plt.show()
plot_hidden(res.x)

9. 结果

训练后的网络具有高准确率,能够识别手写数字。

通过以上步骤,我们实现了反向传播算法,训练了一个能够识别手写数字的神经网络,并可视化了隐藏层中的特征。

上一篇:机器学习之二:回归分析
下一篇:机器学习实战四:好事达保险索赔预测 Allstate Claims Severity (xgboost)

发表评论

最新留言

不错!
[***.144.177.141]2025年05月15日 11时06分39秒