【吴恩达deeplearning】第一门课 - 第二周 - 神经网络的编程基础(笔记+习题+编程作业)

第一门课 - 神经网络和深度学习(第二周 - 神经网络的编程基础)

  • 2.1 二分类(Binary Classification)
    • 二分类中的逻辑回归
  • 2.2 逻辑回归(Logistic Regression)
  • 2.3 逻辑回归的代价函数
    • 损失函数(误差函数)
    • 代价函数(成本函数)
  • 2.4 梯度下降法
  • 2.8 使用计算图求导数
  • 2.9 逻辑回归中的梯度下降
    • 单个样本实例
    • m个样本的梯度下降
  • 2.11 向量化
  • 2.14 向量化逻辑回归
    • 代码流程(非向量化)
    • 代码流程(向量化)
  • 2.15 Python中的广播(Broadcasting)
  • 【概念习题】
  • 【编程作业】
    • 一.numpy入门,函数向量化实现
      • 1.numpy基本使用
        • 1.1 math.exp( )和np.exp( )
        • 1.2 Sigmoid gradient
        • 1.3 重塑数组
        • 1.4 行标准化(归一化)
        • 1.5 广播和softmax函数
      • 2.向量化
        • 2.1 实现L1和L2损失函数
    • 二.用神经网络思想实现逻辑回归

2.1 二分类(Binary Classification)

二分类中的逻辑回归

逻辑回归是一个用于二分类的算法。

在二分类问题中,我们的目标就是习得一个分类器。

符号定义

  • x:表示一个 n x nx nx维数据,为输入数据,维度为 ( n x , 1 ) (nx, 1) (nx,1)
  • y:表示输出结果,取值为(0,1);
  • ( x ( i ) , y ( i ) ) (x^{(i)} , y^{(i)} ) (x(i),y(i)):表示第 i i i组数据,可能是训练数据,也可能是测试数据,此处默认为训练数据;
  • = [ x ( 1 ) , x ( 2 ) , . . . , x ( m ) ] [x^{(1)}, x^{(2)}, . . . , x^{(m)}] [x(1),x(2),...,x(m)]:表示所有的训练数据集的输入值,放在一个 n x × m n_x × m nx×m的矩阵中, 其中表示样本数目,这个矩阵的高度记为 n x n_x nx;
  • = [ y ( 1 ) , y ( 2 ) , . . . , y ( m ) ] [y^{(1)}, y^{(2)} , . . . , y^{(m)} ] [y(1),y(2),...,y(m)]:对应表示所有训练数据集的输出值,维度为1 × m m m
  • M t r a i n M_{train} Mtrain:强调这是训练样本的个数。
  • M t e s t M_{test} Mtest:来表示测试集的样本数。

2.2 逻辑回归(Logistic Regression)

y ^ = ω T + b \hat{y}=\omega^T+b y^=ωT+b 是一个关于输入x的线性函数,实际上这是在做线性回归时用到的,但是这对于二元分类问题来讲不是一个非常好的算法。因此,在逻辑回归中,我们的输出 y ^ \hat{y} y^ 应该将上面得到的线性函数式子作为 sigmoid 函数的自变量,将线性函数转换为非线性函数,公式如下:
y ^ = σ ( ω T + b ) . \hat{y}=\sigma(\omega^T+b). y^=σ(ωT+b).

sigmoid函数: σ ( z ) = 1 1 + e − z \sigma(z)=\frac{1}{1+e^{-z}} σ(z)=1+ez1,图像魏为:【吴恩达deeplearning】第一门课 - 第二周 - 神经网络的编程基础(笔记+习题+编程作业)_第1张图片

2.3 逻辑回归的代价函数

为了训练逻辑回归模型的参数 w w w 和参数 b b b ,我们需要一个代价函数,通过训练代价函数来得到参数 w w w 和参数 b b b 。先看一下逻辑回归的输出函数:

【吴恩达deeplearning】第一门课 - 第二周 - 神经网络的编程基础(笔记+习题+编程作业)_第2张图片

为了让模型通过学习调整参数,需要给予一个 m m m 样本的训练集,这会让你在训练集上找到参数 w w w 和参数 b b b ,来得到你的输出。

损失函数(误差函数)

损失函数 L ( y ^ , y ) L(\hat{y},y) L(y^,y)用来衡量算法的运行情况,衡量预测输出值和实际值有多接近。

