numpy框架探究

性质与创建

简述

ndarray(N-dimensional array,即N维数组)是NumPy的核心数据结构。可将ndarray看作是一个“智能容器”。相比于python原生数据结构,他有更好的特性,因此性能更优。他在数学上等同于一个张量,不过有些性质为了程序设计的合理性,并不符合数学直觉,后面会一一谈到。

ndarray之所以比python原生数据结构更高效,主要由以下三个性质决定,从这里也可以明显看出:ndarray在内存管理上更像c,而不是python

  • 同质数据类型:ndarray要求所有元素具有相同的数据类型。这种同质性使得ndarray在内存管理和数据操作上更加高效,避免了类型转换带来的额外开销。
  • 多维结构:ndarray支持多维结构,能够表示各种复杂的数据形式。
  • 连续内存存储:NumPy 的 ndarray 采用连续内存存储,即其在内存中连续分配空间。与之不同,Python 列表元素在内存里分散存储,各元素有独立内存地址,且列表含指向这些元素的指针。这种分散存储在访问元素时需多次指针跳转,致使访问效率低。而 ndarray 凭借连续内存存储,计算机只需依据元素索引和数组起始地址进行简单计算,就能直接定位元素内存位置,实现快速访问。

轴(axis)

轴定义了ndarray的维度,数学上几维张量就有几个轴,ndarray亦是如此,以计算机视觉中常常涉及到的三通道彩色图像为例

pEelG1e.md.jpg

对于一个三通道的彩色图像,通常用一个形状为 (height, width, channels) 的三维 ndarray 来表示,其中: - axis = 0:对应图像的高度方向,也就是垂直方向。沿着这个轴操作,会对图像的不同行进行处理。 - axis = 1:对应图像的宽度方向,即水平方向。沿着这个轴操作,会对图像的不同列进行处理。 - axis = 2:对应图像的通道方向,即红、绿、蓝三个通道。沿着这个轴操作,会对同一像素位置的不同颜色通道进行处理。

这种定义的好处是设计接口同一,但也导致会一些反数学直觉的现象:比如形状(1,3)和形状为(3,)的ndarray不是同一个东西,前者是一个二维矩阵,后者是一个一维向量,这将导致他们在数学运算上展示出一些差异。

使用np.array()创建数组

numpy.array() 是 NumPy 库中用于创建数组的核心函数,

1
numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)

详细解释各个参数的含义:

object

object表示要转换为 ndarray 的输入数据。可以是多种类型的对象,常见的有: - 列表(list):例如 [1, 2, 3][[1, 2], [3, 4]],分别可以转换为一维和二维数组。 - 元组(tuple):像 (1, 2, 3) 也能被转换为一维数组。 - 其他对象:包括ndarray对象,pdread出来的对象等

1
2
3
4
5
6
7
8
import numpy as np
import pandas as pd

# 从 CSV 文件读取数据
data = pd.read_csv('data.csv')
# 转换为 NumPy 数组
X = np.array(data.drop('target', axis=1))
y = np.array(data['target'])

dtype

dtype 用于指定数组元素的数据类型,在选择数据类型时,性能差异是一个需要重点考虑的因素。常见的数据类型包括 Python 内置的 int、float、bool 等,以及 NumPy 特有的具体位数类型,如 np.int32、np.float64 等。后者效率远远高于前者,因为python原生数据包含结构引用计数和类型指针等额外信息。不过在不指定 dtype 时,NumPy 多数情况会自动使用合适的 NumPy 数据类型,但为了性能和代码的健壮性,明确指定 dtype 是更好的做法。

在机器学习中,对于大规模数据集,选择合适的数据类型至关重要。例如,图像数据通常可以使用 np.uint8 类型,而神经网络中的权重和偏置通常使用 np.float32 以平衡精度和计算速度。

1
2
3
4
5
6
7
import numpy as np
import cv2

# 读取图像
image = cv2.imread('image.jpg')
# 转换为 NumPy 数组并指定数据类型
image_array = np.array(image, dtype=np.uint8)

copy(不常用)

可选参数,是一个布尔值,默认为 True。如果 copyTrue,则会创建输入对象的一个副本;如果为 False,则尽可能不复制,而是直接使用输入对象的数据。当输入本身就是 ndarray 时,这个参数会影响是否创建新的数组对象。

