Python 之 NumPy 切片索引和广播机制

news2024/11/16 2:15:21

文章目录

  • 一、切片和索引
    • 1. 一维数组
    • 2. 二维数组
  • 二、索引的高级操作
    • 1. 整数数组索引
    • 2. 布尔数组索引
  • 三、广播机制
    • 1. 广播机制规则
    • 2. 对于广播规则另一种简单理解

一、切片和索引

  • ndarray 对象的内容可以通过索引或切片来访问和修改(),与 Python 中 list 的切片操作一样。
  • ndarray 数组可以基于 0 - n 的下标进行索引(先行后列,都是从 0 开始)。

在这里插入图片描述

  • 区别在于:数组切片是原始数组视图(这就意味着,如果做任何修改,原始都会跟着更改)。 这也意味着,如果不想更改原始数组,我们需要进行显式的复制,从而得到它的副本(.copy())。
  • 冒号分隔切片参数 [start:stop:step]
  • 在开始之前,先导入numpy包
import numpy as np

1. 一维数组

  • 通过 numpy.arange() 生成一个等区间的数组(起始值默认为 0,步长默认为 1,终止值设置为 10)。
ar1 = np.arange(10)
ar1
#array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
  • 从索引 2 开始到索引 7 停止,间隔为 2。
ar2 = ar1[2:7:2]
ar2
#array([2, 4, 6])
  • 这里需要解释以下冒号的作用:
  • 如果只放置一个参数,如果是 [2],将返回与该索引相对应的单个元素;如果为 [2:],表示从该索引开始以后的所有项都将被提取;如果为 [:2],表示不限制开始元素,但会在该元素截止。
  • 如果使用了两个参数,如 [2:7],那么则提取两个索引(不包括停止索引)之间的项。
  • 返回索引对应的数据(注意是从0开始的)。
print('ar1:',ar1)
print('ar1[4]:',ar1[4])
#ar1: [0 1 2 3 4 5 6 7 8 9]
#ar1[4]: 4
  • 通过 numpy.arange() 生成一个等区间的数组(起始值设置为 1,终止值设置为 20,步长设置为 2)。
ar3 = np.arange(1,20,2)
ar3
#array([ 1,  3,  5,  7,  9, 11, 13, 15, 17, 19])
  • 那么,我们如何取出元素 9?
  • 由于索引是从 0 开始的,因此,我们输出 ar3[4] 即可。
  • (1) 从该索引开始以后的所有项都将被提取
  • 从索引 2 开始,提取出后面所有数据。
print(ar3)
ar3[2:]
#[ 1  3  5  7  9 11 13 15 17 19]
#array([ 5,  7,  9, 11, 13, 15, 17, 19])
  • (2) 从索引开始,到索引结束(不包含结束)
  • 从索引 2 开始到索引 7(包含索引 7)。
print(ar3)
ar3[2:7]
ar3[:-2]
#[ 1  3  5  7  9 11 13 15 17 19]
#array([ 1,  3,  5,  7,  9, 11, 13, 15])
  • (3) 步长
  • 取所有数据,步长为 -1(负数代表从右往左数)。
ar3[::-1]
#array([19, 17, 15, 13, 11,  9,  7,  5,  3,  1])
  • 取数据 1 到 17 之间, 并且间隔一位的数据。
ar3[1:-2:2]
print(ar3)
print(ar3[:6])
print(ar3[6:])
#[ 1  3  5  7  9 11 13 15 17 19]
#[ 1  3  5  7  9 11]
#[13 15 17 19]
  • (4) 为什么切片和区间会忽略最后一个元素
  • 计算机科学家 edsger w.dijkstra(艾兹格·W·迪科斯彻),delattr 这一风格的解释应该是比较好的:
  • (1) 当只有最后一个位置信息时,我们可以快速看出切片和区间里有几个元素:range(3) 和 my_list[:3]。
  • (2) 当起始位置信息都可见时,我们可以快速计算出切片和区间的长度,用有一个数减去第一个下表(stop-start)即可。
  • (3) 这样做也让我们可以利用任意一个下标把序列分割成不重叠的两部分,只要写成 my_list[:x] 和 my_list[x:] 就可以了。

