深度学习:反向传播算法

深度学习这部分做的笔记比较少,所展示的笔记是组会时个人汇报的部分。本文参考Michael Nielsen的Neural Network and Deep Learning第2章,给出了反向传播的四个基本方程及证明、反向传播算法步骤,以及代码示例。

最后给出BP算法的代码示例:(注意,代码中使用了mnist_loader.py,有需要的可自行在下面中下载)GitHub - mnielsen/neural-networks-and-deep-learning: Code samples for my book "Neural Networks and Deep Learning"Code samples for my book "Neural Networks and Deep Learning" - mnielsen/neural-networks-and-deep-learningicon-default.png?t=N7T8https://github.com/mnielsen/neural-networks-and-deep-learning/tree/master

class Network(object):

    def __init__(self, sizes):
        self.num_layers = len(sizes) # sizes 为每层的神经元数量
        self.sizes = sizes
        # 初始化权重和偏置, sizes[1:] 是一个列表切片(从第二个元素开始到列表末尾).
        # 对于列表中的每个元素 y, 调用 np.random.randn(y, 1) 生成一个随机的 y 行 1 列的数组
        self.biases = [np.random.randn(y, 1) for y in sizes[1:]]
        self.weights = [np.random.randn(y, x) for x, y in zip(sizes[:-1], sizes[1:])]

    def feedforward(self, a): # 正向传播, 返回的是被激活函数作用后的激活值
        for b, w in zip(self.biases, self.weights):
            a = sigmoid(np.dot(w, a)+b)
        return a

    def SGD(self, training_data, epochs, mini_batch_size, eta, test_data=None): # 梯度下降算法
        training_data = list(training_data) # 将输入的训练数据转换成列表, n 表示列表长度
        n = len(training_data)
        if test_data: # 如果测试集非空, 则执行下面代码
            test_data = list(test_data)
            n_test = len(test_data)
        for j in range(epochs): # 迭代
            random.shuffle(training_data) # random.shuffle 作用是随机打乱列表中元素的顺序
            mini_batches = [training_data[k:k+mini_batch_size] for k in range(0, n, mini_batch_size)] # 每 mini_batch_size 个样本为一批数据
            for mini_batch in mini_batches:
                self.update_mini_batch(mini_batch, eta) # 使用这样一批数据更新参数(权重和偏置)
            if test_data:
                print("Epoch {} : {} / {}".format(j,self.evaluate(test_data),n_test))
            else:
                print("Epoch {} complete".format(j))

    def update_mini_batch(self, mini_batch, eta):
        nabla_b = [np.zeros(b.shape) for b in self.biases] # 初始化权重和偏置
        nabla_w = [np.zeros(w.shape) for w in self.weights]
        for x, y in mini_batch:
            delta_nabla_b, delta_nabla_w = self.backprop(x, y) # 反向传播算法
            nabla_b = [nb+dnb for nb, dnb in zip(nabla_b, delta_nabla_b)]
            nabla_w = [nw+dnw for nw, dnw in zip(nabla_w, delta_nabla_w)]
        self.weights = [w-(eta/len(mini_batch))*nw for w, nw in zip(self.weights, nabla_w)] # 更新权重和偏置
        self.biases = [b-(eta/len(mini_batch))*nb for b, nb in zip(self.biases, nabla_b)]

    def backprop(self, x, y):
        nabla_b = [np.zeros(b.shape) for b in self.biases] # 初始化权重和偏置
        nabla_w = [np.zeros(w.shape) for w in self.weights]
        # 前向传播
        activation = x # x 表示输入值
        activations = [x] # 用列表储存 x 的值
        zs = [] # z 表示未被激活的加权值, 并用列表 zs 储存
        for b, w in zip(self.biases, self.weights):
            z = np.dot(w, activation)+b # 计算隐藏层每个神经元处的输入值
            zs.append(z) # 用列表 zs 储存
            activation = sigmoid(z) # 激活 z, 并将其储存在列表 activations 中
            activations.append(activation)
        # 反向传播
        # 下面三个方程是反向传播的基本方程, 用于计算误差, 权重和偏置
        delta = self.cost_derivative(activations[-1], y) * sigmoid_prime(zs[-1]) # 这里计算的是输出层处反向传播的各个参数
        nabla_b[-1] = delta
        nabla_w[-1] = np.dot(delta, activations[-2].transpose())
        for l in range(2, self.num_layers): # 反向传播, 遍历前面的 layers
            z = zs[-l]
            sp = sigmoid_prime(z)
            delta = np.dot(self.weights[-l+1].transpose(), delta) * sp # 反向传播的基本方程, 建立了相邻层误差的联系
            nabla_b[-l] = delta
            nabla_w[-l] = np.dot(delta, activations[-l-1].transpose())
        return (nabla_b, nabla_w)

    def evaluate(self, test_data):
        # 这里使用了 np.argmax() 函数来找到具有最高概率的预测结果的类别标签
        # 然后将预测结果与实际标签 y 进行比较, 形成由 (预测结果, 实际标签) 组成的元组列表 test_results
        # 最后统计预测结果与实际标签相同的数量, 并将其作为函数的返回值
        test_results = [(np.argmax(self.feedforward(x)), y) for (x, y) in test_data]
        return sum(int(x == y) for (x, y) in test_results)

    def cost_derivative(self, output_activations, y): # 定义代价函数的导数
        return (output_activations-y)


