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)会被用到。
注意:
- 损失函数用于评估模型的性能。损失越大,预测值
与实际值
的差异越大。在深度学习中,可以使用梯度下降等优化算法,或者可以继续修改模型以最小化成本。
- L1 损失的定义如下:
# 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()
。
如果,则
np.dot(x,x)
=。
- L2损失的定义如下:
# 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循环,而是将向量化后的数据作为输入。这样可以最大程度地加快运算速度,并且能大大简化我们的模型。
文章出处登录后可见!
已经登录?立即刷新