Python吴恩达深度学习作业 1 -- Numpy入门与函数向量化

Numpy 基础

大家好,这里是你们的第一个作业,即使你之前没有用过python,这个作业也会帮助你熟悉接下来会用到的功能

  • 操作指南:
    • 请使用python3
    • 避免使用for循环,除非题目里要求
    • 不要更改(# GRADED FUNCTION [function name])的注释
    • 写完代码,运行下面的cell确认你的输出是对的
  • 做完这个作业,你能学会:
    • 用ipython notebook
    • 用numpy,包括函数调用及向量矩阵运算
    • 理解“广播”的概念
    • 向量化代码

让我们开始吧!

关于iPython笔记本

iPython Notebook是嵌入在网页中的交互式编码环境。 你将在此类中使用iPython笔记本。 你只需要在### START CODE HERE ###和### END CODE HERE ###注释之间编写代码。 编写代码后,通过按“ SHIFT” +“ ENTER”或单击笔记本上部栏中的“Run Cell”来运行该单元块。


我们通常会在注释中说明“(≈X行代码)”,以告诉你需要编写多少行代码。 当然这只是一个粗略的估计,当你的代码更长或更短时,也不用在意。



练习:运行下面的两个单元格中将test设为“ Hello World”,并输出“ Hello World”。

test = "Hello World"
print("test: " + test)
test: Hello World

1-使用numpy构建基本函数

Numpy是Python中主要的科学计算包。它由一个大型社区维护。在本练习中,你将学习一些关键的numpy函数,例如np.exp,np.log和np.reshape。你需要知道如何使用这些函数去完成将来的练习。

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

提示:

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):
    s = 1 / (1 + math.exp(-x))
    return s
basic_sigmoid(3)
0.9525741268224334

因为函数的输入是实数,所以我们很少在深度学习中使用“math”库。 而深度学习中主要使用的是矩阵和向量,因此numpy更为实用。

x = [1, 2, 3]
basic_sigmoid(x)
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

~\AppData\Local\Temp\ipykernel_9164\2766938880.py in 
      1 x = [1, 2, 3]
----> 2 basic_sigmoid(x)


~\AppData\Local\Temp\ipykernel_9164\905362836.py in basic_sigmoid(x)
      2 
      3 def basic_sigmoid(x):
----> 4     s = 1 / (1 + math.exp(-x))
      5     return s


TypeError: bad operand type for unary -: 'list'

如果 x = ( x 1 , x 2 , . . . , x n ) x=(x_1,x_2,...,x_n) x=(x1,x2,...,xn)是行向量,则 n p . e x p ( x ) np.exp(x) np.exp(x)会将指数函数应用于x的每个元素。
因此,输入为: n p . e x p ( x ) = ( e 1 x , e 2 x , . . . , e n x ) np.exp(x)=(e^x_1,e^x_2,...,e^x_n) np.exp(x)=(e1x,e2x,...,enx)

import numpy as np
x = np.array([1, 2, 3])
print(np.exp(x))
[ 2.71828183  7.3890561  20.08553692]

如果x是向量,则 s = x + 3 s=x+3 s=x+3 s = 1 x s=\frac {1}{x} s=x1之类的Python运算将输出与x维度大小相同的向量s。

x = np.array([1, 2, 3])
print(x + 3)
[4 5 6]

练习:使用numpy实现sigmoid函数。

说明:x可以是实数,向量或矩阵。 我们在numpy中使用的表示向量、矩阵等的数据结构称为numpy数组。现阶段你只需了解这些就已足够。
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 ) sigmoid(x)=sigmoid\left( \begin{matrix} x_1 \\ x_2 \\ ... \\ x_n \end{matrix} \right)=\left( \begin{matrix} \frac {1}{1+e^{-x_1}} \\ \frac {1}{1+e^{-x_2}} \\ ... \\ \frac {1}{1+e^{-x_n}} \end{matrix} \right) sigmoid(x)=sigmoid x1x2...xn = 1+ex111+ex21...1+exn1
For x ∈ R n x \in R^n xRn