2. 二维数组

  • 同样适用上述索引提取方法:
  • 我们定义 4 行 5 列的数据。
  • np.arange(20) 表示起始值默认为 0,终止值设置为 20,步长默认为 1。
  • reshape(4,5) 表示生成一个 4 行 5 列的二维数组。
ar4_5 = np.arange(20).reshape(4,5)
ar4_5
#array([[ 0,  1,  2,  3,  4],
#       [ 5,  6,  7,  8,  9],
#       [10, 11, 12, 13, 14],
#       [15, 16, 17, 18, 19]])
  • 我们通过 ar4_5.ndim 返回 ar4_5 的秩(也就是几维)。
ar4_5.ndim
#2
  • 切片表示的是下一维度的一个元素,所以其代表一维数组。
ar4_5[2]
#array([10, 11, 12, 13, 14])
  • 我们也可以通过二次索引取得一维数组当中的元素。
ar4_5[2][2]
#12
  • 打印出 ar4_5 整体数组,便于后续的操作观察。
print(ar4_5)
#[[ 0  1  2  3  4]
# [ 5  6  7  8  9]
# [10 11 12 13 14]
# [15 16 17 18 19]]
  • 我们可以取出从第三行和第四行的元素。
ar4_5[2:]
#array([[10, 11, 12, 13, 14],
#       [15, 16, 17, 18, 19]])
  • 注意:切片还可以使用省略号 “…”,如果在行位置使用省略号,那么返回值将包含所有行元素,反之,则包含所有列元素。
  • 例如,我们需要取得第二列数据(由于索引是从 0 开始的,因此 第二列的元素就是 1)。
  • 取出的就是每一行和第二列交叉的数据,也就是 1,6,11,16。
ar4_5[...,1]#array([ 1,  6, 11, 16])
  • 我们需要返回第二列后的所有项。
ar4_5[...,1:]
#array([[ 1,  2,  3,  4],
#       [ 6,  7,  8,  9],
#       [11, 12, 13, 14],
#       [16, 17, 18, 19]])
  • 我们需要返回第 2 行第 3 列的数据(对于取出单个数值,两种方法是一样的)。
ar4_5[1,2]  # 对应(1,2) 的元素
#7
  • 对于返回第 2 行第 3 列的数据,我们也可以使用如下方法。
ar4_5[1][2]
#7
  • 对于上述关于取出单个数据的方法,是否可以映射到取出一列元素呢?
  • 如下例子所示,答案是否定的。
  • 首先,我们执行第一步操作,就是 ar4_5[…]。此时,代表取出 ar4_5 的每一行元素,也就是打印 ar4_5 本身。
  • 然后,我们执行第二步操作 ar4_5[…][1] ,就是切片,在 ar4_5 本身上打印处第二行,也就是 [5, 6, 7, 8, 9]。
ar4_5[...][1] 
array([5, 6, 7, 8, 9])

二、索引的高级操作

  • 在 NumPy 中还可以使用高级索引方式,比如整数数组索引、布尔索引,以下将对两种种索引方式做详细介绍。

1. 整数数组索引

  • 我们先创建一个二维数组。
x = np.array([
        [1,2],
        [3,4],
        [5,6]
    ])
y = x[[0,1,2],[0,1,0]] 
y
#array([1,4,5])
  • 其中,[0,1,2] 代表行索引,[0,1,0] 代表列索引,表示 y 分别获取 x 中的 (0,0)、(1,1) 和 (2,0) 表示的数据。
  • 然后,我们先创建一个 43 的数组,创建完成之后,获取了 43 数组中的四个角上元素,它们对应的行索引是 [0,0] 和 [3,3],列索引是 [0,2] 和 [0,2]。
b = np.array([[ 0, 1, 2],
              [ 3, 4, 5],
              [ 6, 7, 8],
              [ 9,10,11]])
              ​
a = b[[0,0,3,3],[0,2,0,2]]  # (0,0) (0,2) (3,0) (3,2)​

