反向传播算法(代码笔记)

import numpy as np
#反向传播算法定义损失函数和激活函数

def loss(network_y, real_y):
    '''
    返回函数的编导,损失函数使用 MSE
    L = 1/2 (netowork_y - real_y)^2
    delta_L = network_y - real_y
    损失函数使用了均方误差作为该神经网络的损失函数,因此求导后的输入分别为网络的预测值和真实输出值,
    输出为两者的差。激活函数采用 Sigmoid 函数
    '''
    return (network_y - real_y)
def sigmoid(z):
    """
    激活函数使用 sigmoid
    :param z:
    :return:
    """
    return 1.0 / (1.0 + np.exp(-z))

def sigmoid_der(z):
    """digmoid 函数的导数 dervation of sigmoid"""
    return sigmoid(z) * (1 - sigmoid(z))

#反向传播算法的具体实现
"""backprop() 函数的输入为 x 和 y ,其中x 为(3,1)的矩阵, y 为(2,1)的矩阵。
根据反向传播算法的四个基本公式(BP1 —BP4)的计算中需要知道每一层的神经元的激活值和加权输入值,因此在进行向前椽传播时,
使用activation 记录每一层的激活值和 zs 记录每一层的加权输入值
首先从L 层进行计算,因此先计算输出层的误差,然后计算损失函数关于输出层L 中的偏置和权值参数的偏导。
最后循环为range(2,num_laylwes), 意思时从网络的倒数第二层开始,往前计算第 l 层的损失值
以及损失函数关于第 l 层的偏置和权值的偏导。最后输出一次反向传播后, 得到关于损失函数的所有参数的偏导
"""
def backprop(x, y):
    """反向传播算法的实现"""
    """初始化网网络参数的导数,权值 w  的偏导和偏置 b 的偏导"""
    delta_w = [np.zeros(w.shape) for w  in weights]
    delta_b = [np.zeros(b.shape) for b in biases]
    """向前传播 feed forward"""
    activation = x # 把输入的数据作为第一次激活值
    activations = [x] #存储网络的激活值
    zs = []     #存储网络的加权输入值 ( z = wx +b)
    for w,b in zip(weights, biases):
        z = np.dot(w, activation) + b
        activation = sigmoid(z)
        activations.append(activation)
        zs.append(z)

    """反向传播 back propagation"""
    #BP1 计算输出层误差

    delta_L = loss(activation[-1], y)*sigmoid_der(zs[-1])
    #BP3 损失函数在输出层关于偏置的偏导
    delta_b[-1] = delta_L
    #BP4 损失函数在输出层关于权值的偏导

    delta_w[-1] = np.dot(delta_L, activations [-2].transpose())

    delta_l = delta_L
    for l in range(2, num_layers):
        # BP2 计算第1层误差
        z = zs [-1]
        sp = sigmoid_der(z)
        delta_l = np.dot(weights[-l + 1].transpose(), delta_l) *sp
        # BP3 损失函数在 l 层关于偏置的偏导
        delta_b[-1] = delta_l
        # BP4 损失函数 在 l 层关于权值的偏导
        delta_w[-1] = np.dot(delta_l, activations[-l-1].transpose())
    return (delta_w, delta_b)
""" 定义神经网络的模型架构[ input , hidden, output ] 
根据网络模型的大小,利用高斯分布函数的权值参数 weights 和 偏置参数 biases 产生 均值为 0 , 方差为1 
的随机值。

"""
network_sizes = [3, 4, 2]
#初始化该神经网络的参数
sizes = network_sizes
num_layers = len (sizes)
biases = [np.random.randn(h, 1) for h in sizes[1:]]
weights = [np.random.randn(y, x) for y, x in zip(sizes[:-1], sizes[1:])]

# 产生训练的数据

training_x = np.random.rand(3).reshape(3, 1)
training_y = np.array([0, 1]).reshape(2, 1)
print("training data x :{},training data y :{}".format(training_x,training_y))
backprop(training_x, training_y)

 

你可能感兴趣的:(学习笔记)