import numpy as np

def sigmoid(x):
    s = 1 / (1 + np.exp(-x))
    return s
x = np.array([1, 2, 3])
sigmoid(x)
array([0.73105858, 0.88079708, 0.95257413])

1.2- Sigmoid gradient

正如你在教程中所看到的,我们需要计算梯度来使用反向传播优化损失函数。 让我们开始编写第一个梯度函数吧。

练习:创建函数sigmoid_grad()计算sigmoid函数相对于其输入x的梯度。 公式为:
s i g m o i d _ d e r i v a t i v e ( x ) = δ ′ = δ ( x ) ( 1 − δ ( x ) ) sigmoid\_derivative(x)=\delta^\prime=\delta(x)(1-\delta(x)) sigmoid_derivative(x)=δ=δ(x)(1δ(x))

我们通常分两步编写此函数代码:

1.将s设为x的sigmoid。 你可能会发现sigmoid(x)函数很方便。

2.计算 δ ′ ( x ) = s ( 1 − s ) \delta^\prime(x)=s(1-s) δ(x)=s(1s)

def sigmoid_derivative(x):
    s = sigmoid(x)
    ds = s * (1 - s)
    return ds
x = np.array([1, 2, 3])
print ("sigmoid_derivative(x) = " + str(sigmoid_derivative(x)))
sigmoid_derivative(x) = [0.19661193 0.10499359 0.04517666]

1.3- 重塑数组

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

  • X.shape用于获取矩阵/向量X的shape(维度)。
  • X.reshape(…)用于将X重塑为其他尺寸。

例如,在计算机科学中,图像由shape为 ( l e n g t h , h e i g h t , d e p t h = 3 ) (length,height,depth = 3) (length,height,depth=3)的3D数组表示。但是,当你读取图像作为算法的输入时,会将其转换为维度为 ( l e n g t h ∗ h e i g h t ∗ 3 , 1 ) (length * height * 3, 1) (lengthheight3,1)的向量。换句话说,将3D阵列"展开"或重塑为1D向量。
Python吴恩达深度学习作业 1 -- Numpy入门与函数向量化_第1张图片

练习:实现image2vector() ,该输入采用维度为(length, height, 3)的输入,并返回维度为 ( l e n g t h ∗ h e i g h t ∗ 3 , 1 ) (length * height * 3, 1) (lengthheight3,1)的向量。例如,如果你想将形为(a,b,c)的数组v重塑为维度为(a*b, 3)的向量,则可以执行以下操作:

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 [0]等来查找所需的数量。
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],
        [ 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)))
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- 行标准化

我们在机器学习和深度学习中使用的另一种常见技术是对数据进行标准化。 由于归一化后梯度下降的收敛速度更快,通常会表现出更好的效果。 通过归一化,也就是将x更改为 x ∣ ∣ x ∣ ∣ \frac {x}{||x||} ∣∣x∣∣x(将x的每个行向量除以其范数)。

例如:
x = [ 0 3 4 2 6 4 ] x= \begin{bmatrix} 0&3&4 \\ 2&6&4 \end{bmatrix} x=[023644]
then
∣ ∣ x ∣ ∣ = n p . l i n a l g . n o r m ( x , a x i s = 1 , k e e p d i m s = T r u e ) = [ 5 = 0 2 + 3 2 + 4 2 56 = 2 2 + 6 2 + 4 2 ] ||x||=np.linalg.norm(x,axis=1,keepdims=True)= \begin{bmatrix} 5=\sqrt{0^2+3^2+4^2} \\ \sqrt{56}=\sqrt{2^2+6^2+4^2} \end{bmatrix} ∣∣x∣∣=np.linalg.norm(x,axis=1,keepdims=True)=[5=02+32+42 56 =22+62+42 ]
and
x n o r m a l i z e d = x ∣ ∣ x ∣ ∣ = [ 0 3 5 4 5 2 56 6 56 4 56 ] 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} xnormalized=∣∣x∣∣x=[056 25356 65456 4]
请注意,你可以划分不同大小的矩阵,以获得更好的效果:这称为broadcasting,我们将在第5部分中学习它。

