Numpy的基础用法
# 高效提取相应切片的索引方法(Indexing)'''[[1 2 3][4 5 6][7 8 9]]'''x = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])print(x[:, 0]) # 将会输出 [1 4 7]print(x[:, 1]) # 将会输出 [2 5 8]print(x[2, :]) # 将会输出 [7 8 9]print(x[:2, 0]) # 将会输出 [1 4]print(x[1, :2]) # 将会输出 [4 5]print(x[:2, :2]) # 将会输出 [[1 2], [4 5]]# 初始化为全0、全1、随机等x1 = np.zeros((3, 3)) # 建立3x3的全0矩阵print(x1)x2 = np.ones((3, 3)) # 建立3x3的全1矩阵print(x2)x3 = np.random.random((3, 3)) # 建立3x3的随机矩阵(0到1之间均匀分布)print(x3)# Numpy数组的加、减、乘、除x = np.array([[1, 2], [3, 4]])y = np.array([[4, 3], [2, 1]])# Numpy加法print(x + y) # 将会输出[[5, 5], [5, 5]]# Numpy减法print(x - y) # 将会输出[[-3, -1], [1, 3]]# Numpy乘法print(x * y) # element-wise乘法,将会输出[[4, 6], [6, 4]]print(np.dot(x, y)) # 矩阵乘法,将会输出[[8, 5], [20, 13]]# Numpy除法print(x / y) # 将会输出[[0.25, 2/3], [1.5, 4]]# Numpy支持一些列对高维数组的数学运算操作# 对每个元素取e的指数print(np.exp(x)) # 将会输出[[e^1, e^2], [e^3, e^4]]# 对每个元素取根号print(np.sqrt(x)) # 将会输出[[1, 根号2], [根号3, 2]]# 对第一个axis取平均值print(np.average(x, axis = 0)) # 将会输出[2, 3]# 对第二个axis取平均值print(np.average(x, axis = 1)) # 将会输出[1.5, 3.5]
'''
axis概念解释:不同的axis可以视为不同深度的for循环所对应的数据:
1、第一个axis对应着第一层for循环所能达到的数据;
2、第二个axis对应着第二层for循环所能达到的数据;
n、第n个axis对应着第n层for循环所能达到的数据。
'''
x = np.array([[1, 2], [3, 4]])
print(x)
# 对第一个axis取平均值
print(np.average(x, axis = 0)) # 将会输出[2, 3]
# 对第二个axis取平均值
print(np.average(x, axis = 1)) # 将会输出[1.5, 3.5]
# axis = 0 的等价描述
result = np.zeros(2)
for elem in x:
result += elem
print(result / 2)
# axis = 1 的等价描述
result = np.zeros(2)
idx = 0
for row in x:
for elem in row:
result[idx] += elem
idx += 1
print(result / 2)

算法的向量化与“升维”
'''
算法向量化与“升维”两点思想:
1、将for循环替换成Numpy运算;
2、将难以直接向量化的算法所对应的数组进行“升维”;
'''
import time
# 第一点是向量化思维的基石
x = np.random.random((1000, 1000))
ans = np.zeros((1000, 1000))
# 目的:计算 x + 1 并将结果存进ans中
# 编写繁琐、效率低下的for循环写法
t = time.time()
for i, row in enumerate(x):
for j, elem in enumerate(row):
ans[i][j] = elem + 1
t = time.time() - t
print(t)
# 利用Numpy运算直接进行实现
t = time.time()
ans = x + 1
t = time.time() - t
print(t)
# 更快、更省内存的写法
t = time.time()
np.add(x, 1, ans)
t = time.time() - t
print(t)
# 第二点是对广播(Broadcasting)的高级应用,利用Broadcasting来将某一段重复的运算进行向量化
x = np.array([1, 2, 3])
y = np.array([[1, 1, 1], [2, 2, 2], [3, 3, 3]])
z = y - x
print(z)
# 方式一:利用Numpy自带的函数——np.tile
x = y = np.array([1, 2, 3])
y = np.tile(y, [3, 1]).T # 此时y变为 [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
z = y - x
print(z)
# 方式二:利用Numpy的Broadcasting进行“升维”运算
# y“宽度”为1,x“宽度”为3,Numpy的Broadcasting内部对y隐性进行“扩张”以“适配”x的宽度
x = y = np.array([1, 2, 3])
z = y[:, None] - x
print(z)
高效应用Numpy的一个思想
使用Numpy时,应该尽量避免不必要的拷贝。
比如:
计算ans = x + 1时,最快的实现方式是np.add(x, 1, ans)
- 对于np.add(x, 1, ans),在计算x+1时会将结果直接写进ans;
- 对于ans = x + 1, 会将x+1的结果放进内存,再把内存中的结果赋值给ans。
建议:
- x = x + 1(建议使用x+=1);
- y = x.flatten()(建议使用y = x.ravel());
- x = x.T(无替换方案,不过我们要尽量少用转置)
在觉得程序运行不如想象中的高效时,检查是否引发了不必要的拷贝时一个重要的应用思想。