一般我们用预测值和实际值的平方差或者它们平方差的一半 L ( y ^ , y ) = 1 2 ( y ^ − y ) 2 L(\hat{y},y)=\frac12(\hat{y}-y)^2 L(y^,y)=21(y^y)2,但是通常在逻辑回归中不这么做,因为在学习逻辑回归参数的时候,会发现我们的优化目标不是凸优化,会找到多个局部最优值,梯度下降法很可能找不到全局最优值。

实际用到的损失函数如下:
L ( y ^ , y ) = − [   y ⋅ l o g y ^   + ( 1 − y ) ⋅ l o g ( 1 − y ^ ) ] . L(\hat{y},y)=-[\ y\cdot log\hat{y}\ +(1-y)\cdot log(1-\hat{y})]. L(y^,y)=[ ylogy^ +(1y)log(1y^)].

我们约定 y ^ = p ( y = 1 ∣ x ) \hat y = p(y = 1|x) y^=p(y=1∣x),即算法的输出是给定训练样本 x x x 条件下 y y y 等于 1 的概率

  • 如果 y = 1 y = 1 y=1,在给定训练样本 x x x 条件下 y = y ^ y = \hat y y=y^,代表 y = 1 y = 1 y=1 的概率;
  • 如果 y = 0 y = 0 y=0,在给定训练样本 x x x 条件下 y = 1 − y ^ y = 1 − \hat y y=1y^,代表 y = 0 y = 0 y=0 的概率。

我们讨论的是二分类问题的损失函数,因此, y y y的取值只能是 0 或者 1。上述的两个条件概率公式可以合并成如下公式:

  • p ( y ∣ x ) = y ^ y ( 1 − y ^ ) ( 1 − y ) p(y|x) = \hat y^y (1 − \hat y)^{(1− y)} p(yx)=y^y(1y^)(1y)

log 函数是严格单调递增的函数,最大化 p ( y ∣ x ) p(y|x) p(yx) 等价于最大化 l o g ( p ( y ∣ x ) ) log(p(y|x)) log(p(yx)) ,通过对数函数化简为: y l o g y ^ + ( 1 − y ) l o g ( 1 − y ^ ) ylog\hat y + (1 − y)log(1 − \hat y) ylogy^+(1y)log(1y^)

代价函数(成本函数)

损失函数是在单个训练样本中定义的,它衡量的是算法在单个训练样本中表现如何。为了衡量算法在全部训练样本上的表现如何,我们需要定义一个算法的代价函数.算法的代价函数是对 m m m 个样本的损失函数求和然后除以 m m m
J ( w , b ) = 1 m Σ i = 1 m L ( y ^ ( i ) , y ( i ) ) = − 1 m Σ i = 1 m ( y ( i ) l o g y ^ ( i ) ) + ( 1 − y ( i ) ) l o g ( 1 − y ^ ( i ) ) ) \begin{aligned} J(w,b)&=\frac1m\Sigma^m_{i=1}L(\hat{y}^{(i)},y^{(i)}) \\ &=-\frac1m\Sigma^m_{i=1}\Bigl(y^{(i)}log\hat{y}^{(i)})+(1-y^{(i)})log(1-\hat{y}^{(i)})\Bigr) \end{aligned} J(w,b)=m1Σi=1mL(y^(i),y(i))=m1Σi=1m(y(i)logy^(i))+(1y(i))log(1y^(i)))
在训练逻辑回归模型时候,我们需要找到合适的 w w w b b b,来让代价函数 J J J 的总代价降到最低。

2.4 梯度下降法

梯度下降(Gradient Descent)简单来说就是一种寻找目标函数最小化的方法,它利用梯度信息,通过不断迭代调整参数来寻找合适的目标值。

下图是梯度下降法的形象化说明。代价函数 J ( w , b ) J(w,b) J(w,b)是在水平轴和上的曲面,此曲面的高度是 J ( w , b ) J(w,b) J(w,b)在某一点的函数值。我们要找到使得 J ( w , b ) J(w,b) J(w,b)函数值最小的参数 w w w b b b
【吴恩达deeplearning】第一门课 - 第二周 - 神经网络的编程基础(笔记+习题+编程作业)_第3张图片【吴恩达deeplearning】第一门课 - 第二周 - 神经网络的编程基础(笔记+习题+编程作业)_第4张图片

