VoxPoser:使用大语言模型(GPT-4)来对机器人操作的可组合三维值图【论文解读】

news2024/11/16 17:40:16

这是最近斯坦福的李飞飞团队的一篇论文:VoxPoser: Composable 3D Value Maps for Robotic Manipulation with Language Models
主要是通过大语言模型LLM和视觉语言模型VLM结合,来对机器人做各种日常操作,我们可以先来看下实际效果:大语言模型加视觉模型的通用机器人
可以看到在不同的实际场景中都可以很好的进行日常操作,而且具备对机器人不需要进行训练的优势。对于这篇论文的解读,尽量通俗的按照自己的理解来表达,希望对大家有帮助,当然水平有限,有误之处,欢迎指正,一起进步。

1、VoxPoser开发的初衷

在以往的机器人操作当中,我们都是需要先预定义轨迹,这就使得机器人变得比较局限,更重要的是大规模的机器人数据的获取都是比较困难的,这就限制了机器人领域的发展。而ChatGPT4的出色回答,让我们感到让机器人成为通用机器人成为可能,可以利用这样的LLM来进行推理,然后给出机器人一些有用的步骤,再通过VLM来规划路径,这样理论上就做到了,机器人可以通过自然语言而跟现实世界进行交互了。所以VoxPoser就被开发出来了,这个工作的目标就是合成机器人轨迹,也就是接下来将要介绍的使用6自由度的末端执行器规划路径点序列,还开放了指令集和对象集。
我们先来看一张VOXPOSER示意图:

左边是VoxPoser的概览图,右边是一些操作的演示。
可以看到我们是在大语言模型提取了支持和约束(这里的支持就是机器人的操作目标,下面也可能有叫功能或功能可见性等叫法,意思是一样的,约束就是机器人在操作过程中要避开的东西),也可能叫做回避,比如这里的“Open the top drawer, and watch out for that vase!”(打开最上面的抽屉,小心那个花瓶!),故这里的抽屉就是支持,花瓶就是约束。
得到的步骤如下:
        1、应抓住最上面的抽屉把手
        2、把手需要向外平移
        3、机器人应远离花瓶
这些步骤再结合视觉语言模型,使用VOXPOSER提供的代码接口就能够规划出机器人的轨迹。

2、VoxPoser原理实现

上面我们大概介绍了VOXPOSER,接下来具体介绍VOXPOSER的原理,上面的示意图我们仔细观察左边那个机器人所在的空间,会发现每个区域的颜色是有区别的,看那个颜色条,左边是high cost,右边是high reward,也就是成本越高颜色是红颜色,高奖励的地方是蓝色,这样就会让机器人对此作出路径规划。

2.1、LLM+VLM

那具体是如何去实现的呢?同样的,来看一张示意图:

这里给出了两个函数的代码,affordance_map()constraint_map(),分别表示需要操作的目标和需要避开的目标的映射。
大语言模型生成与视觉语言模型交互的代码,以此来生成基于机器人观察空间的一系列3D功能图和约束图(统称为值图),然后,合成的值图作为运动规划者合成机器人操作轨迹的目标函数。
从两个函数来看,大同小异,都是先初始化一个三维数组(张量)映射,然后各自检测目标detect('handle')detect('vase'),不同点就是affordance_map是需要将目标对象的位置(top_handle.pos)都设置为1,在constraint_map里面是将检测到的对象所占用的格子(vase.occupancy_grid)的位置都设置为-1,最后两个分别返回其对应的值图。
经过上述处理之后,就有了Motion Planning运动规划:一种在机器人学和自动控制领域中用于规划物体在空间中的运动路径的方法,以避免碰撞并满足其他约束条件。

2.2、方法与公式

我们知道语言所表达出来的东西是比较自由的,或者说比较的宽泛,而机器人需要的是,具体的有针对性的操作指令。

比如说,“打开最上面的抽屉”,单纯根据这句话可能生成轨迹就很困难,所以我们将一个问题进行分解,拆分成具体的子任务,明确地去指定操作任务,可以分解为“抓住顶层抽屉的把手”和“拉开抽屉”,这种由高级规划器(如LLM或基于搜索的规划器)得到的具体子任务就变得可操作性了。
接下来就是将每个子任务进行优化,这里的子任务是LLM语言指令和机器人的运动路径,其中运动路径是由操作空间控制器执行的密集末端执行器路径点序列,每个路径点是由6自由度末端执行器姿态、末端执行器速度和夹持器动作组成