r = np.array([[0,0] ,[3,3]]).reshape(4) #用r代替[0,0,3,3]
l = np.array([[0,2] ,[0,2]]).reshape(4) #用l代替[0,2,0,2]
s = b[r,l].reshape((2,2))
s
#array([[ 0,  2],
#       [ 9, 11]])
  • 然后,我们先创建一个 3*3 的数组,创建完成之后,行取出第 2 行和第 3 行的元素,列取出第 2 列和第 3 列的数据。
  • 这里需要注意的是,不包含终止索引值。
a = np.array([
        [1,2,3], 
        [4,5,6],
        [7,8,9]
    ])
b = a[1:3, 1:3]
b
​#array([[5, 6],
#       [8, 9]])
  • 也就是 1:3 == [1,2]
  • 高级索引操作与常规的索引操作相同,都可以使用 … 表示所有行,1: 表示从第二列开始的所有列。
c = a[1:3,[1,2]]
d = a[...,1:]print(b)
print(c)
print(d)
#[[5 6]
# [8 9]]
#[[5 6]
# [8 9]]
#[[2 3]
# [5 6]
# [8 9]]
  • 在了解了上述高级索引操作之后,我们可以尝试创建一个 8x8 的国际象棋棋盘矩阵,其中黑块代表是 0,白块代表是 1,具体棋盘如下所示。
  1. [0 1 0 1 0 1 0 1]
  2. [1 0 1 0 1 0 1 0]
  3. [0 1 0 1 0 1 0 1]
  4. [1 0 1 0 1 0 1 0]
  5. [0 1 0 1 0 1 0 1]
  6. [1 0 1 0 1 0 1 0]
  7. [0 1 0 1 0 1 0 1]
  8. [1 0 1 0 1 0 1 0]]
  • 对于上述棋盘,我们可以先生成一个 8x8 的全 0 数组,然后将对应的元素设置为 1 即可。
  • (1) 通过行索引从 1 开始,步长为 2,不设置终止值,将第 1,3,5,7 行元素全部设置为 1。
  • (2) 通过列索引从 0 开始,步长为 2,不设置终止值,将第 1,3,5,7 行元素对应的列元素设置为 0。
  • (3) 通过列索引从 1 开始,步长为 2,不设置终止值,将第 1,3,5,7 列元素全部设置为 1。
  • (4) 通过行索引从 0 开始,步长为 2,不设置终止值,将第 1,3,5,7 行元素对应的行元素设置为 0。
  • 具体实现代码如下所示。
Z = np.zeros((8, 8), dtype=int)
Z[1::2,::2] = 1
Z[::2,1::2] = 1
​Z
#array([[0, 0, 0, 0, 0, 0, 0, 0],
#       [1, 0, 1, 0, 1, 0, 1, 0],
#       [0, 0, 0, 0, 0, 0, 0, 0],
#       [1, 0, 1, 0, 1, 0, 1, 0],
#       [0, 0, 0, 0, 0, 0, 0, 0],
#       [1, 0, 1, 0, 1, 0, 1, 0],
#       [0, 0, 0, 0, 0, 0, 0, 0],
#       [1, 0, 1, 0, 1, 0, 1, 0]])

2. 布尔数组索引

  • 当输出的结果需要经过布尔运算(如比较运算)时,此时会使用到另一种高级索引方式,即布尔数组索引。
  • 下面示例返回数组中大于 6 的的所有元素:
x = np.array([[ 0,  1,  2],[ 3,  4,  5],[ 6,  7,  8],[ 9, 10, 11]])
print(x.shape)
x[x>6]
#(4, 3)
#array([ 7,  8,  9, 10, 11])
  • 布尔索引所实现的是通过一维数组中的每个元素的布尔型数值对一个与一维数组有着同样行数或列数的矩阵进行符合匹配。
  • 这种作用,其实是把一维数组中布尔值为 True 的相应行或列给抽取了出来。
  • 这里需要注意的是,一维数组的长度必须和想要切片的维度或轴的长度一致。
  • 练习
  • (1) 提取出数组中所有奇数。
