Neural Networks and Deep Learning ( Week 2 )

本周学习重点在于将逻辑回归的低效循环实现转换为向量化形式,提高计算速度。介绍了向量化概念,展示了如何将内积、幂运算、对数、绝对值、比较和倒数等操作向量化。同时讲解了广播机制和Python/Numpy中的向量处理,特别提醒避免使用特定形状的秩为1数组,推荐使用reshape和断言来优化代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

整个第二周的第一个任务就是将一个低效的用循环实现的逻辑回归计算图用向量化的形式改写,以提升速率。

Vectorization

此节阐述了概念并证明了向量化可以显著提升性能。向量化是指将循环操作的向量运算转化为直接的向量运算。可以显著提升性能。

  • 内积
//a,b 分别为百万数量级的数组,求两个数组的内积

//向量化
c = np.dot(a, b) 
//消耗时间约1.5ms 

//非向量化

for i in range(1000000):
    c += a[i]*b[i]
// 消耗时间约500ms

注意: np.dot只有在运算秩为 1 的向量(即数组)的时候,会直接把两个向量直接做内积(因为行向量和列向量并没有区别)
对于普通矩阵来说,会遵循矩阵乘法规律

More Vectorization Examples

一些可以向量化的计算例子。

  • 矩阵内元素作为幂指数
import numpt as np
u = np.exp(v)

完成了从:

v=v1...vn v = [ v 1 . . . v n ]

到:

u=ev1...evn u = [ e v 1 . . . e v n ]

的转换。

同样支持向量的还有:

  • 对数转换:
np.log(v) \\以 e 为底
np.log10(v)\\以 10 为底
  • 绝对值:
np.abs(v)
  • 比较大小:
np.maxium(v, 0)
  • 乘方:
v**2
  • 倒数
1 / v

Vectorizing Logistic Regression

Vectorizing Logistic Regression’s Gradient Output

改写过程

基于计算图:
这里写图片描述

可以写一个低效的实现:

// 1. 初始化各变量
J = 0; dw1 = 0; dw2 = 0; db = 0;
// 2. 求导过程
for  i = 1 to m:
    //正向传播
    z = w.T * x[i] + b //假设 x[i] 为第i个样本,列向量
    a = sigmoid(z)
    J += -( y[i]log(a) + (1-y[i])log(1-a) ) // y[i]为第 i 个真值
    //反向
    dz = a - y[i] // dz为单样本导数,即 L 对 z 求导
    //此时 J 并非为代价函数值,同理 J dw db 也都为累加器
    //[ Update: 这里使用了遍历每个 w 来累加的方法,相当于一个 for 循环,可以使用向量化消解]
    dw1 += x[i][0]dz
    dw2 += x2[i][1]dz
    db += dz
J /= m //此时 J 为代价函数值
dw1 /= m 
dw2 /= m
db /= m

改写为:

// 首先将 m 个样本组织为 nx * m 的矩阵,每一列为一个样本。针对上方计算图 nx 为 2,命名为 X
// m 个真值组织为长度为 m 的行向量 Y
// 权值 w 则初始化为长度为 nx 的列向量,命名为 W
// 偏置 b 为一个数

// 1. 初始化其他各变量
dw = np.zeros((nx,1)); // 将 dw 初始化为容量为 nx 的列向量  
J = np.zeros((m,1)); // 将 J 初始化为容量为 m 的列向量
db = 0;

// 2. 正向传播
Z = np.dot(w.T, X) + b // Z 为 1 * m 的行向量
A = sigmoid (Z) // A 为 1 * m 的行向量
//J = -( np.dot(log(A), Y.T) + np.dot(log(1-A), (1 - Y)) )

// 3. 反向传播
dZ = A - Y // dZ 为 1 * m 的行向量 
dw = 1 / m * np.dot(X, dZ.T) //dw 显然为一长度为 nx 的列向量
db = 1 / m * np.sum(dZ)

// 4. 更新权重
W = W - alpha * dw
b = b - alpha * db

Broadcasting in Python

General rules

这里写图片描述

  • 向量加常量,会自动展常量变向量

这里写图片描述

  • 当(m, n) 矩阵和 (1, n)矩阵发生运算,则后者展为(m, n)

这里写图片描述

  • 当(m, n) 矩阵和 (m, 1) 矩阵发生运算,后者展为(m, n)
import numpy as np

A = np.array([[56.0, 0.0, 4.4, 68.0],
                   [1.2, 104.0, 52.0, 8.0],
                   [1.8, 135.0, 99.0, 0.9]])

print(A)

// [[ 56.    0.    4.4  68. ]
// [  1.2 104.   52.    8. ]
// [  1.8 135.   99.    0.9]]

cal = A.sum(axis=0) //(沿着第0维度求和,即垂直求和,得到每列的和)

print (cal) 

// [ 59.  239.  155.4  76.9]

new_cal = cal.reshape(1,4)

print(new_cal)

// [[ 59.  239.  155.4  76.9]] 数组化为 1 * 4 的矩阵

percentage = 100 * A / new_cal // [ 广播 ] : 3 * 4 的矩阵 乘上(除以) 1 * 4 的矩阵

print(percentage)

// [[94.91525424  0.          2.83140283 88.42652796]
// [ 2.03389831 43.51464435 33.46203346 10.40312094]
// [ 3.05084746 56.48535565 63.70656371  1.17035111]]

A note on python/numpy vectors

  • 秩为 1 的数组

import numpy as np

a = np.random.randn(5)
print(a)

// [-1.97883759 -0.28026896  1.16111207  1.2592107   1.28862289]

print(a.shape) 

// (5,) 这是一个秩为 1 的数组

print(a.T)

// [-1.97883759 -0.28026896  1.16111207  1.2592107   1.28862289] 
// 转置和本身相同

print(np.dot(a,a.T))

// 8.588690696216716

基于以上特殊特性,尽量不要使用这种形状的数组。

作为代替使用:

a = np.random.randn(5)
print(a)

/*
[[-2.26039006]
 [ 0.21935117]
 [ 0.36571892]
 [-1.70798974]
 [ 0.42144928]]
 得到一个 5 * 1 的列向量
 */
  • 断言语句
assert(a.shape == (5,1))
  • reshape 语句
a = a.reshape(n, m)

Explanation of logistic regression cost function (optional)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值