站点图标 AI技术聚合

神经网络的编程基础2

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

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

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)会被用到。

注意:

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

# 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循环,而是将向量化后的数据作为输入。这样可以最大程度地加快运算速度,并且能大大简化我们的模型。

文章出处登录后可见!

已经登录?立即刷新
退出移动版