x = np.array([[ 0,  1,  2],[ 3,  4,  5],[ 6,  7,  8],[ 9, 10, 11]])
x[x%2 == 1]
#array([ 1,  3,  5,  7,  9, 11])
  • (2) 将奇数值修改为 -1。
x = np.array([[ 0,  1,  2],[ 3,  4,  5],[ 6,  7,  8],[ 9, 10, 11]])
x[x%2 == 1] = -1
x
#array([[ 0, -1,  2],
#       [-1,  4, -1],
#       [ 6, -1,  8],
#       [-1, 10, -1]])
  • 筛选出指定区间内数据
  • & 表示和。
  • | 表示或。
  • 将数组 x 中大于 4 并且小于 9 的数据提取出来。
x = np.array([[ 0,  1,  2],[ 3,  4,  5],[ 6,  7,  8],[ 9, 10, 11]])
x[(x>4) & (x<9)]
#array([5, 6, 7, 8])
  • 将数组 x 中小于4或者大于 9 的数据提取出来。
x = np.array([[ 0,  1,  2],[ 3,  4,  5],[ 6,  7,  8],[ 9, 10, 11]])
x[(x<4) | (x>9)]#array([ 0,  1,  2,  3, 10, 11])
  • True 和 False 的形式表示需要和不需要的数据
  • 我们先创建 3*4 的数组,元素通过 np.arange(12) 自动生成,表示从起始值 0 到终止值(不包括终止值)12,步长是 1。
a3_4 = np.arange(12).reshape((3,4))
a3_4
#array([[ 0,  1,  2,  3],
#       [ 4,  5,  6,  7],
#       [ 8,  9, 10, 11]])
  • 将行变量和列变量分别用 True 和 False 表示,其中行变量和列变量按如下代码设置。
row1 = np.array([False,True,True])
column1 = np.array([True,False,True,False])
  • a3_4 是 3 行, 做切片时也提供 3 个元素的数组,轴的长度一致。
  • 通过 row1 和 column1 中的 True 和 False 就可以输出我们需要的元素,True 表示需要,False 表示不需要。
a3_4[row1]
#array([[ 4,  5,  6,  7],
#       [ 8,  9, 10, 11]])

a3_4[:,column1]
#array([[ 0,  2],
#       [ 4,  6],
#       [ 8, 10]])
  • 那么我们是否可以用两个一维布尔数组进行切片呢?我们继续进行试验得到如下结果:
a3_4[row1,column1]
#array([ 4, 10])
  • 从结果上看,它实际上等价于下面的代码。
a3_4[[1, 2],[0, 2]]
  • 输出的相当于是坐标序号为 (0,1),(2,2) 的数。
  • 索引形状不匹配
  • 从上面的结果可以知道,能够进行切片的前提是:两个一维布尔数组中 True 的个数需要相等,否则会出现下面的情况。
  • 行变量当中存在 2 个 True 元素,列变量当中存在 3 个 True 元素。
row2 = np.array([False,True,True])
​column2 = np.array([True,False,True,True])
  • 其中,行变量和列变量当中的 True 元素个数不一致,会导致错误。
  • a3_4[row2, column2] 就相当于 a3_4[[1,2],[0,2,3]]。
  • 报错信息如下:indexError: shape mismatch: indexing arrays could not be broadcast together with shapes (2,) (3,)。
  • 是因为所选索引形状不匹配:索引数组无法与该形状一起广播。
  • 当访问 numpy 多维数组时,用于索引的数组需要具有相同的形状(行和列)。numpy 将有可能去广播,所以,若要为了实现不同维度的选择, 可分两步对数组进行选择。
  • (1) 例如我需要选择第 1 行和最后一行的第 1,3,4 列时,先选择行,再选择列。
  • (2) 先读取数组 a3_4 的第一行和最后一行,保存到 temp ,然后再筛选相应的列即可。
