学习笔记-Numpy知识
文章目录
- 学习笔记-Numpy知识
-
- Numpy介绍
- Numpy数组的创建
- Numpy索引与切片
- [数组中的Shape 和 Reshape](#数组中的Shape 和 Reshape)
- Numpy中的数组运算
- 矩阵运算
- Numpy中的统计操作
- dtype
-
- [type和 dtype的区别](#type和 dtype的区别)
- Numpy中的随机数
- 布尔索引
- Numpy数组的复制、拼接与拆分
- Numpy与PyTorch
-
- Numpy与PyTorch
- [torch.tensor() 和 torch.from_numpy()](#torch.tensor() 和 torch.from_numpy())
- Tensor和ndarray的shape
- NumPy和PyTorch的相同点
Numpy介绍
NumPy 全名是 "Numerical Python",也就是"用于数值计算的 Python 库"。
普通 Python 当然也可以进行数学计算,但要是进行大量的向量计算、矩阵计算、机器学习数据处理,NumPy 会方便很多。
ndarray介绍
ndarray 是 Numpy 中最核心的数据结构,其可以理解成一个专门用于数学计算的高级数组。
python
import numpy as np
a = np.array([1, 2, 3]) # 这里的操作就是把Python的列表转化为Numpy数组
print(a) # 输出[1 2 3]
为什么不直接使用 Python 列表?
Python列表不能直接用于计算,还需要转换,步骤繁琐,Numpy可以直接进行计算。
python
# 直接在python中计算
a = [1, 2, 3]
a * 2 # 这里会输出[1, 2, 3, 1, 2, 3],因为"*"在python中是重复列表操作
python
import numpy as np
a = np.array([1, 2, 3])
print(a * 2) # 这里会输出[2 4 6],可以直接对整个数组进行数学运算
Numpy中的多维数组
python
# 一维 可以想象成 1 2 3
a = np.array([1, 2, 3])
"""
二维 可以想象成:
1 2 3
4 5 6
"""
b = np.array([
[1, 2, 3],
[4, 5, 6]
])
# 三维 可以想象成很多个二维矩阵一层一层堆叠起来
c = np.array([
[
[1, 2],
[3, 4]
],
[
[5, 6],
[7, 8]
]
])
shape属性
python
import numpy as np
a = np.array([
[1, 2, 3],
[4, 5, 6]
])
print(a.shape) # 输出(2, 3),这个数组有2 行、3 列
a = np.array([
[1, 2],
[3, 4],
[5, 6]
])
print(a.shape) # 输出(3, 2),这个数组有3行、2列
ndim属性
python
import numpy as np
a = np.array([1, 2, 3])
print(a.ndim) # 输出1,这个数组是1维的
a = np.array([
[1, 2, 3],
[4, 5, 6]
])
print(a.ndim) # 输出2,这个数组是2维的
总结
| 属性 | 含义 |
|---|---|
shape |
每个维度有多少个元素 |
ndim |
有多少个维度 |
完整例子
python
import numpy as np # 引入Numpy包
data = np.array([ # 创建Numpy数组
[10, 20, 30],
[40, 50, 60]
])
print(data)
print(data.shape) # 打印data数组每个维度的元素个数 输出(2,3)
print(data.ndim) # 打印data数组的维度 输出2
result = data * 2 # 对data数组中所有元素进行乘2操作
print(result)
# 上述代码运行结果
[[10 20 30]
[40 50 60]]
(2, 3)
2
[[ 20 40 60]
[ 80 100 120]]
Numpy数组的创建
常用的几种创建方式
- 使用
np.array()创建:最常用的创建方式
python
import numpy as np
a = np.array([1, 2, 3])
print(a) # 输出 [1 2 3]
a = np.array([
[1, 2, 3],
[4, 5, 6]
])
print(a)
"""
输出
[[1 2 3]
[4 5 6]]
"""
- 使用
np.zeros()创建:创建全0数组
python
a = np.zeros(5) # 创建包含5个0的一维数组
print(a) # 输出[0. 0. 0. 0. 0.]
a = np.zeros((2, 3)) # 创建二维数组,第一维度有两个元素,第二维度有3个元素,第二维度的元素都为0
print(a)
"""
输出
[[0. 0. 0.]
[0. 0. 0.]]
"""
- 使用
np.ones()创建:创建全1数组
python
a = np.ones((2, 3)) # 此用法与zeros相似,只不过0全部变为1
print(a)
"""
输出
[[1. 1. 1.]
[1. 1. 1.]]
"""
- 使用
np.arange()创建:创建连续数字数组
python
a = np.arange(5) # 创建连续数组的数组 依旧遵循range左闭右开的原则
print(a) # 输出 [0 1 2 3 4]
np.arange(0, 10, 2) # 可以设置步长
print(a) # 输出 [0 2 4 6 8]
示例
python
import numpy as np
a = np.zeros((2, 3)) # 创建全零的二维数组
b = np.ones((3, 2)) # 创建全1的二维数组
c = np.arange(2, 8, 2) # 创建1维的连续数字数组,数字从2开始到8结束,不包含8
Numpy索引与切片
一维数组索引
在Numpy中,一维数字索引与python中用法相同
python
# 一维数字索引
import numpy as np
a = np.array([10, 20, 30, 40, 50])
print(a[0]) # 输出10
print(a[2]) # 输出20
print(a[4]) # 输出30
二维数组索引
python
# 二维数字索引
a = np.array([
[10, 20, 30],
[40, 50, 60]
])
print(a[0,0]) # 输出10,代表的是第0行、第0列的元素
print(a[1,2]) # 输出60,代表的是第1行、第2列的元素
在Numpy中,"a0"代表的不是第一个数字,其意思为取第0行
python
a = np.array([
[10, 20, 30],
[40, 50, 60]
])
print(a[0]) # 输出[10 20 30]
print(a[1]) # 输出[40 50 60]
一维数组切片
Numpy中的切片与python列表基本一致
python
# 一维切片
a = np.array([10, 20, 30, 40, 50])
print(a[1:4]) # 输出[20 30 40],依旧遵循左闭右开的原则
二维数组切片
python
# 二维数组切片
a = np.array([
[10, 20, 30],
[40, 50, 60],
[70, 80, 90]
])
print(a[0:2]) # 这表示的含义是取第0行到第2行之前
"""
输出结果为:
[[10 20 30]
[40 50 60]]
"""
":"的含义
在Numpy中,":"可以被理解为这一维全部取
python
a = np.array([
[10, 20, 30],
[40, 50, 60],
[70, 80, 90]
])
print(a[:,0]) # 表示取所有行的第0列,最后输出为[10 40 70]
print(a[:,1]) # 表示取所有行的第1列,最后输出为[20 50 80]
print(a[:,1:3]) # 表示取所有行的第1列到第3列之前
"""
a[:,1:3]最后输出为:
[[20 30]
[50 60]
[80 90]]
"""
数组中的Shape 和 Reshape
shape
shape用于输出数组每个维度有多少个元素
python
import numpy as np
a = np.array([
[1, 2, 3],
[4, 5, 6]
])
print(a.shape) # 输出(2,3) 表示2行3列,一共2*3个元素
reshape
reshape的意思为"改变数组的形状",reshape不会改变数据本身,数据没有增加,也没有减少,只是重新排列成了不同的形状。
python
a = np.array([1, 2, 3, 4, 5, 6])
b = a.reshape(2, 3) # 将原来的一维数组变为二维数组
print(b)
"""
b的输出结果为:
[[1 2 3]
[4 5 6]]
"""
遵循原则:reshape 前后,两个数组的元素总数量必须相同。
以上述内容为例,原数组为1 2 3 4 5 6,共有6个元素,这里就可以进行reshape(2,3),因为2*3=6,当然也可以reshape(3,2)
python
import numpy as np
data = np.arange(1, 13) # 得到[1 2 3 4 5 6 7 8 9 10 11 12]
print(data) # 输出[1 2 3 4 5 6 7 8 9 10 11 12]
data = data.reshape(3, 4) # 利用reshape进行转换,转换为3行4列的数组
print(data)
"""
最后的输出结果为:
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
"""
Numpy中的数组运算
Numpy最强大的地方在于可以直接对数组进行数学运算, 其会把运算作用到每一个元素
python
import numpy as np
a = np.array([1, 2, 3])
print(a + 10) # 整体元素全部加10 输出[11 12 13]
print(a * 2) # 整体元素全部乘2 输出[2 4 6]
print(a - 1) # 整体元素全部减1 输出[0 1 2]
print(a / 2) # 整体元素全部除2 输出[0.5 1. 1.5]
a = np.array([
[1, 2],
[3, 4]
])
print(a * 2)
"""
输出结果为:
[[2 4]
[6 8]]
"""
在Numpy中,两个数组也可以直接进行运算
python
a = np.array([1, 2, 3])
b = np.array([10, 20, 30])
print(a + b) # 输出为[11 22 33]
print(a * b) # a*b不是矩阵乘法,是对应位置的元素分别相乘 输出为[10 40 90]
广播机制
python
a = np.array([
[1, 2, 3],
[4, 5, 6]
])
b = np.array([10, 20, 30])
print(a + b)
"""
Numpy自动把[10 20 30]广播到a的每一行,然后进行运算
输出结果为:
[[11 22 33]
[14 25 36]]
"""
矩阵运算
在Numpy中,"*"与"@"完全不同,前者代表的是对应元素相乘,后者代表的是矩阵乘法
*:对应元素相乘
python
import numpy as np
a = np.array([
[1, 2],
[3, 4]
])
b = np.array([
[10, 20],
[30, 40]
])
print(a * b)
"""
实际上,a*b进行的操作是元素进行运算
a*b输出结果为:
[[10 40]
[90 160]]
"""
@:矩阵乘法
python
import numpy as np
a = np.array([
[1, 2],
[3, 4]
])
b = np.array([
[10, 20],
[30, 40]
])
print(a @ b) # 这里对应的是矩阵乘法
"""
根据线性代数
第1行第1列的数值为1*10+2*30=70,第1行第2列的数值为1*20+2*40=100
第2行第1列的数值为3*10+4*30=150,第2行第2列的数值为3*20+4*40=220
最后a @ b的结果为:
[[ 70 100]
[150 220]]
"""
矩阵乘法中的重要规则
tex
假设:
A.shape = (2, 3)
B.shape = (3, 4)
则:
A @ B是可以被计算的,即前矩阵的列数对应后矩阵的行数,这里输出的是(2,4)的矩阵
Numpy中的统计操作
常用统计函数
python
np.sum() # 求和函数
np.mean() # 平均值函数
np.max() # 最大值函数
np.min() # 最小值函数
python
import numpy as np
a = np.array([10, 20, 30, 40])
print(np.sum(a)) # 输出100
print(np.mean(a)) # 输出25.0
print(np.max(a)) # 输出40
print(np.min(a)) # 输出10
axis(轴)
二维数组中,np.sum()是所有元素相加,但是np.sum(a, axis=0)与np.sum(a, axis=1)的结果不同,axis是Numpy中的"轴"概念,对于二维数组,axis=0是按列计算,axis=1是按行计算,axis 指的是"沿着哪个维度进行压缩/聚合"
python
# axis=0 → 压缩行这个方向 → 每列得到一个结果
# axis=1 → 压缩列这个方向 → 每行得到一个结果
a = np.array([
[1, 2, 3],
[4, 5, 6]
])
np.sum(a, axis=0) # 这里指的是沿着第0维进行计算,也就是把每一列往下加 结果为[5 7 9]
np.sum(a, axis=1) # 这里可以理解成把每一行的元素加起来 结果为[6 15]
a = np.array([
[10, 20, 30],
[40, 50, 60],
[70, 80, 90]
])
np.sum(a) # 输出450
np.sum(a, axis=0) # 输出[120 150 180]
np.sum(a, axis=1) # 输出[60 150 240]
axis不止适用于求和函数,同样适用于其他统计函数
python
a = np.array([
[10, 20, 30],
[40, 50, 60]
])
np.mean(a, axis=0) # 根据列计算每列的平均值,结果为[25. 35. 45.]
np.mean(a, axis=1) # 根据行计算每行的平均值,结果为[20. 50.]
python
# 综合检验
import numpy as np
data = np.arange(1, 13) # 从1开始到13结束(不包含13)的一维数组
data = data.reshape(3, 4) # 利用reshape1完成数组转换,3行4列
print(data)
print(data.shape) # 输出(3,4)
print(data[:, 1]) # 输出data中所有行第2列,为[2 6 10]
print(data * 2) # 对data中的元素进行乘2操作
print(np.sum(data, axis=0)) # 按列对data中的元素进行求和,为[15 18 21 24]
print(np.mean(data, axis=1)) # 按行对data中的元素进行平均,为[2.5 6.5 10.5]
dtype
type和 dtype的区别
python
import numpy as np
a = np.array([1, 2, 3])
print(type(a)) # 输出 <class 'numpy.ndarray'> 这里输出的是a是什么类型的对象
print(a.dtype) # 输出 int64 这里输出的是a里面的数据是什么类型
python
a = np.array([1, 2, 3], dtype=float) # 指定dtype,要求把它保存成浮点数
print(a) # 输出[1. 2. 3.]
print(a.dtype) # 输出float64
Numpy中的随机数
np.random.rand()
python
import numpy as np
a = np.random.rand(3) # 随机生成3个0到1之间的随机浮点数
print(a) # 每次运行结果不同
# 可以生成二维数组
a = np.random.rand(2, 3) # 随机生成2行3列的二维数组,数组中的元素为0到1之间的随机浮点数
np.random.randint()
python
a = np.random.randint(1, 10, 5) # 随机生成1到10(不包含10)之间的数,生成5个
print(a)
# 生成二维数组
a = np.random.randint(1, 10, (2, 3)) # 随机生成2行3列的二维数组,数组中的元素为1到10(不包含)之间的随机整数
print(a)
布尔索引
布尔索引就是把满足条件的元素筛选出来,做数据集处理、异常值处理、模型参数分析时都会用到
python
a = np.array([10, 20, 30, 40, 50])
print(a>30) # 输出[False False False True True]
print(a[a>30]) # 输出[40 50]
多条件布尔索引
python
a = np.array([10, 20, 30, 40, 50, 60, 70])
result = a[(a > 30) & (a < 60)] # 找出大于30并且小于60的数据
result = a[(a < 20) | (a > 60)] # 找出小于20或者大于60的数据
result = a[~(a > 30)] # 找出小于等于30的数据
Numpy数组的复制、拼接与拆分
数组的复制:copy()
python
import numpy as np
a = np.array([1, 2, 3])
b = a
b[0] = 100 # b进行变化后,a也会发生相应变化,这里可以理解为b和a指向了同一个数组
print(a) # 输出[100 2 3],受到了影响
print(b)
真正的复制:copy()
python
import numpy as np
a = np.array([1, 2, 3])
b = a.copy() # 这里相当于复制操作,创建了一共真正独立的新数组
b[0] = 100
print(a) # 输出[1 2 3],不受影响
print(b) # 输出[100 2 3]
数组拼接
机器学习处理数据时,经常需要把多个数组合在一起,其中最基础的是:np.concatenate()
python
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.concatenate([a, b])
print(c) # 输出[1 2 3 4 5 6],将2个数组进行了拼接
二维数组的拼接
python
a = np.array([
[1, 2],
[3, 4]
])
b = np.array([
[5, 6],
[7, 8]
])
c = np.concatenate([a, b], axis=0) # 以列为单位进行拼接 这里进行的是上下拼接
c = np.concatenate([a, b], axis=1) # 以行为单位进行拼接 这里进行的是左右拼接
数组拆分
最基础的数组拆分是np.split()
python
a = np.array([1, 2, 3, 4, 5, 6])
b, c = np.split(a, 2) # 将原来的单个数组拆分为2个,即6个元素平均拆成2份
print(b) # 输出[1 2 3]
print(c) # 输出[4 5 6]
Numpy与PyTorch
NumPy 的数组叫ndarray,PyTorch 的核心数据结构叫Tensor,可以将两种理解为功能十分相似的两种多维数组
python
import numpy as np
import torch
a = np.array([1, 2, 3])
b = torch.tensor([1, 2, 3])
Numpy与PyTorch
python
# NumPy → PyTorch
import numpy as np
import torch
a = np.array([1, 2, 3])
b = torch.tensor(a) # 这里是将NumPy中的ndarray数据结构转换为了PyTorch Tensor
print(b)
python
# PyTorch → NumPy
import numpy as np
import torch
a = torch.tensor([1, 2, 3])
b = a.numpy() # 这里是将PyTorch中的tensor数据结构转换为了NumPy ndarray
print(b)
torch.tensor() 和 torch.from_numpy()
python
import numpy as np
import torch
a = np.array([1, 2, 3])
b = torch.from_numpy(a) # 把 NumPy 数组转换成Tensor
两者均可完成NumPy → Tensor,两者在数据共享、复制行为、dtype 等细节上存在区别
Tensor和ndarray的shape
python
a = np.array([
[1, 2, 3],
[4, 5, 6]
])
print(a.shape) # 输出(2, 3)
b = torch.tensor([
[1, 2, 3],
[4, 5, 6]
])
print(b.shape) # 输出torch.Size([2, 3])
NumPy和PyTorch的相同点
绝大多数Numpy中知识可以迁移到Pytorch中
| NumPy | PyTorch |
|---|---|
ndarray |
Tensor |
a.shape |
b.shape |
a.reshape() |
b.reshape() |
a.sum() |
b.sum() |
a.mean() |
b.mean() |
a @ b |
a @ b |
a.dtype |
b.dtype |
python
import numpy as np # 导入Numpy包
data = np.arange(1, 13) # 创建一个一维的连续数组
data = data.reshape(3, 4) # 将数组转换为3行4列的数组[[1 2 3 4][5 6 7 8][9 10 11 12]]
print(data.shape) # 输出data的shape,为(3,4)
selected = data[data > 5] # 选出data中大于5的元素并进行赋值 [6 7 8 9 10 11 12]
print(selected) # [6 7 8 9 10 11 12]
mean = np.mean(data, axis=0) # 按列进行求平均数
print(mean) # 输出平均数
new_data = data * 2 # 对data中所有元素进行乘2操作
print(new_data) # 输出乘2操作后的data
a = np.array([1, 2, 3]) # 创建一维数组
b = a.copy() # 复制操作
b[0] = 100 # 对b进行修改
print(a) # [1 2 3]
print(b) # [100 2 3]