NumPy 数组计算:广播机制

article/2025/6/18 22:58:16

文章目录

  • NumPy 数组计算:广播机制
    • 一、广播机制简介
    • 二、广播机制的规则
      • 1. 广播机制示例 1
      • 2. 广播机制示例 2
      • 3. 广播机制示例 3
    • 三、广播机制实战
      • 1. 数组的中心化
      • 2. 绘制二维函数

NumPy 数组计算:广播机制

我们在NumPy数组的计算:通用函数中看到,NumPy 的通用函数可以用于向量化操作,从而避免缓慢的 Python 循环。本章将讨论广播机制:这是一组规则,使得 NumPy 能够在不同大小和形状的数组之间应用二元操作(如加法、减法、乘法等)。

一、广播机制简介

回忆一下,对于相同大小的数组,二元操作是按元素逐一进行的:

import numpy as np
a = np.array([0, 1, 2])
b = np.array([5, 5, 5])
a + b
array([5, 6, 7])

广播机制允许这些类型的二元操作在不同大小的数组之间进行——例如,我们同样可以轻易将一个标量(可以看作是零维数组)加到一个数组上:

a + 5
array([5, 6, 7])

我们可以将其看作是一个操作,将数值 5 扩展或复制为数组 [5, 5, 5],然后进行相加。

同样,我们可以将这个思想扩展到更高维的数组。请观察当我们将一维数组与二维数组相加时的结果:

M = np.ones((3, 3))
M
array([[1., 1., 1.],[1., 1., 1.],[1., 1., 1.]])
M + a
array([[1., 2., 3.],[1., 2., 3.],[1., 2., 3.]])

这里一维数组 a 被扩展(广播)到第二个维度,以匹配 M 的形状。

虽然这些例子相对容易理解,但更复杂的情况可能涉及到对两个数组的广播。请看下面的例子:

a = np.arange(3)
b = np.arange(3)[:, np.newaxis]print(a)
print(b)
[0 1 2]
[[0][1][2]]
a + b
array([[0, 1, 2],[1, 2, 3],[2, 3, 4]])

就像之前将一个值扩展或广播以匹配另一个的形状一样,这里我们将 ab 都扩展到了一个共同的形状,结果是一个二维数组!
这些例子的几何关系可以通过下图进行可视化。(生成该图的代码可以在在线附录中找到,现将代码罗列如下,并改编自astroML 文档中发布的资源。已获许可使用。)