a3_4
#array([[ 0,  1,  2,  3],
#       [ 4,  5,  6,  7],
#       [ 8,  9, 10, 11]])
  • 那么,我们需要选择第 1 行和最后一行的第 1,3,4 列元素,操作步骤如下:
  • (1) 先选行。
temp = a3_4[[0,-1],:]
temp
#array([[ 0,  1,  2,  3],
#       [ 8,  9, 10, 11]])
  • (2) 再选择列。
temp[:,[0,2,3]]
temp
#array([[ 0,  2,  3],
#       [ 8, 10, 11]])
  • (3) 合并一条。
a3_4[[0,-1],:][:,[0,2,3]]
  • 但是,如果有一个一维数组长度是 1 时,这时又不会报错:
  • 比如说,如果我们需要提取第二行,第 1,3 列的数据。
a3_4[[1],[0,2]]
#array([4, 6])
  • 以上相当于 (1,0) 和 (1,2)。
  • 数组索引及切片的值更改会修改原数组
  • 一个标量赋值给一个索引/切片时,会自动改变/传播原始数组。
ar = np.arange(10)
print(ar)
ab = ar[:]
ar[5] = 100
print(ab)
#[0 1 2 3 4 5 6 7 8 9]
#[  0   1   2   3   4 100   6   7   8   9]
  • 可以使用复制操作。
ar = np.arange(10)
b = ar.copy()
  • 或者可以使用 b = np.array(ar)。
b[7:9] = 200
print('ar:',ar)
print('b:',b)

三、广播机制

  • 广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算的方式, 对数组的算术运算通常在相应的元素上进行。
  • 如果两个数组 a 和 b 形状相同,即满足 a.shape == b.shape,那么 a*b 的结果就是 a 与 b 数组对应位相乘。这要求维数相同,且各维度的长度相同。
a = np.array([1,2,3,4]) 
b = np.array([10,20,30,40]) 
c = a * b 
print (c)
#[ 10  40  90 160]
  • 但如果两个形状不同的数组呢?它们之间就不能做算术运算了吗?
  • 当然不是!为了保持数组形状相同,NumPy 设计了一种广播机制, 这种机制的核心是对形状较小的数组,在横向或纵向上进行一定次数的重复,使其与形状较大的数组拥有相同的维度
a = np.array([[ 0, 0, 0],
           [10,10,10],
           [20,20,20],
           [30,30,30]])
b = np.array([1,2,3])
print(a + b)
  • 下面的图片展示了数组 b 如何通过广播来与数组 a 兼容。

在这里插入图片描述

  • 4x3 的二维数组与长为 3 的一维数组相加,等效于把数组 b 在二维上重复 4 次再运算。

1. 广播机制规则

  • 广播具有如下规则:
  • (1) 让所有输入数组都向其中形状最长的数组看齐,形状中不足的部分都通过在前面加 1 补齐。
  • (2) 输出数组的形状是输入数组形状的各个维度上的最大值。
  • (3) 如果输入数组的某个维度和输出数组的对应维度的长度相同或者其长度为 1 时,这个数组能够用来计算,否则出错。
  • (4) 当输入数组的某个维度的长度为 1 时,沿着此维度运算时都用此维度上的第一组值。
  • ** 为了更清楚的理解这些规则看,来看几个具体的示例**
  • 我们通过 np.ones() 生成一个全 1 数组,np.arange() 生成一个有规律元素的数组。
  • 两个数组的形状分别为 M.shape=(2,3),a.shape=(3,)。
  • 可以看到,根据规则 1,数组 a 的维度更小,所以在其左边补 1,变为 M.shape -> (2,3), a.shape -> (1,3)。
  • 根据规则 2,第一个维度不匹配,因此扩展这个维度以匹配数组:M.shape ->(2,3), a.shape -> (1,3)。
  • 现在两个数组的形状匹配了,可以看到它们的最终形状都为(2,3)。
