吴恩达深度学习-第二周编程作业

第二周编程作业

1-packges

在开始之前,我们有需要引入的库:

  • numpy :是用Python进行科学计算的基本软件包。
  • h5py:是与H5文件中存储的数据集进行交互的常用软件包。
  • matplotlib:是一个著名的库,用于在Python中绘制图表。
  • lr_utils :在本文的资料包里,一个加载资料包里面的数据的简单功能的库。
import numpy as np
import copy
import matplotlib.pyplot as plt
import h5py
import scipy
from PIL import Image
from scipy import ndimage
from lr_utils import load_dataset
from public_tests import *

%matplotlib inline
%load_ext autoreload
%autoreload 2

2- Overview of the Problem set

问题陈述:有一个训练集和测试集,其中有被标记为猫和非猫的数据,要以此构建一个简单的图像识别算法。

加载数据

# Loading the data (cat/non-cat)
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()

在图像数据集(训练和测试)的末尾添加了“_orig”是为了对它们进行预处理。
我们来随机查看一下训练集中的图片。

# Example of a picture
index = 25
plt.imshow(train_set_x_orig[index])
print ("y = " + str(train_set_y[:, index]) + ", it's a '" + classes[np.squeeze(train_set_y[:, index])].decode("utf-8") +  "' picture.")

输出的结果为
吴恩达深度学习-第二周编程作业

2-1 Exercise 1

已知数据集中参数:

  • m_train :训练集里图片的数量。
  • m_test :测试集里图片的数量。
  • num_px : 训练、测试集里面的图片的宽度和高度(均为64x64)

提示:
train_set_x_orig 是一个维度为(m_​​train,num_px,num_px,3)的数组。
可以通过 train_set_x_orig.shape[0] 得到 m_​​train。

#(≈ 3 lines of code)
# m_train = 
# m_test = 
# num_px = 
# YOUR CODE STARTS HERE
m_train = train_set_x_orig.shape[0]
m_test = test_set_x_orig.shape[0]
num_px = train_set_x_orig.shape[1] 

# YOUR CODE ENDS HERE

print ("Number of training examples: m_train = " + str(m_train))
print ("Number of testing examples: m_test = " + str(m_test))
print ("Height/Width of each image: num_px = " + str(num_px))
print ("Each image is of size: (" + str(num_px) + ", " + str(num_px) + ", 3)")
print ("train_set_x shape: " + str(train_set_x_orig.shape))
print ("train_set_y shape: " + str(train_set_y.shape))
print ("test_set_x shape: " + str(test_set_x_orig.shape))
print ("test_set_y shape: " + str(test_set_y.shape))

输出结果
吴恩达深度学习-第二周编程作业

2-2 Exercise 2

将维度为 (num_px, num_px, 3)的训练集和测试集数组平铺为(num_px ∗ num_px ∗ 3, 1)。
提示:
当你想将形状(a,b,c,d)的矩阵X平铺成形状(b * c * d,a)的矩阵X_flatten时,可以使用以下代码:

X_flatten = X.reshape(X.shape[0], -1).T      # X.T is the transpose of X
#reshape(m,-1) 改变维度为m行d列,-1表示列数自动计算

因此有

# Reshape the training and test examples
#(≈ 2 lines of code)
# train_set_x_flatten = ...
# test_set_x_flatten = ...
# YOUR CODE STARTS HERE
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

# YOUR CODE ENDS HERE

# Check that the first 10 pixels of the second image are in the correct place
assert np.alltrue(train_set_x_flatten[0:10, 1] == [196, 192, 190, 193, 186, 182, 188, 179, 174, 213]), "Wrong solution. Use (X.shape[0], -1).T."
assert np.alltrue(test_set_x_flatten[0:10, 1] == [115, 110, 111, 137, 129, 129, 155, 146, 145, 159]), "Wrong solution. Use (X.shape[0], -1).T."

print ("train_set_x_flatten shape: " + str(train_set_x_flatten.shape))
print ("train_set_y shape: " + str(train_set_y.shape))
print ("test_set_x_flatten shape: " + str(test_set_x_flatten.shape))
print ("test_set_y shape: " + str(test_set_y.shape))