我们将这些表述为如下的一个公式: 

T_i :环境状态的演化
T_i^r \subseteq T_i :机器人轨迹
C(T_i) :相关的动力学和运动学约束,subject to 受制于的意思。
F_{task} :T_i 完成指令的程度进行评分
F_{control} :指定控制成本,例如,鼓励 T_i^r 最小化总控制时间

通过对每个子任务求解这个优化问题,我们得到一系列机器人轨迹,这些轨迹共同完成指令L指定的总体任务。

对于自由形式的语言指令,计算F_{task}是极具挑战性的,不仅因为语义语言可以传达的空间丰富,而且因为缺乏机器人标记数据。然而,我们提供了一个关键的观察结果,即在机器人的观察空间中,大量的任务可以用一个体素值映射V \in R^{w*h*d}来表征。这里的体素值可以理解成空间三维的数组或坐标,然后做映射。

“抓住顶层抽屉把手”(由LLMs推断)。“感兴趣的实体”是机器人的末端执行器,体素值映射应该反映对抽屉手柄的吸引力。通过进一步命令“小心花瓶”,地图也可以更新,以反映来自花瓶的排斥。
我们表示“感兴趣的实体”为e,其轨迹为T^e,使用给定指令的体素值映射, F_{task}任务可以通过累加遍历的e值来近似,公式如下:

其中的p_j^e\in N^3e在第j步的离散(x, y, z)的位置,由于这些位置是稀疏的,我们通过平滑操作来增加体素地图的密度,鼓励运动规划器优化更平滑的轨迹。
由于VoxPoser使用具有丰富常识的大语言模型来合成机器人轨迹,因此零射击合成轨迹 T_0^r 可以作为行动抽样分布 P(a_t | o_t,T_0^r) 的有用的先验偏差,这可以显著加快学习过程。在实践中,这可以通过在 T_0^r 附近的采样动作来实现,通过添加小噪声ε来鼓励局部探索,而不是在整个行动空间中探索。

2.3、重建点云

LLM使用他们自己生成的代码,其中每个语言模型程序language model program(LMP)负责一个独特的功能(例如,处理感知调用)。本论文用的是OpenAI的GPT-4开放的API。
我们先来看下对比基线的实验结果:

可以看到VoxPoser有着很高的执行日常任务的成功率,不仅在可见任务有着高成功率,而且在不可见的任务中同样有着差不多的成功率。
具体有哪些操作呢?
给定来自LLM的对象/部件的查询,我们首先调用open-vocab检测器OWL-ViT获取边界框,将其馈入到Segment Anything (Meta的分割一切对象模型)获取掩码,并使用视频跟踪器XMEM (基于Atkinson-Shiffrin记忆模型的长视频对象分割)跟踪掩码。利用跟踪掩码与RGB-D观测相结合,重建目标或部分的点云。

2.4、值图(映射)与运动规划器

我们定义了以下类型的值图:affordance功能可见、avoidance回避、end-effector velocity末端执行器速度、end-effector rotation末端执行器旋转和gripper action抓取动作。
每种类型使用不同的语言模型程序(LMP),它接受指令并输出形状为(100,100,100,k)的体素图,其中k对于每个值图是不同的(例如,k=1用于功能可见和回避,k=4用于旋转)
我们将Euclidean distance欧氏距离变换应用于功能可见性的映射,高斯滤波器则应用于回避映射。在值映射LMP的基础上,我们定义了两个高级LMPs来协调它们的行为:planner规划器以用户指令L作为输入(例如,“打开抽屉”)并输出一系列子任务l_{1:N},然后composer以子任务l_i为输入并调用相关的值映射LMPs,并进行详细的语言参数化。

接下来就是构造运动规划器,在规划器优化中只考虑可见性映射和回避映射,使用贪心搜索找到一系列无碰撞的末端执行器位置p_{1:N} \in R^3。然后我们通过剩余的值映射(例如,旋转映射,速度映射)在每个p上强制其他参数化。运动规划器使用的代价映射被计算为权值为2和1的归一化可视性和回避映射的加权和的负数,合成6自由度轨迹后,执行第一个航路点,然后以5Hz的频率重新规划新的轨迹。