# Adapted from astroML: see http://www.astroml.org/book_images/appendix/fig_broadcast_visual.html
import numpy as np
from matplotlib import pyplot as plt#------------------------------------------------------------
# Draw a figure and axis with no boundary
fig = plt.figure(figsize=(6, 4.5), facecolor='w')
ax = plt.axes([0, 0, 1, 1], xticks=[], yticks=[], frameon=False)def draw_cube(ax, xy, size, depth=0.4,edges=None, label=None, label_kwargs=None, **kwargs):"""draw and label a cube.  edges is a list of numbers between1 and 12, specifying which of the 12 cube edges to draw"""if edges is None:edges = range(1, 13)x, y = xyif 1 in edges:ax.plot([x, x + size],[y + size, y + size], **kwargs)if 2 in edges:ax.plot([x + size, x + size],[y, y + size], **kwargs)if 3 in edges:ax.plot([x, x + size],[y, y], **kwargs)if 4 in edges:ax.plot([x, x],[y, y + size], **kwargs)if 5 in edges:ax.plot([x, x + depth],[y + size, y + depth + size], **kwargs)if 6 in edges:ax.plot([x + size, x + size + depth],[y + size, y + depth + size], **kwargs)if 7 in edges:ax.plot([x + size, x + size + depth],[y, y + depth], **kwargs)if 8 in edges:ax.plot([x, x + depth],[y, y + depth], **kwargs)if 9 in edges:ax.plot([x + depth, x + depth + size],[y + depth + size, y + depth + size], **kwargs)if 10 in edges:ax.plot([x + depth + size, x + depth + size],[y + depth, y + depth + size], **kwargs)if 11 in edges:ax.plot([x + depth, x + depth + size],[y + depth, y + depth], **kwargs)if 12 in edges:ax.plot([x + depth, x + depth],[y + depth, y + depth + size], **kwargs)if label:if label_kwargs is None:label_kwargs = {}ax.text(x + 0.5 * size, y + 0.5 * size, label,ha='center', va='center', **label_kwargs)solid = dict(c='black', ls='-', lw=1,label_kwargs=dict(color='k'))
dotted = dict(c='black', ls='-', lw=0.5, alpha=0.5,label_kwargs=dict(color='gray'))
depth = 0.3#------------------------------------------------------------
# Draw top operation: vector plus scalar
draw_cube(ax, (1, 10), 1, depth, [1, 2, 3, 4, 5, 6, 9], '0', **solid)
draw_cube(ax, (2, 10), 1, depth, [1, 2, 3, 6, 9], '1', **solid)
draw_cube(ax, (3, 10), 1, depth, [1, 2, 3, 6, 7, 9, 10], '2', **solid)draw_cube(ax, (6, 10), 1, depth, [1, 2, 3, 4, 5, 6, 7, 9, 10], '5', **solid)
draw_cube(ax, (7, 10), 1, depth, [1, 2, 3, 6, 7, 9, 10, 11], '5', **dotted)
draw_cube(ax, (8, 10), 1, depth, [1, 2, 3, 6, 7, 9, 10, 11], '5', **dotted)draw_cube(ax, (12, 10), 1, depth, [1, 2, 3, 4, 5, 6, 9], '5', **solid)
draw_cube(ax, (13, 10), 1, depth, [1, 2, 3, 6, 9], '6', **solid)
draw_cube(ax, (14, 10), 1, depth, [1, 2, 3, 6, 7, 9, 10], '7', **solid)ax.text(5, 10.5, '+', size=12, ha='center', va='center')
ax.text(10.5, 10.5, '=', size=12, ha='center', va='center')
ax.text(1, 11.5, r'${\tt np.arange(3) + 5}$',size=12, ha='left', va='bottom')#------------------------------------------------------------
# Draw middle operation: matrix plus vector# first block
draw_cube(ax, (1, 7.5), 1, depth, [1, 2, 3, 4, 5, 6, 9], '1', **solid)
draw_cube(ax, (2, 7.5), 1, depth, [1, 2, 3, 6, 9], '1', **solid)
draw_cube(ax, (3, 7.5), 1, depth, [1, 2, 3, 6, 7, 9, 10], '1', **solid)draw_cube(ax, (1, 6.5), 1, depth, [2, 3, 4], '1', **solid)
draw_cube(ax, (2, 6.5), 1, depth, [2, 3], '1', **solid)
draw_cube(ax, (3, 6.5), 1, depth, [2, 3, 7, 10], '1', **solid)draw_cube(ax, (1, 5.5), 1, depth, [2, 3, 4], '1', **solid)
draw_cube(ax, (2, 5.5), 1, depth, [2, 3], '1', **solid)
draw_cube(ax, (3, 5.5), 1, depth, [2, 3, 7, 10], '1', **solid)# second block
draw_cube(ax, (6, 7.5), 1, depth, [1, 2, 3, 4, 5, 6, 9], '0', **solid)
draw_cube(ax, (7, 7.5), 1, depth, [1, 2, 3, 6, 9], '1', **solid)
draw_cube(ax, (8, 7.5), 1, depth, [1, 2, 3, 6, 7, 9, 10], '2', **solid)draw_cube(ax, (6, 6.5), 1, depth, range(2, 13), '0', **dotted)
draw_cube(ax, (7, 6.5), 1, depth, [2, 3, 6, 7, 9, 10, 11], '1', **dotted)
draw_cube(ax, (8, 6.5), 1, depth, [2, 3, 6, 7, 9, 10, 11], '2', **dotted)draw_cube(ax, (6, 5.5), 1, depth, [2, 3, 4, 7, 8, 10, 11, 12], '0', **dotted)
draw_cube(ax, (7, 5.5), 1, depth, [2, 3, 7, 10, 11], '1', **dotted)
draw_cube(ax, (8, 5.5), 1, depth, [2, 3, 7, 10, 11], '2', **dotted)# third block
draw_cube(ax, (12, 7.5), 1, depth, [1, 2, 3, 4, 5, 6, 9], '1', **solid)
draw_cube(ax, (13, 7.5), 1, depth, [1, 2, 3, 6, 9], '2', **solid)
draw_cube(ax, (14, 7.5), 1, depth, [1, 2, 3, 6, 7, 9, 10], '3', **solid)draw_cube(ax, (12, 6.5), 1, depth, [2, 3, 4], '1', **solid)
draw_cube(ax, (13, 6.5), 1, depth, [2, 3], '2', **solid)
draw_cube(ax, (14, 6.5), 1, depth, [2, 3, 7, 10], '3', **solid)draw_cube(ax, (12, 5.5), 1, depth, [2, 3, 4], '1', **solid)
draw_cube(ax, (13, 5.5), 1, depth, [2, 3], '2', **solid)
draw_cube(ax, (14, 5.5), 1, depth, [2, 3, 7, 10], '3', **solid)ax.text(5, 7.0, '+', size=12, ha='center', va='center')
ax.text(10.5, 7.0, '=', size=12, ha='center', va='center')
ax.text(1, 9.0, r'${\tt np.ones((3,\, 3)) + np.arange(3)}$',size=12, ha='left', va='bottom')#------------------------------------------------------------
# Draw bottom operation: vector plus vector, double broadcast# first block
draw_cube(ax, (1, 3), 1, depth, [1, 2, 3, 4, 5, 6, 7, 9, 10], '0', **solid)
draw_cube(ax, (1, 2), 1, depth, [2, 3, 4, 7, 10], '1', **solid)
draw_cube(ax, (1, 1), 1, depth, [2, 3, 4, 7, 10], '2', **solid)draw_cube(ax, (2, 3), 1, depth, [1, 2, 3, 6, 7, 9, 10, 11], '0', **dotted)
draw_cube(ax, (2, 2), 1, depth, [2, 3, 7, 10, 11], '1', **dotted)
draw_cube(ax, (2, 1), 1, depth, [2, 3, 7, 10, 11], '2', **dotted)draw_cube(ax, (3, 3), 1, depth, [1, 2, 3, 6, 7, 9, 10, 11], '0', **dotted)
draw_cube(ax, (3, 2), 1, depth, [2, 3, 7, 10, 11], '1', **dotted)
draw_cube(ax, (3, 1), 1, depth, [2, 3, 7, 10, 11], '2', **dotted)# second block
draw_cube(ax, (6, 3), 1, depth, [1, 2, 3, 4, 5, 6, 9], '0', **solid)
draw_cube(ax, (7, 3), 1, depth, [1, 2, 3, 6, 9], '1', **solid)
draw_cube(ax, (8, 3), 1, depth, [1, 2, 3, 6, 7, 9, 10], '2', **solid)draw_cube(ax, (6, 2), 1, depth, range(2, 13), '0', **dotted)
draw_cube(ax, (7, 2), 1, depth, [2, 3, 6, 7, 9, 10, 11], '1', **dotted)
draw_cube(ax, (8, 2), 1, depth, [2, 3, 6, 7, 9, 10, 11], '2', **dotted)draw_cube(ax, (6, 1), 1, depth, [2, 3, 4, 7, 8, 10, 11, 12], '0', **dotted)
draw_cube(ax, (7, 1), 1, depth, [2, 3, 7, 10, 11], '1', **dotted)
draw_cube(ax, (8, 1), 1, depth, [2, 3, 7, 10, 11], '2', **dotted)# third block
draw_cube(ax, (12, 3), 1, depth, [1, 2, 3, 4, 5, 6, 9], '0', **solid)
draw_cube(ax, (13, 3), 1, depth, [1, 2, 3, 6, 9], '1', **solid)
draw_cube(ax, (14, 3), 1, depth, [1, 2, 3, 6, 7, 9, 10], '2', **solid)draw_cube(ax, (12, 2), 1, depth, [2, 3, 4], '1', **solid)
draw_cube(ax, (13, 2), 1, depth, [2, 3], '2', **solid)
draw_cube(ax, (14, 2), 1, depth, [2, 3, 7, 10], '3', **solid)draw_cube(ax, (12, 1), 1, depth, [2, 3, 4], '2', **solid)
draw_cube(ax, (13, 1), 1, depth, [2, 3], '3', **solid)
draw_cube(ax, (14, 1), 1, depth, [2, 3, 7, 10], '4', **solid)ax.text(5, 2.5, '+', size=12, ha='center', va='center')
ax.text(10.5, 2.5, '=', size=12, ha='center', va='center')
ax.text(1, 4.5, r'${\tt np.arange(3).reshape((3,\, 1)) + np.arange(3)}$',ha='left', size=12, va='bottom')ax.set_xlim(0, 16)
ax.set_ylim(0.5, 12.5)
(0.5, 12.5)