练习:执行 normalizeRows()来标准化矩阵的行。 将此函数应用于输入矩阵x之后,x的每一行应为单位长度(即长度为1)向量。

def normalizeRows(x):
    x_norm = np.linalg.norm(x, axis = 1, keepdims = True)
    x = x / x_norm
    
    return x
x = np.array([
    [0, 3, 4],
    [1, 6, 4]])
print("normalizeRows(x) = " + str(normalizeRows(x)))
normalizeRows(x) = [[0.         0.6        0.8       ]
 [0.13736056 0.82416338 0.54944226]]

注意

在normalizeRows()中,你可以尝试print查看 x_norm和x的维度,然后重新运行练习cell。 你会发现它们具有不同的w维度。 鉴于x_norm采用x的每一行的范数,这是正常的。 因此,x_norm具有相同的行数,但只有1列。 那么,当你将x除以x_norm时,它是如何工作的? 这就是所谓的广播broadcasting,我们现在将讨论它!

1.5- 广播和softmax函数

在numpy中要理解的一个非常重要的概念是“广播”。 这对于在不同形状的数组之间执行数学运算非常有用。

练习: 使用numpy实现softmax函数。 你可以将softmax理解为算法需要对两个或多个类进行分类时使用的标准化函数。 你将在本专业的第二门课中了解有关softmax的更多信息。

s o r t m a x ( x ) = s o f t m a x ( [ x 1 x 2 . . . x n ] ) = [ e 1 x ∑ j e x j e 2 x ∑ j e x j . . . e n x ∑ j e x j ] sortmax(x)=softmax( \begin{bmatrix} x_1&x_2&...&x_n \end{bmatrix} )= \begin{bmatrix} \frac{e^x_1}{\sum_je^xj}&\frac{e^x_2}{\sum_je^xj}&...&\frac{e^x_n}{\sum_je^xj} \end {bmatrix} sortmax(x)=softmax([x1x2...xn])=[jexje1xjexje2x...jexjenx]

def softmax(x):
    x_exp = np.exp(x)
    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)))
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]]

注意

-如果你在上方输出 x_exp,x_sum和s的维度并重新运行练习单元,则会看到x_sum的纬度为(2,1),而x_exp和s的维度为(2,5)。 x_exp/x_sum 可以使用python广播。

恭喜你! 你现在已经对python numpy有了很好的理解,并实现了一些将在深度学习中用到的功能。

你需要记住的内容

  • np.exp(x)适用于任何np.array x并将指数函数应用于每个坐标
  • sigmoid函数及其梯度
  • image2vector通常用于深度学习
  • np.reshape被广泛使用。 保持矩阵/向量尺寸不变有助于我们消除许多错误。
  • numpy具有高效的内置功能
  • broadcasting非常有用

2-向量化

在深度学习中,通常需要处理非常大的数据集。 因此,非计算最佳函数可能会成为算法中的巨大瓶颈,并可能使模型运行一段时间。 为了确保代码的高效计算,我们将使用向量化。 例如,尝试区分点/外部/元素乘积之间的区别。

import time

x1 = [9, 2, 5, 0, 0, 7, 5, 0, 0, 0, 9, 2, 5, 0, 0]
x2 = [9, 2, 2, 9, 0, 9, 2, 5, 0, 0, 9, 2, 5, 0, 0]

### CLASSIC DOT PRODUCT OF VECTORS IMPLEMENTATION ###
tic = time.process_time()
dot = 0
for i in range(len(x1)):
    dot+= x1[i]*x2[i]