M = np.ones((2,3))
print(M)
a = np.arange(3)
print(a)
M + a
#[[1. 1. 1.]
# [1. 1. 1.]]
#[0 1 2]
#array([[1., 2., 3.],
#       [1., 2., 3.]])
  • 我们通过 np.arange() 生成两个有规律元素数组,其中一个设置为三行一列,便于对广播机制进行验证。
  • 两个数组的形状设置为 a.shape=(3,1), b.shape=(3,)。
  • 规则 1 告诉我们,需要用 1 将 b 的形状补全:a.shape -> (3,1), b.shape -> (1,3)。
  • 规则 2 告诉我们,需要更新这两个数组的维度来相互匹配:a.shape -> (3,3), b.shape -> (3,3)
  • 因为结果匹配,所以这两个形状是兼容的。
a = np.arange(3).reshape((3,1))
print('a:',a)
b = np.arange(3)
print('b:',b)
a + b
#a: [[0]
# [1]
# [2]]
#b: [0 1 2]
#array([[0, 1, 2],
#       [1, 2, 3],
#       [2, 3, 4]])

2. 对于广播规则另一种简单理解

  • (1) 将两个数组的维度大小右对齐,然后比较对应维度上的数值。
  • (2) 如果数值相等或其中有一个为1或者为空,则能进行广播运算。
  • (3) 输出的维度大小为取数值大的数值。否则不能进行数组运算。
  • 数组 a 大小为(2, 3),数组 b 大小为 (1,),对其进行右对齐操作。
   2   3
       1
----------
   2   3
  • 所以最后两个数组运算的输出大小为:(2, 3),下面对其进行代码验证。
a = np.arange(6).reshape(2, 3)
print('a:', a)
b = np.array([5])
print('b:',b)
c = a * b 
c
#a: [[0 1 2]
# [3 4 5]]
#b: [5]
#array([[ 0,  5, 10],
#       [15, 20, 25]])
  • 数组 a 大小为 (2, 1, 3),数组 b 大小为 (4, 1),对其进行右对齐操作。
 2  1  3
    4  1
----------
 2  4  3
  • 所以最后两个数组运算的输出大小为:(2, 4, 3)。
a= np.arange(6).reshape(2, 1, 3)print('a:',a)
print('-'*10)
b = np.arange(4).reshape(4, 1)
print('b:',b)
print('-'*10)
c = a + b
print(c,c.shape)
#​a: [[[0 1 2]]
#
# [[3 4 5]]]
#----------
#b: [[0]
# [1]
# [2]
# [3]]
#----------
#[[[0 1 2]
#  [1 2 3]
#  [2 3 4]
#  [3 4 5]]
#
# [[3 4 5]
#  [4 5 6]
#  [5 6 7]
#  [6 7 8]]] (2, 4, 3)
  • 从这里能够看出:
  • (1) 两个数组右对齐以后,对应维度里的数值要么相等,要么有一个为 1,要么缺失取大值。
  • (2) 除此之外就会报错。像下面的两个数组就不能做运算。
  • 数组 a 大小为 (2, 1, 3),数组 b 大小为 (4, 2),对其进行右对齐操作。
 2  1  3
    4  2
----------
  • 2 跟 3 不匹配,此时就不能做运算。
a = np.arange(6).reshape(2, 1, 3)
print('a:',a)
print('-'*10)
b = np.arange(8).reshape(4, 2)
print('b:',b)
print('-'*10)
a + b
#a: [[[0 1 2]]
#
# [[3 4 5]]]
#----------
#b: [[0 1]
# [2 3]
# [4 5]
# [6 7]]
#----------
#---------------------------------------------------------------------------
#ValueError                                Traceback (most recent call last)
#<ipython-input-68-2ebfaa0877fb> in <module>
#      9 print('-'*10)
#     10 # 运行报错
#---> 11 a + b
#
#ValueError: operands could not be broadcast together with shapes (2,1,3) (4,2) 
  • 广播机制能够处理不同大小的数组,数组之间必须满足广播的规则,否则就会报错。
  • 事实上,相同大小的数组运算也遵循广播机制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/342566.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

30、基于51单片机交通灯车流量管控数码管显示系统设计

