实用指南:python中numpy库学习笔记(1)
前言:
关于深度学习中需要掌握python中的numpy模块关于数组相关的知识点,目前我们的学习重点如下图的知识点学习思路和场景。
| 知识点 | 学习重点 | 深度学习场景应用 | 代码示例 |
|---|---|---|---|
| 数组创建 | 1. 基础创建:np.array()(从列表 / 元组转换,深度学习中加载数据集后常用);2. 特殊数组:np.zeros()(初始化权重矩阵)、np.ones()(占位符)、np.eye()(单位矩阵,常用于初始化参数)、np.arange()(生成序列)、np.random(生成随机数,深度学习初始化权重、打乱数据集) | 初始化模型参数、生成噪声数据、构建批次数据 | # 生成符合正态分布的权重(深度学习常用)<br>weights = np.random.normal(0, 0.01, (100, 10)) # 均值0,方差0.01,100行10列 |
| 数组属性 | shape(维度,如 (32,28,28) 代表 32 张 28x28 的图片)、dtype(数据类型,深度学习常用 float32 节省内存)、ndim(维度数)、size(元素总数) | 查看数据集维度、校验数据格式是否符合模型输入要求 | # 模拟一批图片数据(32批次,28x28像素,单通道)<br>imgs = np.random.randint(0,255,(32,28,28),dtype=np.float32)<br>print(imgs.shape) # 输出(32,28,28)<br>print(imgs.dtype) # 输出float32 |
本章我将按照学习的思路逐步剖析python中关于numpy库的学习思路逐个难点重点讲解,逐步解决在学习中遇到的问题
1.维度的理解
numpy最常用是对多维数组进行操作,首先我们得知道维度是怎么区分的,常用XD来表示几维(0D,1D,2D...),通常用 ndim 属性表示数组的维度数量,我们首先给大家列举一下在python中的numpy常见的维度实例。
| 维度 | 名称 | 形状示例 | 核心用途 |
|---|---|---|---|
| 0 | 标量数组 | () | 单个数值存储 |
| 1 | 向量 | (n,) | 序列数据(如时间序列) |
| 2 | 矩阵 | (m, n) | 表格数据、线性代数运算 |
| 3 | 张量 | (k, m, n) | 3D 数据(如 3D 图像) |
| 4+ | 高维数组 | (b, k, m, n) | 批量处理复杂数据(如批量图像) |
简单理解:
axis称之为轴,有几个轴称之为几维,可以理解为不同领域的评判标准,数学上理解可以认为经过同一点的N条不平行的直线,理论上可以有N维,每个轴(axis)确实对应一个 “独立的描述维度”,每个维度相似但不相同。
深刻理解:在上述同一点外的任意确定一点,对每个轴作垂线都会得到该点在相应轴上指代的是哪一个标准,将该点对应n个轴的位置的标准组成列表[标准1,标准2,......],共同组成多维数组。
2.数组的创建
import numpy as np 1.def array(p_object, dtype=None, *args, **kwargs)参数讲解:
p_object:参数常用list置换,意为数组转换的对象
dtype:指定数组中元素的数据类型,可以用来节省内存或保证数值精度
dtype取值:
float32相比float64占用一半的内存,而精度通常足够。2.np.ones() 创建全为1的数组
ones_arr = np.ones((1, 5), dtype=np.int32) print("Ones Array:", ones_arr) #Ones Array: [[1 1 1 1 1]]3.np.arange()创建连续序列(左闭右开)
# 从 0 到 9 (不包含10),步长为 1 arr_seq1 = np.arange(10) print("Sequence 1:", arr_seq1) #Sequence 1: [0 1 2 3 4 5 6 7 8 9]4.
np.linspace():创建指定数量的等间隔点# 在 0 和 1 之间生成 5 个等间隔的点 (包含 endpoints) lin_arr = np.linspace(0, 1, 5) print("Linear Space:", lin_arr) #Linear Space: [0. 0.25 0.5 0.75 1. ]5.
np.random模块:创建随机数组常用场景:设置随机种子数
#1.设置随机种子,保证每次运行结果一致 np.random.seed(42) #2.np.random.rand() 场景:设置[0,1)之间的均匀分布的随机数 rand_arr = np.random.rand(2, 2) print("Random Array (uniform [0,1)):\n", rand_arr) #3.np.random.randn() 设置生成标准正态分布(μ=0, σ=1)的随机数 场景:初始化神经网络权重最常用的方法之一(例如 He 初始化、Xavier 初始化都基于正态分布) # 生成一个 3x1 的随机向量 randn_arr = np.random.randn(3, 1) print("Random Array (standard normal):\n", randn_arr) ''' Random Array (standard normal): [[ 1.52302986] [-0.23415337] [-0.23413695]] ''' #4.np.random.randint(): 生成指定范围内的整数随机数 # 生成一个 1x5 的数组,元素在 [0, 10) 之间的整数 randint_arr = np.random.randint(low=0, high=10, size=(1, 5)) print("Random Integers [0, 10):", randint_arr) ''' Random Integers [0, 10): [[4 8 6 2 6]] '''
函数 功能 常用场景 np.array()从列表创建数组 加载和转换数据 np.zeros()创建全 0 数组 参数初始化、占位符 np.ones()创建全 1 数组 参数初始化、占位符 np.arange()创建连续序列 生成索引、简单数据 np.linspace()创建等间隔序列 生成测试数据、可视化 np.random.rand()均匀分布随机数 简单随机初始化 np.random.randn()标准正态分布随机数 神经网络权重初始化
np.random.randint()整数随机数 打乱数据集、采样
3.数组的索引与切片
本质:数组的索引是指获取数组中单一元素的操作,而切片是获取数组中一部分元素并组成一个新数组的操作。
1.一维数组的索引与切片与python中的列表十分类似
数组的索引 arr[index]
数组的切片 arr[start:stop:step] 注意[start,stop)
#一维数组的索引 import numpy as np arr = np.arange(10) # 创建数组 [0 1 2 3 4 5 6 7 8 9] # 获取索引为 0 的元素 print(arr[0]) # 输出: 0 # 获取索引为 7 的元素 print(arr[-3]) # 输出: 7,倒数第三个元素 #一维数组的切片(arr[start:stop:step]左闭右开) arr = np.arange(10) # [0 1 2 3 4 5 6 7 8 9] # 获取从索引 2 到 5 的元素(不包含 5) print(arr[2:5]) # 输出: [2 3 4] # 获取从索引 0 到 5 的元素,步长为 2 print(arr[0:5:2]) # 输出: [0 2 4] # 省略 start,表示从开头开始 print(arr[:5]) # 输出: [0 1 2 3 4] # 省略 stop,表示到末尾结束 print(arr[5:]) # 输出: [5 6 7 8 9] # 步长为负数,表示反向切片 print(arr[::-1]) # 输出: [9 8 7 6 5 4 3 2 1 0] (反转数组)
2.二维数组的索引与切片
数组的索引:arr[row_index, col_index]
数组的切片:arr[start:stop:step,start:stop:step]
arr_2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # 获取第 0 行的所有元素 print(arr_2d[0, :]) # 输出: [1 2 3] # 获取所有行的第 1 列元素 print(arr_2d[:, 1]) # 输出: [2 5 8] # 获取第 0-1 行,第 1-2 列的元素 print(arr_2d[0:2, 1:3]) # 输出: # [[2 3] # [5 6]] # 获取所有行,步长为 2 的列 print(arr_2d[:, ::2]) # 输出: # [[1 3] # [4 6] # [7 9]]
3.多维数组的索引与切片
本质:多个维度上的索引与切片原理其实一致,arr(axis=0上的索引/切片,axis=1上的索引/切片,axis=2上的索引/切片...)最终都能取到相应的值
4.高级索引:
1.布尔索引:通过布尔数组来筛选元素,返回所有对应True位置的元素(多个数组判定条件则可以使用 & | 运算符进行分割条件)
2.整数数组索引:通过整数数组来指定要获取的元素索引,返回一个新数组,其元素为原数组中对应索引的元素。
1.布尔索引的案例 arr = np.arange(10) # [0 1 2 3 4 5 6 7 8 9] # 创建一个布尔数组 mask = arr > 5 # [False False False False False False True True True True] # 使用布尔数组进行索引 print(arr[mask]) # 输出: [6 7 8 9] # 也可以直接在索引中使用条件表达式 print(arr[arr % 2 == 0]) # 输出: [0 2 4 6 8] (筛选偶数) 2.整数数组索引 arr = np.arange(10) # [0 1 2 3 4 5 6 7 8 9] # 获取索引为 0, 2, 4 的元素 print(arr[[0, 2, 4]]) # 输出: [0 2 4] # 也可以使用多维整数数组 arr_2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # 获取 (0,0), (1,2), (2,1) 位置的元素 print(arr_2d[[0, 1, 2], [0, 2, 1]]) # 输出: [1 6 8]
| 操作类型 | 语法 | 功能 |
|---|---|---|
| 索引 | arr[index] | 获取单个元素 |
| 切片 | arr[start:stop:step] | 获取一部分元素 |
| 布尔索引 | arr[mask] | 根据布尔条件筛选元素 |
| 整数数组索引 | arr[[index1, index2, ...]] | 根据索引数组获取元素 |
注意:上述整数数组索引的值取的方式是每个轴上数据依次取值,例arr_2d[[0, 1, 2], [0, 2, 1]],取值取的是axis=0轴上的0和axis = 1轴上的0组成第一个索引(0,0),依次类推取(1,2),(2,1),多维整数数组索引取值类似。
4.多维数组的索引
思路步骤:
step1:查看索引的种类(整数索引,切片索引,花式索引)
step2:
1.如果是连续轴操作:对应索引的shape去掉,没有操作的轴位置不变,选择连续的轴中最高维度的数组形成新的shape,替换到原有的shape。
2.如果是不连续的轴操作:值按先后顺序合并放到最后面,选择其他切片最高维度的数组构成新的shape,放到前面组成新的shape。
'''
总结:
step1. 原 shape(3,4,5,6,7)
step2. 看索引 --> 整数索引,切片索引,花式索引 。
1. 索引是一个整体,只对 axis=0
2. 多个索引个数 <= len(shape(3,4,5,6,7)) <= 5 对应轴 axis (0,1,2,3,4)
step3. 只要对 axis 进行索引(连续=轴)操作,对应索引的 shape 去掉。没有操作的轴,位置不变
如:[1, [2, 1], ...] => (3,4,5,6,7) = > (shape(高纬度 2,) ,5,6,7)
如:[:, [2, 1], [[1, 2]], ...] => (3,4,5,6,7) = > (3, shape(高纬度 1,2) ,6,7)
step4: 原shape(3,4,5,6,7)只要对 axis 进行索引(不连续=轴)操作,没有操作的轴,值合并放到最后面,前面shape(高)
如:[[1,1] :, [1,1], ...] 。 对 0 轴和2 轴操作,1 和 3轴和4轴没有操作(4,6,7)最后
shape(shape(高纬度1,2),(4,6,7)) -> (1,2,4,6,7)
如:[:, [[1,2],[2,1]], ..., [1,1] ] 对 1 轴 和 最后一个轴 操作
(3,4,5,6,7)=》 shape(shape(高维2,2),(3,5,6)放到最后)
'''
5.索引函数
1.
np.where():用于根据条件从数组中选择元素或其索引语法:
np.where(condition, x, y)condition是数组判断条件,符合条件返回x的值,不符合则返回y的值
#机器学习中处理缺失值 (使用平均值填充缺失值) import numpy as np np.random.seed(42) X = np.random.randn(5, 3) X[1, 0] = np.nan # 人为制造一个缺失值 X[3, 2] = np.nan print("Original X:\n", X) # 计算每列的平均值,忽略 NaN col_means = np.nanmean(X, axis=0) print("Column means (ignoring NaN):", col_means) # 使用 np.where 填充缺失值 X_filled = np.where(np.isnan(X), col_means, X) print("\nX after filling NaNs:\n", X_filled)获得满足条件的元素索引
arr = np.array([[1, 2], [3, 4], [5, 6]]) print("Original array:\n", arr) # 找出所有大于 3 的元素的索引 indices = np.where(arr > 3) print("Indices of elements > 3:", indices) # 输出: (array([1, 2, 2]), array([1, 0, 1])) # 解释:第一个数组是行索引 [1, 2, 2],第二个数组是列索引 [1, 0, 1] # 对应的元素是 arr[1,1]=4, arr[2,0]=5, arr[2,1]=6 # 可以直接用这些索引来获取元素 print("Elements > 3:", arr[indices]) # 输出: [4 5 6]
newaxis 的作用:当使用切片或索引时,在数组的某个位置增加一个维度(轴)相当于 None。伪索引本质上就是将原数组升维。
arr = np.array([1,2,3]) 其中shape=(3,)
可以使用newaxis对其扩维,其本质就是在新维度添加了一个None
arr[:, np.newaxis] = arr[:, None] =》 shape=(3,1)
arr[np.newaxis, :] = arr[None, :] =》 shape = (1,3)
6.广播机制
广播的本质:NumPy 会自动扩展(广播)较小的数组,使其形状与较大的数组匹配,以便进行逐元素运算。
判断两个数组能否进行广播:需要比较他们的shape,从最低维度开始对比
1.标量与数组
arr = np.arange(5) scalar = 2 result = arr * scalar print(result) # 输出: [0 2 4 6 8] # 广播机制在这里隐式地将标量 `2` 扩展成了数组 `[2, 2, 2, 2, 2]`2.一维数组和二维数组
matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) vector = np.array([10, 20, 30]) result = matrix + vector print(result) # 输出: # [[11 22 33] # [14 25 36] # [17 28 39]] # 广播机制将一维向量 `[10, 20, 30]` 沿着行的方向(axis=0)复制了 3 次, # 变成了一个和 matrix 形状相同的二维数组 [[10, 20, 30], [10, 20, 30], [10, 20, 30]]广播机制的判定条件:
1.当维度不同时,先在维度少的数组前面补1,直到两个数组的维度数量相同。
2.逐维度比较,必须满足条件,从最后一个维度开始,逐个比较两个数组的维度大小,满足下面两个条件之一才可以
(1)两个维度大小相等
(2).其中一个维度是1
广播机制的总结:(判定标准与目的)
1.「先补 1 齐维度,再从后往前比,非等即 1 才兼容」
2.「节省内存」(不用实际复制数据)和 「简化代码」
概念 / 函数 核心功能 关键应用场景 np.where()条件选择元素或索引 数据清洗、缺失值填充、基于规则的筛选 伪索引 - 整数数组索引 通过索引数组选择元素 按特定顺序提取样本或特征 - 布尔索引 通过布尔掩码筛选元素 基于条件过滤样本(如异常值检测) 广播机制 自动扩展数组形状以进行逐元素运算 特征缩放、批量数据处理、矩阵与向量的运算
总结:
本文是笔者在学习numpy中的时候所整理到的一些笔记,包括维度的理解与数组的索引和切片方法,以及常用的一个np.where内置函数,到最后数组中广播机制的使用标准与判定条件,由于内容较多所以首先整理一部分出来,后续关于常用的函数在后面的章节会逐步整理。
浙公网安备 33010602011771号