实用指南: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内置函数,到最后数组中广播机制的使用标准与判定条件,由于内容较多所以首先整理一部分出来,后续关于常用的函数在后面的章节会逐步整理。

posted @ 2026-01-23 13:32  clnchanpin  阅读(2)  评论(0)    收藏  举报