BP 算法
基本思想: 学习过程由信号的正向传播和误差的反向传播两个过程组成 (这一步体现在 propagate() 函数)
数学工具: 微积分的链式求导法则 (这一步体现在 propagate() 函数中第 34 行)
求解最小化成本函数 (cost function): 梯度下降法(这一步体现在 optimize() 函数)
说明
实现功能: 这段代码主要实现的功能是判断一张图片是否有 cat, 实现的是二分类, 有就为 1, 没有就为 0
训练方法: BP 网络, 此代码很简单, 只有一个神经元, 故权值 w 是一维 (这一步体现在 initialiize_with_zeros() 中第 21 行)
难点说明: 第 34 行: dw = (1./m)*np.dot(X,((A-Y).T)) 此处的 dw 是指(dL/dw), 即损失函数对权值 w 的导数, 此公式是由微积分的链式求导法则推导出来的, 吴恩达视频里有, 不清楚的请看视频(2.9 logistic 回归中的梯度下降法), 这里如果理解了, 整个代码也没啥难度了
注意
1. 损失函数和代价函数的区别:
损失函数(Loss function): 指单个训练样本进行预测的结果与实际结果的误差
代价函数 (Cost function): 整个训练集, 所有样本误差总和(所有损失函数总和) 的平均值 (这一步体现在 propagate() 函数中的第 32 行)
- #!/usr/bin/env python3
- # -*- coding: utf-8
- import numpy as np
- import matplotlib.pyplot as plt
- import h5py
- import scipy
- from PIL import Image
- from scipy import ndimage
- from lr_utils import load_dataset
- import pylab
- #sigmoid 函数
- def sigmoid(z):
- s = 1./(1+np.exp(-z))
- return(s)
- #初始化权值阈值
- def initialiize_with_zeros(dim):
- #这里只有一个神经元, w 是一维的
- w = np.zeros(shape = (dim,1), dtype = np.float32)
- b = 0
- #断言函数, 判断是否为真
- assert(w.shape == (dim,1))
- assert(isinstance(b,float) or isinstance(b,int))
- return(w,b)
- def propagate(w,b,X,Y):
- m = X.shape[1]
- #forward propagation
- A = sigmoid(np.dot(w.T,X) + b)
- cost = (-1./m)*np.sum(Y*np.log(A) + (1-Y)*np.log(1-A),axis = 1)# 按行相加
- #backward propagation
- dw = (1./m)*np.dot(X,((A-Y).T))#dw 就是损失函数对 w 的求导
- db = (1./m)*np.sum(A-Y, axis=1)#axis=0 按列相加, axis=1 按行相加
- assert(dw.shape == w.shape)
- assert(db.dtype == float)
- cost = np.squeeze(cost)#squeeze 函数的作用是去掉维度为 1 的维, 在这就是将一个一维变成一个数字
- # [ 6.00006477]
- # 6.000064773192205
- assert(cost.shape == ())
- grads = {"dw": dw,
- "db": db}
- return grads, cost
- def optimize(w,b,X,Y,num_iterations,learning_rate,print_cost = False):
- costs = []
- for i in range(num_iterations):
- grads, cost = propagate(w=w, b=b, X=X, Y=Y)
- dw = grads["dw"]
- db = grads["db"]
- w = w - learning_rate*dw
- b = b - learning_rate*db
- if i % 100 == 0:
- costs.append(cost)
- if print_cost and i % 100 == 0:# 这句没懂
- print ("Cost after iteration %i: %f" %(i, cost))
- params = {"w": w,
- "b": b}
- grads = {"dw": dw,
- "db": db}
- return params, grads, costs
- def predict(w, b, X):
- m = X.shape[1]
- Y_prediction = np.zeros((1,m))
- w = w.reshape(X.shape[0], 1)
- A = sigmoid(np.dot(w.T, X) + b)
- # [print(x) for x in A]这句没懂, 但对代码没啥影响
- for i in range(A.shape[1]):
- if A[0, i]>= 0.5:
- Y_prediction[0, i] = 1
- else:
- Y_prediction[0, i] = 0
- assert(Y_prediction.shape == (1, m))
- return Y_prediction
- def model(X_train, Y_train, X_test, Y_test, num_iterations = 2000, learning_rate = 0.5, print_cost = False):
- #初始化权值阈值
- w, b = initialiize_with_zeros(X_train.shape[0])
- #梯度下降法寻优获取最佳权值阈值
- parameters, grads, costs = optimize(w, b, X_train, Y_train, num_iterations, learning_rate, print_cost)
- w = parameters["w"]
- b = parameters["b"]
- #测试集进行预测
- Y_prediction_test = predict(w, b, X_test)
- Y_prediction_train = predict(w, b, X_train)
- #输出正确率
- print("train accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100))
- print("test accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100))
- #将所有结果以字典形式保存并返回
- d = {"costs": costs,
- "Y_prediction_test": Y_prediction_test,
- "Y_prediction_train" : Y_prediction_train,
- "w" : w,
- "b" : b,
- "learning_rate" : learning_rate,
- "num_iterations": num_iterations}
- return d
主程序从这里开始
- #获取训练数据, 测试数据
- train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()
- #reshape()方法来更改数组的形状, train_set_x_orig.shape[0]是行数,-1 是代表列数未知, 需要 numpy 自动计算出列数
- #这里的列数: 就是一张图片 64*64*3 数据变成一行数据的个数
- train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0], -1).T
- test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0], -1).T
- #归一, 颜色的数值是 0~255
- train_set_x = train_set_x_flatten/255.
- test_set_x = test_set_x_flatten/255.
- #训练模型
- d = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 2000, learning_rate = 0.005, print_cost = True)
- print(d)
- #!/usr/bin/env python3
- # -*- coding: utf-8
- import numpy as np
- import matplotlib.pyplot as plt
- import h5py
- import scipy
- from PIL import Image
- from scipy import ndimage
- from lr_utils import load_dataset
- import pylab
- #sigmoid 函数
- def sigmoid(z):
- s = 1./(1+np.exp(-z))
- return(s)
- # 初始化权值阈值
- def initialiize_with_zeros(dim):
- #这里只有一个神经元, w 是一维的
- w = np.zeros(shape = (dim,1), dtype = np.float32)
- b = 0
- #断言函数, 判断是否为真
- assert(w.shape == (dim,1))
- assert(isinstance(b,float) or isinstance(b,int))
- return(w,b)
- def propagate(w,b,X,Y):
- m = X.shape[1]
- #forward propagation
- A = sigmoid(np.dot(w.T,X) + b)
- cost = (-1./m)*np.sum(Y*np.log(A) + (1-Y)*np.log(1-A),axis = 1)# 按行相加
- #backward propagation
- dw = (1./m)*np.dot(X,((A-Y).T))#dw 就是损失函数对 w 的求导
- db = (1./m)*np.sum(A-Y, axis=1)#axis=0 按列相加, axis=1 按行相加
- assert(dw.shape == w.shape)
- assert(db.dtype == float)
- cost = np.squeeze(cost)#????squeeze 函数的作用是去掉维度为 1 的维, 在这就是将一个一维变成一个数字
- # [ 6.00006477]
- # 6.000064773192205
- assert(cost.shape == ())
- grads = {"dw": dw,
- "db": db}
- return grads, cost
- def optimize(w,b,X,Y,num_iterations,learning_rate,print_cost = False):
- costs = []
- for i in range(num_iterations):
- grads, cost = propagate(w=w, b=b, X=X, Y=Y)
- dw = grads["dw"]
- db = grads["db"]
- w = w - learning_rate*dw
- b = b - learning_rate*db
- if i % 100 == 0:
- costs.append(cost)
- if print_cost and i % 100 == 0:# 这句没懂
- print ("Cost after iteration %i: %f" %(i, cost))
- params = {"w": w,
- "b": b}
- grads = {"dw": dw,
- "db": db}
- return params, grads, costs
- def predict(w, b, X):
- m = X.shape[1]
- Y_prediction = np.zeros((1,m))
- w = w.reshape(X.shape[0], 1)
- A = sigmoid(np.dot(w.T, X) + b)
- # [print(x) for x in A]
- for i in range(A.shape[1]):
- # Convert probabilities A[0,i] to actual predictions p[0,i]
- ### START CODE HERE ### ( 4 lines of code)
- if A[0, i]>= 0.5:
- Y_prediction[0, i] = 1
- else:
- Y_prediction[0, i] = 0
- ### END CODE HERE ###
- assert(Y_prediction.shape == (1, m))
- return Y_prediction
- def model(X_train, Y_train, X_test, Y_test, num_iterations = 2000, learning_rate = 0.5, print_cost = False):
- #初始化权值阈值
- w, b = initialiize_with_zeros(X_train.shape[0])
- #梯度下降法寻优获取最佳权值阈值
- parameters, grads, costs = optimize(w, b, X_train, Y_train, num_iterations, learning_rate, print_cost)
- w = parameters["w"]
- b = parameters["b"]
- #测试集进行预测
- Y_prediction_test = predict(w, b, X_test)
- Y_prediction_train = predict(w, b, X_train)
- #输出正确率
- print("train accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100))
- print("test accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100))
- #将所有结果以字典形式保存并返回
- d = {"costs": costs,
- "Y_prediction_test": Y_prediction_test,
- "Y_prediction_train" : Y_prediction_train,
- "w" : w,
- "b" : b,
- "learning_rate" : learning_rate,
- "num_iterations": num_iterations}
- return d
主程序从这里开始
- # 获取训练数据, 测试数据
- train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()
- #reshape()方法来更改数组的形状, train_set_x_orig.shape[0]是行数,-1 是代表列数未知, 需要 numpy 自动计算出列数
- # 这里的列数: 就是一张图片 64*64*3 数据变成一行数据的个数
- train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0], -1).T
- test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0], -1).T
- # 归一, 颜色的数值是 0~255
- train_set_x = train_set_x_flatten/255.
- test_set_x = test_set_x_flatten/255.
- # 训练模型
- d = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 2000, learning_rate = 0.005, print_cost = True)
- print(d)
来源: http://www.bubuko.com/infodetail-2546787.html