order(不常用)

可选参数,用于指定数组在内存中的存储顺序,有三个可选值:

subok(不常用)

在机器学习库中,有时会自定义数组子类以实现特定的功能。如果需要保留这些子类的属性和方法,将 subok 设置为 True;否则,使用默认的 False 会返回普通的 ndarray。

ndmin

确保数组具有最小的维度,这在处理一些需要固定维度输入的机器学习模型时非常有用。例如,某些模型要求输入数据至少是二维的,使用 ndmin 可以保证输入数据符合要求。

使用函数生成数组

np.arange()

类似于python的range()函数,接受参数为首项开,末项闭合,步长可指定

np.arange(start,stop,step,dtype=None)

在超参数调优时,我们可能需要对某个超参数进行等间隔取值来评估模型性能。例如,在调整学习率时,我们可以使用 np.arange 生成一系列等间隔的学习率值。

1
2
3
4
5
6
7
8
9
# 生成一系列等间隔的学习率值
learning_rates = np.arange(0.01, 0.1, 0.01)

for lr in learning_rates:
model = LogisticRegression(C=1/lr)
model.fit(X_train, y_train)
score = model.score(X_test, y_test)
print(f"Learning rate: {lr}, Accuracy: {score}")

np.linspace()/np.logspace()

np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None):用于创建一个线性等分的数组>在绘制模型的损失曲线或准确率曲线时,我们需要在一定范围内均匀地取一些点作为横坐标。这时候可以使用 np.linspace 生成一系列等间隔的训练轮数作为画图用的横坐标

1
2
3
4
5
6
7
# 假设我们训练了 100 轮,我们想以 10 为轮数间隔画图
epochs = np.linspace(1, 100, 10)
# losses为记录好的损失变化数组
plt.plot(epochs, losses)
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.show()

stop, num
1
2
3
4
5
6
7
8
9
10

