我们来说一下步骤:

初始化网络参数

前向传播

2.1 计算一层的中线性求和的部分

2.2 计算激活函数的部分(ReLU使用L-1次,Sigmod使用1次)

2.3 结合线性求和与激活函数

计算误差

反向传播

4.1 线性部分的反向传播公式

4.2 激活函数部分的反向传播公式

4.3 结合线性部分与激活函数的反向传播公式

更新参数

  请注意,对于每个前向函数,都有一个相应的后向函数。 这就是为什么在我们的转发模块的每一步都会在cache中存储一些值,cache的值对计算梯度很有用, 在反向传播模块中,我们将使用cache来计算梯度。 现在我们正式开始分别构建两层神经网络和多层神经网络。

本文会提到**[LINEAR-> ACTIVATION]转发函数,比如我有一个多层的神经网络,结构是输入层->隐藏层->隐藏层->···->隐藏层->输出层**,在每一层中,我会首先计算Z = np.dot(W,A) + b,这叫做【linear_forward】线性部分,然后再计算A = relu(Z) 或者 A = sigmoid(Z),这叫做【linear_activation_forward】激活部分,合并起来就是这一层的计算方法,所以每一层的计算都有两个步骤,先是计算Z,再计算A

 

具体步骤 :

一.初始化参数:

二.前向传播函数:

 cache - 一个包含“linear_cache”和“activation_cache”的字典,我们需要存储它以有效地计算后向传递

线性部分【LINEAR】

参数 linear_forward(A,W,b)

 返回Z,cache = (A,W,b)

线性激活部分【LINEAR - >ACTIVATION】

参数linear_activation_forward(A_prev,W,b,activation):A_prev - 来自上一层(或输入层)的激活,维度为(上一层的节点数量,示例数)activation - 选择在此层中使用的激活函数名,字符串类型,【"sigmoid" | "relu"】

