编程实践-Week2
这是整个深度学习课程1的第一个编程作业,这次编程的目的是设计实现Logistic Regression并对猫的图片进行分类。在第一次的编程过程中,提升了许多我对Numpy,包括Python的理解。下面是学习中的一些误区和心得。
整个深度学习框架中用到python包如下:
import numpy as np # numpy是一个科学计算包
import matplotlib.pyplot as plt import h5py # h5py是一个用于与存储在H5文件中的数据集进行交互的包
import scipy
from PIL import Image from scipy import ndimage from lr_utils import load_dataset # 数据集 %matplotlib inline # Notebook的魔法命令。意思是将那些用matplotlib绘制的图显示在页面里而不是弹出一个窗口
在学习的最开始,我们有如下训练集:
(1) m_train个带标签(猫=0,不是猫=1)的训练集。
(2) m_test个带标签的测试集。
(3) 每张图片的大小为(height, width, 3),其中3表示RGB三色通道。
通过X.shape函数,我们可以获得m_train,m_test,height和width。
m_train = train_set_x_orig.shape[0] m_test = test_set_x_orig.shape[0] num_px = train_set_x_orig.shape[2]
为了方便数据的处理,我们应将图片大小(height, width, 3)转换为(height * width * 3, 1)。
使用reshape函数来重新构造数组,这里可以使用一个trick:如果我们打算将矩阵X(a,b,c,d)变为矩阵X_f (b * c * d, ),可以使用如下函数:
X_f = X.reshape(X.shape[0] ,-1). T
# Reshape the training and test examples 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
train_set_x = train_set_x_flatten/255.
test_set_x = test_set_x_flatten/255.
同时上述代码对数据进行了标准化(Standardize)的处理,因为RGB最大像素值为255,因此可以将输入像素映射到[0,1]上。
一个普通的逻辑回归过程如图所示:

对于每个样本xi,前向传播计算的公式为:

同样的,计算损失函数的公式为:
![]()
在我们设计神经网络时,整个的思路可以分为以下3步:
1. 定义网络中的超参数(层数,隐藏单元数等)
2. 初始化模型中的参数
3. 循环以下操作
(1) 计算损失函数(前向传播)
(2) 计算梯度(反向传播)
(3) 梯度下降
首先使用 Numpy实现最基本的sigmoid函数,
def sigmoid(z): """ Compute the sigmoid of z Arguments: z -- A numpy array. Return: s -- sigmoid(z) """ s = 1.0/( 1+ np.exp(-z)) #使用np.exe(a) 可以实现矩阵的指数运算 return s sigmoid(np.array([0,2]))
接下来初始化模型中的参数,使用np.zeros(a, b)来初始化W,b。
def initialize_with_zeros(dim): """ This function creates a vector of zeros of shape (dim, 1) for w and initializes b to 0. Argument: dim -- size of the w vector we want (or number of parameters in this case) Returns: w -- initialized vector of shape (dim, 1) b -- initialized scalar (corresponds to the bias) """ w=np.zeros((dim,1),dtype=float) #注意函数中的dtype b=0 assert(w.shape == (dim, 1)) assert(isinstance(b, float) or isinstance(b, int)) return w, b dim = 2 w, b = initialize_with_zeros(dim)
初始化参数后,我们可以执行神经网络中的前向传播算法方程,

反向传播方程:

(注意:在反向传播中,理解在下一步梯度下降的意义:寻找最小的参数W,b使得cost函数J得到最小值(如图所示))

(为什么梯度下降算法 A = A - learning_rate * dA 是有效的梯度下降算法? )

