版权声明:本文为博主原创文章,未经博主允许不得转载。                        https://blog.csdn.net/u013733326/article/details/79639509                    </div><link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-3019150162.css"><div id="content_views" class="markdown_views"><!-- flowchart 箭头图标 勿删 --><svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path></svg><h1 id="吴恩达课后编程作业course-1-神经网络和深度学习-第二周作业-具有神经网络思维的logistic回归">【吴恩达课后编程作业】Course 1 - 神经网络和深度学习 - 第二周作业 - 具有神经网络思维的Logistic回归</h1>

上一篇: 【课程1 - 第二周测验】※※※※※ 【回到目录】※※※※※下一篇: 【课程1 - 第三周测验】


在开始之前,首先声明本文参考【Kulbear】的github上的文章,本文参考Logistic Regression with a Neural Network mindset,我基于他的文章加以自己的理解发表这篇博客,力求让大家以最轻松的姿态理解吴恩达的视频,如有不妥的地方欢迎大家指正。


本文所使用的资料已上传到百度网盘【点击下载】,请在开始之前下载好所需资料,然后将文件解压到你的代码文件同一级目录下,请确保你的代码那里有lr_utils.py和datasets文件夹。


【博主使用的python版本:3.6.2】


我们要做的事是搭建一个能够【识别猫】 的简单的神经网络,你可以跟随我的步骤在Jupyter Notebook中一步步地把代码填进去,也可以直接复制完整代码,在完整代码在本文最底部。

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

  • numpy :是用Python进行科学计算的基本软件包。
  • h5py:是与H5文件中存储的数据集进行交互的常用软件包。
  • matplotlib:是一个著名的库,用于在Python中绘制图表。
  • lr_utils :在本文的资料包里,一个加载资料包里面的数据的简单功能的库。

如果你没有以上的库,请自行安装。

import numpy as np
import matplotlib.pyplot as plt
import h5py
from lr_utils import load_dataset
  • 1
  • 2
  • 3
  • 4
  • 5

lr_utils.py代码如下,你也可以自行打开它查看:

import numpy as np
import h5pydef 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 featurestrain_set_y_orig = np.array(train_dataset["train_set_y"][:]) # your train set labelstest_dataset = h5py.File('datasets/test_catvnoncat.h5', "r")test_set_x_orig = np.array(test_dataset["test_set_x"][:]) # your test set featurestest_set_y_orig = np.array(test_dataset["test_set_y"][:]) # your test set labelsclasses = np.array(test_dataset["list_classes"][:]) # the list of classestrain_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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

解释以下上面的load_dataset() 返回的值的含义:

  • train_set_x_orig :保存的是训练集里面的图像数据(本训练集有209张64x64的图像)。
  • train_set_y_orig :保存的是训练集的图像对应的分类值(【0 | 1】,0表示不是猫,1表示是猫)。
  • test_set_x_orig :保存的是测试集里面的图像数据(本训练集有50张64x64的图像)。
  • test_set_y_orig : 保存的是测试集的图像对应的分类值(【0 | 1】,0表示不是猫,1表示是猫)。
  • classes : 保存的是以bytes类型保存的两个字符串数据,数据为:[b’non-cat’ b’cat’]。

现在我们就要把这些数据加载到主程序里面:

train_set_x_orig , train_set_y , test_set_x_orig , test_set_y , classes = load_dataset()
  • 1

我们可以看一下我们加载的文件里面的图片都是些什么样子的,比如我就查看一下训练集里面的第26张图片,当然你也可以改变index的值查看一下其他的图片。

index = 25
plt.imshow(train_set_x_orig[index])
#print("train_set_y=" + str(train_set_y)) #你也可以看一下训练集里面的标签是什么样的。
  • 1
  • 2
  • 3

运行结果如下:

现在我们可以结合一下训练集里面的数据来看一下我到底都加载了一些什么东西。