toc = time.process_time()
print ("dot = " + str(dot) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")

### CLASSIC OUTER PRODUCT IMPLEMENTATION ###
tic = time.process_time()
outer = np.zeros((len(x1),len(x2))) # we create a len(x1)*len(x2) matrix with only zeros
for i in range(len(x1)):
    for j in range(len(x2)):
        outer[i,j] = x1[i]*x2[j]
toc = time.process_time()
print ("outer = " + str(outer) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")

### CLASSIC ELEMENTWISE IMPLEMENTATION ###
tic = time.process_time()
mul = np.zeros(len(x1))
for i in range(len(x1)):
    mul[i] = x1[i]*x2[i]
toc = time.process_time()
print ("elementwise multiplication = " + str(mul) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")

### CLASSIC GENERAL DOT PRODUCT IMPLEMENTATION ###
W = np.random.rand(3,len(x1)) # Random 3*len(x1) numpy array
tic = time.process_time()
gdot = np.zeros(W.shape[0])
for i in range(W.shape[0]):
    for j in range(len(x1)):
        gdot[i] += W[i,j]*x1[j]
toc = time.process_time()
print ("gdot = " + str(gdot) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")
dot = 278
 ----- Computation time = 0.0ms
outer = [[81. 18. 18. 81.  0. 81. 18. 45.  0.  0. 81. 18. 45.  0.  0.]
 [18.  4.  4. 18.  0. 18.  4. 10.  0.  0. 18.  4. 10.  0.  0.]
 [45. 10. 10. 45.  0. 45. 10. 25.  0.  0. 45. 10. 25.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [63. 14. 14. 63.  0. 63. 14. 35.  0.  0. 63. 14. 35.  0.  0.]
 [45. 10. 10. 45.  0. 45. 10. 25.  0.  0. 45. 10. 25.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [81. 18. 18. 81.  0. 81. 18. 45.  0.  0. 81. 18. 45.  0.  0.]
 [18.  4.  4. 18.  0. 18.  4. 10.  0.  0. 18.  4. 10.  0.  0.]
 [45. 10. 10. 45.  0. 45. 10. 25.  0.  0. 45. 10. 25.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]]
 ----- Computation time = 0.0ms
elementwise multiplication = [81.  4. 10.  0.  0. 63. 10.  0.  0.  0. 81.  4. 25.  0.  0.]
 ----- Computation time = 0.0ms
gdot = [27.21704242 27.00032077 26.69452292]
 ----- Computation time = 0.0ms
x1 = [9, 2, 5, 0, 0, 7, 5, 0, 0, 0, 9, 2, 5, 0, 0]
x2 = [9, 2, 2, 9, 0, 9, 2, 5, 0, 0, 9, 2, 5, 0, 0]

### VECTORIZED DOT PRODUCT OF VECTORS ###
tic = time.process_time()
dot = np.dot(x1,x2)
toc = time.process_time()
print ("dot = " + str(dot) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")

### VECTORIZED OUTER PRODUCT ###
tic = time.process_time()
outer = np.outer(x1,x2)
toc = time.process_time()
print ("outer = " + str(outer) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")

### VECTORIZED ELEMENTWISE MULTIPLICATION ###
tic = time.process_time()
mul = np.multiply(x1,x2)
toc = time.process_time()
print ("elementwise multiplication = " + str(mul) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")

### VECTORIZED GENERAL DOT PRODUCT ###
tic = time.process_time()
dot = np.dot(W,x1)
toc = time.process_time()
print ("gdot = " + str(dot) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")
dot = 278
 ----- Computation time = 0.0ms
outer = [[81 18 18 81  0 81 18 45  0  0 81 18 45  0  0]
 [18  4  4 18  0 18  4 10  0  0 18  4 10  0  0]
 [45 10 10 45  0 45 10 25  0  0 45 10 25  0  0]
 [ 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0]
 [ 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0]
 [63 14 14 63  0 63 14 35  0  0 63 14 35  0  0]
 [45 10 10 45  0 45 10 25  0  0 45 10 25  0  0]
 [ 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0]
 [ 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0]
 [ 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0]
 [81 18 18 81  0 81 18 45  0  0 81 18 45  0  0]
 [18  4  4 18  0 18  4 10  0  0 18  4 10  0  0]
 [45 10 10 45  0 45 10 25  0  0 45 10 25  0  0]
 [ 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0]
 [ 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0]]
 ----- Computation time = 0.0ms
elementwise multiplication = [81  4 10  0  0 63 10  0  0  0 81  4 25  0  0]
 ----- Computation time = 0.0ms
gdot = [27.21704242 27.00032077 26.69452292]
 ----- Computation time = 0.0ms

你可能注意到了,向量化的实现更加简洁高效。 对于更大的向量/矩阵,运行时间的差异变得更大。

注意 不同于np.multiply()和* 操作符(相当于Matlab / Octave中的 .*)执行逐元素的乘法,np.dot()执行的是矩阵-矩阵或矩阵向量乘法,

2.1实现L1和L2损失函数

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

提示

  • 损失函数用于评估模型的性能。 损失越大,预测( y ^ \hat{y} y^) 与真实值( y y y)的差异也就越大。 在深度学习中,我们使用诸如Gradient Descent之类的优化算法来训练模型并最大程度地降低成本。
  • L1损失函数定义为:
    L 1 ( y ^ , y ) = ∑ i = 0 m ∣ y ( i ) − y ^ ( i ) ∣ L_1(\hat{y},y)=\sum_{i=0}^{m}|y^{(i)}-\hat{y}^{(i)}| L1(y^,y)=i=0my(i)y^(i)
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)))
L1 = 1.1

练习:实现L2损失函数的Numpy向量化版本。 有好几种方法可以实现L2损失函数,但是还是np.dot()函数更好用。 提醒一下,如果 x = [ x 1 , x 2 , . . . , x n ] x=\begin{bmatrix}x_1,x_2,...,x_n\end{bmatrix} x=[x1,x2,...,xn],则np.dot(x,x)= ∑ j = 0 n x j 2 \sum_{j=0}^{n}x_j^2 j=0nxj2

  • L2损失函数定义为:
    L 2 ( y ^ , y ) = ∑ i = 0 m ( y ( i ) − y ^ ( i ) ) 2 L_2(\hat{y},y)=\sum_{i=0}^{m}(y^{(i)}-\hat{y}^{(i)})^2 L2(y^,y)=i=0m(y(i)y^(i))2
def L2(yhat, y):
    loss = np.dot((y - yhat), (y - yhat).T)
    return loss
yhat = np.array([.9, 0.2, 0.1, .4, .9])
y = np.array([1, 0, 0, 1, 1])
print("L2 = " + str(L2(yhat,y)))
L2 = 0.43

你需要记住的内容

  • 向量化在深度学习中非常重要, 它保证了计算的效率和清晰度。
  • 了解L1和L2损失函数。
  • 掌握诸多numpy函数,例如np.sum,np.dot,np.multiply,np.maximum等。
    egin{bmatrix}x_1,x_2,…,x_n\end{bmatrix}$,则np.dot(x,x)= ∑ j = 0 n x j 2 \sum_{j=0}^{n}x_j^2 j=0nxj2
  • L2损失函数定义为:
    L 2 ( y ^ , y ) = ∑ i = 0 m ( y ( i ) − y ^ ( i ) ) 2 L_2(\hat{y},y)=\sum_{i=0}^{m}(y^{(i)}-\hat{y}^{(i)})^2 L2(y^,y)=i=0m(y(i)y^(i))2
def L2(yhat, y):
    loss = np.dot((y - yhat), (y - yhat).T)
    return loss
yhat = np.array([.9, 0.2, 0.1, .4, .9])
y = np.array([1, 0, 0, 1, 1])
print("L2 = " + str(L2(yhat,y)))
L2 = 0.43

你需要记住的内容

  • 向量化在深度学习中非常重要, 它保证了计算的效率和清晰度。
  • 了解L1和L2损失函数。
  • 掌握诸多numpy函数,例如np.sum,np.dot,np.multiply,np.maximum等。

你可能感兴趣的:(深度学习,python,深度学习,开发语言)