如图所示,在我们仅考虑一个参数的影响(如W)时,随机选取一个初始点,如左边箭头所指向的A点,A点处 dW < 0,因此更新后的W = W - learning_rate *dW会使得W增大,即往最低点的方向靠近,右边箭头所指的B点同理,在B点 dW>0,因此更新后W会减小,同样向最低点靠近。·
回到逻辑回归中的正向传播和反向传播具体实现如下:
def propagate(w, b, X, Y): """ Implement the cost function and its gradient for the propagation explained above Arguments: w -- weights, a numpy array of size (num_px * num_px * 3, 1) b -- bias, a scalar X -- data of size (num_px * num_px * 3, number of examples) Y -- true "label" vector (containing 0 if non-cat, 1 if cat) of size (1, number of examples) Return: cost -- negative log-likelihood cost for logistic regression dw -- gradient of the loss with respect to w, thus same shape as w db -- gradient of the loss with respect to b, thus same shape as b Tips: - Write your code step by step for the propagation. np.log(), np.dot() """ m = X.shape[1] # FORWARD PROPAGATION (FROM X TO COST) A = sigmoid(np.dot((w.T),X) + b) # compute activation cost = (-1/m)*np.sum((np.multiply(Y,np.log(A)))+ np.multiply((1-(Y)),np.log(1-A))) # compute cost # BACKWARD PROPAGATION (TO FIND GRAD) dw = np.dot(X,(A - Y).T)/m db = (np.sum(A - Y))/m assert(dw.shape == w.shape) assert(db.dtype == float) cost = np.squeeze(cost) assert(cost.shape == ()) grads = {"dw": dw, "db": db} return grads, cost w, b, X, Y = np.array([[1],[2]]), 2, np.array([[1,2],[3,4]]), np.array([[1,0]]) grads, cost = propagate(w, b, X, Y)
梯度下降的代码如下:
def optimize(w, b, X, Y, num_iterations, learning_rate, print_cost = False): """ This function optimizes w and b by running a gradient descent algorithm Arguments: w -- weights, a numpy array of size (num_px * num_px * 3, 1) b -- bias, a scalar X -- data of shape (num_px * num_px * 3, number of examples) Y -- true "label" vector (containing 0 if non-cat, 1 if cat), of shape (1, number of examples) num_iterations -- number of iterations of the optimization loop learning_rate -- learning rate of the gradient descent update rule print_cost -- True to print the loss every 100 steps Returns: params -- dictionary containing the weights w and bias b grads -- dictionary containing the gradients of the weights and bias with respect to the cost function costs -- list of all the costs computed during the optimization, this will be used to plot the learning curve. Tips: You basically need to write down two steps and iterate through them: 1) Calculate the cost and the gradient for the current parameters. Use propagate(). 2) Update the parameters using gradient descent rule for w and b. """ costs = [] for i in range(num_iterations): # Cost and gradient calculation grads, cost = propagate(w, b, X, Y) # Retrieve derivatives from grads dw = grads["dw"] db = grads["db"] # update rule w = w-learning_rate*dw b = b-learning_rate*db # Record the costs if i % 100 == 0: costs.append(cost) # Print the cost every 100 training examples 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 params, grads, costs = optimize(w, b, X, Y, num_iterations= 100, learning_rate = 0.009, print_cost = False)
再次回顾整个神经网络的方法过程,从设计神经网络的超参数,到执行前向传播和反向传播,再进行梯度下降的更新。在执行完所有的以上过程后,就可以将数据输入训练好的模型中进行预测:
def predict(w, b, X): ''' Predict whether the label is 0 or 1 using learned logistic regression parameters (w, b) Arguments: w -- weights, a numpy array of size (num_px * num_px * 3, 1) b -- bias, a scalar X -- data of size (num_px * num_px * 3, number of examples) Returns: Y_prediction -- a numpy array (vector) containing all predictions (0/1) for the examples in X ''' m = X.shape[1] Y_prediction = np.zeros((1,m)) w = w.reshape(X.shape[0], 1) # Compute vector "A" predicting the probabilities of a cat being present in the picture A = sigmoid(np.dot((w.T),X) + b) for i in range(A.shape[1]): # Convert probabilities A[0,i] to actual predictions p[0,i] Y_prediction[0,i] = A[0,i]>0.5 #判断大小这一行代码就够了 assert(Y_prediction.shape == (1, m)) return Y_prediction predict(w, b, X)
到此,我们已经完成了整个逻辑回归网络中所有小模块的设计,下一步是将这些小模块整合起来,形成完整的代码:
def model(X_train, Y_train, X_test, Y_test, num_iterations = 2000, learning_rate = 0.5, print_cost = False): """ Builds the logistic regression model by calling the function you've implemented previously Arguments: X_train -- training set represented by a numpy array of shape (num_px * num_px * 3, m_train) Y_train -- training labels represented by a numpy array (vector) of shape (1, m_train) X_test -- test set represented by a numpy array of shape (num_px * num_px * 3, m_test) Y_test -- test labels represented by a numpy array (vector) of shape (1, m_test) num_iterations -- hyperparameter representing the number of iterations to optimize the parameters learning_rate -- hyperparameter representing the learning rate used in the update rule of optimize() print_cost -- Set to true to print the cost every 100 iterations Returns: d -- dictionary containing information about the model. """ ### START CODE HERE ### # initialize parameters with zeros w, b = initialize_with_zeros(X_train.shape[0]) # Gradient descent parameters, grads, costs = optimize(w, b, X_train, Y_train, num_iterations= 100, learning_rate = 0.009, print_cost = False) # Retrieve parameters w and b from dictionary "parameters" w = parameters["w"] b = parameters["b"] # Predict test/train set examples
Y_prediction_test = predict(w, b, X_test) Y_prediction_train = predict(w, b, X_train) # Print train/test Errors 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 d = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 2000, learning_rate = 0.005, print_cost = True)
最终的实验结果为

由最后的实验结果看出,虽然逻辑回归算法在训练集上有较好的效果,但是在测试集中只有70%的正确率,因此,我们需要寻找更复杂的神经网络来获得更高的准确率。
通过这第一次编程,发现自己对Python和Numpy的掌握上连入门都谈不上,还是应该去多动手多试验才能加深对知识的理解。

浙公网安备 33010602011771号