广播原理

浅色的方框代表被广播的值。以这种方式思考广播机制,可能会让人担心其内存使用效率,但不用担心:NumPy 的广播实际上并不会在内存中复制被广播的值。不过,在理解广播机制时,这种思维模型依然非常有用。

二、广播机制的规则

NumPy 中的广播机制遵循一套严格的规则,以确定两个数组之间的交互方式:

  • 规则 1:如果两个数组的维度数不同,则维度较少的数组会在其前(左)侧用 1 进行填充。
  • 规则 2:如果两个数组在某个维度上的形状不匹配,但其中一个数组在该维度上的长度为 1,则该数组会被拉伸以匹配另一个数组的形状。
  • 规则 3:如果在任何一个维度上,两个数组的长度不相等且都不为 1,则会引发错误。

为了更清楚地说明这些规则,下面我们将通过几个例子进行详细说明。

1. 广播机制示例 1

假设我们想将一个二维数组与一个一维数组相加:

M = np.ones((2, 3))
a = np.arange(3)

让我们考虑对这两个数组进行操作,它们的形状如下:

  • 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 变为 (2, 3)

此时形状已经一致,最终的结果形状为 (2, 3)

M + a
array([[1., 2., 3.],[1., 2., 3.]])

2. 广播机制示例 2