摘要 随着社会主义的建设&#xff0c;城市的规模在不断扩大&#xff0c;城市的交通也在不断的提高和改进&#xff0c;交通的顺畅已经成为制约社会主义建设的一个重要因素。目前&#xff0c;伴随着机动车辆的不断增加&#xff0c;尤其是十字路口的交通建设 颇为关键&#xff0c…

PID控制算法简介

目录 1 简介 2 比例Proportional 3 积分Integral 4 微分Differential 5 公式 6 积分限幅 7 积分限行 8 相关代码 1 简介 PID控制中有P、I、D三个参数&#xff0c;PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&#…

【渝偲医药】实验室关于核磁共振波谱NMR的知识(原理、用途、分析、问题)

核磁共振波谱法&#xff08;Nuclear Magnetic Resonance&#xff0c;简写为NMR&#xff09;与紫外吸收光谱、红外吸收光谱、质谱被人们称为“四谱"&#xff0c;是对各种有机和无机物的成分、结构进行定性分析的强有力的工具之一&#xff0c;亦可进行定量分析。 核磁共振&…

目标检测的旋框框文献学习

这是最近打算看完的文献&#xff0c;一天一篇 接下来将记录一下文献阅读笔记&#xff0c;避免过两天就忘了 RRPN 论文题目&#xff1a;Arbitrary-Oriented Scene Text Detection via Rotation Proposals 论文题目&#xff1a;通过旋转方案进行任意方向的场景文本检测&#x…

深度学习刷 SOTA 有哪些 trick?

“深度学习刷 SOTA 有哪些 trick&#xff1f;”&#xff0c;此问题在知乎上有超 1700 人关注&#xff0c;浏览量超 32 万&#xff0c;相信是大家都非常关心的问题&#xff0c;快一起看看下面的分享吧&#xff0c;希望可以帮助到大家~对于图像分类任务&#xff0c;让我们以 Swin…

阿里前端必会手写面试题汇总

实现节流函数&#xff08;throttle&#xff09; 节流函数原理:指频繁触发事件时&#xff0c;只会在指定的时间段内执行事件回调&#xff0c;即触发事件间隔大于等于指定的时间才会执行回调函数。总结起来就是&#xff1a; 事件&#xff0c;按照一段时间的间隔来进行触发 。 像d…

啪,还敢抛出异常

&#x1f649; 作者简介&#xff1a; 全栈领域新星创作者 &#xff1b;天天被业务折腾得死去活来的同时依然保有对各项技术热忱的追求&#xff0c;把分享变成一种习惯&#xff0c;再小的帆也能远航。 &#x1f3e1; 个人主页&#xff1a;xiezhr的个人主页 前言 去年又重新刷了…

DELL游匣ubuntu2004系统 RTX3060显卡,cuda11.4,cudnn8.2.4安装

1.安装Ubuntu2004的系统2.驱动安装前的准备工作第一步&#xff1a;修改设置下载源~阿里源。在Software Updater在第一栏Ubuntu Software页面中&#xff0c;找到Download from&#xff0c;选择->China->mirrors.aliyun.com,点击确认。第二步&#xff1a;sudo apt-get upda…

都说爱有回音,这次情人节驱动人生宠你!

来了来了&#xff0c;它又来了——那个一波人狂欢&#xff0c;一波人孤单的节日。 眼看着身边人在订花订餐厅&#xff0c;选礼物&#xff0c;空气中弥漫着微妙的氛围&#xff0c;驱动哥脑海里只有明天下班的地铁挤不挤得过这群约会的人。 不过根据哥的观察&#xff0c;发现一个…

【GlobalMapper精品教程】046:空间操作(3)——并集(Union)

本文讲解globalmapper空间操作中一种很重要的工具:并集。 文章目录 一、工具介绍1. 并集原理2. GM并集工具二、案例演示1. 加载数据2. 并集运算三、结果分析1. 空间变化2. 属性表变化3. 空间和属性对应关系一、工具介绍 1. 并集原理 并集(union)操作创建由两个输入图层的所…

80 90后表示真干不过,部门新来的00后已经把我卷奔溃了,不想干了····