#打印出当前的训练标签值
#使用np.squeeze的目的是压缩维度,【未压缩】train_set_y[:,index]的值为[1] , 【压缩后】np.squeeze(train_set_y[:,index])的值为1
#print("【使用np.squeeze:" + str(np.squeeze(train_set_y[:,index])) + ",不使用np.squeeze: " + str(train_set_y[:,index]) + "】")
#只有压缩后的值才能进行解码操作
print("y=" + str(train_set_y[:,index]) + ", it's a " + classes[np.squeeze(train_set_y[:,index])].decode("utf-8") + "' picture")
  • 1
  • 2
  • 3
  • 4
  • 5

打印出的结果是:y=[1], it's a cat' picture,我们进行下一步,我们查看一下我们加载的图像数据集具体情况,我对以下参数做出解释:

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

请记住,train_set_x_orig 是一个维度为(m_​​train,num_px,num_px,3)的数组。

m_train = train_set_y.shape[1] #训练集里图片的数量。
m_test = test_set_y.shape[1] #测试集里图片的数量。
num_px = train_set_x_orig.shape[1] #训练、测试集里面的图片的宽度和高度(均为64x64)。#现在看一看我们加载的东西的具体情况
print ("训练集的数量: m_train = " + str(m_train))
print ("测试集的数量 : m_test = " + str(m_test))
print ("每张图片的宽/高 : num_px = " + str(num_px))
print ("每张图片的大小 : (" + str(num_px) + ", " + str(num_px) + ", 3)")
print ("训练集_图片的维数 : " + str(train_set_x_orig.shape))
print ("训练集_标签的维数 : " + str(train_set_y.shape))
print ("测试集_图片的维数: " + str(test_set_x_orig.shape))
print ("测试集_标签的维数: " + str(test_set_y.shape))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

运行之后的结果:

训练集的数量: m_train = 209
测试集的数量 : m_test = 50
每张图片的宽/高 : num_px = 64
每张图片的大小 : (64, 64, 3)
训练集_图片的维数 : (209, 64, 64, 3)
训练集_标签的维数 : (1, 209)
测试集_图片的维数: (50, 64, 64, 3)
测试集_标签的维数: (1, 50)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

为了方便,我们要把维度为(64,64,3)的numpy数组重新构造为(64 x 64 x 3,1)的数组,要乘以3的原因是每张图片是由64x64像素构成的,而每个像素点由(R,G,B)三原色构成的,所以要乘以3。在此之后,我们的训练和测试数据集是一个numpy数组,【每列代表一个平坦的图像】 ,应该有m_train和m_test列。

当你想将形状(a,b,c,d)的矩阵X平铺成形状(b * c * d,a)的矩阵X_flatten时,可以使用以下代码:

#X_flatten = X.reshape(X.shape [0],-1).T #X.T是X的转置
#将训练集的维度降低并转置。
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
  • 1
  • 2
  • 3
  • 4
  • 5

这一段意思是指把数组变为209行的矩阵(因为训练集里有209张图片),但是我懒得算列有多少,于是我就用-1告诉程序你帮我算,最后程序算出来时12288列,我再最后用一个T表示转置,这就变成了12288行,209列。测试集亦如此。

然后我们看看降维之后的情况是怎么样的:

print ("训练集降维最后的维度: " + str(train_set_x_flatten.shape))
print ("训练集_标签的维数 : " + str(train_set_y.shape))
print ("测试集降维之后的维度: " + str(test_set_x_flatten.shape))
print ("测试集_标签的维数 : " + str(test_set_y.shape))
  • 1
  • 2
  • 3
  • 4

执行之后的结果为:

训练集降维最后的维度: (12288, 209)
训练集_标签的维数 : (1, 209)
测试集降维之后的维度: (12288, 50)
测试集_标签的维数 : (1, 50)
  • 1
  • 2
  • 3
  • 4

