让我们进入第一次编程作业学习。你将会建立一个逻辑回归分类器识别猫。此作业将指导您如何使用神经网络思维模式进行此操作,因此也将磨练您对深度学习的直觉。
介绍:在我们的代码中尽量不要使用循环语句(比如for/while),除非有特别说明要求你这么做。
在本次编程作业你将会学习到:
1 构建学习算法的通用架构,包括:
(1)初始化参数
(2)计算损失函数和它的梯度
(3)使用正则化(梯度下降算法)
2 按正确的顺序将上述三个功能聚集到一个主函数中
所有的代码都在pycharm上运行。
首先将下载的lr_utils.py和datasets文件夹放在建立的项目下。
1 导入有关库:
2 问题集的概述
问题陈述:在dataset文件夹下的(“data.h5”)包含以下:
- a training set of m_train images labeled as cat (y=1) or non-cat (y=0)
- a test set of m_test images labeled as cat or non-cat
- each image is of shape (num_px,num_px,3) where 3 is for the 3 channels (RGB).Thus,each image is square (height = num_px) and (width = num_px).
你将建立一个简单的图像识别算法能够正确的将猫或者不是猫的图片分类。
接下来,让我们熟悉针对数据集的操作吧。
我们在训练集和测试集末尾加上“orig”是将要对数据集进行预处理,处理后的结果为train_set_x和test_set_x(train_set_y和test_set_y不需要进行预处理)。
train_set_x_orig和test_set_x_orig的每一行都是一个表示图像的数组。 您可以通过运行以下代码来可视化示例。 您也可以随意更改索引值并重新运行以查看其他图像。关于squeeze函数已在作业一介绍,这里不再赘述。
2.1 Figure out the dimensions and shapes of the problem
深度学习中的许多软件错误来自于不适合的矩阵/向量维度。 如果你可以保持你的矩阵/矢量尺寸,你将在很长一段时间内消除许多错误。
练习:算出下列值:
-m_train(训练样本的数量)
-m_test(测试样本的数量)
-num_px(图片的宽度或者高度)
因为train_set_x_orig和test_set_x_orig是一个(m_train,num_px,num_px,3)类型的数组,因此上面的值可以用以下代码算出:
输出结果:
2.2 Reshape the datasets
为方便起见,你应该将图片维度(num_px,num_px,3)重塑成维度(num_px*num_px*3,1)。之后我们的训练和测试数据集是每列代表一个扁平的图像数组,这数组有训练集中:m_train(或测试集中:m_test)列
练习:将图像数组维度(num_px,num_px,3)重塑成一个扁平的向量,维度为(num_px * num_px *3,1)。
可用下面代码实现:
输出结果:
2.3 Standardize the data
要表示彩色图像,必须为每个像素指定红色,绿色和蓝色通道(RGB),因此像素值实际上是三个数字的矢量,范围从0到255。
机器学习中一个常见的预处理步骤是集中和标准化您的数据集,这意味着您从每个示例中减去整个numpy数组的平均值,然后将每个示例除以整个numpy数组的标准偏差。但是对于图片数据集,它更简单,更方便,几乎可以将数据集的每一行除以255(像素通道的最大值)。
接下来让我们标准化我们的数据集:
你要记住的:预处理一个新的数据集通常的步骤是:
(1)知道问题(数据集)的维度和形状(m_train,m_test,num_px,…)
(2)重塑数据集,使每个示例现在都是大小(num_px*num_px*3,1)的向量
(3)“标准化”这个数据
3 学习算法的一般体系架构
现在是时候设计一种简单的算法来区分猫图像和非猫图像。
您将使用神经网络思维模式构建Logistic回归。下图解释了为什么Logistic回归实际上是一个非常简单的神经网络!
算法的数学表达式:
主要步骤:在这个练习中,你将会实行下列步骤:
1 初始化模型参数
2 通过最小化成本来了解模型的参数
3 使用学习的参数进行预测(在测试集上)
4 分析结果并得出结论
4 构建我们算法的各个部分
构建一个神经网络的主要步骤是:
1 定义模型结构(例如输入要素的数量)
2 初始化模型的参数
3 循环:
(1)计算当前的损失(前向传播)
(2)计算当前的梯度(后向传播)
(3)更新参数(梯度下降)
您经常单独构建1-3并将它们集成到我们调用的一个函数中
4.1 Helper functions
练习:使用“Python Basics”的代码,实现sigmoid()。正如你在上图看到的那样,你需要去计算去做预测。使用np.exp()。
输出结果:
4.2 初始化参数
练习:您必须将w初始化为零向量。 如果您不知道要使用什么numpy函数,请在Numpy库的文档中查找np.zeros()。
输出结果:
4.3 前向和后向传播
现在您的参数已初始化,您可以执行“前进”和“后退”传播步骤来学习参数。
练习:实现一个函数propagate()来实现这个损失函数和它的梯度。
提示:
前向传播:
- 有数据X
- 计算
- 计算损失函数:
以下是您将使用的两个公式:
输出结果:
优化:
1 你已经初始化参数
2 你也能计算损失函数和它的梯度
3 现在,你想使用梯度下降算法来更新参数
练习:优化函数的目标是通过最小化损失函数J不断学习w和b。对于一个参数θ,这个更新规则是θ = θ – αdθ,这个α是学习率。
输出结果:
练习:上一个函数将输出学习的w和b。 我们能够使用w和b来预测数据集X的标签。实现predict()函数。 计算预测有两个步骤:
- 计算
- 将a的条目转换为0(如果激活<= 0.5)或1(如果激活> 0.5),将预测存储在向量Y_prediction中。 如果您愿意,可以在for循环中使用if / else语句(尽管还有一种方法可以对此进行向量化)。
输出结果:
5 将所有函数合并到model()中
现在,您将通过将所有构建块(前面部分中实现的功能)按正确顺序放在一起来了解整个模型的结构。
练习:实现model()函数。使用下列表示法:
1 Y_prediction用于测试集的预测
2 Y_prediction_train用于训练集的预测
3 w,costs,grads 是从optimize()输出
输出结果:
结果评论:训练准确率几乎接近100%。这是一个合理的检查:你的模型是有效的并且有足够的能力去适应训练数据。测试错误是68%。考虑到我们使用的小数据集并且逻辑回归是线性分类器,这个简单模型实际上并不坏,但不用担心,下周将会建立一个更好的分类器。
此外,您会发现该模型显然过度拟合了训练数据。 在本专业化的后期,您将学习如何减少过度拟合,例如使用正则化。 使用下面的代码(并更改索引变量),您可以查看测试集图片上的预测。
输出结果:(显然,预测结果是错误的)
接下来画出损失函数和梯度
输出结果:
解释:你可以看到成本在下降。 它表明正在学习参数。 但是,您可以看到您可以在训练集上进一步训练模型。 尝试增加上面单元格中的迭代次数,然后重新运行单元格。 您可能会看到训练集精度上升,但测试集精度下降。 这称为过度拟合。
6 进一步分析
让我们进一步分析它,并检查学习率α的可能选择
学习率的选择:为了使Gradient Descent有效,您必须明智地选择学习率。学习率α决定了我们更新参数的速度。 如果学习率太大,我们可能会“超调”最佳值。 同样,如果它太小,我们将需要太多的迭代来收敛到最佳值。 这就是为什么使用良好调整的学习率至关重要。
让我们将我们模型的学习曲线与几种学习率选择进行比较。
输出结果:
解释:
1 不同的学习率会产生不同的成本,从而产生不同的预测结果
2 如果学习率太大(0.01),则成本可能上下波动。 它甚至可能发散(尽管在这个例子中,使用0.01仍然最终会以很高的成本结束)。
3 较低的成本并不意味着更好的模型。 你必须检查是否有可能过度拟合。 当训练精度远高于测试精度时,就会发生这种情况。
4 深度学习中,通常推荐:
(1)选择更好地降低成本函数的学习率。
(2)如果您的模型过度拟合,请使用其他技术来减少过度拟合。 (我们将在以后的视频中讨论这个问题。)
7 测试你自己的图片
从项目当前image文件夹中选择图片“cat_in_iran.jpg”,测试这张图片是否有一只猫。
输出结果:
输出结果会有警告,这是因为在scipy 1.0.0以上版本移除了imread()和imsize()函数,我们按照提示修改代码即可。
结果将会正确输出,没有警告,其他和上述结果一样。、
8 顺便贴上完整代码
"lr_utils.py":
import numpy as np
import h5py
def load_dataset():
train_dataset = h5py.File('datasets/train_catvnoncat.h5', "r")
train_set_x_orig = np.array(train_dataset["train_set_x"][:]) # your train set features
train_set_y_orig = np.array(train_dataset["train_set_y"][:]) # your train set labels
test_dataset = h5py.File('datasets/test_catvnoncat.h5', "r")
test_set_x_orig = np.array(test_dataset["test_set_x"][:]) # your test set features
test_set_y_orig = np.array(test_dataset["test_set_y"][:]) # your test set labels
classes = np.array(test_dataset["list_classes"][:]) # the list of classes
train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0]))
test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0]))
return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes
"assignment2_2.py"
#!/usr/bin/python
#-*- coding:utf-8 -*-
from __future__ import print_function
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import h5py
import scipy
from PIL import Image
from scipy import ndimage
from lr_utils import load_dataset
#Loading the data (cat/non-cat)
train_set_x_orig,train_set_y,test_set_x_orig,test_set_y,classes = load_dataset()
#Example of a picture
index = 5
# plt.imshow(train_set_x_orig[index])
# plt.show()
# print ("y = " + str(train_set_y[:, index]) + ", it's a '" +
# classes[np.squeeze(train_set_y[:, index])].decode("utf-8") + "' picture.")
#values of m_train,m_test and num_px
m_train = train_set_x_orig.shape[0]
m_test = test_set_x_orig.shape[0]
num_px = train_set_x_orig.shape[1]
# print("m_train =" + str(m_train))
# print("m_test = " + str(m_test))
# print("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))
#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
# 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))
# print("sanity check after reshaping: " + str(train_set_x_flatten[0:5,0]))
#standardize dataset
train_set_x = train_set_x_flatten / 255
test_set_x = test_set_x_flatten / 255
#building sigmoid()
def sigmoid(z):# z:A scalar or numpy array of any size
s = 1 / (1 + np.exp(-z))
return s
#print("sigmoid([0,2])=" + str(sigmoid(np.array([0,2]))))
#initialize parameters
def initialize_with_zeros(dim):
w = np.zeros((dim,1)) #w:initialized vector of shape(dim,1)
b = 0 #b:initialized scalar(corresponds to the bias)
assert (w.shape == (dim,1))
assert (isinstance(b,float) or isinstance(b,int))
return w,b
# dim = 2
# w,b = initialize_with_zeros(dim)
# print("w = " + str(w))
# print("b = " + str(b))
#building propagate()
def propagate(w,b,X,Y):
"""
:param w: weights,a numpy array of size(num_px * num_px * 3,1)
:param b: bias,a scalar
:param X: data of size(num_px * num_px * 3,number of examples)
:param Y: true "label" vector(containing 0 if non-cat,1 if cat) of size(1,number of example)
: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
"""
m = X.shape[1]
A = sigmoid(np.dot(w.T,X) + b)
cost = -1 / m * np.sum(Y * np.log(A) + (1 - Y) * np.log(1 - A))
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 == ())
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)
# print("dw = " + str(grads["dw"]))
# print("db = " + str(grads["db"]))
# print("cost = " + str(cost))
#building optimize()
def optimize(w,b,X,Y,num_iterations,learning_rate,print_cost = False):
"""
:param num_iterations: number of iterations of the optimization loop
:param learning_rate:learning rate of the gradient descent update rule
:param print_cost:True to print the loss every 100 steps
:return:
: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
"""
costs = []
for i in range(num_iterations):
grads,cost = propagate(w,b,X,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
# w, b, X, Y = np.array([[1],[2]]), 2, np.array([[1,2],[3,4]]), np.array([[1,0]])
# 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)
#building predict()
def predict(w,b,X):
"""
:return:
: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)
A = sigmoid(np.dot(w.T,X) + b)
for i in range(A.shape[1]):
if A[0,i] <= 0.5:
Y_prediction[0,i] = 0
else:
Y_prediction[0,i] = 1
assert (Y_prediction.shape == (1,m))
return Y_prediction
# w, b, X = np.array([[1],[2]]), 2, np.array([[1,2],[3,4]])
# print("predictions = " + str(predict(w,b,X)))
#building model()
def model(X_train,Y_train,X_test,Y_test,num_iterations = 2000,learning_rate = 0.5,print_cost = False):
"""
:param X_train: training set represented by a numpy array of shape(num_px * num_px * 3,m_train)
:param Y_train: training labels represented by a numpy array (vector) of shape (1, m_train)
:param X_test: test set represented by a numpy array of shape (num_px * num_px * 3, m_test)
:param Y_test: test labels represented by a numpy array (vector) of shape (1, m_test)
:param num_iterations: hyperparameter representing the number of iterations to optimize the parameters
:param learning_rate: hyperparameter representing the learning rate used in the update rule of optimize()
:param print_cost: Set to true to print the cost every 100 iterations
:return:
:d: dictionary containing information about the model
"""
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 = 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
d = model(train_set_x,train_set_y,test_set_x,test_set_y,num_iterations= 2000,learning_rate= 0.005,
print_cost= True)
#Example of a picture that was wrongly classified.
# index = 1
# plt.imshow(test_set_x[:,index].reshape((num_px,num_px,3)))
# plt.show()
# print("y = " + str(test_set_y[0,index]) + ",you predicted that it is a \"" +
# classes[int(d["Y_prediction_test"][0,index])].decode("utf-8") + "\" picture.")
#
# #plot learning curve (with costs)
# costs = np.squeeze(d['costs'])
# plt.plot(costs)
# plt.ylabel('cost')
# plt.xlabel('iterations(per hundreds)')
# plt.title("Learning rate = " + str(d["learning_rate"]))
# plt.show()
#choice of learning rate
# learning_rates = [0.01,0.001,0.0001]
# models = {}
# for i in learning_rates:
# print("learning rate is: " + str(i))
# models[str(i)] = model(train_set_x, train_set_y, test_set_x, test_set_y,
# num_iterations=1500, learning_rate=i,print_cost=False)
# print('\n' + "-------------------------------------------------------" + '\n')
#
# for i in learning_rates:
# plt.plot(np.squeeze(models[str(i)]["costs"]),label = str(models[str(i)]["learning_rate"]))
#
# plt.ylabel('cost')
# plt.xlabel('iterations')
#
# legend = plt.legend(loc = 'upper center',shadow = True)
# fram = legend.get_frame()
# fram.set_facecolor('0.90')
# plt.show()
#test with your own image
my_image = "cat_in_iran.jpg"
fname = "./image/" + my_image
#image = np.array(ndimage.imread(fname, flatten=False))
image = np.array(plt.imread(fname))
#my_image = scipy.misc.imresize(image, size=(num_px,num_px)).reshape((1, num_px*num_px*3)).T
my_image = np.array(Image.fromarray(image).resize((num_px,num_px))).reshape((1, num_px*num_px*3)).T
my_predicted_image = predict(d["w"], d["b"], my_image)
plt.imshow(image)
plt.show()
print("y = " + str(np.squeeze(my_predicted_image)) + ", your algorithm predicts a \""
+ classes[int(np.squeeze(my_predicted_image)),].decode("utf-8") + "\" picture.")