具体来说,我们首先使用VoxPoser合成k个不同的轨迹,每个轨迹都表示为一系列末端执行器路径点。然后,我们学习了一个MLP动态模型,通过迭代过程从o_ta_t预测o_{t+1},其中代理在数据收集和模型学习之间交替进行。在MPC的动作抽样分布中,我们加入o_{t+1},将初始合成轨迹作为先验到T_0^r中的每个路径点,鼓励本地探索,使用这些轨迹作为先验探索,我们可以在不到3分钟的在线交互中学习有效的动力学模型,从而获得较高的最终成功率。相比之下,如果没有先验,学习动态模型是非常困难的,因为大多数动作不会导致有意义的环境变化。

3、应对突发状况

大模型的一些不可预测现象,如何应对,这里我们使用了LLM,有着丰富的世界知识。特别是,我们将研究重点放在VoxPoser独有的行为能力上。我们观察到以下能力:

1.估计物理性质:给定两个未知质量的块,机器人的任务是使用可用的工具进行物理实验,以确定哪个块更重。
2.行为常识推理:在机器人布置桌子的任务中,用户可以指定行为偏好,例如“我是左撇子”,这需要机器人在任务的上下文中理解其含义。
3.细粒度的语言纠错:对于“用壶盖盖住茶壶”等要求高精度的任务,用户可以给机器人精确的指令,比如“你向左偏差了1cm”,这种精确的要求也可以没有问题的。
4.多步可视化程序:给定一个“精确打开抽屉一半”的任务,由于对象模型不可用,信息不足,VoxPoser可以提出多步操作策略,根据视觉反馈,首先在记录手柄位移的同时将抽屉完全打开,然后将其关闭回中点以满足要求。

上述的应急能力,对应体现在如下图:

4、VoxPoser局限性 

在这项工作中,我们提出了VoxPoser,一个通用的机器人操作框架,从LLM中提取功能和约束,为开放集指令和对象提供了显著的泛化优势。特别是,我们使用代码编写LLMVLM进行交互,以组成基于观测空间的3D值图,用于合成日常操作任务的轨迹。此外,我们展示了VoxPoser可以通过有效地学习一个动态模型来完成丰富的接触任务,从而从在线交互中受益。
当然VoxPoser也存在下面几点的限制:

首先,它依赖于外部感知模块,这在需要整体视觉推理或理解细粒度物体几何形状的任务中受到限制。
其次,虽然适用于高效的动态学习,但仍然需要一个通用的动态模型来实现具有相同泛化水平的多接触任务。
第三,我们的运动规划器只考虑末端执行器轨迹,而全臂规划也是可行的,可能是更好的设计选择。

5、VoxPoser的Transforms3d

其中VoxPoser的核心就是向LLM提供代码支持,除了有NumpyTransforms3d库之外,还提供了很多APIs
Transforms3d库的详细说明:
http://matthew-brett.github.io/transforms3d/index.html
安装transforms3d命令,带上阿里云镜像速度快点:
pip install transforms3d -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com 

再检验下是否安装成功:

import transforms3d
transforms3d.__version__
#'0.4.1'
dir(transforms3d)
#['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', '_version', 'affines', 'axangles', 'euler', 'quaternions', 'reflections', 'shears', 'taitbryan', 'utils', 'zooms']

这个库主要是矩阵变换、欧拉角、四元数等等的转换,具体详细用法可以看前面给出的链接。

6、VoxPoser的APIs

我们来看下VoxPoser提供了哪些对外接口:
detect(obj name):接受一个对象名并返回一个字典列表,其中每个字典对应于匹配对象的一个实例,包含中心位置、占用网格和平均法向量(正态均值向量)

execute(movable,affordance map,avoidance map,rotation map,velocity map,gripper map):接受“感兴趣的实体”作为“可移动的”(由detect返回的字典)和(可选的)值映射列表,并调用运动规划器来执行轨迹。请注意,在MPC设置中,“可移动”和输入值映射是可以重新评估以反映最新环境观察的函数,另外这里的感兴趣实体就是机器人的末端执行器,通过它的移动来操作目标。

cm2index(cm,direction):沿方向获取所需的偏移距离(以厘米为单位),并返回以体素坐标反映位移的三维向量