为了表示彩色图像,必须为每个像素指定红色,绿色和蓝色通道(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
  • 2


现在总算是把我们加载的数据弄完了,我们现在开始构建神经网络。

以下是数学表达式,如果对数学公式不甚理解,请仔细看一下吴恩达的视频。

对于 x(i)x(i)

然后通过对所有训练样例求和来计算成本:

J=1m∑i=1mL(a(i),y(i))(4)(4)J=1m∑i=1mL(a(i),y(i))

建立神经网络的主要步骤是:
1. 定义模型结构(例如输入特征的数量)
2. 初始化模型的参数
3. 循环:

3.1 计算当前损失(正向传播)3.2 计算当前梯度(反向传播)3.3 更新参数(梯度下降)
  • 1
  • 2
  • 3
  • 4
  • 5

现在构建sigmoid(),需要使用 sigmoid(w ^ T x + b) 计算来做出预测。

def sigmoid(z):"""参数:z  - 任何大小的标量或numpy数组。返回:s  -  sigmoid(z)"""s = 1 / (1 + np.exp(-z))return s
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

我们可以测试一下sigmoid(),检查一下是否符合我们所需要的条件。

#测试sigmoid()
print("====================测试sigmoid====================")
print ("sigmoid(0) = " + str(sigmoid(0)))
print ("sigmoid(9.2) = " + str(sigmoid(9.2)))
  • 1
  • 2
  • 3
  • 4

打印出的结果为:

====================测试sigmoid====================
sigmoid(0) = 0.5
sigmoid(9.2) = 0.999898970806
  • 1
  • 2
  • 3

既然sigmoid测试好了,我们现在就可以初始化我们需要的参数w和b了。

def initialize_with_zeros(dim):"""此函数为w创建一个维度为(dim,1)的0向量,并将b初始化为0。参数:dim  - 我们想要的w矢量的大小(或者这种情况下的参数数量)返回:w  - 维度为(dim,1)的初始化向量。b  - 初始化的标量(对应于偏差)"""w = np.zeros(shape = (dim,1))b = 0#使用断言来确保我要的数据是正确的assert(w.shape == (dim, 1)) #w的维度是(dim,1)assert(isinstance(b, float) or isinstance(b, int)) #b的类型是float或者是intreturn (w , b)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

初始化参数的函数已经构建好了,现在就可以执行“前向”和“后向”传播步骤来学习参数。

我们现在要实现一个计算成本函数及其渐变的函数propagate()。

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

写好之后我们来测试一下。

#测试一下propagate
print("====================测试propagate====================")
#初始化一些参数
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))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

测试结果是:

====================测试propagate====================
dw = [[ 0.99993216][ 1.99980262]]
db = 0.499935230625
cost = 6.00006477319
  • 1
  • 2
  • 3
  • 4
  • 5

现在,我要使用渐变下降更新参数。

目标是通过最小化成本函数 JJ 是学习率。

