Neural Networks and Deep Learning(week 2_python 编程练习)

Neural Networks and Deep Learning(week 2_python 编程练习)

吴恩达深度学习课程第二周编程练习——python的numpy基础

Python Basics with Numpy

这个练习会对python作一个简要的介绍,熟悉python部分函数的使用。 (原练习中有一小部分介绍了iPython Botebooks(jupyter notebook)的使用,此文省略)

Instructions:

  • 学习使用python3
  • 在题目没有明确要求时,避免使用for、while循环

学习目标:

  • 学会使用numpy函数以及numpy的矩阵操作
  • 理解python中broadcasting广播的概念
  • 学会向量化代码的编写

1. 运行最基本的numpy函数

在这个练习中可以学到几个关键的numpy函数比如np.exp,np.log,np.reshape

1.1 sigmoid函数,np.exp()

在使用np.exp()之前,先使用math.exp()来运行sigmoid函数。通过比较,能够看出为什么np.exp()math.exp()更好。

Exercise 1 - Basic_sigmoid

写一个函数返回sigmoid的计算值。使用math.exp()作为指数运算函数。

Reminder: sigmoid函数通常也被叫做回归函数logistic function。sigmoid是个非线性函数,在机器学习(Logistic regression)和深度学习中均有应用。

sigmoid

s i g m o i d ( x ) = 1 1 + e − x sigmoid(x)=\frac{1}{1+e^{-x}} sigmoid(x)=1+ex1
要使用一个特定库中的函数,使用package_name.function。运行以下代码,观察使用了math.exp()的例子。

import math
def basic_sigmoid(x):
	"""
	计算sigmoid(x)
	
	参数:
		x -- A,标量
		s -- sigmoid(X)
	"""
  s = 1/(1+math.exp(-x))
  return s
print("basic_sigmoid(1) = " + str(basic_sigmoid(1)))

正确的输出应为basic_sigmoid(1) = 0.7310585786300049

事实上,在深度学习中很少使用math库,math库的输入均为实数,而在深度学习中使用的几乎都是矩阵和向量。这就是numpy更有用的原因。

### 在深度学习中使用numpy而不是math的原因 ###
x = [1, 2, 3] # x是python中的列表对象
basic_sigmoid(x) # 运行时会出错,因为x是一个向量。

如果 x = ( x 1 , x 2 , . . . , x n ) x=(x_1, x_2, ... ,x_n) x=(x1,x2,...,xn)是一个行向量,那么np.exp(x)能将指数运算作用在行向量的每个元素 x x x上。np.exp(x)=(e^{x_1},e^{x_2},...,e^{x_n})

import numpy as np
 #np.exp的例子
t_x = np.array([1, 2, 3])
print(np.exp(t_x)) #结果是(exp(1), exp(2), exp(3))
print(1/t_x)

正确的输出应为:

[ 2.71828183 7.3890561 20.08553692] [1. 0.5 0.33333333]

另外,如果x是向量,那么s = x +3s = 1/x这样的python运算,输出的结果s也会是一个向量,并且维度与x相同。

# example of vector operation
t_x = np.array([1, 2, 3])
print (t_x + 3)

正确的输出为:[4 5 6]

更多有关numpy函数的信息,可以登陆numpy官网查看。

Exercise 2 - sigmoid

使用numpy.exp()计算sigmoid。

Instructions: x既可以是一个实数,也可以是一个向量或矩阵。在numpy中表示向量、矩阵等的数据结构叫做numpy arrays

For  x ∈ R n ,  s i g m o i d ( x ) = s i g m o i d ( x 1 x 2 . . . x n ) = ( 1 1 + e − x 1 1 1 + e − x 2 . . . 1 1 + e − x n ) \text{For } x \in \mathbb{R}^n \text{, } sigmoid(x) = sigmoid\begin{pmatrix} x_1 \\ x_2 \\ ... \\ x_n \\ \end{pmatrix} = \begin{pmatrix} \frac{1}{1+e^{-x_1}} \\ \frac{1}{1+e^{-x_2}} \\ ... \\ \frac{1}{1+e^{-x_n}} \\ \end{pmatrix} For xRnsigmoid(x)=sigmoidx1x2...xn=1+ex111+ex21...1+exn1