返回 A,cache = (linear_cache,activation_cache) 其中  1.inear_cache = linear_forward(A_prev, W, b) 中的cache(AWB)   2.activation_cache = relu(Z)/sigmoid(Z

多层模型的前向传播计算模型

def L_model_forward(X,parameters):

    parameters - initialize_parameters_deep()的输出


返回:
    AL - 最后的激活值
    caches - 包含以下内容的缓存列表:
    linear_relu_forward()的每个cache(有L-1个,索引为从0到L-2)
    linear_sigmoid_forward()的cache(只有一个,索引为L-1)

三.计算成本

def compute_cost(AL,Y):

返回cost = -np.sum(np.multiply(np.log(AL),Y) + np.multiply(np.log(1 - AL), 1 - Y)) / m 交叉熵成本

 

 

 

四 .反向传播:

同正向传播,也分线性和激活两部分

线性部分【LINEAR backward】

def linear_backward(dZ,cache)

    dZ - 相对于(当前第l层的)线性输出的成本梯度  

    cache - 来自当前层前向传播的值的元组(A_prev,W,b)

返回:

    dA_prev - 相对于激活(前一层l-1)的成本梯度,与A_prev维度相同

    dW - 相对于W(当前层l)的成本梯度,与W的维度相同

    db - 相对于b(当前层l)的成本梯度,与b维度相同

相当于接收一个cash,返回一个dA[L-1] dw db用来进行梯度下降

 

线性激活部分【LINEAR -> ACTIVATION backward】

两种反向激活函数在别处实现

 def linear_activation_backward(dA,cache,activation="relu"):

参数:
    dA - 当前层l的激活后的梯度值
    cache - 我们存储的用于有效计算反向传播的值的元组(值为linear_cache,activation_cache)
    activation - 要在此层中使用的激活函数名,字符串类型,【"sigmoid" | "relu"】
返回:
    dA_prev - 相对于激活(前一层l-1)的成本梯度值,与A_prev维度相同
    dW - 相对于W(当前层l)的成本梯度值,与W的维度相同
    db - 相对于b(当前层l)的成本梯度值,与b的维度相同

而这一部分则是计算dz(既 所谓激活层 其实就是说在正向计算从z到A,而反向计算从dA到dZ)

 

 

dAL = - (np.divide(Y, AL) - np.divide(1 - Y, 1 - AL))

构建多层模型反向传播:

def L_model_backward(AL,Y,caches):                          对[LINEAR-> RELU] *(L-1) - > LINEAR - > SIGMOID组执行反向传播,就是多层网络的向后传播

参数:
    AL - 概率向量,正向传播的输出(L_model_forward())
    Y - 标签向量(例如:如果不是猫,则为0,如果是猫则为1),维度为(1,数量)
    caches - 包含以下内容的cache列表:
        linear_activation_forward("relu")的cache,不包含输出层 这里头装的是
        linear_activation_forward("sigmoid")的cache
返回:
    grads - 具有梯度值的字典
    grads [“dA”+ str(l)] = ...
    grads [“dW”+ str(l)] = ...
    grads [“db”+ str(l)] = ...

更新参数

 

def update_parameters(parameters, grads, learning_rate):
"""
使用梯度下降更新参数

参数:
    parameters - 包含你的参数的字典
    grads - 包含梯度值的字典,是L_model_backward的输出

返回:
parameters - 包含更新参数的字典
    参数[“W”+ str(l)] = ...
    参数[“b”+ str(l)] = ...

正式搭建

 

 

 

两层神经网络:

def two_layer_model(X,Y,layers_dims,learning_rate=0.0075,num_iterations=3000,print_cost=False,isPlot=True):

参数:
    X - 输入的数据,维度为(n_x,例子数)
    Y - 标签,向量,0为非猫,1为猫,维度为(1,数量)
    layers_dims - 层数的向量,维度为(n_y,n_h,n_y)
    learning_rate - 学习率
    num_iterations - 迭代的次数
    print_cost - 是否打印成本值,每100次打印一次
    isPlot - 是否绘制出误差值的图谱
返回:
    parameters - 一个包含W1,b1,W2,b2的字典变量
(n_x,n_h,n_y) = layers_dims

parameters = initialize_parameters(n_x, n_h, n_y) 初始化参数

for i in range(0,num_iterations): 迭代多少次在这决定

 

#前向传播

A1, cache1 = linear_activation_forward(X, W1, b1, "relu")

A2, cache2 = linear_activation_forward(A1, W2, b2, "sigmoid")

#计算成本

#后向传播

##初始化后向传播

dA2 = - (np.divide(Y, A2) - np.divide(1 - Y, 1 - A2))

##向后传播,输入:“dA2,cache2,cache1”。 输出:“dA1,dW2,db2;还有dA0(未使用),dW1,db1”。

##向后传播完成后的数据保存到grads

#更新参数

#打印成本值,如果print_cost=False则忽略

#迭代完成,根据条件绘制图

#返回parameters

 

 

经网络

都整完了 可以编预测函数啊


先略过 因为和多重一样,直接用多重当例子

def L_layer_model(X, Y, layers_dims, learning_rate=0.0075, num_iterations=3000, print_cost=False,isPlot=True):
    """
    实现一个L层神经网络:[LINEAR-> RELU] *(L-1) - > LINEAR-> SIGMOID。
    
    参数:
        X - 输入的数据,维度为(n_x,例子数)
        Y - 标签,向量,0为非猫,1为猫,维度为(1,数量)
        layers_dims - 层数的向量,维度为(n_y,n_h,···,n_h,n_y)
        learning_rate - 学习率
        num_iterations - 迭代的次数
        print_cost - 是否打印成本值,每100次打印一次
        isPlot - 是否绘制出误差值的图谱
    
    返回:
     parameters - 模型学习的参数。 然后他们可以用来预测。
    """
    np.random.seed(1)
    costs = []
    
    parameters = initialize_parameters_deep(layers_dims)
    
    for i in range(0,num_iterations):
        AL , caches = L_model_forward(X,parameters)
        前进
        cost = compute_cost(AL,Y)
        代价函数计算
        grads = L_model_backward(AL,Y,caches)
        反向传播计算梯度
        parameters = update_parameters(parameters,grads,learning_rate)
        更新各项参数 
        #打印成本值,如果print_cost=False则忽略
        if i % 100 == 0:
            #记录成本
            costs.append(cost)
            #是否打印成本值
            if print_cost:
                print("", i ,"次迭代,成本值为:" ,np.squeeze(cost))
    #迭代完成,根据条件绘制图
    if isPlot:
        plt.plot(np.squeeze(costs))
        plt.ylabel('cost')
        plt.xlabel('iterations (per tens)')
        plt.title("Learning rate =" + str(learning_rate))
        plt.show()
    return parameters

图像数据集的处理:

train_set_x_orig , train_set_y , test_set_x_orig , test_set_y , classes = lr_utils.load_dataset()

train_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0], -1).T 
test_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0], -1).T

train_x = train_x_flatten / 255
train_y = train_set_y
test_x = test_x_flatten / 255
test_y = test_set_y

预测函数

def predict(X, y, parameters):
    """
    该函数用于预测L层神经网络的结果,当然也包含两层
    
    参数:
     X - 测试集
     y - 标签
     parameters - 训练模型的参数
    
    返回:
     p - 给定数据集X的预测
    """
    
    m = X.shape[1]
    n = len(parameters) // 2 # 神经网络的层数
    p = np.zeros((1,m))
    
    #根据参数前向传播
    probas, caches = L_model_forward(X, parameters)
    
    for i in range(0, probas.shape[1]):
        if probas[0,i] > 0.5:
            p[0,i] = 1
        else:
            p[0,i] = 0
    
    print("准确度为: "  + str(float(np.sum((p == y))/m)))
        
    return p

训练加预测

#训练
layers_dims = [12288, 20, 7, 5, 1] #  5-layer model
parameters = L_layer_model(train_x, train_y, layers_dims, num_iterations = 2500, print_cost = True,isPlot=True)
#预测
pred_train = predict(train_x, train_y, parameters) #训练集
pred_test = predict(test_x, test_y, parameters) #测试集

分析

可以用来查看到底哪些数据被判定错了

def print_mislabeled_images(classes, X, y, p):
    """
    绘制预测和实际不同的图像。
        X - 数据集
        y - 实际的标签
        p - 预测
    """
    a = p + y#由数学基础得,只有实际与预测不符的时候,a==1
    mislabeled_indices = np.asarray(np.where(a == 1))
        #np.where(condition, x, y)
        #满足条件(condition),输出x,不满足输出y。
        #只有条件 (condition),没有x和y,则输出满足条件 (即非0) 元素的坐标 (等价于 
        #numpy.nonzero)。这里的坐标以tuple的形式给出,通常原数组有多少维,输出 
        #的tuple中就包含几个数组,分别对应符合条件元素的各维坐标。
    plt.rcParams['figure.figsize'] = (40.0, 40.0) # set default size of plots
    num_images = len(mislabeled_indices[0])
    for i in range(num_images):
        index = mislabeled_indices[1][i]
        
        plt.subplot(2, num_images, i + 1)
        plt.imshow(X[:,index].reshape(64,64,3), interpolation='nearest')
        plt.axis('off')
        plt.title("Prediction: " + classes[int(p[0,index])].decode("utf-8") + " \n Class: " + classes[y[0,index]].decode("utf-8"))


print_mislabeled_images(classes, test_x, test_y, pred_test)

plt.rcParams[]

 pylot使用rc配置文件来自定义图形的各种默认属性,称之为rc配置或rc参数。通过rc参数可以修改默认的属性,

包括窗体大小、每英寸的点数、线条宽度、颜色、样式、坐标轴、坐标和网络属性、文本、字体等。

 

 

 

 

 

posted on 2020-03-08 16:36  路途陌客  阅读(498)  评论(0)    收藏  举报