如何训练含两层及以上的神经网络?
如何修改神经网络训练函数以支持多层网络?
我已经用Python从零实现了神经网络,定义了Neuron、Layer和NeuralNetwork类,成功训练并使用了含1层、1个神经元、3个输入的网络。现在想构建两层及以上、每层神经元数量任意的网络,但不知道怎么修改train函数来训练这类网络。目前已经实现了前向传播:第0层输入网络输入,非0层输入前一层的输出,但后续训练步骤不清楚。
以下是当前代码:
import numpy as np from numpy import exp, random import math from sklearn.datasets import make_blobs import matplotlib.pyplot as plt np.random.seed(1) class Neuron: def __init__(self, weights, bias): self.weights = weights self.bias = bias def sigmoid(self, x): output = 1/(1+exp(-x)) return output def compute(self, inputs): self.output = self.sigmoid(np.dot(inputs, self.weights) + self.bias) return self.output class Layer: def __init__(self, numberOfNeurons, numberOfInputs): self.neurons = [] self.outputs = [] self.numberOfNeurons = numberOfNeurons self.numberOfInputs = numberOfInputs self.initialiseWeightsAndBiases() for i in range(0,numberOfNeurons): self.neurons.append(Neuron(self.weights, self.biases)) def initialiseWeightsAndBiases(self): self.weights = 2 * random.random((self.numberOfInputs, self.numberOfNeurons)) - 1 self.biases = 2 * random.random((1, self.numberOfNeurons)) - 1 def forward(self, inputs): self.outputs = np.array([]) for i in self.neurons: self.outputs = np.append(self.outputs, i.compute(inputs)) class NeuralNetwork: def __init__(self, layers): self.layers = layers def forwardPass(self, inputs): for i in range(0,len(layers)): if i == 0: layers[i].forward(inputs) else: layers[i].forward(layers[i-1].outputs) return layers[-1].outputs def calculateError(self, predictedOutputs, trueOutputs): error = (trueOutputs - predictedOutputs) * predictedOutputs * (1 - predictedOutputs) return error def trainNetwork(self, trainingDataInputs, trainingDataOutputs, numberOfIterations): for y in range(0, numberOfIterations): predictedOutputs = self.forwardPass(trainingDataInputs) error = self.calculateError(predictedOutputs, trainingDataOutputs) for i in layers[0].neurons: i.weights += np.dot(trainingDataInputs.T, error.T) def visualiseNetwork(self): pass # 测试单层网络 inputLayer = Layer( 1, 3) layers = [inputLayer] network1 = NeuralNetwork(layers) inputTrainingData = np.array([[0, 0, 1], [1, 1, 1], [1, 0, 1], [0, 1, 1]]) outputTrainingData = [[0, 1, 1, 0]] network1.trainNetwork(inputTrainingData, outputTrainingData, 10000) outputs = network1.forwardPass([[0,1,1]]) print(outputs)
核心修改方案:实现反向传播算法
要支持多层网络训练,必须实现反向传播——从输出层反向计算每一层的误差项,再基于误差更新对应层的权重和偏置。以下是具体修改步骤:
1. 修正forwardPass的变量引用问题
原代码直接使用全局变量layers,改为引用类成员self.layers,避免多层网络时出现逻辑错误:
def forwardPass(self, inputs): current_input = inputs for layer in self.layers: layer.forward(current_input) current_input = layer.outputs return self.layers[-1].outputs
2. 修复Layer类的神经元权重初始化问题
原代码中同一层所有神经元共享一组权重,这是错误的——每个神经元需要独立的权重和偏置:
class Layer: def __init__(self, numberOfNeurons, numberOfInputs): self.neurons = [] self.outputs = [] self.numberOfNeurons = numberOfNeurons self.numberOfInputs = numberOfInputs # 为每个神经元初始化独立的权重和偏置 for _ in range(numberOfNeurons): weights = 2 * random.random((numberOfInputs, 1)) - 1 bias = 2 * random.random(1) - 1 self.neurons.append(Neuron(weights, bias)) def forward(self, inputs): self.outputs = np.array([]) for neuron in self.neurons: self.outputs = np.append(self.outputs, neuron.compute(inputs)) self.outputs = self.outputs.reshape(-1) # 统一维度方便后续计算
3. 重写trainNetwork函数,实现完整反向传播
添加学习率参数,从输出层到输入层依次计算误差,再更新权重和偏置:
def trainNetwork(self, trainingDataInputs, trainingDataOutputs, numberOfIterations, learning_rate=0.1): # 调整输出数据维度,匹配网络输出格式 trainingDataOutputs = np.array(trainingDataOutputs).T for _ in range(numberOfIterations): # 前向传播获取预测结果 predictedOutputs = self.forwardPass(trainingDataInputs).reshape(-1, 1) # 初始化误差列表,从输出层开始计算 errors = [] # 输出层误差:结合真实值、预测值和sigmoid导数 output_error = (trainingDataOutputs - predictedOutputs) * predictedOutputs * (1 - predictedOutputs) errors.append(output_error) # 反向计算隐藏层误差 for i in reversed(range(len(self.layers)-1)): next_layer = self.layers[i+1] next_error = errors[0] # 基于下一层的误差和权重,推导当前层误差 current_error = np.dot(next_error, next_layer.weights.T) * self.layers[i].outputs.reshape(-1,1) * (1 - self.layers[i].outputs.reshape(-1,1)) errors.insert(0, current_error) # 更新每一层的权重和偏置 for i in range(len(self.layers)): layer = self.layers[i] # 获取当前层的输入:输入层用训练数据,隐藏层用前一层输出 layer_input = trainingDataInputs if i == 0 else self.layers[i-1].outputs.reshape(-1, layer.numberOfInputs) # 计算权重和偏置的更新量 delta_weights = learning_rate * np.dot(layer_input.T, errors[i]) delta_biases = learning_rate * np.mean(errors[i], axis=0) # 更新参数 layer.weights += delta_weights layer.biases += delta_biases.reshape(layer.biases.shape)
4. 测试多层网络
现在可以创建两层及以上的网络进行测试:
# 构建两层网络:输入层(2个神经元,3输入)+ 输出层(1个神经元,2输入) input_layer = Layer(2, 3) output_layer = Layer(1, 2) layers = [input_layer, output_layer] network = NeuralNetwork(layers) inputTrainingData = np.array([[0, 0, 1], [1, 1, 1], [1, 0, 1], [0, 1, 1]]) outputTrainingData = [[0, 1, 1, 0]] # 训练网络 network.trainNetwork(inputTrainingData, outputTrainingData, 10000, learning_rate=0.2) # 测试预测 outputs = network.forwardPass([[0,1,1]]) print(outputs) # 输出应接近0
内容的提问来源于stack exchange,提问作者Matthew Haywood
相关产品推荐
相关产品推荐