现在让我们来看一个需要对两个数组都进行广播的例子:

a = np.arange(3).reshape((3, 1))
b = np.arange(3)

再次,我们首先确定数组的形状:

  • a.shape(3, 1)
  • b.shape(3,)

规则 1 告诉我们需要用 1 填充 b 的形状:

  • a.shape 仍为 (3, 1)
  • b.shape 变为 (1, 3)

根据规则 2,我们需要将这些 1 升级为与另一个数组对应维度的大小:

  • a.shape 变为 (3, 3)
  • b.shape 变为 (3, 3)

由于最终形状一致,这些形状是兼容的。我们可以通过下面的例子看到这一点:

a + b
array([[0, 1, 2],[1, 2, 3],[2, 3, 4]])

3. 广播机制示例 3

接下来,让我们看一个两个数组不兼容的例子:

M = np.ones((3, 2))
a = np.arange(3)

这与第一个示例只是略有不同:矩阵 M 被转置了。
这会如何影响计算呢?数组的形状如下:

  • M.shape(3, 2)
  • a.shape(3,)

同样,规则 1 告诉我们需要用 1 填充 a 的形状:

  • M.shape 仍为 (3, 2)
  • a.shape 变为 (1, 3)

根据规则 2,a 的第一个维度会被扩展以匹配 M

  • M.shape 仍为 (3, 2)
  • a.shape 变为 (3, 3)

此时我们遇到了规则 3——最终的形状并不匹配,因此这两个数组是不兼容的,正如我们尝试进行该操作时会发现的一样:

M + a
---------------------------------------------------------------------------ValueError                                Traceback (most recent call last)Cell In[14], line 1
----> 1 M + aValueError: operands could not be broadcast together with shapes (3,2) (3,) 
a[:, np.newaxis].shape
(3, 1)
M + a[:, np.newaxis]
array([[1., 1.],[2., 2.],[3., 3.]])

还要注意,虽然我们这里主要关注的是 + 运算符,但这些广播规则适用于任何二元通用函数(ufunc)。
例如,下面是 logaddexp(a, b) 函数,它可以比朴素方法更精确地计算 log(exp(a) + exp(b))

np.logaddexp(M, a[:, np.newaxis])
array([[1.31326169, 1.31326169],[1.69314718, 1.69314718],[2.31326169, 2.31326169]])

关于更多可用的通用函数,请参考NumPy数组的计算:通用函数。

三、广播机制实战

广播操作构成了本书中许多示例的核心。
接下来我们将看看广播机制在实际中的一些有用场景。

1. 数组的中心化

在NumPy数组的计算:通用函数中,我们看到 ufunc(通用函数)让 NumPy 用户无需显式编写缓慢的 Python 循环。广播机制进一步扩展了这种能力。
在数据科学中,一个常见的例子是从数据数组中减去每一行的均值。
假设我们有一个包含 10 个观测值的数组,每个观测值由 3 个数值组成。
按照标准惯例,我们将其存储为一个 10 × 3 10 \times 3 10×3 的数组:

rng = np.random.default_rng(seed=1701)
X = rng.random((10, 3))

我们可以通过在第一个维度上使用 mean 聚合来计算每一列的均值:

Xmean = X.mean(0)
Xmean
array([0.38503638, 0.36991443, 0.63896043])

现在我们可以通过减去均值来对 X 数组进行中心化(这就是一次广播操作):

X_centered = X - Xmean

为了确认我们的操作是否正确,我们可以检查中心化后的数组的均值是否接近于零:

X_centered.mean(0)
array([ 4.99600361e-17, -4.44089210e-17,  0.00000000e+00])

在机器精度范围内,均值现在为零。

2. 绘制二维函数

广播机制常常在基于二维函数显示图像时派上用场。
如果我们想定义一个函数 z = f ( x , y ) z = f(x, y) z=f(x,y),可以利用广播机制在整个网格上计算该函数:

# x 和 y 从0 到 5 生成 50 个点
x = np.linspace(0, 5, 50)
y = np.linspace(0, 5, 50)[:, np.newaxis]
# 计算 z 的值,z = sin(x)^10 + cos(10 + y * x) * cos(x)
z = np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)

我们将使用 Matplotlib 来绘制这个二维数组,如下图所示:

%matplotlib inline
import matplotlib.pyplot as plt
plt.imshow(z, origin='lower', extent=[0, 5, 0, 5])
plt.colorbar();

二维数组图

结果是对这个二维函数的精彩可视化展示。


http://www.hkcw.cn/article/VkQxfaUijv.shtml

相关文章

Codesys FOR 循环之轴控

关于多伺服的轴控,不管怎么写都会很复杂,要么编程的时候代码行数多,要么是后期检查时非常麻烦,目前还未找到一个两全其美的方法,今天介绍的是通过FOR循环的轴控,就属于后者,代码行数较少,控制的轴数也没有限制,不需要一个轴一个的复制FB块,但是想在调试的时候实时查看…

欧冠决赛杜埃梅开二度 新星闪耀赛场

北京时间6月1日,本赛季的欧冠决赛中,19岁的杜埃表现出色,梅开二度并送出一次助攻,帮助巴黎圣日耳曼在比赛进行到73分钟时以4-0领先国际米兰。据统计,杜埃成为自1964年国际米兰名宿桑德罗-马佐拉以来,首位在欧冠决赛中完成梅开二度并且送出助攻的球员。本赛季,杜埃代表巴…

使用VSCode在WSL和Docker中开发

通过WSL,开发人员可以安装 Linux 发行版(例如 Ubuntu、OpenSUSE、Kali、Debian、Arch Linux 等),并直接在 Windows 上使用 Linux 应用程序、实用程序和 Bash 命令行工具,不用进行任何修改,也无需使用传统虚…

《汇编语言》第12章 内中断——实验12 编写0号中断的处理程序

编写0号中断的处理程序,使得在除法溢出发生时,在屏幕中间显示字符串"divide error!",然后返回到DOS。 要求:仔细跟踪调试,在理解整个过程之前,不要进行后面课程的学习。 ;sy12.asm …

黑马k8s(十八)

一:安全认证 1.安全认证-概述 2.安全认证-认证方式 认证管理 3.安全认证-授权管理 因为没有授予角色deployment的权限,所以不能查看 4.安全认证-准入控制 二:DashBoard 之前在kubernetes中完成的所有操作都是通过命令行工具kubectl完成的…

python:PyMOL 使用教程 及实用示例

安装参阅:开源版PyMol安装保姆级教程 百度网盘下载 提取码:csub 简介: PyMOL是一个Python增强的分子图形工具。它擅长蛋白质、小分子、密度、表面和轨迹的3D可视化。它还包括分子编辑、射线追踪和动画。 PyMol的名字来源于“Py”表示该软件基于Python这…

第十二节:第三部分:集合框架:List系列集合:特点、方法、遍历方式、ArrayList集合的底层原理

List系列集合特点 List集合的特有方法 List集合支持的遍历方式 ArrayList集合的底层原理 ArrayList集合适合的应用场景 代码:List系列集合遍历方式 package com.itheima.day19_Collection_List;import java.util.ArrayList; import java.util.Iterator; import jav…

ZC-OFDM雷达通信一体化减小PAPR——SC-FDMA技术

