要使用NumPy实现一个前馈神经网络(Feedforward Neural Network),我们需要从基础开始构建,包括初始化网络参数、定义激活函数及其导数、实现前向传播、计算损失函数、以及实现反向传播算法来更新网络权重和偏置。这里,我将详细介绍一个包含单个隐藏层的前馈神经网络的实现。
前馈神经网络是一种最基础的神经网络结构,其中信息只向前传播,不形成循环。它通常由输入层、若干隐藏层(至少一层)和输出层组成。在这个实现中,我们将构建一个具有一个隐藏层的前馈神经网络,用于解决二分类问题。
首先,我们需要导入NumPy库,并定义一些基本的函数,如激活函数及其导数。
import numpy as np
def sigmoid(x):
"""Sigmoid激活函数"""
return 1 / (1 + np.exp(-x))
def sigmoid_derivative(x):
"""Sigmoid激活函数的导数"""
return x * (1 - x)
def mse_loss(y_true, y_pred):
"""均方误差损失函数"""
return np.mean((y_true - y_pred) ** 2)
接下来,我们定义网络的结构,包括输入层、隐藏层和输出层的节点数。
input_size = 3 # 输入层节点数
hidden_size = 4 # 隐藏层节点数
output_size = 1 # 输出层节点数
# 初始化权重和偏置
np.random.seed(0) # 为了可重复性设置随机种子
weights_input_to_hidden = np.random.randn(input_size, hidden_size) * 0.01
bias_hidden = np.zeros((1, hidden_size))
weights_hidden_to_output = np.random.randn(hidden_size, output_size) * 0.01
bias_output = np.zeros((1, output_size))
前向传播涉及将输入数据通过网络传播到输出层。
def forward_pass(X):
# 输入层到隐藏层
hidden_layer_input = np.dot(X, weights_input_to_hidden) + bias_hidden
hidden_layer_output = sigmoid(hidden_layer_input)
# 隐藏层到输出层
output_layer_input = np.dot(hidden_layer_output, weights_hidden_to_output) + bias_output
output_layer_output = sigmoid(output_layer_input)
return output_layer_output
反向传播用于计算损失函数关于网络参数的梯度,并据此更新这些参数。
def backward_pass(X, y_true, y_pred):
# 输出层梯度
d_output = y_pred - y_true
d_output_wrt_output_input = sigmoid_derivative(y_pred)
d_hidden_to_output = d_output * d_output_wrt_output_input
# 更新输出层权重和偏置
grad_weights_hidden_to_output = np.dot(hidden_layer_output.T, d_hidden_to_output)
grad_bias_output = np.sum(d_hidden_to_output, axis=0, keepdims=True)
# 隐藏层梯度
d_hidden = np.dot(d_hidden_to_output, weights_hidden_to_output.T)
d_hidden_wrt_hidden_input = sigmoid_derivative(hidden_layer_output)
d_input_to_hidden = d_hidden * d_hidden_wrt_hidden_input
# 更新输入层到隐藏层的权重和偏置
grad_weights_input_to_hidden = np.dot(X.T, d_input_to_hidden)
grad_bias_hidden = np.sum(d_input_to_hidden, axis=0, keepdims=True)
return grad_weights_input_to_hidden, grad_bias_hidden, grad_weights_hidden_to_output, grad_bias_output
def update_parameters(def update_parameters(learning_rate, grad_weights_input_to_hidden, grad_bias_hidden, grad_weights_hidden_to_output, grad_bias_output):
"""
根据梯度更新网络的权重和偏置。
Parameters:
- learning_rate: 浮点数,学习率。
- grad_weights_input_to_hidden: 输入层到隐藏层的权重梯度。
- grad_bias_hidden: 隐藏层的偏置梯度。
- grad_weights_hidden_to_output: 隐藏层到输出层的权重梯度。
- grad_bias_output: 输出层的偏置梯度。
"""
global weights_input_to_hidden, bias_hidden, weights_hidden_to_output, bias_output
weights_input_to_hidden -= learning_rate * grad_weights_input_to_hidden
bias_hidden -= learning_rate * grad_bias_hidden
weights_hidden_to_output -= learning_rate * grad_weights_hidden_to_output
bias_output -= learning_rate * grad_bias_output
# 示例数据
X = np.array([[0.1, 0.2, 0.3], [0.4, 0.5, 0.6], [0.7, 0.8, 0.9]]) # 示例输入
y_true = np.array([[0], [1], [0]]) # 示例真实输出(二分类问题,使用0和1表示)
# 训练过程
epochs = 10000 # 训练轮次
learning_rate = 0.1 # 学习率
for epoch in range(epochs):
# 前向传播
y_pred = forward_pass(X)
# 计算损失
loss = mse_loss(y_true, y_pred)
# 如果需要,可以在这里打印损失值以监控训练过程
if epoch % 1000 == 0:
print(f'Epoch {epoch}, Loss: {loss}')
# 反向传播
grad_weights_input_to_hidden, grad_bias_hidden, grad_weights_hidden_to_output, grad_bias_output = backward_pass(X, y_true, y_pred)
# 更新参数
update_parameters(learning_rate, grad_weights_input_to_hidden, grad_bias_hidden, grad_weights_hidden_to_output, grad_bias_output)
# 训练结束后,可以使用训练好的网络进行预测
# ...
在上面的代码中,我们仅打印了训练过程中的损失值来监控训练过程。在实际应用中,你还需要在训练结束后对模型进行评估,并使用它来对新数据进行预测。评估通常涉及在一个与训练集独立的测试集上计算模型的性能指标,如准确率、召回率、F1分数等。
通过上面的介绍,我们了解了如何使用NumPy从头开始实现一个具有单个隐藏层的前馈神经网络。虽然这个实现相对简单,但它为理解更复杂的深度学习模型和框架(如TensorFlow和PyTorch)奠定了基础。在实际应用中,我们通常会使用这些框架来构建和训练神经网络,因为它们提供了更多的功能和优化。然而,了解底层的实现原理对于深入理解深度学习仍然是非常重要的。
全部0条评论
快来发表一下你的评论吧 !