def sigmoid(z): # 定义激活函数
    return 1.0/(1.0+np.exp(-z))

def sigmoid_prime(z): # 定义激活函数的导数
    return sigmoid(z)*(1-sigmoid(z))

## 识别手写数字示例
import mnist_loader # 这里使用了 mnist_loader 用于输入数据, 在此把它视作黑盒即可
training_data, validation_data, test_data = mnist_loader.load_data_wrapper()
training_data = list(training_data)
net = Network([784, 30, 10]) # 这里使用一个浅层神经网络进行训练, 三个数分别对应输入层, 隐藏层, 输出层的神经元数量
net.SGD(training_data, 30, 10, 3.0, test_data=test_data)

  • 15
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
深度学习是一种机器学习方法,其基本思想是通过对数据进行分层抽象和学习,建立多层神经网络模型,实现对数据的高效分类、识别和预测。而反向传播算法深度学习中用于训练神经网络的一种有效方法。下面是反向传播算法Python 代码示例: ```python # 反向传播算法Python 代码示例 import numpy as np # 定义sigmoid函数 def sigmoid(x): return 1 / (1 + np.exp(-x)) # 定义神经网络的前向传播函数 def forward(X, W1, b1, W2, b2): z1 = np.dot(X, W1) + b1 a1 = sigmoid(z1) z2 = np.dot(a1, W2) + b2 y_hat = sigmoid(z2) return y_hat, z1, a1, z2 # 定义损失函数 def loss(y, y_hat): L = -y * np.log(y_hat) - (1 - y) * np.log(1 - y_hat) return L # 定义反向传播函数 def backward(X, y, y_hat, z1, a1, z2, W2): delta2 = (y_hat - y) * y_hat * (1 - y_hat) dW2 = np.dot(a1.T, delta2) db2 = np.sum(delta2, axis=0) delta1 = np.dot(delta2, W2.T) * a1 * (1 - a1) dW1 = np.dot(X.T, delta1) db1 = np.sum(delta1, axis=0) return dW1, db1, dW2, db2 # 训练神经网络 def train(X, y, hidden_size, epochs, lr): input_size = X.shape output_size = y.shape # 随机初始化权重和偏置 W1 = np.random.randn(input_size, hidden_size) b1 = np.zeros((1, hidden_size)) W2 = np.random.randn(hidden_size, output_size) b2 = np.zeros((1, output_size)) # 迭代训练神经网络 for i in range(epochs): # 前向传播计算输出和损失 y_hat, z1, a1, z2 = forward(X, W1, b1, W2, b2) L = loss(y, y_hat) # 反向传播计算梯度 dW1, db1, dW2, db2 = backward(X, y, y_hat, z1, a1, z2, W2) # 更新权重和偏置 W1 -= lr * dW1 b1 -= lr * db1 W2 -= lr * dW2 b2 -= lr * db2 # 每迭代10次输出一次损失 if i % 10 == 0: print("Epoch %d Loss %.4f" % (i, np.mean(L))) return W1, b1, W2, b2 # 测试模型 X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]]) y = np.array([, , , ]) hidden_size = 4 epochs = 1000 lr = 0.5 W1, b1, W2, b2 = train(X, y, hidden_size, epochs, lr) y_hat_test = forward(X, W1, b1, W2, b2) print("Final Prediction") print(y_hat_test) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值