# FUNCTION:sigmoid
def sigmoid(x):
    """
    计算sigmoid(x)

    参数:
    	x -- 标量A或者任意大小的数组(numpy array)
    返回:
    	s -- sigmoid(X)
    """   
    s = 1/(1+np.exp(-x))
    return s
t_x = np.array([1, 2, 3])
print("sigmoid(t_x) = " + str(sigmoid(t_x)))

正确输出应为:sigmoid(t_x) = [0.73105858 0.88079708 0.95257413]

1.2 Sigmoid Gradient(sigmoid函数梯度)

在反向传播中需要计算梯度来优化损失函数,接下来编写梯度函数。

Exercise 3 - sigmoid_derivative

对于输入x,使用函数sigmoid_grad()计算sigmoid函数的梯度。公式为:
s i g m o i d _ d e r i v a t i v e ( x ) = σ ′ ( x ) = σ ( x ) ( 1 − σ ( x ) ) sigmoid\_derivative(x) = \sigma'(x) = \sigma(x) (1 - \sigma(x)) sigmoid_derivative(x)=σ(x)=σ(x)(1σ(x))
编写这个函数需要两步:

  1. 使用exercise 2中的sigmoid()函数,s = sigmoid(x)
  2. 计算 σ ′ ( x ) = s ( 1 − s ) \sigma'(x)=s(1-s) σ(x)=s(1s)
#FUNVTION:sigmoid_derivative

def sigmoid_derivative(x):
    """
    对于输入x,计算sigmoid(x)的梯度(导数,坡度)
    可以将sigmoid函数的输出存为变量,再使用这个变量来计算梯度。
    参数:
    	x -- 标量A或者任意大小的数组(numpy array)
    
    返回:
    	ds -- 计算出的梯度
    """

    def sigmoid(x):
        s = 1/(1+np.exp(-x))
        return s
    s = sigmoid(x)
    ds = s*(1-s)#写相乘的代码时,记得写上"*"
    return ds
t_x = np.array([1, 2, 3])
print ("sigmoid_derivative(t_x) = " + str(sigmoid_derivative(t_x)))

正确的输出为:sigmoid_derivative(t_x) = [0.19661193 0.10499359 0.04517666]

1.3 Reshaping arrays(改变数组的维度)

深度学习中常用的两个numpy函数:np.shape()np.reshape()

  • X.shape:获得矩阵/向量X的维度。
  • X.reshape():改变X的维度。

例如,在计算机科学中,一个图像可以被3D的数组(length,height,depth=3)表示。当你要将图片作为算法的输入时,需要将其转化为(length* height * depth,1)的向量。换言之,需要将3D的数组展开称为1D的向量。

RGB

Exercise 4 - image2vector

编写函数image2vector(),输入为(length,height,3)的数组,输出为(length*height *3,1)的向量。

