本文是根据 DataWhale 『巨硬的 numpy 』文档进行学习, 辅之以天池平台, 之前学习过, 此时进行进一步的整理, 着重学习未完全熟悉的知识点.
详细的代码我也放入了天池学习的AI训练营合集中
安装和导库
首先是安装 numpy .
pip install numpy
然后是导入库, 通常简写为 np .
import numpy as np
import matplotlib.pyplot as plt
数组的创建和生成
数组 ndarry 是 numpy 内最基本的数据结构, 本意是: n-dim array , 即 n 维的数组. 判断数组维度, 一般是根据轴 (axis) 来判断, 几个轴就是几维, 这个参数后续再提, 很多方法中会使用. 更简单的, 可以直接数括号 😏.
首先创建和生成 numpy 数组对象 array , 通常我们有几种常见的创建方式:
- 使用列表或元组
- 使用
arange - 使用
linspace / logspace (常用于绘制坐标轴) - 使用
ones / zeros - 使用
random (常用于生成一些模拟数据) - 从文件读取
使用列表创建
np.array([1,2,3])
其中存在一个小数 float , 那么 numpy 就会为了保持数据类型相同, 都转换为 float .
np.array([[1, 2., 3], [4, 5, 6]])
如果指定了 dtype , 输入的值都会被转为对应的类型, 而且不会四舍五入.
lst = [
[1, 2, 3],
[4, 5, 6.8]
]
np.array(lst, dtype=np.int32)
使用 arange 生成
arange 的原理类似于 python 内置的整数序列生成器 range , 通常在需要创建连续一维向量时使用.
np.arange(12)
np.arange(12).reshape(3, 4)
需要注意的是, reshape 前后的元素个数必须相同, 否则 reshape 会出现错误.
np.arange(10, 40, 2.5).reshape(3, 2, 2)
使用 linspace/logspace 生成
linspace 是一个线性序列, 需要三个参数 (开始, 结尾, 数量), 而不是步长, 这里需要注意.logspace 是 linspace 的扩展, 是指数序列, 需要的参数多了一个 base , 默认是 10 .
np.linspace(0, 9, 10).reshape(2, 5)
np.logspace(0, 9, 6, base=np.e).reshape(2, 3)
画图观察一下(黑暗主题可能看不见坐标轴)
N = 20
x = np.arange(N)
y1 = np.linspace(0, 10, N) * 100
y2 = np.logspace(0, 10, N, base=2)
plt.plot(x, y2, '*');
plt.plot(x, y1, 'o');
补充: 关于数组的比较
比较的结果依旧是一个由布尔值组成的 array .
arr = np.array([1, 2, 3])
cond1 = arr > 2
cond1
如果需要进行 if 判断一些是否存在 true , 或者全部为 true 的, 则需要使用 any() 或 all() 来使用
if cond1.any():
print("只要有一个为True就可以,所以——我可以")
if cond1.all():
print("所有值为True才可以,我正好这样")
使用 ones/zeros/full 创建
需要常数值的矩阵时使用, 注意是有 s 的.
- 零数组
- zeros()函数: 返回给定形状和类型的零数组.
- zeros_like()函数: 返回与给定数组形状和类型相同的零数组.
np.ones(shape=(2, 3))
np.full(shape=(2,3), fill_value=666)
np.zeros_like(np.ones((2,3,3)))
使用 eye/diag 创建
- eye()函数: 返回一个对角线上为1, 其它地方为零的单位数组.
- diag(v, k=0)函数: 提取对角线或构造对角数组, k代表向左上偏移几个单位.
x = np.eye(4)
print(x)
x = np.eye(2, 3)
print(x)
x = np.arange(9).reshape((3, 3))
print(x)
print(np.diag(x))
print(np.diag(x, k=1))
print(np.diag(x, k=-1))
v = [1, 3, 5, 7]
x = np.diag(v,k=1)
print(x)
使用 random 生成
random 是本章相对重要且常用的内容, 一般用来生成用于测试的随机数组.
但是在1.17 版本后, 更推荐使用新的API来生成, 即使用rng = np.random.default_rng(seed) 来获得 Generator , 在此基础上再进行各种分布的随机数生成.
连续均匀分布
产生符合 0-1 分布的随机数
np.random.rand()
np.random.rand(2, 3)
np.random.random(size=(3, 2))
指定上下限的随机数.
np.random.uniform(-100, 100, size=(2, 3))
使用推荐的 default_rng 的方法.
rng = np.random.default_rng(10086)
rng.random(size=(2, 3))
rng.uniform(0, 1, size=(2, 3))
离散均匀分布(整数)
生成随机整数
np.random.randint(10, size=2)
np.random.randint(20, 30, size=(2, 3))
使用推荐的 default_rng 的方法.
rng.integers(10, size=2)
rng.integers(0, 10, size=(2, 3))
标准正态分布
np.random.randn(2, 4)
使用推荐的 default_rng 的方法.
rng.standard_normal(size=(2, 4))
高斯分布
np.random.normal(loc=0, scale=1, size=(3, 5))
使用推荐的 default_rng 的方法.
rng.normal(loc=0, scale=1, size=(3, 5))
以上新旧版本的写法其实很类似, 简单来说就是使用了一个生成器 rng 来代替原本的 np.random , 习惯就好.
从文件中读写矩阵
主要是用于加载已经进行预处理的数组或保存好的权重参数, 便于一些耗时项目直接存储, 不需要重复训练.
注意: 此处保存的时候不需要增加后缀, 会自动添加
保存矩阵
np.save('./data/a', np.array([[1, 2, 3], [4, 5, 6]]))
np.savez("./data/b", a=np.arange(12).reshape(3, 4), b=np.arange(12.).reshape(4, 3))
np.savez_compressed("./data/c", a=np.arange(12).reshape(3, 4), b=np.arange(12.).reshape(4, 3))
读取矩阵
np.load("data/a.npy")
是否压缩并不影响读取文件.
arr = np.load("data/b.npz")
arr["a"]
其他创建方法
除了常见的np.array 创建新数组, 还可以使用其他方法进行创建.
使用 asarray() 进行创建
与 array 相同, 都可以将普通的结构数据转化为 ndarray 但是当数据源就是 ndarray时 , 且 dtype 不变时, asarray 创建的数组将不会开辟一个新的内存地址, 也就是, 而 array 则都会开辟一个新的内存空间来创建.
x = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]])
y = np.array(x)
z = np.asarray(x)
x[1][2] = 2
print(x,type(x),x.dtype)
print(y,type(y),y.dtype)
print(z,type(z),z.dtype)
使用 fromfunction() 进行创建
该方法是根据函数来创建数组, 常在绘图时使用. 该函数的参数 x, y 分别代表数组的坐标位置, 所以在绘图时非常方便.
def func(x, y):
return 10 * x + y
x = np.fromfunction(func, (5, 4), dtype=int)
print(x)
x = np.fromfunction(lambda i, j: i == j, (3, 3), dtype=int)
print(x)
个人收获
这里将原本的 numpy 知识重新回归了一下, 并且学到了一个新的创建数组的方法, 既然是新方法就应该多多适应, 在以后的使用中, 对比其中的优劣.
|