都说00后躺平了&#xff0c;但是有一说一&#xff0c;该卷的还是卷。这不&#xff0c;刚开年我们公司来了个00后&#xff0c;工作没两年&#xff0c;跳槽到我们公司起薪18K&#xff0c;都快接近我了。 后来才知道人家是个卷王&#xff0c;从早干到晚就差搬张床到工位睡觉了。 …

操作系统开发:启用内存分页机制

目前我们已进入保护模式,但依然会受到限制,虽然地址空间达到了4GB,但此空间是包括操作系统共享的4GB空间&#xff0c;我们把段基址段内偏移地址称为线性地址&#xff0c;线性地址是唯一的&#xff0c;只属于某一个进程。在我们机器上即使只有512MB的内存&#xff0c;每个进程自…

开发微服务电商项目演示(四)

一&#xff0c;网关服务限流熔断降级第1步&#xff1a;启动sentinel-dashboard控制台和Nacos注册中心服务第2步&#xff1a;在网关服务中引入sentinel依赖<!-- sentinel --> <dependency><groupId>com.alibaba.cloud</groupId><artifactId>sprin…

快速排序基本原理

快速排序基本原理1.快速排序1.1 基本原理1.2 快速排序执行步骤1.2.1 分区包含步骤1.2.1 分区步骤1.3 快速排序大O记法表示2. 将[0,5,2,1,6,3]进行快速排序 【实战】2.1 第一次分区步骤2.2 第二次分区步骤2.3 第三次分区步骤2.4 第四次分区步骤3.快速排序代码实现1.快速排序 1.…

一文盘点,ZBC的应用场景与通缩场景

进入到2023年&#xff0c;Zebec生态正在向新的叙事方向发展。一方面我们看到&#xff0c;流支付生态Zebec在此前正式走向DAO&#xff0c;并上线了DAO治理投票平台Zebec Node&#xff0c;任何持有ZBC的用户都可以参与投票。另一方面我们看到生态正在朝着最初的愿景迸发&#xff…

3.28 haas506 2.0开发教程-example-蓝牙多设备扫描(仅支持M320,HD1)

haas506 2.0开发教程-example-蓝牙多设备扫描案例说明蓝牙信息克隆1.手机蓝牙改名信息克隆代码测试案例说明 开发板扫描蓝牙设备&#xff0c;获取并打印蓝牙设备mac地址。mac地址每个设备不同&#xff0c;且不能更改。本案例仅适用于M320开发板和HD1-RTU。案例使用手机与iBeac…

LeetCode(剑指offer) Day1

1.用两个栈实现一个队列。队列的声明如下&#xff0c;请实现它的两个函数 appendTail 和 deleteHead &#xff0c;分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素&#xff0c;deleteHead 操作返回 -1 ) 解题过程记录&#xff1a;本题就是用两个栈&…

如何激励你的内容团队产出更好的创意

对于一个品牌而言&#xff0c;如何创造吸引受众并对受众有价值内容是十分关键的。随着市场数字化的推进&#xff0c;优质的创意和内容输出对一个品牌在市场中有着深远的影响。对于很多内容策划和创作者来说&#xff0c;不断地产出高质量有创意的内容是一件非常有挑战性的事情。…

【零基础入门前端系列】—超链接和文本格式化标签(四)

【零基础入门前端系列】—超链接和文本格式化标签&#xff08;四&#xff09; 一、超链接 HTML使用标签 <a>来设置超文本链接。超链接可以是一个字&#xff0c;一个词&#xff0c;或者一组词&#xff0c;也可以是一幅图像&#xff0c;您可以点击这些内容来跳转到新的文…

别再问我供应商质量工程师(SQE)是干什么的了,这是最好的解释。

供应商质量工程师&#xff08;SQE&#xff09;是指一种负责监督供应商质量的职业。SQE的工作主要包括以下几项内容&#xff1a; 核查供应商质量&#xff1a;通过对供应商的产品、服务和生产流程的评估&#xff0c;来确保供应商的质量符合公司的标准和要求。开展质量审核&#…