我们以如图的小红点的坐标来初始化参数 w w w和(也可以采用随机初始化的方法),朝最陡的下坡方向走一步,不断地迭代,直到走到全局最优解或者接近全局最优解的地方。

逻辑回归的代价函数(成本函数) J ( w , b ) J(w,b) J(w,b)是含有两个参数的。
w : = w − α ⋅ d J ( w , b ) d w b : = b − α ⋅ d J ( w , b ) d b w:=w-\alpha\cdot\frac{dJ(w,b)}{dw}\\ b:=b-\alpha\cdot\frac{dJ(w,b)}{db} w:=wαdwdJ(w,b)b:=bαdbdJ(w,b)

α \alpha α 表示学习率,用来控制步长,即向下走一步的长度; d J ( w ) d w \frac{dJ(w)}{dw} dwdJ(w) 就是函数 J ( w ) J(w) J(w) w w w 求导。

2.8 使用计算图求导数

一个神经网络的计算,都是按照前向或反向传播过程组织的。首先我们计算出一个新的网络的输出(前向过程)(黑色箭头),紧接着进行一个反向传输操作(红色箭头),后者我们用来计算出对应的梯度或导数(链式法则)。

【吴恩达deeplearning】第一门课 - 第二周 - 神经网络的编程基础(笔记+习题+编程作业)_第5张图片
在这里插入图片描述

2.9 逻辑回归中的梯度下降

单个样本实例

假设现在只考虑单个样本的情况,单个样本的代价函数定义如下: L ( a , y ) = − ( y l o g ( a ) + ( 1 − y ) l o g ( 1 − a ) ) L(a,y) = −(ylog(a)+(1 − y)log(1−a)) L(a,y)=(ylog(a)+(1y)log(1a)) 。其中 a a a是逻辑回归的输出, y y y是样本的标签值。

w w w b b b 的修正量可以表达如下: w : = w − α ∂ J ( w , b ) ∂ w , b : = b − α ∂ J ( w , b ) ∂ b w: = w − \alpha \frac{\partial J(w,b)}{\partial w},b: = b − \alpha \frac{\partial J(w,b)}{\partial b} w:=wαwJ(w,b)b:=bαbJ(w,b)

∵ d L ( a , y ) d a = − y a + 1 − y 1 − a ,    d a d z = a ⋅ ( 1 − a ) \because \frac{dL(a,y)}{da} = −\frac ya + \frac{1 − y}{1 − a},\ \ \frac{da}{dz} = a ⋅ (1 − a) dadL(a,y)=ay+1a1y,  dzda=a(1a)

∴ 设 d z = d L ( a , y ) d z = ( d L ( a , y ) d a ) ⋅ ( d a d z ) = ( − y a + 1 − y 1 − a ) ⋅ a ( 1 − a ) = a − y \therefore设dz=\frac{dL(a,y)}{dz} = ( \frac{dL(a,y)}{da}) ⋅ ( \frac{da}{dz} )=(−\frac ya + \frac{1 − y}{1 − a})\cdot a (1 − a)=a-y dz=dzdL(a,y)=(dadL(a,y))(dzda)=(ay+1a1y)a(1a)=ay

∴ d w 1 = ∂ L ∂ w 1 = x 1 ⋅ d z ,    d w 2 = ∂ L ∂ w 2 = x 2 ⋅ d z ,    d b = d z . \therefore dw_1=\frac{\partial L}{\partial w_1} = x_1 ⋅ dz,\ \ dw_2=\frac{\partial L}{\partial w_2} = x_2 ⋅ dz,\ \ db=dz. dw1=w1L=x1dz,  dw2=w2L=x2dz,  db=dz.

然后更新 w 1 = w 1 − α ⋅ d w 1 , w 2 = w 2 − α ⋅ d w 2 , b = b − α ⋅ d b w_1 = w_1 − \alpha ⋅dw_1, w_2 = w_2 − \alpha ⋅dw_2, b = b − \alpha ⋅db w1=w1αdw1w2=w2αdw2b=bαdb
【吴恩达deeplearning】第一门课 - 第二周 - 神经网络的编程基础(笔记+习题+编程作业)_第6张图片

m个样本的梯度下降