index2cm(index,direction):接受一个整数“索引”和一个“方向”向量,并返回被体素坐标中的“整数”所取代的世界坐标中的距离

pointat2quat(vector):为末端执行器获取所需的指向方向,并返回一个令人满意的目标四元数

set_voxel_by_radius(voxel_map,voxel_xyz,radius_cm,value):从“voxel_map体素图”中的“voxel_xyz”中为“半径”内的voxel体素分配值。

get_empty_affordance_map():返回初始化为0的功能可见性图(映射),其中高值将吸引实体。
其中对affordance的翻译比较多,有功能可见性,功能可供性,自解释性,启示等,初次接触可能有点懵,没有关系,这里的关键点是需要知道具体是什么意思就行了。意思是说这个东西自己呈现出来的功能,自然会联想到怎么去使用它,比如看到抽屉手柄,就会想着去拉或者推;看到家里的水龙头,就可能是旋转进行关停;看到按钮就知道是按压,这就是所谓的功能可见性。

get_empty_avoidance_map(): 返回初始化为0的避障图(映射),其中高值将排斥实体。

get_empty_rotation_map():返回用当前末端执行器四元数初始化的默认旋转映射。

get_empty_gripper_map():返回用当前抓取器动作初始化的默认抓取器映射,其中1表示“关闭”,0表示“打开”

get_empty_velocity_map():返回一个初始化为1的默认功能映射,其中数字表示比例因子(例如,0.5表示默认速度的一半)

reset_to_default_pose():重置机器人为休息姿势

7、Prompts提示

最后是将上述在日常操作任务中,需要用到的提示,以及一些不可见的属性之类的,分解成具体的步骤。当然目前站点对下面这些代码还没有公开,后期应该会很快开放。

7.1、planner计划器

接收用户指令L并生成一系列子任务l_i,这些子任务l_i被送入composer(注意,在模拟中不使用计划器,因为评估的任务由单个操作阶段组成)。
https://voxposer.github.io/prompts/real_planner_prompt.txt
摘要如下

import numpy as np
from env_utils import execute
from perception_utils import parse_query_obj
import action_utils import composer

objects = ['blue block', 'yellow block', 'mug']# ['蓝色块','黄色块','马克杯']
# Query: place the blue block on the yellow block, and avoid the mug at all time.
# 把蓝色块放在黄色块上,并且一直避免杯子

composer("grasp the blue block while keeping at least 15cm away from the mug")#抓住蓝色方块,同时与杯子保持至少15厘米的距离
composer("back to default pose")#回到默认姿势
composer("move to 5cm on top of the yellow block while keeping at least 15cm away from the mug")#移动到黄色方块上方5厘米处,同时与杯子保持至少15厘米的距离
composer("open gripper")# 打开抓取器

可以看到,提供的方法还是很清晰简洁的,首先就是保存需要关注和避开的objects对象列表,然后通过composer去解析每条具体的语言指令。

7.2、composer编写器

接受子任务指令l_i,调用必要的值映射LMPs组成功能映射和约束映射。
下面都将分为模拟器和真实环境
simulation: https://voxposer.github.io/prompts/sim_composer_prompt.txt
real-world: https://voxposer.github.io/prompts/real_composer_prompt.txt
摘要如下:

import numpy as np
from env_utils import execute, reset_to_default_pose
from perception_utils import parse_query_obj
from plan_utils import get_affordance_map, get_avoidance_map, get_velocity_map, get_rotation_map, get_gripper_map

# Query: move ee forward for 7cm.
# 将对象ee向前移动7厘米
movable = parse_query_obj('ee')
affordance_map = get_affordance_map(f'a point 7cm in front of {movable.position}')
execute(movable, affordance_map)

7.3、parse_query_obj

接受对象/部件名称的文本查询并返回一个字典列表,其中每个字典对应于包含中心位置、占用网格和正态均值向量的匹配对象的一个实例。
simulation: https://voxposer.github.io/prompts/sim_parse_query_obj_prompt.txt
real-world: https://voxposer.github.io/prompts/real_parse_query_obj_prompt.txt
摘要如下:

import numpy as np
from perception_utils import detect

objects = ['green block', 'yellow line']
# Query: ee.
ee = detect('ee')[0]
ret_val = ee