输出
吴恩达深度学习-第二周编程作业
为了表示彩色图像,必须为每个像素指定红色,绿色和蓝色通道(RGB),因此像素值实际上是从0到255范围内的三个数字的向量。机器学习中一个常见的预处理步骤是对数据集进行居中和标准化,这意味着可以减去每个示例中整个numpy数组的平均值,然后将每个示例除以整个numpy数组的标准偏差。但对于图片数据集,它更简单,更方便,几乎可以将数据集的每一行除以255(像素通道的最大值),因为在RGB中不存在比255大的数据,所以我们可以放心的除以255,让标准化的数据位于[0,1]之间,现在标准化我们的数据集:

train_set_x = train_set_x_flatten / 255.
test_set_x = test_set_x_flatten / 255.

对新数据集进行预处理的常见步骤是:
1、找出问题的尺寸和形状(m_train, m_test, num_px,…)
2、重塑数据集,使每个示例现在都是大小为(num_px * num_px * 3,1)的向量。
3、“标准化”的数据

3 - General Architecture of the learning algorithm

接下来要设计一个简单的算法,使用逻辑回归的神经网络。
吴恩达深度学习-第二周编程作业
数学表达式:
吴恩达深度学习-第二周编程作业

4 - Building the parts of our algorithm

建立神经网络的主要步骤是:

1、定义模型结构(例如输入特征的数量)

2、初始化模型的参数

3、循环:

3.1 计算当前损失(正向传播)

3.2 计算当前梯度(反向传播)

3.3 更新参数(梯度下降)

4.1 - Helper functions- Exercise 3

构建sigmoid()。
吴恩达深度学习-第二周编程作业

# GRADED FUNCTION: sigmoid

def sigmoid(z):
    """
    Compute the sigmoid of z

    Arguments:
    z -- 任何大小的标量或numpy数组。

    Return:
    s -- sigmoid(z)
    """

    #(≈ 1 line of code)
    # s = ...
    # YOUR CODE STARTS HERE
    s = 1 / (1 + np.exp(-z))
    
    # YOUR CODE ENDS HERE
    
    return s

让我们来测试一下sigmoid()函数

print ("sigmoid([0, 2]) = " + str(sigmoid(np.array([0,2]))))
#输出分别为sigmoid(0)和sigmoid(2)
sigmoid_test(sigmoid)

吴恩达深度学习-第二周编程作业

x = np.array([0.5, 0, 2.0])
output = sigmoid(x)
print(output)

吴恩达深度学习-第二周编程作业

4.2 - Initializing parameters- Exercise 4

实现参数初始化

提示
使用 np.zeros() 。返回来一个给定形状和类型的用0填充的数组。

def initialize_with_zeros(dim):
    """
        此函数为w创建一个维度为(dim,1)的0向量,并将b初始化为0。
        
        参数:
            dim  - 我们想要的w矢量的大小(或者这种情况下的参数数量)
        
        返回:
            w  - 维度为(dim,1)的初始化向量。
            b  - 初始化的标量(对应于偏差)
    """
    w = np.zeros(shape = (dim,1))
    b = float(0) #注意这个地方一定要定义为浮点型,否则会报错
    #使用断言来确保我要的数据是正确的
    assert(w.shape == (dim, 1)) #w的维度是(dim,1)
    assert(isinstance(b, float) or isinstance(b, int)) #b的类型是float或者是int
    
    return (w , b)

4.3 - Forward and Backward propagation- Exercise 5

现在可以执行向前/向后传播步骤来学习参数了。
首先,要实现一个计算成本函数及其渐变的函数propagate()。
提示:
吴恩达深度学习-第二周编程作业

提示
使用 np.log()和 np.dot()【(两个矩阵相乘)】和np.sum()【可以用于计算i的累加】。