【吴恩达deeplearning】第一门课 - 第二周 - 神经网络的编程基础(笔记+习题+编程作业)_第7张图片

2.11 向量化

在逻辑回归中需要去计算 z = w T x + b z = w^Tx + b z=wTx+b w \bold w w x \bold x x都是列向量,w ∈ R n x ℝ^{n_x} Rnx , x ∈ R n x x ∈ ℝ^{n_x} xRnx
z = n p . d o t ( w , x ) + b z=np.dot(w,x)+b z=np.dot(w,x)+b向量化计算 w T x w^Tx wTx的方法,通过 numpy 内置函数避开显式循环的方式,从而有效提高代码速度。下面是一个例子来说明二者在计算速度上的差别:

import numpy as np
import time #导入时间库
a = np.random.rand(1000000)
b = np.random.rand(1000000) #通过 round 随机得到两个一百万维度的数组
tic = time.time() #现在测量一下当前时间
#向量化的版本
c = np.dot(a,b)
toc = time.time()
print(c)
print(“Vectorized version:+ str(1000*(toc-tic)) +”ms”) #打印时间
#非向量化的版本
c = 0
tic = time.time()
for i in range(1000000):
 c += a[i]*b[i]
toc = time.time()
print(c)
print(“For loop:+ str(1000*(toc-tic)) + “ms”) #打印时间

输出结果:
【吴恩达deeplearning】第一门课 - 第二周 - 神经网络的编程基础(笔记+习题+编程作业)_第8张图片

结果表明,和 for 循环相比,向量化可以快速得到结果。

numpy库提供了很多内置函数来避开显式循环:

import numpy as np
u = np.zeros(n,1)	#将u初始化为n×1的向量
u = np.dot(A,v)		#计算矩阵A和矩阵v的乘积
u = np.exp(v)		#u等于e的v次方
u = np.log(v)		#u=log(v)
u = np.abs()		#计算数据的绝对值
u = np.maximum(v,0)	#计算v中元素与0相比的

a = np.random.rand(5,1)	#生成一个5*1的矩阵
a = np.random.rand(5,)	#生成一个长度为5的一维数组

2.14 向量化逻辑回归

代码流程(非向量化)

一次梯度下降,重复多次