def optimize(w , b , X , Y , num_iterations , learning_rate , 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的梯度下降法则更新参数。"""costs = []for i in range(num_iterations):grads, cost = propagate(w, b, X, Y)dw = grads["dw"]db = grads["db"]w = w - learning_rate * dwb = b - learning_rate * db#记录成本if i % 100 == 0:costs.append(cost)#打印成本数据if (print_cost) and (i % 100 == 0):print("迭代的次数: %i , 误差值: %f" % (i,cost))params  = {"w" : w,"b" : b }grads = {"dw": dw,"db": db } return (params , grads , costs)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

现在就让我们来测试一下优化函数:

#测试optimize
print("====================测试optimize====================")
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"]))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

测试结果为:

====================测试optimize====================
w = [[ 0.1124579 ][ 0.23106775]]
b = 1.55930492484
dw = [[ 0.90158428][ 1.76250842]]
db = 0.430462071679
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

optimize函数会输出已学习的w和b的值,我们可以使用w和b来预测数据集X的标签。

现在我们要实现预测函数predict()。计算预测有两个步骤:

  1. 计算 Y^=A=σ(wTX+b)Y^=A=σ(wTX+b)

  2. 将a的值变为0(如果激活值<= 0.5)或者为1(如果激活值> 0.5),

然后将预测值存储在向量Y_prediction中。

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 = sigmoid(np.dot(w.T , X) + b)for i in range(A.shape[1]):#将概率a [0,i]转换为实际预测p [0,i]Y_prediction[0,i] = 1 if A[0,i] > 0.5 else 0#使用断言assert(Y_prediction.shape == (1,m))return Y_prediction
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

老规矩,测试一下。

#测试predict
print("====================测试predict====================")
w, b, X, Y = np.array([[1], [2]]), 2, np.array([[1,2], [3,4]]), np.array([[1, 0]])
print("predictions = " + str(predict(w, b, X)))
  • 1
  • 2
  • 3
  • 4

就目前而言,我们基本上把所有的东西都做完了,现在我们要把这些函数统统整合到一个model()函数中,届时只需要调用一个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和bw , 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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

把整个model构建好之后我们这就算是正式的实际测试了,我们这就来实际跑一下。

print("====================测试model====================")
#这里加载的是真实的数据,请参见上面的代码部分。
d = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 2000, learning_rate = 0.005, print_cost = True)
  • 1
  • 2
  • 3

执行后的数据:

====================测试model====================
迭代的次数: 0 , 误差值: 0.693147
迭代的次数: 100 , 误差值: 0.584508
迭代的次数: 200 , 误差值: 0.466949
迭代的次数: 300 , 误差值: 0.376007
迭代的次数: 400 , 误差值: 0.331463
迭代的次数: 500 , 误差值: 0.303273
迭代的次数: 600 , 误差值: 0.279880
迭代的次数: 700 , 误差值: 0.260042
迭代的次数: 800 , 误差值: 0.242941
迭代的次数: 900 , 误差值: 0.228004
迭代的次数: 1000 , 误差值: 0.214820
迭代的次数: 1100 , 误差值: 0.203078
迭代的次数: 1200 , 误差值: 0.192544
迭代的次数: 1300 , 误差值: 0.183033
迭代的次数: 1400 , 误差值: 0.174399
迭代的次数: 1500 , 误差值: 0.166521
迭代的次数: 1600 , 误差值: 0.159305
迭代的次数: 1700 , 误差值: 0.152667
迭代的次数: 1800 , 误差值: 0.146542
迭代的次数: 1900 , 误差值: 0.140872
训练集准确性: 99.04306220095694 %
测试集准确性: 70.0 %
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

我们更改一下学习率和迭代次数,有可能会发现训练集的准确性可能会提高,但是测试集准确性会下降,这是由于过拟合造成的,但是我们并不需要担心,我们以后会使用更好的算法来解决这些问题的。


到目前为止,我们的程序算是完成了,但是,我们可以在后面加一点东西,比如画点图什么的。

#绘制图
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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

跑一波出来的效果图是这样的,可以看到成本下降,它显示参数正在被学习:

让我们进一步分析一下,并研究学习率alpha的可能选择。为了让渐变下降起作用,我们必须明智地选择学习速率。学习率αα 决定了我们更新参数的速度。如果学习率过高,我们可能会“超过”最优值。同样,如果它太小,我们将需要太多迭代才能收敛到最佳值。这就是为什么使用良好调整的学习率至关重要的原因。

我们可以比较一下我们模型的学习曲线和几种学习速率的选择。也可以尝试使用不同于我们初始化的learning_rates变量包含的三个值,并看一下会发生什么。

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)
frame = legend.get_frame()
frame.set_facecolor('0.90')
plt.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

跑一下打印出来的结果是:

learning rate is: 0.01
训练集准确性: 99.52153110047847 %
测试集准确性: 68.0 %-------------------------------------------------------learning rate is: 0.001
训练集准确性: 88.99521531100478 %
测试集准确性: 64.0 %-------------------------------------------------------learning rate is: 0.0001
训练集准确性: 68.42105263157895 %
测试集准确性: 36.0 %-------------------------------------------------------
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17


【完整代码】:

# -*- coding: utf-8 -*-
"""
Created on Wed Mar 21 17:25:30 2018博客地址 :http://blog.csdn.net/u013733326/article/details/79639509@author: Oscar
"""import numpy as np
import matplotlib.pyplot as plt
import h5py
from lr_utils import load_datasettrain_set_x_orig , train_set_y , test_set_x_orig , test_set_y , classes = load_dataset()m_train = train_set_y.shape[1] #训练集里图片的数量。
m_test = test_set_y.shape[1] #测试集里图片的数量。
num_px = train_set_x_orig.shape[1] #训练、测试集里面的图片的宽度和高度(均为64x64)。#现在看一看我们加载的东西的具体情况
print ("训练集的数量: m_train = " + str(m_train))
print ("测试集的数量 : m_test = " + str(m_test))
print ("每张图片的宽/高 : num_px = " + str(num_px))
print ("每张图片的大小 : (" + str(num_px) + ", " + str(num_px) + ", 3)")
print ("训练集_图片的维数 : " + str(train_set_x_orig.shape))
print ("训练集_标签的维数 : " + str(train_set_y.shape))
print ("测试集_图片的维数: " + str(test_set_x_orig.shape))
print ("测试集_标签的维数: " + str(test_set_y.shape))#将训练集的维度降低并转置。
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).Tprint ("训练集降维最后的维度: " + str(train_set_x_flatten.shape))
print ("训练集_标签的维数 : " + str(train_set_y.shape))
print ("测试集降维之后的维度: " + str(test_set_x_flatten.shape))
print ("测试集_标签的维数 : " + str(test_set_y.shape))train_set_x = train_set_x_flatten / 255
test_set_x = test_set_x_flatten / 255def sigmoid(z):"""参数:z  - 任何大小的标量或numpy数组。返回:s  -  sigmoid(z)"""s = 1 / (1 + np.exp(-z))return sdef initialize_with_zeros(dim):"""此函数为w创建一个维度为(dim,1)的0向量,并将b初始化为0。参数:dim  - 我们想要的w矢量的大小(或者这种情况下的参数数量)返回:w  - 维度为(dim,1)的初始化向量。b  - 初始化的标量(对应于偏差)"""w = np.zeros(shape = (dim,1))b = 0#使用断言来确保我要的数据是正确的assert(w.shape == (dim, 1)) #w的维度是(dim,1)assert(isinstance(b, float) or isinstance(b, int)) #b的类型是float或者是intreturn (w , b)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)def optimize(w , b , X , Y , num_iterations , learning_rate , 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的梯度下降法则更新参数。"""costs = []for i in range(num_iterations):grads, cost = propagate(w, b, X, Y)dw = grads["dw"]db = grads["db"]w = w - learning_rate * dwb = b - learning_rate * db#记录成本if i % 100 == 0:costs.append(cost)#打印成本数据if (print_cost) and (i % 100 == 0):print("迭代的次数: %i , 误差值: %f" % (i,cost))params  = {"w" : w,"b" : b }grads = {"dw": dw,"db": db } return (params , grads , costs)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 = sigmoid(np.dot(w.T , X) + b)for i in range(A.shape[1]):#将概率a [0,i]转换为实际预测p [0,i]Y_prediction[0,i] = 1 if A[0,i] > 0.5 else 0#使用断言assert(Y_prediction.shape == (1,m))return Y_predictiondef 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和bw , 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 dd = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 2000, learning_rate = 0.005, print_cost = True)#绘制图
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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
            <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-e44c3c0e64.css" rel="stylesheet"></div>

具有神经网络思维的Logistic回归相关推荐

  1. AILearning 吴恩达 L1 Week2 02 用神经网络思想实现Logistic回归(Cat)

    pyL 1 Week 2 02 用神经网络思想实现Logistic回归 #导入数据 import h5py #通过h5 选择加载数据的方式 加载规则 并且根据训练集和测试集分别存放 #查看关键key ...

  2. 003_wz_wed_DL_课程一第二周编程题(Logistic回归;神经网络思维;)

    具有神经网络思维的Logistic回归 一.目的 搭建一个能够识别猫的简单的神经网络 二.训练集与测试集 百度网盘,提取码:1234 三.编程 注:本编程未使用提供的py文件--lr_utils.py ...

  3. 【机器学习小记】【Logistic回归】deeplearning.ai course1 2nd week programming

    具有神经网络思维的Logistic回归 数据集介绍 数据拉平后 模型搭建 参数初始化 前向传播 反向传播 梯度下降更新参数 前向传播-预测predict 建议 其他 结果 目标:搭建一个能够[识别猫] ...

  4. 吴恩达《神经网络和深度学习》第二周编程作业—用神经网络思想实现逻辑回归

    吴恩达<神经网络和深度学习>-用神经网络思想实现逻辑回归 1 安装包 2 问题概述 3 学习算法的一般架构 4 构建算法的各个部分 4.1 激活函数 4.2 初始化参数 4.3 前向和后向 ...

  5. 神经网络logistic回归模型,logistic回归的基本理论

    神经网络挖掘模型与logistic回归挖掘模型的不同点有哪些? 逻辑回归有点像线性回归,但是它是当因变量不是数字时使用.比如说因变量是布尔变量(如是/否响应),这时候就需要逻辑回归.它称为回归,但实际 ...

  6. 深度学习(二)向量化 Logistic 回归及其梯度输出

    概述 本篇属于理论篇,你将了解什么是向量化.向量化对神经网络训练优化的重要性,以及如何向量化 Logistic 回归及其梯度输出. 转自猴开发博客:深度学习(二)向量化 Logistic 回归及其梯度 ...

  7. logistic回归 如何_第七章:利用Python实现Logistic回归分类模型

    免责声明:本文是通过网络收集并结合自身学习等途径合法获取,仅作为学习交流使用,其版权归出版社或者原创作者所有,并不对涉及的版权问题负责.若原创作者或者出版社认为侵权,请联系及时联系,我将立即删除文章, ...

  8. 神经网络基础及逻辑回归实现

    神经网络基础及逻辑回归实现 1. Logistic回归 1.1 Logistic回归 逻辑回归是一个主要用于二分分类类的算法.逻辑回归是给定一个x , 输出一个该样本属于1对应类别的预测概率​​=P( ...

  9. Coursera吴恩达《神经网络与深度学习》课程笔记(2)-- 神经网络基础之逻辑回归...

    转至:https://blog.csdn.net/red_stone1/article/details/77851177 上节课我们主要对深度学习(Deep Learning)的概念做了简要的概述.我 ...

最新文章

  1. 在R语言环境中无法载入rJava包的解决办法
  2. 我愿意参加计算机俱乐部的英文,如果你是一英语俱乐部的负责人你会组织什么活动...
  3. 非常好!!!---bash转义序列笔记---打印语句printf用法【转】
  4. STM8S103 PB4和PB5
  5. List, Set, Map是否继承自Collection接口?
  6. datagrid vue_类似 easyui 中 datagrid 使用习惯的 element-ui 数据表格组件(el-datagrid)...
  7. 【numpy】np.random.normal()函数
  8. python中常见的运行时错误_新手常见Python运行时错误汇总
  9. 数据结构 红黑树(RBTree)的原理与实现
  10. [转载] python之flask框架
  11. spring-boot spring-security-oauth2
  12. java.lang.Exception: Test class should have exactly one public constructor
  13. atitit.故障排除--- 当前命令发生了严重错误。应放弃任何可能产生的结果sql server 2008
  14. js中更改div的背景颜色:
  15. RoaringBitMap学习和实践
  16. 解决h5py.h5 ImportError问题
  17. 湖南现代物流职业技术学院校历课表
  18. python-字典练习3 -数字重复统计
  19. 百度短网址 php,调用百度短网址API生成短网址
  20. Imagemotion for Mac(PS动画插件)

热门文章

  1. 计算机屏幕剪切是怎人们剪切呀,如何使用剪切工具在Windows 10中截取屏幕截图...
  2. Java面试之画出HashMap结构图,并说说HashMap和HashTable的区别
  3. 我为什么鼓励程序员写blog
  4. 开发版无法发送短信的问题
  5. matlab里脚本循环语句,Matlab中while循环语句的用
  6. EL表达式判断Map是否为空和map的取值
  7. Python调用API打造一个语音合成系统(百度智能云)
  8. Python生成一张图片让iphone屏幕秒变随身直尺
  9. go 中 map 排序
  10. EZView/智U客户端设备列表中的EZView_Demo删除后如何恢复