def propagate(w, b, X, Y):
	"""
    实现前向和后向传播的成本函数及其梯度。
    参数:
        w  - 权重,大小不等的数组(num_px * num_px * 3,1)
        b  - 偏差,一个标量
        X  - 矩阵类型为(num_px * num_px * 3,训练数量)
        Y  - 真正的“标签”矢量(如果非猫则为0,如果是猫则为1),矩阵维度为(1,训练数据数量)

    返回:
        cost- 逻辑回归的负对数似然成本
        dw  - 相对于w的损失梯度,因此与w相同的形状
        db  - 相对于b的损失梯度,因此与b的形状相同
    """
	m = X.shape[1]
    
    #正向传播
    A = sigmoid(np.dot(w.T,X) + b) #计算激活值,请参考公式2。
    cost = (- 1 / m) * np.sum(Y * np.log(A) + (1 - Y) * (np.log(1 - A))) #计算成本,请参考公式3和4。
    
    #反向传播
    dw = (1 / m) * np.dot(X, (A - Y).T) #请参考视频中的偏导公式。
    db = (1 / m) * np.sum(A - Y) #请参考视频中的偏导公式。
	
	#使用断言确保我的数据是正确的
    assert(dw.shape == w.shape)
    assert(db.dtype == float)
    cost = np.squeeze(cost)
    assert(cost.shape == ())
    
    #创建一个字典,把dw和db保存起来。
    grads = {
                "dw": dw,
                "db": db
             }
    return (grads , cost)

然后进行测试

w =  np.array([[1.], [2]])
b = 1.5
X = np.array([[1., -2., -1.], [3., 0.5, -3.2]])
Y = np.array([[1, 1, 0]])
grads, cost = propagate(w, b, X, Y)

assert type(grads["dw"]) == np.ndarray
assert grads["dw"].shape == (2, 1)
assert type(grads["db"]) == np.float64


print ("dw = " + str(grads["dw"]))
print ("db = " + str(grads["db"]))
print ("cost = " + str(cost))

propagate_test(propagate)

输出为
吴恩达深度学习-第二周编程作业

4.4 - Optimization- Exercise 6

使用梯度下降来更新参数。
目标是通过最小化成本函数 J 来学习 w 和b 。其中 θ \theta θ 的更新规则是 θ = θ − α d ( θ ) \theta = \theta-\alpha d( \theta ) θ=θ−αd(θ). 其中 α \alpha α 是学习率。

# GRADED FUNCTION: optimize

def optimize(w, b, X, Y, num_iterations=100, learning_rate=0.009, print_cost=False):
    """
    此函数通过运行梯度下降算法来优化w和b
    
    参数:
        w  - 权重,大小不等的数组(num_px * num_px * 3,1)
        b  - 偏差,一个标量
        X  - 维度为(num_px * num_px * 3,训练数据的数量)的数组。
        Y  - 真正的“标签”矢量(如果非猫则为0,如果是猫则为1),矩阵维度为(1,训练数据的数量)
        num_iterations  - 优化循环的迭代次数
        learning_rate  - 梯度下降更新规则的学习率
        print_cost  - 每100步打印一次损失值
    
    返回:
        params  - 包含权重w和偏差b的字典
        grads  - 包含权重和偏差相对于成本函数的梯度的字典
        成本 - 优化期间计算的所有成本列表,将用于绘制学习曲线。
    
    提示:
    我们需要写下两个步骤并遍历它们:
        1)计算当前参数的成本和梯度,使用propagate()。
        2)使用w和b的梯度下降法则更新参数。

    """
    
    w = copy.deepcopy(w)
    b = copy.deepcopy(b)
    
    costs = []
    
    for i in range(num_iterations):
        # (≈ 1 lines of code)
        # Cost and gradient calculation 
        # grads, cost = ...
        # YOUR CODE STARTS HERE
        grads, cost =   propagate(w, b, X, Y)     

        
        # YOUR CODE ENDS HERE
        
        # Retrieve derivatives from grads
        dw = grads["dw"]
        db = grads["db"]
        
        # update rule (≈ 2 lines of code)
        # w = ...
        # b = ...
        # YOUR CODE STARTS HERE
        w = w - learning_rate* dw
        b = b - learning_rate * db
        
        # YOUR CODE ENDS HERE
        
        # Record the costs
        if i % 100 == 0:
            costs.append(cost)
        
            # Print the cost every 100 training iterations
            if print_cost:
                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)

print ("w = " + str(params["w"]))
print ("b = " + str(params["b"]))
print ("dw = " + str(grads["dw"]))
print ("db = " + str(grads["db"]))
print("Costs = " + str(costs))

optimize_test(optimize)

输出
吴恩达深度学习-第二周编程作业

4.4 - Optimization- Exercise 7

optimize函数会输出已学习的w和b的值,我们可以使用w和b来预测数据集X的标签。现在我们要实现预测函数predict()。计算预测有两个步骤:
吴恩达深度学习-第二周编程作业