文章目录 前言一、SC-FDMA 技术1、简介2、原理 二、MATLAB 仿真1、核心代码2、仿真结果 三、资源自取 前言 在 OFDM 雷达通信一体化系统中,信号的传输由多个子载波协同完成,多个载波信号相互叠加形成最终的发射信号。此叠加过程可能导致信号峰值显著高于…

【算法】贪心算法

一、贪心算法基本思想 贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从 整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。 我们希望贪心算法得到的最终结果也是整体最优的。虽然贪心算法不 能对所有问题都得到整体最优解(O…

通义灵码深度实战测评:从零构建智能家居控制中枢,体验AI编程新范式

一、项目背景:零基础挑战全栈智能家居系统 目标:开发具备设备控制、环境感知、用户习惯学习的智能家居控制中枢(PythonFlaskMQTTReact) 挑战点: 需集成硬件通信(MQTT)、Web服务(Flask)、前端交互(React) 调用天气AP…

C 语言开发中常见的开发环境

目录 1.Dev-C 2.Visual Studio Code 3.虚拟机 Linux 环境 4.嵌入式 MCU 专用开发环境 1.Dev-C 使用集成的 C/C 开发环境(注:较老旧方案,适合基础学习) 2.Visual Studio Code 结合 C/C 扩展 GCC/MinGW 编译器,配置…

关于用Cloudflare的Zero Trust实现绕过备案访问国内站点说明

cloudflare 是一个可免费的CDN,CDN(Content Delivery Network,内容分发网络)加速国内网站,通常是已备案的。Zero Trust类似FRP,可以将请求转发到目标服务器。在使用Zero Trust绕过备案访问国内网站需要&…

火语言UI组件--播放器

【组件功能】:引用网络播放地址的视频播放器。 样式预览 设置 基础设置 属性名称属性释义输入值类型网络资源地址(url)播放视频的网络地址字符串类型音量(volume)播放视频的音量(参考值:0 ~ 1)浮点型(Float)自动播放(autoplay)视频是否自动…

Linux基本指令

文章目录 1.ls指令1.1 ls -l指令1.2 ls-a指令1.2.1文件的类型1.2.2隐藏文件1.2.3[.]\[..]的含义 1.3 ls -d指令1.4 ls-F指令1.5ls指令子功能大全 2.pwd指令2.1路径分割符2.2/根目录 3.mkdir指令3.1 mkdir-p3.2mkdir常用功能 4.cd指令4.1多叉树概念4.2绝对/相对路径4.2.1绝对路径…

桥 接 模 式

在玩游戏的时候我们常常会遇到这样的机制:我们可以随意选择不同的角色,搭配不同的武器。这时只有一个抽象上下文的策略模式就不那么适用了,因为一旦我们使用继承的方式,武器和角色总有一方会变得难以扩展。这时,我们就…

leetcode3128. 直角三角形-medium

1 题目:直角三角形 官方标定难度:中 给你一个二维 boolean 矩阵 grid 。 如果 grid 的 3 个元素的集合中,一个元素与另一个元素在 同一行,并且与第三个元素在 同一列,则该集合是一个 直角三角形。3 个元素 不必 彼此…

数据资产入表的数据质量评估

在数据资产入表过程中,对数据质量进行全面、系统的评估至关重要。下面将从数据完整性评估、数据准确性校验、数据一致性检查、数据时效性分析、数据可信度评价、数据规范性审核、数据安全性检测和数据可用性考察等方面,对数据资产入表的数据质量进行详细…

精简多功能办公软件

今天向大家推荐一款功能强大的实用软件。 软件介绍 这款名为"一个MH"的软件界面简洁明了,虽然体积小巧,却集成了多种实用功能,相当于整合了多个软件的功能于一身。软件将各类工具进行了系统分类,并配备了便捷的搜索功…

windows+APP PDFgear 免费工具

在处理PDF文件中,我们会遇到合并,编辑旋转、添加水印、转换格式等,这些在wps上是需要会员才能享受的功能,今天他来了--PDFgear,免费、离线、无任何附加条件的 PDF 编辑器。 文件大小:100M左右。 页面展示…

【深度学习】15. Segment Anything Model (SAM) :基于提示的分割新时代

Segment Anything Model (SAM) :基于提示的分割新时代 基本介绍 The first foundation model for promptable segmentation. Segment Anything Model(简称 SAM)是 Meta AI 于 2023 年提出的一种通用型图像分割基础模型。与以往分割模型不同&…