```py
# 生成一系列对数间隔的正则化参数 C 值
C_values = np.logspace(-3, 3, 7)

for C in C_values:
model = SVC(C=C)
model.fit(X_train, y_train)
score = model.score(X_test, y_test)
print(f"C: {C}, Accuracy: {score}")

np.random.normal()

np.random.normal(loc=0.0, scale=1.0, size=None):用于生成服从正态分布的随机数数组,loc 是均值(默认为 0),scale 是标准差(默认为 1),size 是数组的形状(接受一个元组

常常用于权重的初始化

快速生成可以直接用

1
2
# 0-1 连续均匀分布
np.random.rand(2, 3)

np.ones(元组)/np.zeros(元组)

1
2
3
4
5
np.ones((2, 3))
"""
array([[1., 1., 1.],
[1., 1., 1.]])
"""

统计与属性

以下是对 NumPy 中常用统计和属性相关函数用法的总结:主要明白两点基本原则 - shape,ndim,size是属性,不加括号 - 凡是按照轴操作的函数,操作完后都会减少一个维度

尺寸相关

np.shape

  • 功能:返回一个元组,表示数组形状。 #### arr.ndim
  • 功能:返回一个整数表示数组维度。

arr.size

  • 功能:返回一个整数表示数组元素个数

最值

np.max(arr,axis=?)np.min(arr,axis=?)

  • 功能:分别返回数组中的最大值和最小值。可以通过 axis 参数指定在哪个轴上进行操作。

  • 易错axis=0axis=1 操作后数组的维度会减少,返回的是一维数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import numpy as np

arr = np.array([[1, 2, 3],
[4, 5, 6]])

# 不指定 axis,返回整个数组的最值
max_val = np.max(arr)
min_val = np.min(arr)
print(f"整个数组最大值: {max_val},类型: {type(max_val)}") # 整个数组最大值: 6,类型: <class 'numpy.int32'>
print(f"整个数组最小值: {min_val},类型: {type(min_val)}") # 整个数组最小值: 1,类型: <class 'numpy.int32'>

# 指定 axis=0,按列求最值,降低arr一个维度
max_col = np.max(arr, axis=0)
min_col = np.min(arr, axis=0)
print(f"按列最大值: {max_col}{np.shape(max_col)}") # 按列最大值: [4 5 6], (3,)
print(f"按列最小值: {min_col}{np.shape(min_col)}") # 按列最小值: [1 2 3], (3,)

# 指定 axis=1,按行求最值,降低arr一个维度
max_row = np.max(arr, axis=1)
min_row = np.min(arr, axis=1)
print(f"按行最大值: {max_row}{np.shape(max_row)}") # 按行最大值: [3 6], (2,)
print(f"按行最小值: {min_row}{np.shape(min_row)}") # 按行最小值: [1 4], (2,)

平均求和标准差

np.average(arr,axis=?,weights=?arr)

  • 功能:计算数组的(加权)平均值。可通过 axis 参数指定计算轴,weights 参数指定权重。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    import numpy as np

    arr = np.array([[1, 2, 3],
    [4, 5, 6]])
    weights = np.array([0.2, 0.3, 0.5])

    # 不指定 axis,计算整个数组的加权平均
    avg = np.average(arr)
    print(f"整个数组平均值: {avg},类型: {type(avg)}") # 输出浮点数 3.5

    # 指定 axis=0,按列计算加权平均
    avg_col = np.average(arr, axis=0, weights=weights)
    print(f"按列加权平均值: {avg_col},类型: {type(avg_col)},形状: {np.shape(avg_col)}") # 输出一维数组

    # 指定 axis=1,按行计算加权平均
    avg_row = np.average(arr, axis=1, weights=weights)
    print(f"按行加权平均值: {avg_row},类型: {type(avg_row)},形状: {np.shape(avg_row)}") # 输出一维数组
  • 易错点:若指定 weights,其形状要与计算轴的形状匹配。

另外,不加权重的时候可以直接用np.mean(arr,axis=?)

np.sum(arr,axis=?)

  • 功能:计算数组元素的总和。可通过 axis 参数指定计算轴。

np.std

  • 功能:计算数组的标准差。可通过 axis 参数指定计算轴。

这里标准差涉及到总体标准差和样本标准差的区别,np.std提供了一个一接口调整自由度

总体标准差用 $$ \sigma = \sqrt{\frac{\sum_{i = 1}^{N}(x_i - \mu)^2}{N}} $$

np.std 函数中,当 ddof(Delta Degrees of Freedom,自由度)参数设置为 0 时,计算的就是总体标准差。示例代码如下:

1
2
3
4
5
6
7
8
import numpy as np

# 定义一个数组
data = np.array([1, 2, 3, 4, 5])

# 计算总体标准差
population_std = np.std(data, ddof=0)
print("总体标准差:", population_std)

样本标准差用 $$ s = \sqrt{\frac{\sum_{i = 1}^{n}(x_i - \bar{x})^2}{n - 1}} $$np.std 函数中,把 ddof 参数设置为 1 时,计算的就是样本标准差。

形状与变化

注意:本章节中涉及的所有操作都是在创建视图 - 视图:是原数组的一个引用,与原数组共享底层数据存储。对视图的修改会直接反映到原数组上,反之亦然。

1
2
3
4
5
6
b = a.reshape(3,4)
# 此时a不变

b[0,0]=100 # 或者b[0][0]=100
# 此时a[0,0]也会变

np.expand_dims(arr,axis=?)

  • 功能:在数组的指定位置插入新的轴,从而增加数组的维度。新axis插入后,原来位于该位置的轴,以及之后的轴的编号都会依次向后移动一位。 例如:
  • 对于一维数组 arr = np.array([1, 2, 3]),其形状为 (3,)
    • axis = 0 时,在第 0 个位置插入新轴,原来的元素都在新轴的下一级,所以形状变为 (1, 3)
    • axis = 1 时,在第 1 个位置插入新轴,原来的每个元素都被单独放在新轴的一个位置,形状变为 (3, 1)
  • 示例:在深度学习中,很多模型要求输入具有 (batch_size, channels, height, width) 的格式。当我们有一个单张图像(假设为灰度图),其形状为 (height, width) 时,需要将其扩展为 (1, 1, height, width) 以满足模型输入要求。
    1
    2
    3
    4
    5
    6
    7
    8
    import numpy as np

    # 模拟一张 28x28 的灰度图像
    image = np.random.rand(28, 28)
    # 扩展维度以匹配模型输入
    input_image = np.expand_dims(np.expand_dims(image, axis=0), axis=0)
    print("原图像形状:", image.shape) # 输出: (28, 28)
    print("扩展维度后的图像形状:", input_image.shape) # 输出: (1, 1, 28, 28)

np.squeeze

  • 功能:从数组中移除所有长度为 1 的轴。
1
2
3
4
5
6
7
8
import numpy as np

# 创建带有单维度轴的数组
arr = np.array([[[1, 2, 3]]])
squeezed_arr = np.squeeze(arr)

print("原数组形状:", arr.shape) # 输出: (1, 1, 3)
print("压缩后数组形状:", squeezed_arr.shape) # 输出: (3,)
  • 机器学习实战代码示例:在模型预测后,输出结果可能会带有不必要的单维度轴。例如,一个模型对单样本进行预测,输出形状为 (1, 10),我们可以使用 np.squeeze 去掉多余的维度,得到 (10,) 的结果。

np.reshape((元组))arr.reshape((元组))

  • 功能:改变数组的形状,但保持元素总数不变。
  • 由于python可以自动解包,不传入元组,直接arr.reshape(n,m)也行
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import numpy as np

    arr = np.arange(12)
    # 使用 np.reshape
    reshaped_arr_1 = np.reshape(arr, (3, 4))
    # 使用 arr.reshape
    reshaped_arr_2 = arr.reshape((3, 4))

    print("原数组形状:", arr.shape) # 输出: (12,)
    print("使用 np.reshape 后的形状:", reshaped_arr_1.shape) # 输出: (3, 4)
    print("使用 arr.reshape 后的形状:", reshaped_arr_2.shape) # 输出: (3, 4)

注意: - reshape函数返回一个原数组的视图,不会使原数组形状改变。 - 可以用-1代替某个不想计算的维度,用于自动计算,如果只使用一个-1相当于flatten

arr.T

  • 功能:对于二维数组,交换行和列;对于更高维数组,反转维度顺序。
  • 一般代码示例
    1
    2
    3
    4
    5
    6
    7
    import numpy as np

    arr = np.array([[1, 2, 3], [4, 5, 6]])
    transposed_arr = arr.T

    print("原数组形状:", arr.shape) # 输出: (2, 3)
    print("转置后数组形状:", transposed_arr.shape) # 输出: (3, 2)

np.transpose

  • 功能:可以指定轴的新顺序来对数组进行转置,比 arr.T 更灵活。
    1
    2
    3
    4
    5
    6
    7
    8
    import numpy as np

    arr = np.arange(24).reshape((2, 3, 4))
    # 指定轴的新顺序进行转置
    transposed_arr = np.transpose(arr, (1, 0, 2))

    print("原数组形状:", arr.shape) # 输出: (2, 3, 4)
    print("转置后数组形状:", transposed_arr.shape) # 输出: (3, 2, 4)
  • 机器学习示例:在深度学习中,不同的深度学习框架对数据的存储格式可能不同。例如,有些框架要求图像数据的格式为 (channels, height, width),而我们的数据可能是 (height, width, channels) 格式,这时可以使用 np.transpose 进行转换。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    import numpy as np

    # 模拟一张 28x28 的 RGB 图像,格式为 (height, width, channels)
    image = np.random.rand(28, 28, 3)
    # 转换为 (channels, height, width) 格式
    transposed_image = np.transpose(image, (2, 0, 1))

    print("原图像形状:", image.shape) # 输出: (28, 28, 3)
    print("转置后图像形状:", transposed_image.shape) # 输出: (3, 28, 28)

分解与组合

切片和索引

总体上来说,切片的方式大致是

1
arr[row,col]
逗号前对行操作,逗号后对列操作,我们先以行操作为例子。

索引或切片方式 代码示例 功能说明 是否返回视图
取单行 arr[0] 取数组的第 0 行
取单元素 arr[0, 1] 取数组第 0 行第 1 列的元素 否(返回单个元素值)
连续行切片 arr[0:3] 取数组的第 1 - 3 行(索引 0 到 2)
离散行索引 arr[[0, 3]] 取数组的第 1 行和第 4 行(索引 0 和 3) 否(返回副本)
行从某行到最后 arr[3:] 从数组中提取第 4 行(索引为 3)开始直至最后一行的元素 视图
行从开始到某行(开) arr[:3] 相当于arr[0:3] 视图
行带步长切片 arr[1: 4: 2] 从数组中提取第 2 行至第 4 行(对应索引 1 到 3)的元素,按步长 2 选取,即选取第 2 行和第 4 行 视图

想要结合列进行索引和切片,在逗号后进行列的操作即可

索引或切片类型 代码示例 功能详细说明 返回结果性质
行和列连续切片 arr[1:3, 1] 从数组中提取第 2 行至第 3 行(对应索引 1 到 2)里第 2 列(索引为 1)的元素 视图
行和列离散索引 arr[[1,3], [0]] 从数组中提取第 2 行和第 4 行(对应索引 1 和 3)里第 1 列(索引为 0)的元素 副本
行和列连续范围切片 arr[:3, 1:3] 从数组中提取第 1 行至第 3 行(对应索引 0 到 2)里第 2 列至第 3 列(对应索引 1 到 2)的元素 视图
行和列带步长切片 arr[1:4:2, 0:3:2] 从数组中提取第 2 行至第 4 行(对应索引 1 到 3),按步长 2 选取;同时提取第 1 列至第 3 列(对应索引 0 到 2),按步长 2 选取相应元素 视图
冒号索引列 arr[:,1] 从数组中提取所有行里第 2 列(索引为 1)的元素 视图

总体来说,涉及离散索引(如使用列表或数组指定不连续的索引)时通常返回副本,而连续切片操作大多返回视图。可以通过检查数组的 base 属性来判断返回的是视图还是副本,如果 arr.base 是原数组,则 arr 是视图;如果 arr.baseNone,则 arr 是副本。

切片和索引在机器学习中用的是很多的,举几个常用例子

数据集划分

1
2
3
4
5
6
train_size = int(len(data)*0.8)
val_size = int(len(data)*0.1)

train_data = data[:train_size]
val_data = data[train_size:train_size+val_size]
test_data = data[train_size+val_size:]

特征选择

1
2
data = np.random.rand(100,5)
X = data[:,[0,2]]

批量训练

使用批量梯度下降算法进行模型训练,需要将数据集划分为多个小批量。切片操作可以实现批量数据的提取。

1
2
3
4
5
6
7
8
9
# 批量大小
batch_size = 10

# 遍历每个批量
for i in range(0, len(data), batch_size):
batch_data = data[i:i + batch_size]
batch_labels = labels[i:i + batch_size]
# 这里可以进行模型训练操作
print(f"第 {i // batch_size + 1} 个批量的数据形状:", batch_data.shape)

拼接

维度不变:拼接

np.concatenate 函数用于沿着指定的轴将多个数组连接在一起,要求除了指定轴之外的其他轴的形状必须一致

1
2
import numpy as np
np.concatenate((arr1, arr2, ...), axis=0)
1738916424602.jpg

可以用于特征拼接或者数据集合并等操作

维度增加:堆叠

np.stack 函数用于沿着新的轴将多个数组堆叠在一起,要求所有输入数组的形状必须完全相同。 axis用于指定新的,用于堆叠的轴的方向

1
2
import numpy as np
np.stack((a1, a2, ...), axis=0)

在计算机视觉中,有时需要将多个单通道的图像合并成多通道图像。例如,将红、绿、蓝三个单通道的图像合并成一个 RGB 图像。

1
2
3
4
5
6
7
8
9
10
import numpy as np

# 模拟三个单通道图像
red_channel = np.random.rand(256, 256)
green_channel = np.random.rand(256, 256)
blue_channel = np.random.rand(256, 256)

# 沿着新的轴(第 2 轴)堆叠通道
rgb_image = np.stack((red_channel, green_channel, blue_channel), axis=2)
print("合并后 RGB 图像的形状:", rgb_image.shape)

筛选和过滤

布尔数组直接筛选

用numpy写比for循环快得多,NumPy 的布尔索引筛选耗时远远小于 for 循环筛选耗时,并且随着数组规模的增大,这种性能差距会更加明显。这是因为 NumPy 的向量化操作能够并行处理数组元素,而 for 循环是串行执行的,效率较低。

1
2
3
4
5
6
7
8
9
10
11
12
13
import numpy as np

# 创建一个示例数组
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])

# 创建布尔数组,筛选出大于 5 的元素
condition = arr > 5
filtered_arr = arr[condition]

print("原数组:", arr)
print("布尔数组:", condition)
print("筛选出大于 5 的元素:", filtered_arr)

三参数np.where()

三参数形式:np.where(condition, x, y)
参数: - condition:同样是一个布尔数组,用于指定筛选条件。 - x 和 y:可以是数组或者标量。当 condition 中的元素为 True 时,结果数组中对应位置的值取自 x;当 condition 中的元素为 False 时,结果数组中对应位置的值取自 y。 - 返回值:返回一个新的数组,其形状与 condition 相同,数组中的元素根据条件从 x 或 y 中选取。

1
2
# 不满足条件的赋值,将 <=50 的替换为 -1
np.where(arr > 50, arr, -1)
这一函数一般用于处理缺失值或者数据二值化

数据集中可能存在缺失值(如 NaN),可以使用 np.where 将缺失值替换为特定的值

1
2
cleaned_data = np.where(np.isnan(data), mean_value, data)
print("处理后的数据:", cleaned_data)
在某些分类任务中,需要将连续型数据转换为二值数据(0 或 1),可以根据特定的阈值使用 np.where 进行转换。
1
2
3
4
5
# 模拟特征数据
features = np.array([0.2, 0.7, 0.1, 0.9, 0.4])
# 根据阈值 0.5 进行二值化
binary_features = np.where(features > 0.5, 1, 0)
print("二值化后的特征:", binary_features)

矩阵与运算

以下是两个表格,分别总结了 NumPy 常见运算和矩阵运算的用法:

表格一:NumPy 常见运算总结

运算类型 函数/操作符 功能描述 示例代码
逐元素算术运算 +-*/ 对数组进行四则运算 arr * 2
** 对数组进行幂运算 arr ** 2
np.sqrt 对数组元素开方 np.sqrt(arr)
np.log 对数组元素求自然对数 np.log(arr)
np.mod 对数组元素取模,可指定多个被除数 np.mod(arr, 3)
np.mod(arr, arr - 5)
条件运算 np.minimum 将数组中超过指定值的元素替换为该值 np.minimum(arr, 5)
np.maximum 将数组中低于指定值的元素替换为该值 np.maximum(arr, 5)
np.round 对数组元素进行四舍五入 np.round(np.sqrt(arr), 2)
np.floor 对数组元素向下取整 np.floor(np.sqrt(arr))
np.ceil 对数组元素向上取整 np.ceil(np.sqrt(arr))
广播机制 操作符结合不同形状数组 较小数组在较大数组上广播以适配形状 a + [1, 2, 3, 4]
a + [[1], [2], [3]]
np.mod(a, [1, 2, 3, 4])

表格二:NumPy 矩阵运算总结

运算类型 函数/操作符 功能描述 示例代码 高维差异说明
矩阵乘法 np.dot 计算两个数组的点积,常用于矩阵乘法 np.dot(a, b)
a.dot(b)
处理高维数组时规则与 matmul 不同
np.matmul@ 计算两个数组的矩阵乘积 np.matmul(a, b)
a @ b
会将矩阵像元素一样堆叠在一起广播
点积 np.vdot 计算两个数组的点积 np.vdot(a, a) 等价于 np.sum(a * a)
内积 np.inner 计算两个数组的内积 np.inner(a, a) 等价于 a.dot(a.T)
行列式 np.linalg.det 计算方阵的行列式 np.linalg.det(c) -
逆矩阵 np.linalg.inv 计算方阵的逆矩阵 np.linalg.inv(c) -

关于维度的说明

1
2
3
4
5
6
7
8
9
10
11
12
13
# 目标向量 y,形状为 (4, 1)
y = np.array([[3],
[7],
[11],
[15]])

# 目标向量 y,形状为 (4,)
y = np.array([3, 7, 11, 15])


目标向量 y,形状为 (1, 4)
y = np.array([[3, 7, 11, 15]])

一般而言使用中间的一维向量参与到矩阵运算中即可,不用特意定义好行向量或者列向量,因为广播机制会自动把一维向量赋予行向量或列向量的形式。最后的运算结果如果是向量则为(n,)如果是数值就是数值

如果使用1.3的定义方式也可,但是如果最后的计算结果为数值m的话,事实上会得到[[m]]的形式,需要手动取arr[0,0]获取数值参与其他只接受数值的运算!


numpy框架探究
http://example.com/2025/02/11/编程语言/numpy框架学习/
作者
bradin
发布于
2025年2月11日
许可协议