# GRADED FUNCTION: predict

def predict(w, b, X):
    '''
   使用学习逻辑回归参数logistic (w,b)预测标签是0还是1,
    
    参数:
        w  - 权重,大小不等的数组(num_px * num_px * 3,1)
        b  - 偏差,一个标量
        X  - 维度为(num_px * num_px * 3,训练数据的数量)的数据
    
    返回:
        Y_prediction  - 包含X中所有图片的所有预测【0 | 1】的一个numpy数组(向量)
    '''
    
    m = X.shape[1] #图片的数量
    Y_prediction = np.zeros((1, m))
    w = w.reshape(X.shape[0], 1)
    
    # 计算A,预测猫在图片中出现的概率
    #(≈ 1 line of code)
    # A = ...
    # YOUR CODE STARTS HERE
    A = sigmoid(np.dot(w.T , X) + b)
    
    # YOUR CODE ENDS HERE
    
    for i in range(A.shape[1]):
        
        # Convert probabilities A[0,i] to actual predictions p[0,i]
        #(≈ 4 lines of code)
        # if A[0, i] > ____ :
        #     Y_prediction[0,i] = 
        # else:
        #     Y_prediction[0,i] = 
        # YOUR CODE STARTS HERE
        if A[0, i] > 0.5 :
             Y_prediction[0,i] = 1 
        else:
            Y_prediction[0,i] = 0 
        
        # YOUR CODE ENDS HERE
    
    return Y_prediction

测试

w = np.array([[0.1124579], [0.23106775]])
b = -0.3
X = np.array([[1., -1.1, -3.2],[1.2, 2., 0.1]])
print ("predictions = " + str(predict(w, b, X)))

predict_test(predict)

结果
吴恩达深度学习-第二周编程作业

5 - Merge all functions into a model - Exercise 8

把这些函数统统整合到一个model()函数中。

def model(X_train , Y_train , X_test , Y_test , num_iterations = 2000 , learning_rate = 0.5 , print_cost = False):
    """
    通过调用之前实现的函数来构建逻辑回归模型
    
    参数:
        X_train  - numpy的数组,维度为(num_px * num_px * 3,m_train)的训练集
        Y_train  - numpy的数组,维度为(1,m_train)(矢量)的训练标签集
        X_test   - numpy的数组,维度为(num_px * num_px * 3,m_test)的测试集
        Y_test   - numpy的数组,维度为(1,m_test)的(向量)的测试标签集
        num_iterations  - 表示用于优化参数的迭代次数的超参数
        learning_rate  - 表示optimize()更新规则中使用的学习速率的超参数
        print_cost  - 设置为true以每100次迭代打印成本
    
    返回:
        d  - 包含有关模型信息的字典。
    """
    w , b = initialize_with_zeros(X_train.shape[0])
    
    parameters , grads , costs = optimize(w , b , X_train , Y_train,num_iterations , learning_rate , print_cost)
    
    #从字典“参数”中检索参数w和b
    w , b = parameters["w"] , parameters["b"]
    
    #预测测试/训练集的例子
    Y_prediction_test = predict(w , b, X_test)
    Y_prediction_train = predict(w , b, X_train)
    
    #打印训练后的准确性
    print("训练集准确性:"  , format(100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100) ,"%")
    print("测试集准确性:"  , format(100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100) ,"%")
    
    d = {
            "costs" : costs,
            "Y_prediction_test" : Y_prediction_test,
            "Y_prediciton_train" : Y_prediction_train,
            "w" : w,
            "b" : b,
            "learning_rate" : learning_rate,
            "num_iterations" : num_iterations }
    return d

最后进行测试

logistic_regression_model = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations=2000, learning_rate=0.005, print_cost=True)

结果(迭代的次数:误差值)
吴恩达深度学习-第二周编程作业
图像分类错误的例子

index = 1
plt.imshow(test_set_x[:, index].reshape((num_px, num_px, 3)))
print ("y = " + str(test_set_y[0,index]) + ", you predicted that it is a \"" + classes[int(logistic_regression_model['Y_prediction_test'][0,index])].decode("utf-8") +  "\" picture.")

吴恩达深度学习-第二周编程作业

上一篇:Halcon形状模板匹配


下一篇:[企业框架设计模式]设计模式七大原则之开闭原则