J=0;dw1=0;dw2=0;db=0;	//初始化
for i = 1 to m
    z(i) = wx(i)+b;
    a(i) = sigmoid(z(i));
    J += -[y(i)log(a(i))+(1-y(i))log(1-a(i));
    dz(i) = a(i)-y(i);
    dw1 += x1(i)dz(i);
    dw2 += x2(i)dz(i);
    db += dz(i);
J/= m;
dw1/= m;
dw2/= m;	//n=2,例子中假设有两个特征输入
db/= m;
w=w-α·dw
b=b-α·db

应用此方法在逻辑回归上你需要编写两个 for 循环,但在代码中显式地使用 for 循环会使算法变得低效,由此引出向量化技术,它可以允许代码摆脱显式的for循环。

第一个 for 循环是一个小循环遍历个训练样本;

第二个 for 循环是一个遍历所有特征的 for 循环。这个例子中只有 2 个特征,所以 n n n 等于 2。 但如果有更多特征,相似的计算要从 d w 1 dw_1 dw1 d w 2 dw_2 dw2 d w 3 dw_3 dw3一直下去到 d w n dw_n dwn。所以看来需要一个for 循环遍历所有 n n n 个特征。

代码流程(向量化)

import numpy as np
Z = np.dot(w.T,X) + b
A = σ(Z)
dZ = A - Y
dw = 1/m*X*dZ.T
db = 1/m*np.sum(dz)
w := w-α*dw
b := w-α*db

2.15 Python中的广播(Broadcasting)

【吴恩达deeplearning】第一门课 - 第二周 - 神经网络的编程基础(笔记+习题+编程作业)_第9张图片

【概念习题】


【吴恩达deeplearning】第一门课 - 第二周 - 神经网络的编程基础(笔记+习题+编程作业)_第10张图片


【吴恩达deeplearning】第一门课 - 第二周 - 神经网络的编程基础(笔记+习题+编程作业)_第11张图片


【吴恩达deeplearning】第一门课 - 第二周 - 神经网络的编程基础(笔记+习题+编程作业)_第12张图片


【编程作业】

一.numpy入门,函数向量化实现

1.numpy基本使用

1.1 math.exp( )和np.exp( )
import math
import numpy as np

'''1-使用numpy构建基本函数

练习:构建一个返回实数x的sigmoid的函数。将math.exp(x)用于指数函数。'''


def basic_sigmoid(x_1):
    s = 1 / (1 + math.exp(-x_1))

    return s


print(basic_sigmoid(3))

# 函数的输入可以使用“math”库,而深度学习中主要使用矩阵和向量,因此numpy更为实用。

# print(basic_sigmoid([1, 2, 3]))  # 会报错

x = np.array([1, 2, 3])
print(np.exp(x))
print(x + 3)

'''练习:使用numpy实现sigmoid函数。
说明:x可以是实数,向量或矩阵。 在numpy中使用的表示向量、矩阵等的数据结构称为numpy数组。'''

def sigmoid(x_2):
    s = 1 / (1 + np.exp(-x_2))

    return s


print(sigmoid(x))
1.2 Sigmoid gradient
'''练习:创建函数sigmoid_grad()计算sigmoid函数相对于其输入x的梯度。'''


def sigmoid_derivative(x_3):
    s = sigmoid(x_3)
    ds = s * (1 - s)

    return ds


print("sigmoid_derivative(x) = " + str(sigmoid_derivative(x)))
1.3 重塑数组
# -X.shape用于获取矩阵/向量X的shape(维度)。
# -X.reshape(...)用于将X重塑为其他尺寸。

'''练习:实现image2vector() ,该输入采用维度为(length, height, depth = 3)的输入,并返回维度为(length*height*depth, 1)的向量。
-请不要将图像的尺寸硬编码为常数。而是通过image.shape [0]等来查找所需的数量。'''


# 例如,如果你想将形为(a,b,c)的数组v重塑为维度为(a*b, c)的向量,则可以执行以下操作:
# v = v.reshape((v.shape[0] * v.shape[1], v.shape[2]))  # v.shape[0] = a ; v.shape[1] = b ; v.shape[2] = c

def image2vector(image):
    v = image.reshape(image.shape[0] * image.shape[1] * image.shape[2], 1)
    return v


image = np.array([[[0.67826139, 0.29380381],  # 3个3*2的数组
                   [0.90714982, 0.52835647],
                   [0.4215251, 0.45017551]],

                  [[0.92814219, 0.96677647],
                   [0.85304703, 0.52351845],
                   [0.19981397, 0.27417313]],

                  [[0.60659855, 0.00533165],
                   [0.10820313, 0.49978937],
                   [0.34144279, 0.94630077]]])
print("image2vector(image) = " + str(image2vector(image)))
print(image2vector(image).shape)
1.4 行标准化(归一化)
'''练习:执行 normalizeRows()来标准化矩阵的行。 将此函数应用于输入矩阵x之后,x的每一行应为单位长度(即长度为1)向量。'''

# 在Python中,norm函数用于计算向量的范数。向量的范数是一个标量值,表示向量的大小或长度。
# numpy.linalg.norm(x, ord=None, axis=None, keepdims=False)
# 参数说明:
# - x: 输入的向量或数组。
# - ord: 范数的类型。默认为None,表示计算2范数(欧几里德范数)。
# - axis: 指定按照哪个轴计算范数。默认为None,表示对整个数组进行计算。
# - keepdims: 是否保持结果的维度。默认为False,表示结果为标量。如果设置为True,结果将保持与输入数组相同的维度。
# 范数的计算公式如下:
# - L0范数:向量中非零元素的个数。
# - L1范数:向量中各个元素的绝对值之和。
# - L2范数:向量中各个元素的平方和的平方根。
# - Lp范数:向量中各个元素的p次方和的1/p次方。
# - 无穷范数:向量中绝对值最大的元素的绝对值。
# np.sum(a, axis=0) - ------>列求和
# np.sum(a, axis=1) - ------>行求和

def normalizeRows(x_4):
    x_norm = np.linalg.norm(x_4, axis=1, keepdims=True)
    x_4 = x_4 / x_norm

    return x_4


x = np.array([
    [0, 3, 4],
    [1, 6, 4]])
print("normalizeRows(x) = " + str(normalizeRows(x)))
1.5 广播和softmax函数
练习: 使用numpy实现softmax函数。 可以将softmax理解为算法需要对两个或多个类进行分类时使用的标准化函数。 '''


def softmax(x_5):
    x_exp = np.exp(x_5)
    x_sum = np.sum(x_exp, axis=1, keepdims=True)
    s = x_exp / x_sum

    return s


x = np.array([
    [9, 2, 5, 0, 0],
    [7, 5, 0, 0, 0]])
print("softmax(x) = " + str(softmax(x)))

2.向量化

2.1 实现L1和L2损失函数
练习:实现L1损失函数的Numpy向量化版本。 我们会发现函数abs(x)(x的绝对值)很有用。'''


def L1(yhat, y):
    loss = np.sum(np.abs(y - yhat))

    return loss


yhat = np.array([.9, 0.2, 0.1, .4, .9])
y = np.array([1, 0, 0, 1, 1])
print("L1 = " + str(L1(yhat, y)))

'''练习:实现L2损失函数的Numpy向量化版本。 有好几种方法可以实现L2损失函数,但是还是np.dot()函数更好用。'''


def L2(yhat, y):
    loss = np.dot((y - yhat), (y - yhat).T)

    return loss


print("L2 = " + str(L2(yhat, y)))

二.用神经网络思想实现逻辑回归

import numpy as np
import matplotlib.pyplot as plt
import h5py
from lr_utils import load_dataset

# 本训练集有209张64x64的图像,有list_classes、train_set_x和train_set_y三个group
# 本测试集有50张64x64的图像,有list_classes、test_set_x和test_set_y三个group
# /list_classes : 以bytes类型保存的两个字符串数据,[b’non-cat’ b’cat’]
# /train_set_x  : 训练集的图像数据(矩阵形式)
# /train_srt_y  : 训练集图像对应的分类标签(0--不是猫,1--是猫)
f = h5py.File("./datasets/train_catvnoncat.h5", "r")
for key in f.keys():
    print(f[key].name)
    print(f[key][:])

'''1--加载数据集'''
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()

# 根据索引查看训练集中的图片
index = 208
# plt.imshow(train_set_x_orig[index])  # 将图片做数据处理

'''打印出当前的训练标签值'''

# 使用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")

'''练习: 查找以下各项的值
     m_train(训练集示例数量)
     m_test(测试集示例数量)
     num_px(=训练图像的高度=训练图像的宽度)'''

# 请记住,"train_set_x_orig"是一个维度为(m_train,num_px,num_px,3)的numpy数组。
# 例如,你可以通过编写"train_set_x_orig.shape [0]"来访问"m_train"。

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("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))

'''练习: 重塑训练和测试数据集,将大小(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是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

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))

'''2--标准化数据集'''
train_set_x = train_set_x_flatten / 255
test_set_x = test_set_x_flatten / 255

'''3--构建算法的各个部分'''
'''3.1--辅助函数'''


def sigmoid(z):
    s = 1 / (1 + np.exp(-z))
    return s


# print("sigmoid([0, 2]) = " + str(sigmoid(np.array([0, 2]))))

'''3.2--初始化参数'''


def initialize_with_zeros(dim):
    w = np.zeros((dim, 1))
    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)
# print("w = " + str(w))
# print("b = " + str(b))

'''3.3--前向传播和后向传播'''


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))  # compute cost

    # BACKWARD PROPAGATION
    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


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))

'''3.4--优化函数(更新参数)'''


def optimize(w, b, X, Y, num_iterations, learning_rate, print_cost=False):
    """
    参数:
        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 * dw
        b = 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)


print("====================测试optimize====================")
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"]))

'''3.5--预测标签'''


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)
    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


print("====================测试predict====================")
print("predictions = " + str(predict(w, b, X)))

'''4--将所有功能合并到模型中'''


def model(X_train, Y_train, X_test, Y_test, num_iterations=2000, learning_rate=0.5, print_cost=False):
    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


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)

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()

【吴恩达deeplearning】第一门课 - 第二周 - 神经网络的编程基础(笔记+习题+编程作业)_第13张图片

【吴恩达deeplearning】第一门课 - 第二周 - 神经网络的编程基础(笔记+习题+编程作业)_第14张图片

你可能感兴趣的:(吴恩达深度学习课程,神经网络,笔记,人工智能,机器学习,深度学习)