例如:如果要将一个(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
  • 不要在编写代码时将图片的维度直接写为常数,使用image.shape[]获取需要的维度参数。
  • 可以使用v = v.reshape(-1,1)。-1表示未指定值,即行未指定,列为1。
#FUNCTION:像素数组到向量的转化
def image2vector(image):
    """
    参数:
    	image -- 维度(length, height, depth)的numpy array
    
    返回:
    	v -- 维度为(length*height*depth, 1)的向量
    """

    v = image.reshape(image.shape[0]*image.shape[1]*image.shape[2],1)

    return v
# 这是一个3*3*2的数组,对应图像的维度则为:(num_px_x, num_px_y,3),3表示RGB值。
#此处可以查阅numpy.array()的使用。
#numpy.array(a,b,c)表示创建了a页,b行,c列的数组。
#对应于此处,3*3*2的数组即表示3页,3行2列的数据。
#相应地,图像维度为(num_px_x=3,num_px_y=2,3)
#RGB即红绿蓝,在像素表示时各占一页,所以有3页。
t_image = np.array([[[ 0.67826139,  0.29380381],
                     [ 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(t_image)))

正确的输出为:

image2vector(image) = [[0.67826139]
 [0.29380381]
 [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]]
1.4 Normalizing rows(逐行归一化)

归一化是机器学习和深度学习中常用的技巧,归一化后的数据能在梯度下降中更快地收敛。归一化指将x变为 x ∥ x ∥ \frac{x}{\| x \|} xx(每行向量均除以其模长)。

例如,若:

x = [ 0 3 4 2 6 4 ] x = \begin{bmatrix} 0 & 3 & 4 \\ 2 & 6 & 4 \\ \end{bmatrix} x=[023644]

那么
∥ x ∥ = np.linalg.norm(x, axis=1, keepdims=True) = [ 5 56 ] (4) \| x\| = \text{np.linalg.norm(x, axis=1, keepdims=True)} = \begin{bmatrix} 5 \\ \sqrt{56} \\ \end{bmatrix}\tag{4} x=np.linalg.norm(x, axis=1, keepdims=True)=[556 ](4)

x _ n o r m a l i z e d = x ∥ x ∥ = [ 0 3 5 4 5 2 56 6 56 4 56 ] (5) x\_normalized = \frac{x}{\| x\|} = \begin{bmatrix} 0 & \frac{3}{5} & \frac{4}{5} \\ \frac{2}{\sqrt{56}} & \frac{6}{\sqrt{56}} & \frac{4}{\sqrt{56}} \\ \end{bmatrix}\tag{5} x_normalized=xx=[056 25356 65456 4](5)

可以注意到,不管维度多少的矩阵,这个函数都能很好地运行:这叫broadcasting(广播)。在第五部分会介绍。

keepdims=True时,原矩阵x会自动广播并保持原来的维数不变来进行计算。keepdims默认为false

keepdims是如何保持维度不变的:被减少的轴仍以维度1保留在结果中。

axis=1指按行计算模长进行归一化。axis=0表示按列来计算。

numpy.linalg.norm还有一个参数ord,这个参数用来制定归一化的类型。默认ord=2即二范数。熟悉更多归一化运算,访问numpy.linalg.norm

Exercise 5 - normalize_rows

编写函数normalizeRowa()来按行归一化矩阵。输入x是个矩阵,在将这个函数作用到x上后,x的每一行都应是长度为1的向量。

Note: 不要使用x /= x_norm,操作符/=不适用于矩阵之间的除法。

# FUNCTION:逐行归一化。
def normalize_rows(x):
    """
    编写一个函数能够将矩阵x逐行归一化,归一化后的x每行只有1个元素。
  
    参数:
    x -- (n,m)维的numpy矩阵A
    
    返回:
    x -- 逐行正则化后的矩阵x。
    """

    # 计算x的二范数即模长||x||,存入x_norm中。
    # 使用 np.linalg.norm(...,ord=2,axis = ...,keepdims =True)
    # x除以其模长。
    x_norm = np.linalg.norm(x,axis=1,keepdims=True)#here is keepdims not Keepdims
    x = np.divide(x,x_norm)
    return x
x = np.array([[0, 3, 4],
              [1, 6, 4]])
print("normalizeRows(x) = " + str(normalize_rows(x)))

正确的输出应为:

normalizeRows(x) = [[0.         0.6        0.8       ]
 [0.13736056 0.82416338 0.54944226]]

Note: 在函数normalize_rows()中,你也可以试着打印出x_norm和x的维度,可以发现x_norm和x的维度不同。那不同维度的矩阵是如何相除的?这就叫做广播

Exercise 6 - softmax

使用numpy来实现softmax()。归一化之后,当你还需要进行分类时(两类/多类),就需要使用softmax。

Instructions:

  • 对于 x ∈ R 1 × n x \in \mathbb{R}^{1\times n} xR1×n,
    ( s o f t m a x ( x ) = s o f t m a x ( [ x 1 x 2 . . . x n ] ) = [ e x 1 ∑ j e x j e x 2 ∑ j e x j . . . e x n ∑ j e x j ] ) \begin{pmatrix} softmax(x) &= softmax\left(\begin{bmatrix} x_1 && x_2 && ... && x_n \end{bmatrix}\right) \\&= \begin{bmatrix} \frac{e^{x_1}}{\sum_{j}e^{x_j}} && \frac{e^{x_2}}{\sum_{j}e^{x_j}} && ... && \frac{e^{x_n}}{\sum_{j}e^{x_j}} \end{bmatrix} \end{pmatrix} (softmax(x)=softmax([x1x2...xn])=[jexjex1jexjex2...jexjexn])

  • 对于矩阵 x ∈ R m × n x \in \mathbb{R}^{m\times n} xRm×n, x i j x_{ij} xij为矩阵第i行第j列的元素,有:

( s o f t m a x ( x ) = s o f t m a x [ x 11 x 12 x 13 … x 1 n x 21 x 22 x 23 … x 2 n ⋮ ⋮ ⋮ ⋱ ⋮ x m 1 x m 2 x m 3 … x m n ] = [ e x 11 ∑ j e x 1 j e x 12 ∑ j e x 1 j e x 13 ∑ j e x 1 j … e x 1 n ∑ j e x 1 j e x 21 ∑ j e x 2 j e x 22 ∑ j e x 2 j e x 23 ∑ j e x 2 j … e x 2 n ∑ j e x 2 j ⋮ ⋮ ⋮ ⋱ ⋮ e x m 1 ∑ j e x m j e x m 2 ∑ j e x m j e x m 3 ∑ j e x m j … e x m n ∑ j e x m j ] = ( s o f t m a x (first row of x) s o f t m a x (second row of x) ⋮ s o f t m a x (last row of x) ) ) \begin{pmatrix} softmax(x) &= softmax\begin{bmatrix} x_{11} & x_{12} & x_{13} & \dots & x_{1n} \\ x_{21} & x_{22} & x_{23} & \dots & x_{2n} \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ x_{m1} & x_{m2} & x_{m3} & \dots & x_{mn} \end{bmatrix} \\ \\&= \begin{bmatrix} \frac{e^{x_{11}}}{\sum_{j}e^{x_{1j}}} & \frac{e^{x_{12}}}{\sum_{j}e^{x_{1j}}} & \frac{e^{x_{13}}}{\sum_{j}e^{x_{1j}}} & \dots & \frac{e^{x_{1n}}}{\sum_{j}e^{x_{1j}}} \\ \frac{e^{x_{21}}}{\sum_{j}e^{x_{2j}}} & \frac{e^{x_{22}}}{\sum_{j}e^{x_{2j}}} & \frac{e^{x_{23}}}{\sum_{j}e^{x_{2j}}} & \dots & \frac{e^{x_{2n}}}{\sum_{j}e^{x_{2j}}} \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ \frac{e^{x_{m1}}}{\sum_{j}e^{x_{mj}}} & \frac{e^{x_{m2}}}{\sum_{j}e^{x_{mj}}} & \frac{e^{x_{m3}}}{\sum_{j}e^{x_{mj}}} & \dots & \frac{e^{x_{mn}}}{\sum_{j}e^{x_{mj}}} \end{bmatrix} \\ \\ &= \begin{pmatrix} softmax\text{(first row of x)} \\ softmax\text{(second row of x)} \\ \vdots \\ softmax\text{(last row of x)} \\ \end{pmatrix} \end{pmatrix} softmax(x)=softmaxx11x21xm1x12x22xm2x13x23xm3x1nx2nxmn=jex1jex11jex2jex21jexmjexm1jex1jex12jex2jex22jexmjexm2jex1jex13jex2jex23jexmjexm3jex1jex1njex2jex2njexmjexmn=softmax(first row of x)softmax(second row of x)softmax(last row of x)

Notes: m表示训练样本的数量,每个样本在矩阵中占一列,每个特征在矩阵中占一行。

Notes: 从上面的公式可以看出,在转置前,训练样本为按行排列的,其特征值按列排列。

softmax应当作用于每个训练样本的所有特征值上,所以softmax将会是逐列作用于矩阵的(转置后)。

不过在这个练习中,主要是为了熟悉python的使用,因而使用简单的矩阵 m × n m\times n m×n,即m行n列的矩阵。

# FUNCTION:softmax

def softmax(x):
    """
    逐行计算输入x的softmax()
		完成后的代码应当既能作用于行向量,又能作用于(m,n)维的矩阵。
   
    参数:
    x -- (m,n)维的numpy矩阵A

    返回:
    s -- 与softmax(x)等价的numpy矩阵A,维度为(m,n)
    """
    
    #(≈ 3 lines of code)
    # 使用np.exp(...)将exp()作用于x的每个元素上。
    # x_exp = ...

    # 创建向量x_sum将x_exp逐行想加。使用np.sum(..., axis = 1, keepdims = True).
    # x_sum = ...
    
    # 通过将x_exp与x_sum相除计算softmax(x)。这会自动使用numpy的广播机制。
    # s = ...
    
    # YOUR CODE STARTS HERE
    x_exp = np.exp(x)
    x_sum = np.sum(x_exp,axis = 1,keepdims=True)
    s = np.divide(x_exp,x_sum)
    
    # YOUR CODE ENDS HERE
    
    return s
t_x = np.array([[9, 2, 5, 0, 0],
                [7, 5, 0, 0 ,0]])
print("softmax(x) = " + str(softmax(t_x)))

正确的输出应为:

softmax(x) = [[9.80897665e-01 8.94462891e-04 1.79657674e-02 1.21052389e-04
  1.21052389e-04]
 [8.78679856e-01 1.18916387e-01 8.01252314e-04 8.01252314e-04
  8.01252314e-04]]

Notes:

  • 试着打印出x_exp,x_sum,x的维度,可以看到x_sum的维度是(2,1)而其余的维度都是(2,5)。x_exp/x_sum能够相除,是由于python的广播机制。

总结:

  • Np.exp(x)对任意np.array类型的变量x均有效,并且可以对x中的每个元素作指数运算。
  • sigmoid()和sigmoid()的梯度。
  • Image2vector 在深度学习中经常用到。
  • np.reshape使用很多。如果能使用np.reshape()保证矩阵的维度是你想要的维度,能够避免很多bug的出现。
  • numpy有许多效率很高的函数。
  • broadcasting机制很有用。
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《Neural Networks and Deep Learning》这本书被许多人评价为是关于深度学习的一本非常好的入门书。它以清晰易懂的方式解释了深度学习的核心概念,并且使用大量的图片和代码来帮助读者理解。如果您对深度学习感兴趣,那么这本书是一个不错的选择。 ### 回答2: 《Neural Networks and Deep Learning》是一本非常出色的书籍。它由Michael Nielsen撰写,提供了关于神经网络和深度学习的详细而清晰的介绍。 这本书以易于理解和深入的方式解释了神经网络和深度学习的基本概念和原理。它从基础知识开始,逐步引导读者了解神经元、多层神经网络、反向传播和激活函数等关键概念。通过直观的解释和简单的数学推导,读者可以很好地理解这些复杂的概念。 书中还包含了许多实例和示例,帮助读者将理论应用到实际问题中。例如,它详细介绍了如何使用神经网络解决手写数字识别的问题,并提供了相关的代码实现。这些实例不仅使得理论更加易于理解,也为读者提供了实际操作的经验和技能。 此外,《Neural Networks and Deep Learning》还提供了大量的引用文献和进一步阅读的建议,帮助读者进一步深入学习和探索相关领域的研究。这为读者进一步拓宽知识领域提供了便利。 总体而言,这本书不仅适合对神经网络和深度学习感兴趣的初学者,也适合那些已经有一定了解但希望进一步加深理解的读者。它以简洁明了的方式传递了复杂的概念,提供了大量的实例和引用文献,是一本极具价值的学习资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值