Neural Networks and Deep Learning(week 2_python 编程练习-2)
吴恩达深度学习课程第二周编程练习——python的numpy基础-2
- 本文主要讲python基础编程numpy基础的第二部分,即向量化与非向量化的差别及如何使用numpy进行向量化。
- 第一部分见上篇文章,点链接查看。
Python Basics with Numpy-2
2.向量化
在深度学习中需要处理规格很大的数据集。因此,一个不是最佳的可计算函数会成为算法的致命瓶颈,而且可能导致计算运行结果需要花费数年。为了确保代码计算更有效率,需要使用向量化。首先,试着区分以下例子中dot/outer/elementwise运算结果的不同。
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]
### 基本的向量dot运算 ###
tic = time.process_time()
dot = 0
### 此处表示基本的dot点乘运算即两向量相应位置的元素相乘再相加。
### 最后的结果为一个实数。
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")
### 基本的outer运算 ###
tic = time.process_time()
### 此处表示基本的outer运算,即我们熟知的矩阵/向量乘法运算。
### 假设len(x1)=m,len(x2)=n,x1表示行向量,x2表示列向量。即(m,1)(1,n)维的向量相乘,结果为(m,n)维的矩阵。
### (m,n)维矩阵中元素x_ij = x1(i,1)*x2(1,j)
outer = np.zeros((len(x1), len(x2))) # 创建一个len(x1)*len(x2)维的零矩阵。
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")
### 基本的elementwise运算 ###
tic = time.process_time()
### 与dot运算类似,均是对应位置元素相乘,x1_i * x2_i, 但是不用相加,而是各位置元素相乘得到的值组成一个新向量。
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")
### 基本的总体dot运算 ###
W = np.random.rand(3,len(x1)) # 随机 3*len(x1) 维的numpy array
tic = time.process_time()
### W是随机矩阵,类型为numpy array。此例gdot(1,3)维的向量,gdot中的第i个值,为随机生成的W中第i行向量与x1作dot(点乘运算,即基本向量dot运算)得到的值。
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")
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]
### 向量化后的向量dot运算 ###
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")
### 向量化后的outer运算 ###
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")
### 向量化后的elementwise运算 ###
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")
### 向量化后的general dot运算 ###
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")
你可能注意到了,向量化后的代码更简洁,运算速度也更快。对更大的矩阵/向量来说,运算速度差异会更大。
注意: np.dot()
表示矩阵-矩阵或矩阵-向量相乘,与np.multiply()
和*
操作符不同。
关于np.dot,np.outer,np.multiply的区别可以看此链接。
2.1 计算L1,L2损失函数
Exercise 7 - L1
计算向量化后的L1损失函数,函数abs(x)会被用到。
注意:
- 损失函数是用来评估模型的表现。损失越大,那么预测值 y ^ \hat{y} y^ 和 y y y 的实际值差别越大。在深度学习中,可以使用类似梯度下降的优化算法或者继续修正模型来最小化成本。
- L1 损失的定义如下:
L 1 ( y ^ , y ) = ∑ i = 0 m − 1 ∣ y ( i ) − y ^ ( i ) ∣ L_1(\hat{y}, y) = \sum_{i=0}^{m-1}|y^{(i)} - \hat{y}^{(i)}| L1(y^,y)=i=0∑m−1∣y(i)−y^(i)∣
# FUNCTION:计算L1 loss
def L1(yhat, y):
"""
参数:
yhat -- m维向量(预测值标签)
y -- m维向量 (真实值标签)
返回:
loss -- 上面定义的L1函数的值
"""
loss = np.sum(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
。
Exercise 8 - L2
计算向量化后的L2损失函数。有许多种计算L2损失的方法,不过推荐使用np.dot()
。
若
x
=
[
x
1
,
x
2
,
.
.
.
,
x
n
]
x = [x_1, x_2, ..., x_n]
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 − 1 ( y ( i ) − y ^ ( i ) ) 2 L_2(\hat{y},y) = \sum_{i=0}^{m-1}(y^{(i)} - \hat{y}^{(i)})^2 L2(y^,y)=i=0∑m−1(y(i)−y^(i))2
# FUNCTION:计算L2 loss
def L2(yhat, y):
"""
参数:
yhat -- m维向量(预测值标签)
y -- m维向量 (真实值标签)
返回:
loss -- 上面定义的L2函数的值
"""
loss = np.sum(np.dot(y-yhat,y-yhat))
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
.
总结:
在深度学习中,尽量避免使用for、while循环,而是将向量化后的数据作为输入。这样可以最大程度地加快运算速度,并且能大大简化我们的模型。