objects = ['drawer', 'blue block', 'yellow block']
# Query: topmost handle.
# 顶层把手
handles = detect('drawer handle')
# topmost so sort by z, take the last one
# 最上面:按z排序取最后一个
handles = sorted(handles, key=lambda x: x.position[2])
top_handle = handles[-1]
ret_val = top_handle

7.4、get_affordance_map

从编写器接受自然语言参数化并返回NumPy数组用于任务提供映射。
simulation: https://voxposer.github.io/prompts/sim_get_affordance_map_prompt.txt
real-world: https://voxposer.github.io/prompts/real_get_affordance_map_prompt.txt
摘要如下:

import numpy as np
from perception_utils import parse_query_obj
from plan_utils import get_empty_affordance_map, set_voxel_by_radius, cm2index

# Query: a point 10cm in front of [10, 15, 60].
# 在[10,15,60]位置前面10cm处的一个点
affordance_map = get_empty_affordance_map()
# 10cm in front of so we add to x-axis
# 在前面10cm处,我们添加到x轴
x = 10 + cm2index(10, 'x')
y = 15
z = 60
affordance_map[x, y, z] = 1
ret_val = affordance_map

# Query: a point on the right side of the table.
# 表右侧的一个点
affordance_map = get_empty_affordance_map()
table = parse_query_obj('table')
(min_x, min_y, min_z), (max_x, max_y, max_z) = table.aabb
center_x, center_y, center_z = table.position
# right side so y = max_y
x = center_x
y = max_y
z = center_z
affordance_map[x, y, z] = 1
ret_val = affordance_map

7.5、get_avoidance_map

从编写器接受自然语言参数化并返回NumPy数组用于任务回避映射。
simulation: https://voxposer.github.io/prompts/sim_get_avoidance_map_prompt.txt
real-world: https://voxposer.github.io/prompts/real_get_avoidance_map_prompt.txt
摘要如下:

import numpy as np
from perception_utils import parse_query_obj
from plan_utils import get_empty_avoidance_map, set_voxel_by_radius, cm2index

# Query: 10cm from the bowl.
# 离碗10cm
avoidance_map = get_empty_avoidance_map()
bowl = parse_query_obj('bowl')
set_voxel_by_radius(avoidance_map, bowl.position, radius_cm=10, value=1)
ret_val = avoidance_map

7.6、get_rotation_map

从编写器中接受自然语言参数化,并返回末端执行器旋转图的NumPy数组。
simulation: https://voxposer.github.io/prompts/sim_get_rotation_map_prompt.txt
real-world: https://voxposer.github.io/prompts/real_get_rotation_map_prompt.txt
摘要如下:

import numpy as np
from plan_utils import get_empty_rotation_map, set_voxel_by_radius, cm2index, vec2quat
from perception_utils import parse_query_obj
from transforms3d.euler import euler2quat, quat2euler
from transforms3d.quaternions import qmult, qinverse

# Query: face the support surface of the bowl.
# 面朝碗的支撑面
rotation_map = get_empty_rotation_map()
bowl = parse_query_obj('bowl')
target_rotation = vec2quat(-bowl.normal)
rotation_map[:, :, :] = target_rotation
ret_val = rotation_map

7.7、get_gripper_map

从编写器接受自然语言参数化,并为抓手动作图返回NumPy数组
simulation: https://voxposer.github.io/prompts/sim_get_gripper_map_prompt.txt
real-world: https://voxposer.github.io/prompts/real_get_gripper_map_prompt.txt
摘要如下:

import numpy as np
from perception_utils import parse_query_obj
from plan_utils import get_empty_gripper_map, set_voxel_by_radius, cm2index

# Query: open everywhere except 1cm around the green block.
# 除绿色块周围1cm外,所有地方都打开
gripper_map = get_empty_gripper_map()
# open everywhere
gripper_map[:, :, :] = 0
# close when 1cm around the green block
green_block = parse_query_obj('green block')
set_voxel_by_radius(gripper_map, green_block.position, radius_cm=1, value=1)
ret_val = gripper_map

7.8、get_velocity_map

从编写器中接受自然语言参数化,并返回末端执行器速度图的NumPy数组。
simulation: https://voxposer.github.io/prompts/sim_get_velocity_map_prompt.txt
real-world: https://voxposer.github.io/prompts/real_get_velocity_map_prompt.txt
摘要如下:

import numpy as np
from plan_utils import get_empty_velocity_map, set_voxel_by_radius, cm2index
from perception_utils import parse_query_obj

# Query: faster when on the right side of the table and slower when on the left side of the table.
# 在桌子右边时速度更快,在桌子左边时速度更慢
velocity_map = get_empty_velocity_map()
table = parse_query_obj('table')
center_x, center_y, center_z = table.position
# faster on right side so 1.5 when y > center_y, slower on left side so 0.5 when y < center_y
velocity_map[:, center_y:, :] = 1.5
velocity_map[:, :center_y, :] = 0.5
ret_val = velocity_map

更多的细节,建议看论文原文,这里主要是个人对其的理解,有错误之处,还请指正。
引用:
voxposer:https://voxposer.github.io/
XMem:https://github.com/hkchengrex/XMem

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

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

相关文章

使用LangChain构建问答聊天机器人案例实战(一)

使用LangChain构建问答聊天机器人案例实战 现场演示GPT-4代码生成 本节我们会通过一个综合案例,跟大家讲解LangChain,这个案例产生的代码会直接在浏览器中运行,并且会输出结果,如图14-1所示,用户问:“What was the highest close price of IBM?”(“IBM的最高收盘价是…

【Linux命令200例】mdel删除指定目录下的多个文件

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;本文已收录于专栏&#xff1a;Linux命令大全。 &#x1f3c6;本专栏我们会通过具体的系统的命令讲解加上鲜活的实操案例对各个命令进行深入…

基于注解手写Spring的IOC(上)

一、思路 先要从当前类出发找到对应包下的所有类文件&#xff0c;再从这些类中筛选出类上有MyComponent注解的类&#xff1b;把它们都装入Map中&#xff0c;同时类属性完成MyValue的赋值操作。 二、具体实现 测试类结构&#xff1a; 测试类&#xff1a;myse、mycontor、BigSt…

hcq1-1300-d

禾川的产品&#xff1a;版本V3.22 网口1&#xff1a; IPV4&#xff1a;192.168.188.100 子网掩码&#xff1a;255.255.255.0 网口2&#xff1a; IPV4&#xff1a;192.168.88.100 子网掩码&#xff1a;255.255.255.0 功能按键&#xff1a; 旋转拨码0 切换 SYS\IN\OUT 指示灯及…

NLP From Scratch: 基于注意力机制的 seq2seq 神经网络翻译

NLP From Scratch: 基于注意力机制的 seq2seq 神经网络翻译 这是关于“从头开始进行 NLP”的第三篇也是最后一篇教程&#xff0c;我们在其中编写自己的类和函数来预处理数据以完成 NLP 建模任务。 我们希望在完成本教程后&#xff0c;您将继续学习紧接着本教程的三本教程&…

C#,数值计算——对数正态分布(logarithmic normal distribution)的计算方法与源程序

对数正态分布&#xff08;logarithmic normal distribution&#xff09;是指一个随机变量的对数服从正态分布&#xff0c;则该随机变量服从对数正态分布。对数正态分布从短期来看&#xff0c;与正态分布非常接近。但长期来看&#xff0c;对数正态分布向上分布的数值更多一些。 …

【机器学习】Gradient Descent

Gradient Descent for Linear Regression 1、梯度下降2、梯度下降算法的实现(1) 计算梯度(2) 梯度下降(3) 梯度下降的cost与迭代次数(4) 预测 3、绘图4、学习率 首先导入所需的库&#xff1a; import math, copy import numpy as np import matplotlib.pyplot as plt plt.styl…

Pytest学习教程_装饰器(二)

前言 pytest装饰器是在使用 pytest 测试框架时用于扩展测试功能的特殊注解或修饰符。使用装饰器可以为测试函数提供额外的功能或行为。   以下是 pytest 装饰器的一些常见用法和用途&#xff1a; 装饰器作用pytest.fixture用于定义测试用例的前置条件和后置操作。可以创建可重…

读发布!设计与部署稳定的分布式系统(第2版)笔记26_安全性上

1. 安全问题 1.1. 系统违规并不总是涉及数据获取&#xff0c;有时会出现植入假数据&#xff0c;例如假身份或假运输文件 1.2. 必须在整个开发过程中持续地把安全内建到系统里&#xff0c;而不是把安全像胡椒面那样在出锅前才撒到系统上 2. OWASP 2.1. Open Web Application…

DataStructure--Basic

程序设计数据结构算法 只谈数据结构不谈算法就跟去话剧院看梁山伯与祝英台结果只有梁山伯在演&#xff0c;祝英台生病了没来一样。 本文的所有内容都出自《大话数据结构》这本书中的代码实现部分&#xff0c;建议看书&#xff0c;书中比我本文写的全。 数据结构&#xff0c;直…

论文笔记——Influence Maximization in Undirected Networks

Influence Maximization in Undirected Networks ContributionMotivationPreliminariesNotations Main resultsReduction to Balanced Optimal InstancesProving Theorem 3.1 for Balanced Optimal Instances Contribution 好久没发paper笔记了&#xff0c;这篇比较偏理论&…

【笔试强训选择题】Day32.习题(错题)解析

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训选择题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01; 文章目录 前言 一、Da…

线性代数(应用篇):第五章:特征值与特征向量、第六章:二次型

文章目录 第5章 特征值与特征向量、相似矩阵(一) 特征值与特征向量1.定义2.性质3.求解(1)具体型矩阵试根法、多项式带余除法&#xff1a;三阶多项式分解因式 (2)抽象型矩阵 (二) 相似1.矩阵相似(1)定义(2)性质 2.相似对角化(1)定义(2)相似对角化的条件&#xff08;n阶矩阵A可相…

自动化运维工具——Ansible

自动化运维工具——Ansible 一、Ansible概述二、ansible 环境安装部署1.管理端安装 ansible2.ansible 目录结构3.配置主机清单4.配置密钥对验证 三、ansible 命令行模块1.command 模块2.shell 模块3.cron 模块4.user 模块5.group 模块6.copy 模块7.file 模块8.hostname 模块9&a…

LeetCode102.Binary-Tree-Level-Order-Traversal<二叉树的层序遍历>

题目&#xff1a; 思路&#xff1a; 写过N叉树的层序遍历&#xff0c;(8条消息) LeetCode429.N-Ary-Tree-Level-Order-Traversal&#xff1c;N 叉树的层序遍历&#xff1e;_Eminste的博客-CSDN博客 使用栈保存每一层的结点。然后每次当前层结束。将这一层的值添加进去res中。…

【Jetpack 之 Lifecycle】

Jetpack 之 Lifecycle 在本系列文章中&#xff0c;我们准备分析Jetpack 架构组件。首先我们从最基础的组件开始&#xff1a; Lifecycle&#xff0c; 可以说Jetpack 大部分架构组件都是基于Lifecycle 建立的&#xff0c;此也为Jetpack 架构组件的基础。 关于此此组件的介绍和简…

回答网友 修改一个exe

网友说&#xff1a;他有个很多年前的没有源码的exe&#xff0c;在win10上没法用&#xff0c;让俺看一下。 俺看了一下&#xff0c;发现是窗体设计的背景色的问题。这个程序的背景色用的是clInactiveCaptionText。clInactiveCaptionText 在win10之前的系统上是灰色&#xff0c;但…

【Ajax】笔记-原生jsonp跨域请求案例

原生jsonp跨域请求 输入框&#xff1a;输入后&#xff0c;鼠标移开向服务端发送请求&#xff0c;返回用户不存在(直接返回不存在&#xff0c;不做判断) JS <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><me…

ubuntu22.04 DNSSEC(加密DNS服务) configuration

/etx/systemd/resolved.conf是ubuntu下DNS解析服务配置文件&#xff0c;systemd为ubuntu下system and service配置目录 step 1——修改resolved.conf参数 管理员权限打开 /systemd/resolved.conf sudo nano /etc/systemd/resolved.conf修改如下&#xff1a; # This file i…

17-C++ 数据结构 - 栈

&#x1f4d6; 1.1 什么是栈 栈是一种线性数据结构&#xff0c;具有后进先出&#xff08;Last-In-First-Out&#xff0c;LIFO&#xff09;的特点。可以类比为装满盘子的餐桌&#xff0c;每次放盘子都放在最上面&#xff0c;取盘子时也从最上面取&#xff0c;因此最后放进去的盘…