admin 管理员组文章数量: 886992
前言
在此文之前,我花了一天半,详细解读了清华一研究团队发布的机器人扩散大模型RDT,包括其每一个附录
当时在该文中预告说:下一篇是一个3B的机器人大模型打通7种不同品牌的机械臂,这几个工作宣告机器人真正进入大模型时代
故,本文来了
- 一方面,不断努力,让我的博客成为「大模型开发者和具身智能从业者」的必看,以结交广大同行,以有高频次 高层次 高水平的交流/合作,共同推动行业进步
- 二方面,本文最大的价值和意义在于:一套框架控制7种机械臂,实现各种机械臂的丝滑迁移与平替
且除了我司「七月在线」已经完成的umi/dexcap复现与优化、正在复现/优化的idp3外,如果能把这个π0 在国内商业化、落地,感觉价值也非常大,如有兴趣一块搞的,欢迎私我
此外,考虑到π0算是把基于机器人大模型的「预训练-微调」模式彻底带火了,且这种模式很快会越来越多『犹如此前大模型革命NLP 其次CV等各模态,目前到了robot领域』,算是代表了通用机器人的核心发展方向,故值得把π0写的相对透彻、细致,故我后来在π0的基础上,又详细介绍了:
- 多模态PaliGemma (独立成文)
- Transfusion、Playground v3 (见本文第二部分)
- 流匹配Flow Matching与修正流Rectified Flow (它两的介绍详见此文第五部分)
至于这两在机器人领域的更多应用,则见本文第三部分 - 视觉语言动作模型的持续升级:从VLA模型π0之主要参考Octo到OpenVLA、TinyVLA、DeeR-VLA (独立成文)
第一部分 整体理解π0
1.1 π0——用于通用机器人控制的流匹配VLA模型
1.1.1 背景
在自然语言[1]和计算机视觉[39]领域,预先在多任务数据上训练的通用基础模型往往比那些专门定制的模型表现更佳
例如,如果目标是识别照片中的鸟类,那么与其仅仅在鸟类识别数据上进行训练,不如先在许多不同的图像-语言关联上进行预训练,然后针对鸟类识别任务进行微调或提示
同样地,作者会发现
- 对于有效的专业机器人系统,先在高度多样化的机器人数据上进行预训练,然后针对所需任务进行微调或提示更为有效。这可以解决数据稀缺性挑战,因为通用模型可以获得更多的数据来源——包括其他任务、其他机器人,甚至非机器人来源的数据
- 同时也可以解决鲁棒性和泛化性挑战,因为多样化的数据展示了更广泛的观察和行动覆盖,提供了更多样的场景、修正和恢复行为,这些可能在更狭窄的专业数据中不存在
然而,开发这样的通用机器人策略——即机器人基础模型——涉及许多重大挑战
- 首先,任何此类研究都必须在非常大规模上进行,因为大规模预训练的全部好处通常在较小规模上无法显现[54]
- 其次,需要开发合适的模型架构,这些架构能够有效利用多样化的数据源,同时能够表现出与复杂物理场景交互所需的复杂和微妙行为
- 第三,需要正确的训练策略,包括最近在NLP和计算机视觉领域的大模型进展在很大程度上依赖于精细的策略来策划预训练和后训练数据[35]
1.1.2 预训练的视觉-语言模型VLM主干 + 动作专家通过「流匹配」输出动作
24年10月底,来自Physical Intelligence公司的研究者们提出了一个原型模型和学习框架,称之为π0
- 作者包括Kevin Black, Noah Brown, Danny Driess, Adnan Esmail, Michael Equi, Chelsea Finn、Karol Hausman、Sergey Levine等20多人
其中的Kevin Black是伯克利AI的博士生,也是该公司的研究员
Noah Brown是Google RT1和RT2的二作
Danny Driess也是 RT2的作者之一
Chelsea Finn是斯坦福ALOHA团队的指导老师,也是RT2的作者之一
Karol Hausman则是该公司CEO,曾是谷歌大脑机器人操作研究主管,2021年至今兼任斯坦福客座教授
该公司联创Sergey Levine则是UC伯克利电气工程和计算机科学系副教授,谷歌学术被引用量为超过12.7万 - 其对应的论文为《π0: A Vision-Language-Action Flow Model for General Robot Control》
- 其对应的技术blog为:physicalintelligencepany/blog/pi0
但截止到24年11月中旬,π0没开源、没开放代码,且难度相对较高
下图图1中展示了该模型和系统
为了整合多样的数据源,作者
- 首先利用一个预训练的视觉-语言模型(VLM)来导入互联网规模的经验。通过基于VLM构建他们的模型,继承了语言和视觉-语言模型的通用知识、语义推理和问题解决能力
- 然后,进一步训练他们的模型以整合机器人动作,使其成为一个视觉-语言-动作(VLA)模型。为了能够利用多种不同的机器人数据源,作者采用跨化身训练[10],将多种机器人类型的数据合并到同一个模型中。这些不同的机器人类型具有不同的配置空间和动作表示,包括单臂和双臂系统,以及移动操纵器
其实这点和上一篇文章介绍的RDT是同样的问题,详见此文《RDT——清华开源的双臂机器人扩散大模型(基于DiT改造而成):先预训练后微调,支持语言、图像、动作多种输入》的「1.2.1节解决数据异构性问题,且兼容多个模态的输入」 - 此外,为了能够执行高度灵巧和复杂的物理任务,作者使用带有流匹配「[或叫修正流Rectified Flow,而修正流则是流匹配的一种改进,详见32-Rectified flow: A marginal preserving approach to optimal transport,至于流匹配则详见28- Flow matching for generative modeling],即扩散[20-DDPM,46]的变体」的动作分块架构[57-Learning fine-grained bimanual manipulation with low-cost hardware,即动作分块算法ACT,详见此文:ACT的原理解析:斯坦福炒虾机器人Moblie Aloha的动作分块算法ACT]
来表示复杂的连续动作分布[28,32]
we use an action chunking architecture [57] with flow matching (a variant of diffusion) to represent complex continuous action distributions [28, 32].
相当于通过流匹配微调VLM以生成动作
这使得他们的模型能够以高达50 Hz的频率控制机器人进行如折叠衣物(见上图图1)这样的灵巧任务
且为了将流匹配与VLM结合,他们使用了一种新颖的动作专家,它通过流式输出(flow-based outputs)增强了标准VLM
总之,虽然许多模型被提议结合预训练语言模型与扩散[40,41,14],包括专门将扩散与自回归大型语言模型混合的模型[19,29,59]
这些模型通常关注图像生成,但作者的动作生成模型与Zhou等[59-Transfusion: Predict the next token and diffuse images with one multi-modal model,一个既可以预测下一个token又可以生成图像的多模态模型(相当于训练单个模型来同时预测离散文本token和扩散连续图像),总之,其通过在50%文本和50%图像数据上预训练一个Transformer模型来展示Transfusion]类似,其通过应用于单个序列元素的扩散风格(流匹配)损失训练他们的模型,以替代仅用于解码器的transformers的标准交叉熵损失
Like Zhou et al. [59], we train our model via a diffusion-style (flow matching) loss applied on individual sequence elements, in lieu of the standard cross-entropy lossfor decoder-only transformers
与Liu等[29-Playground v3: Improving text-to-image alignment with deep-fusion large language models.]类似,为对应于扩散的token使用了一套独立的权重(该扩散的token即是机器人的动作),将这些概念融入VLA模型中,作者引入了据他们所知的第一个流匹配VLA,用于生成高频动作块以实现灵巧控制
Like Liu et al. [29], we use a separate set of weights for the tokens corresponding todiffusion. Incorporating these concepts into a VLA model, we introduce what to our knowledge is the first flow matchingVLA that produces high-frequency action chunks for dexterouscontrol.
此外,为了灵活且稳健地执行复杂任务,还需要正确的训练策略,具体而言,模型首先在一个非常大且多样化的语料库上进行预训练,然后在更狭窄且更精心策划的数据上进行微调,以引导出所需的行为模式
流匹配的工作方式和扩散模型有些类似,核心思想都是通过逐步添加噪声来简化数据分布,然后逐步去噪得到隐私数据
- 训练时,随机对动作施加高斯噪声,并训练模型输出去噪向量场
推理时,从高斯噪声开始,通过数值积分向量场生成动作序列- 不同之处在于
流匹配直接对数据和噪声分布之间的映射场(vector field)进行建模,训练目标是匹配这一映射场
而扩散模型通常学习的是每个去噪步骤的条件分布「如还不熟悉扩散模型的,请参见此文《图像生成发展起源:从VAE、VQ-VAE、扩散模型DDPM、DETR到ViT、Swin transformer》的第二部分」总之,流匹配方法能够高精度地建模复杂多峰分布,非常适合高频灵巧操作任务
1.2 模型架构与模型推理
1.2.1 整体架构:PaliGemma + 动作专家 + 流匹配Flow matching
作者首先组装了一个预训练混合体,该混合体由他们自己的灵巧操作数据集(第V-C节)与整个OXE数据集[10]的加权组合组成,该数据集是在7种不同的机器人配置下为68个不同的任务收集的,而OXE数据集包含来自22个机器人的数据
- 预训练阶段(第V-A节)还使用了多样的语言标签,结合了任务名称和段注释(用于子轨迹的细粒度标签,通常长度约为2秒)
预训练阶段的目的是训练一个基础模型,该模型展示了广泛的能力和泛化性,但不一定专注于在任何一个任务上达到高性能。这个基础模型可以遵循语言指令并以基础水平执行多种任务 - 对于复杂和灵巧的任务,随后采用后训练程序(第V-A节),使用高质量的精心策划数据将模型调整为特定的下游任务。他们研究了使用少量到中等量数据的高效后训练,以及使用较大数据集进行复杂任务(如折叠衣物和移动操作)的高质量后训练——即微调
如下图图3所示
- π0模型主要由一个语言模型transformer骨干组成。遵循标准的后期融合视觉语言模型(VLM)方法[3,11,30],图像编码器将机器人的图像观测嵌入到与语言token相同的嵌入空间中
且进一步通过特定于机器人学的输入和输出进行增强——即本体感觉状态和机器人动作「We further augment this backbone with robotics-specific inputs and outputs — namely,proprioceptive state and robot actions.」 - π0使用条件流匹配[28,32]来建模动作的连续分布。流匹配为他们的模型提供了高精度和多模态建模能力,使其特别适合高频灵巧任务
该架构灵感来自Transfusion [59],该方法通过多个目标训练一个单一的transformer,其中与连续输出对应的token(比如机器人的动作)通过流匹配损失进行监督,而与离散输出对应的token则通过交叉熵损失进行监督
Our architecture is inspired by Transfusion [59], which trains a single transformer using multiple objectives, with tokens1 corresponding to continuous outputs supervised via a flow matching loss and tokens corresponding to discrete outputs supervised via a cross-entropy loss.
在Transfusion的基础上,他们还发现,为机器人特定的(动作和状态)token使用一组单独的权重可以提高性能「Building on Transfusion, we additionally found that using a separate set of weights for the robotics-specific (action and state) tokens led to an improvement in performance. 」
这种设计类似于专家混合[45,25,12,16],其中有两个混合元素
- 第一个元素用于图像和文本输入
- 第二个用于机器人特定的输入(比如机器人的状态),和输出(比如预测的机器人动作)
他们将第二组权重称为动作专家
正式地,他们希望对数据分布建模,其中
- 对应于未来动作的动作块(作者在任务中使用H=50)
顺带强调下
当我们看到这个符号时,它表示的是输出的预测动作
当看到这个符号时,它表示的是输入噪声动作
PS,此点记住了,可以避免概念上的混淆(且如果你细心的话,你会发现本文全文中,我特意为了区别,皆是:动作输入用的绿色字体,动作输出用的红色字体) - 而是一个观察,观察由多个RGB图像、语言命令和机器人的本体状态组成,因此
其中
是第i个图像(每个机器人有2或3个图像)
是语言token序列
是关节角度向量 图像和状态通过相应的编码器进行编码,然后通过线性投影层投影到与语言token相同的嵌入空间中
对于动作块中的每个动作,有一个相应的动作token,通过动作专家action expert来处理
具体而言,作者团队在PaliGemma后面接一个专门的动作模块
- 这个 action expert 是怎么工作的呢?它不是直接把自己的参数塞进PaliGemma 模型中,变成一个大模型来输出动作,而是通过一种 "注意力机制"(attention)去关注PaliGemma的参数
- 简单来说,action expert 就是“看着” PaliGemma的参数,根据这些信息生成具体的动作,下一节会详细介绍这个action expert
在训练过程中,使用条件流匹配损失Conditional Flow Matching[28,32]监督这些动作token「前者为学习网络,后者为学习目标,即训练前者去逼近后者」
其中下标表示机器人时间步,上标表示流匹配时间步,
- 最近在高分辨率图像[14]和视频[38]合成方面的研究表明,当与简单的线性高斯(或最优传输)概率路径[28]结合时,流匹配可以实现强大的经验性能
其由下述表达式给出 - 在实践中,网络先通过采样随机噪声进行训练,计算“噪声动作”
相当于先加噪,类似此文中「5.2.1 通过示意图对比:ϵ-prediction、v-prediciton与rectified flow」最后对rectified flow的阐述:或
相当于从动作分布到噪声分布
再去噪,故,便有此举:然后训练网络输出「此为动作块的向量场表示」,以匹配去噪向量场「即training the network outputs vθ (Aτt , ot) to match the denoising vector field u(Aτt |At) = ϵ −At.」
相当于从噪声分布得到动作分布 - 动作专家使用全双向注意力掩码,以便所有动作token彼此关注「The action expert uses a full bidirectional attention mask, so that all action tokens attendto each other」
在训练期间,从一个强调较低(更嘈杂)时间步的贝塔分布中采样流匹配时间步τ。更多细节请参见附录B「During training, we sample the flow matching time step τ from a beta distribution that emphasizes lower(noisier) timesteps. See Appendix B for more details.」
在推理时,作者通过从到积分学习到的向量场来生成动作,从随机噪声开始,且作者使用前向欧拉积分规则「At inference time, we generate actions by integrating thelearned vector field from τ = 0 to τ = 1, starting with randomnoise A0t ∼N(0, I). We use the forward Euler integrationrule:」
其中是积分步长
在他们的实验中,使用了10个积分步骤(对应于)。注意,可以通过缓存前缀的注意力键和值,并且仅对每个积分步骤重新计算与动作token对应的后缀,从而高效地实现推理
他们在附录D中提供了有关推理过程的更多细节,包括模型每个部分的推理时间。虽然原则上他们的模型可以从头初始化或从任何VLM骨干微调,但实际上他们使用PaliGemma [5-PaliGemma: A versatile 3B VLM for transfer]作为他们的基础模型
PaliGemma是一个开源的30亿参数VLM,提供了大小和性能之间的便利折衷。作者为动作专家添加了3亿参数(从头初始化),总共达到33亿参数「关于PaliGemma的详细介绍,请参见此文:多模态PaliGemma——Google推出的基于SigLIP和Gemma的视觉语言模型」
除了他们的主要VLA模型外,他们还训练了一个类似的基线模型——π0-small,该模型在消融实验中没有使用VLM初始化
作者称之为π0-small的这个模型拥有470M参数,没有使用VLM初始化,并且在没有使用VLM初始化的数据训练中,作者发现了一些有助于训练的小差异,这些差异在原论文的附录C中进行了总结
1.2.2 改造VLM模型PaliGemma——后接action expert,使其成为VLA模型
作者遵循PaliGemma VLM [5]的设计
但有以下不同:
- 为机器人特定的token增加了额外的输入和输出投影,包括状态向量和动作向量
- 增加了一个用于结合流匹配时间步的MLP信息
- 以及动作专家的一组较小的权重
具体的改动,分别涉及到以下几点
- 附加输入和输出
标准的PaliGemma架构接收一系列图像,随后是语言指令
但作者附加了输入和输出,即
添加了一个输入,用于机器人的本体状态,通过线性投影映射到transformer嵌入维度
且最终的输入token集对应于噪声动作块,token数量等于动作视界(在作者的任务中H= 50),作者仅使用transformer输出中对应于个噪声动作的部分,并通过线性投影解码为——相当于输出动作块的向量场表示
The final set of input tokens correspond to the noisy action chunk Aτt = [aτt , ..., aτt+H−1], with the number of tokens equal to the action horizon (H = 50 for our tasks). We only use the transformer outputs corresponding to the H noisy actions,which are decoded into vθ (Aτ
t , ot) using a linear projection. - 多层感知机MLP整合流匹配时间步
噪声动作块通过一个MLP映射到transformer的嵌入维度,该MLP还结合了流匹配时间步
对于每个噪声动作,输入到transformer的对应嵌入表达式为
其中是一个正弦位置编码函数[51],且
是动作维度,是动作专家的嵌入维度(或宽度) - 注意力掩码
π0使用具有3个块的分块因果注意力掩码:,,和
在每个块内,存在全双向注意力,而每个块中的token不能关注未来块中的token
第一块包含PaliGemma的VLM预训练中的输入模态,这些模态被防止关注未来块(包含新输入)以最小化预训练带来的分布偏移「The first block includes the input modalities from PaliGemma’s VLM pre-training, which are prevented from attending to future blocks (which include new inputs) to minimize distribution shift from said pre-training」
机器人状态 是它自己的一个模块,因为它在每个流匹配集成步骤中不会变化;阻止它参与最终模块——使得其对应的键和值在采样期间能够被缓存「The robot state qt is its own block because it does not change with each flow matching integration step; preventing it from attending to the final block allows its corresponding keys and values to be cached during sampling」
最后一块对应于噪声动作,可以关注整个输入序列「即The final block corresponds to the noisy actions Aτ t , which can attend to the full input sequence」 - 动作专家「其训练目标用的flow matching」
π0实现为一个单一的transformer,其具有两组权重(也称为专家[45]),每个token被路由到其中一个专家;权重仅通过transformer的自注意力层相互作用
那各个token到底是路由到具体哪个专家呢?很简单
对于图像和语言提示:,被路由到较大的VLM主干——其由PaliGemma初始化
至于VLM预训练期间未见的输入:机器人本体状态和噪声动作,则被路由到动作专家
PaliGemma基于Gemma 2B[49]语言模型,使用多查询注意力[44,关于多查询注意力的介绍详见此文:一文通透各种注意力:从多头注意力MHA到分组查询注意力GQA、多查询注意力MQA的第三部分],和配置{width=2048,depth=18,mlpdim=16,384,num heads=18, num kvheads=1,head dim=256}
由于专家仅在自注意力层中相互作用,width和mlp dim不必在专家之间匹配
另,为了加快推理速度(需要动作专家的多次前向传递),他们将动作专家缩小为{width=1024, mlp dim=4096},参数数量约为∼300M - 采样流匹配时间步
原始流匹配论文[28,32]从均匀分布中采样流匹配时间步:。Esser等人[14]则建议从对数正态分布中采样
作者认为,在高时间步(低噪声水平)时,模型只需学习恒等函数,而在低时间步(高噪声水平)时,模型只需学习数据分布的均值
然而,假设动作预测任务与高分辨率图像合成有细微的不同——虽然在文本标签的条件下预测均值图像可能相对容易,但在机器人观测条件下预测均值动作(即,学习)则是个更难的问题;这是因为观测非常具有信息性,它应该比文本标签对可能动作的分布施加更大的约束
因此,作者设计了一个时间步采样分布,强调低时间步(高噪声水平);此外,超过给定阈值s的时间步根本不被采样,因为只要积分步长δ大于1−s,它们就不需要
分布由,且在实验中使用 s= 0.999,这允许δ > 11000 ,或最多 1,000 个积分步骤
1.2.3 推理
回想一下,模型接受一个观测和噪声动作,并输出需要集成以获得下一个流匹配步骤的向量场「Recall that our model takes an observation ot = [I1t , ..., Int , ℓt, qt] and the noisy actions Aτt and outputs the vector field that needs to be integrated to obtain the next flow matching step, vτt . 」
每次预测一个新的动作块时,必须对每个图像进行编码,在与对应的token上运行一次前向传递,然后运行10步流匹配,其中每一步都需要在与对应的token上运行一次前向传递(与对应的键和值是缓存的)「Each time we predict a new action chunk At, we must encode each of the images I1t , ..., Int , run a forward pass on the tokens corresponding to ot, and then run10 steps of flow matching, where each step requires running a forward pass on the tokens corresponding to Aτt (the keys and values corresponding to ot are cached).」
下表表I总结了使用3个摄像头图像进行此操作的计算时间
这些操作是在NVIDIA GeForce RTX 4090消费级GPU上计时的。对于移动机器人,推理是在Wi-Fi连接上进行的,增加了一小部分网络延迟。当然了,如果做进一步的优化、量化和其他改进可能会进一步减少推理时间
由于模型一次生成整个 H步动作块,作者可以在需要再次运行推理之前执行最多 H个动作。然而,实际可能会比这更频繁地进行推理,并且可以使用各种聚合策略结合来自不同推理调用的动作
作者在早期尝试了ACT算法中的时间集成[57- Learning fine-grained bimanual manipulation with
low-cost hardware,对于这点,我july的个人理解是时间集成是ACT策略中的其中一个选项,故用ACT的过程中,可以不用时间集成这个特征,是不影响对ACT的使用的],发现它对策略性能有害,因此作者选择不聚合动作,而是执行开放循环的动作块
- 对于20Hz的UR5e和Franka机器人,作者每0.8秒进行一次推理(在执行16个动作后)
- 而对于所有其他以50Hz运行的机器人,作者每0.5秒进行一次推理(在执行25个动作后)
1.3 数据收集和训练方案
就像大型语言模型(LLM)的训练通常分为预训练和后训练阶段一样,作者对他们的模型也采用多阶段训练程序
- 预训练阶段的目标是让模型接触到各种各样的任务,以便它能够获得广泛适用和一般的物理能力,而后训练阶段的目标是使模型能够熟练和流畅地执行所需的下游任务
- 因此,预训练和后训练数据集的要求是不同的:
预训练数据集应涵盖尽可能多的任务,并在每个任务中涵盖多样化的行为
后训练数据集则应涵盖有助于有效任务执行的行为,这些行为应表现出一致且流畅的策略。
直观地说,多样化(但质量较低)的预训练数据允许模型从错误中恢复并处理高度变化的情况,这些情况可能在高质量的后训练数据中不会出现,而后训练数据教会模型良好地执行任务
1.3.1 预训练和后训练
在下图图4中提供了作者预训练混合的概述「数据集的概览:预训练混合物由OXE[10]的一个子集和π数据集组成。他们使用OXE的一个子集,称之为OXE魔法汤[24]。右图展示了预训练混合物中不同数据集的权重。左图展示了通过步数衡量的相对大小」,注意,由于每个训练示例对应一个时间步——即一个元组,——在本次讨论中,将以时间步来量化数据
- 训练混合中有9.1%由开源数据集组成,包括OXE [10]、Bridgev2 [52] 和 DROID [23]。这些数据集中的机器人和任务通常配备一到两个摄像头,并使用低频控制,频率在2到10 Hz之间。然而,这些数据集涵盖了广泛的物体和环境
- 为了学习灵巧且更复杂的任务,作者还使用了来自作者自有数据集的903M时间步长的数据,其中106M步来自单臂机器人,797M步来自双臂机器人
这些数据涵盖了68个任务,每个任务由复杂的行为组成——例如,“清理”任务涉及将各种不同的盘子、杯子和餐具放入清理箱,以及将各种垃圾物品放入垃圾桶
请注意,这种任务的定义与之前的工作显著不同,之前的工作通常使用任何名词和动词的组合(例如,“拾起杯子”与“拾起盘子”)来构成一个独立的任务
因此,作者数据集中行为的实际范围比这些“任务”数量所暗示的要广泛得多。他们将在第V-C节中更详细地讨论他们数据集中的具体机器人和任务
此外,由于数据集在大小上有些不平衡(例如,更困难的洗衣折叠任务被过度代表),作者对每个任务-机器人组合赋予权重,其中是该组合的样本数量,以便对过度代表的组合进行降权
- 配置向量和动作向量始终具有数据集中最大机器人的维度大小(在作者的案例中为18,以适应两个6-DoF机械臂、两个夹持器、一个移动底座和一个垂直驱动的躯干)
- 对于配置和动作空间维度较低的机器人,对配置和动作向量进行零填充。对于少于三张图像的机器人,还会屏蔽掉缺失的图像槽
- 在训练后阶段,使用一个较小的任务特定数据集对模型进行微调,以使其专门化用于特定的下游应用。如前所述,对“任务”的定义相当广泛——例如,“收拾”任务需要操作多种不同的物体。不同的任务需要非常不同的数据集,最简单的任务只需5小时,而最复杂的任务需要100小时或更多的数据
1.3.2 语言和高级策略
更复杂的任务需要语义推理和高级策略,例如清理桌子,也可以通过将高级任务(如“清理桌子”)分解为更直接的子任务(如“拿起餐巾”或“将餐巾扔进垃圾桶”)的高级策略来受益
由于作者的模型经过训练可以处理语言输入,故可以使用高级视觉语言模型(VLM)来进行这些语义推理,这种方法类似于LLM/VLM的规划方法,例如SayCan [2]。通过使用这种高级策略来辅助他们的模型在多个实验任务中制定高级策略,正如将在第六节中讨论的那样
1.3.3 可操作的机器人系统:涉及7种机械臂和68个任务
作者灵巧操作数据集包括7种不同的机器人配置和68个任务,如下图图5所示
- UR5e
一个配备平行爪夹持器的手臂,带有一个腕部安装和一个肩上摄像头,总共提供两张相机图像和一个7维的配置和动作空间 - 双臂UR5e
两个UR5e设置,总共提供三张相机图像和一个14维的配置和动作空间 - Franka
Franka设置有两个摄像头和一个8维的配置和动作空间 - 双臂Trossen
此设置有两个基于ALOHA设置[4,57]的6自由度Trossen ViperX手臂,配有两个腕部摄像头和一个基座摄像头,以及一个14维的配置和动作空间 - 双臂ARX和双臂AgileX
此设置使用两个6自由度手臂,支持ARX或AgileX手臂,配有三个摄像头(两个腕部和一个基座),以及一个14维的配置和动作空间。此类别涵盖两个不同的平台,但由于它们的运动学特性相似,故将它们归为一类 - 移动Trossen和移动ARX
此设置基于移动ALOHA[57]平台,具有两个安装在移动基座上的6自由度手臂,可以是ARX手臂或Trossen ViperX手臂。非全向基座增加了两个动作维度,形成一个14维的配置和16维的动作空间。有两个腕部摄像头和一个基座摄像头。此类别涵盖两个不同的平台,但由于它们的运动学特性相似,故将它们归为一类 - 移动Fibocom
两个安装在全向基座上的6自由度ARX手臂。基座增加三个动作维度(两个用于平移,一个用于方向),形成一个14维的配置和17维的动作空间。在上上图-图4中总结了他们数据集中每个机器人的比例
1.4 实验效果及验证
1.4.1 对基础模型的评估
为了做一系列验证对比,作者
- 作者与OpenVLA[24]进行比较,这是一个最初在OXE数据集[10]上训练的7B参数VLA模型。作者在完整混合物上训练OpenVLA。这对于OpenVLA来说是一个非常困难的混合物,因为它不支持动作分块或高频控制
- 此外,还与Octo [50]进行比较,这是一个较小的93M参数模型。虽然Octo不是VLA,但它确实使用扩散过程生成动作,为作者的流匹配VLA提供了一个有价值的比较点
作者还在与他们模型相同的混合物上训练Octo。但由于时间限制,作者无法为OpenVLA和Octo训练与他们完整模型相同的周期数。因此,作者还与“计算平价”版本的模型进行比较,该版本仅训练160k步(而作者的主模型训练了700k步),这相当于或低于为基线提供的步骤数量(OpenVLA为160k,Octo为320k) - 还包括一个仅在UR5e数据上微调的OpenVLA模型版本,不进行跨化身训练,希望在UR5e任务上提供更强的基线
- 最后,作者还包括与上文描述过的π0-small模型的比较,该模型可以视为作者模型的缩小版,没有进行VLM预训练。评估指标使用在每个任务和方法的10个回合中平均的标准化得分,其中一次回合在完全成功时得分为1.0,部分成功时得分为小数
例如,搬运的得分是正确放置在适当容器中的物体的比例,且在附录E中描述了评分标准
结果如下图图7所示
π0在所有零样本任务上取得了迄今为止最好的结果,在衬衫折叠和较简单的搬运任务上接近完美的成功率,并且相对于所有基线有很大改善。经过160k步训练的“parity”版本的π0仍然优于所有基线,甚至π0-small也优于OpenVLA和Octo。OpenVLA在这些任务上表现不佳,因为其自回归离散化架构不支持动作块。仅限UR5e的OpenVLA模型表现较好,但仍远低于π0的性能。Octo确实支持动作块,但其表示能力相对有限
此比较说明了结合大型、具有表现力的架构与通过流匹配或扩散来建模复杂分布的能力的重要性。此外,与π0-small的比较说明了结合VLM预训练的重要性。不幸的是,最后的比较很难做到公平:π0-small使用的参数更少,但较大的模型在没有预训练的情况下难以使用
总体而言,这些实验表明π0提供了一个强大的预训练模型,能够有效地执行各种机器人任务,性能远优于先前的模型
1.4.2 学习新的灵巧任务
如下图图10所示,再看下面对一系列新任务的表现
- UR5e 堆叠碗。这个任务需要堆叠碗,使用四个不同尺寸的碗。由于这个任务需要像预训练数据中的收碗任务一样抓取和移动碗,因此将其归入“简单”层级
训练数据包含各种碗的使用,评估中混合使用已见和未见的碗 - 毛巾折叠。此任务需要折叠毛巾。由于这与衬衫折叠相似,而衬衫折叠在预训练中存在,因此将其归为“简单”级别
- 微波炉中的塑料容器。此任务需要打开微波炉,将塑料容器放入其中并关闭。容器有不同的形状和颜色,评估中混合使用已见和未见的容器。容器的操作类似于预训练数据,但微波炉在预训练中未出现
- 纸巾更换。此任务需要从支架上取下旧的纸巾纸管,并用新的纸巾卷替换。由于在预训练中未找到此类物品,可以认为这属于“困难”级别
- Franka机器人在抽屉中的物品。此任务需要打开抽屉,将物品放入抽屉中并关闭。由于在预训练中没有类似的Franka机器人任务,故也认为这属于“困难”级别
作者在微调后将他们的模型与Open-VLA[24]和Octo [50]进行比较,它们也采用预训练和微调的方法
由于作者的目标是评估特定模型(而非架构),故使用这些模型的公开可用的预训练检查点,这些检查点是在OXE [10]上训练的,然后对每个任务进行微调
- 此外,作者还与纯粹的ACT[57]和Diffusion Policy [9,关于什么是扩散策略,详见此文:Diffusion Policy——斯坦福机器人UMI所用的扩散策略:从原理到其编码实现]进行比较,这些方法专门为从较小的数据集中学习灵活任务而设计
ACT和Diffusion Policy仅在微调数据集上进行训练,这些数据集的大小与ACT和Diffusion Policy实验中使用的各个数据集相似 - 作者通过从他们的预训练基础模型进行微调以及从头开始训练来评估π0。此比较旨在评估π0架构和他们的预训练过程的单独优势
- 作者假设具有VLM初始化的π0架构应该已经为各个任务提供了更强的起点,而预训练过程应该进一步提高其性能,尤其是在较小的微调数据集上
下图图11展示了各种方法在所有任务上的性能「其使用不同数量的数据进行微调。π0即使在数据量较少的情况下也能学习一些简单的任务,并且预训练模型通常比从头开始训练的模型获得更大的提升」,平均每个任务进行10次试验,每个任务使用不同数量的微调数据
作者在叠碗和微波炉中的塑料容器任务上包含了所有基线。由于OpenVLA和Octo的性能显著较差,他们仅在其中一个数据集大小上运行这些模型,因为在现实世界中评估如此多模型的时间成本很高。结果显示,π0通常优于其他方法
有趣的是,最强的先前模型是那些完全从头开始在目标任务上训练的模型,这表明在这些领域利用预训练对先前方法来说是一个重大挑战。虽然在塑料容器任务上π0的5小时策略表现与基线相似,但1小时版本明显更好。正如预期的那样,对于与预训练数据更相似的任务,预训练带来了更大的改进,尽管预训练模型通常优于非预训练模型,有时甚至高达两倍
第二部分(选读) 详解Transfusion和Playground v3
2.1 Transfusion:既可以预测下一个token,又可以扩散图像
2.1.1 Transfusion的提出
来自Meta、Waymo、南加州大学的研究者们推出了Transfusion:使用一个多模态模型预测下一个token并扩散图像,其参数大小为7B,其对应的论文为《Transfusion: Predict the Next Token andDiffuse Images with One Multi-Modal Model》
具体而言,作者通过在50%文本和50%图像数据上预训练一个Transformer模型来得到Transfusion,且对每种模态使用不同的目标:文本使用下一个token预测,图像使用扩散。模型在每个训练步骤中同时接触到两种模态和损失函数
- 标准嵌入层将文本token转换为向量,而patch化层则代表每个图像作为一个patch向量序列。且作者对文本token应用因果注意力,对图像patch应用双向注意力
- 对于推理,作者引入了一种解码算法,将语言模型的文本生成标准实践与扩散模型的图像生成相结合
如下图所示「离散(文本)token以自回归方式处理,并在下一个token预测目标上进行训练。连续(图像)向量并行处理并在扩散目标上进行训练。其中,BOI和EOI标记用于分隔模态」
2.1.2 扩散与潜在图像表示
对于文本预测任务来说,比较简单,比如
- 给定一个从一个封闭词汇中抽取的离散token序列,语言模型预测序列的概率
- 标准语言模型将分解为条件概率的乘积——
这创建了一个自回归分类任务,其中每个标记的概率分布是根据序列的前缀来预测的,使用单个分布参数化为θ
且可以通过最小化与数据经验分布之间的交叉熵来优化模型,从而产生标准的下一个token预测目标,通俗地称为LM损失:一旦训练完成,语言模型还可以通过从模型分布中逐个采样标记来生成文本,通常使用温度和top-p截断
接下来,我们重点看下扩散和潜在图像表示
去噪扩散概率模型(又称DDPM或扩散模型),其基于学习「逆转渐进噪声添加」过程的原理运作 [即Denoising diffusion probabilistic models (a.k.a. DDPM or diffusion models) operate on the principle of learning to reverse a gradual noise-addition proces]
与通常处理离散符号的语言模型不同,扩散模型在连续向量上操作,使其特别适合处理涉及连续数据(如图像)的任务
扩散框架包括两个过程:一个是描述原始数据如何变成噪声的前向过程,另一个是模型学习执行的去噪反向过程
- 前向过程
从数学角度来看,前向过程定义了如何创建作为模型输入的噪声数据
给定一个数据点x0,Ho等人[2020]定义了一个马尔可夫链,该链在T个步骤中逐渐添加高斯噪声,生成一系列噪声逐渐增加的版本
该过程的每一步由定义,其中根据预定义的噪声计划随时间增加
且该过程可以重新参数化,使得能够通过一次高斯噪声采样直接从采样:
这里,,提供了对原始马尔可夫链的有用抽象。事实上,训练目标和噪声调度器最终都以这些术语表达并实现
如果对上面整个过程还不太理解的,或想深入了解更多细节的,均可以参看此文《图像生成发展起源:从VAE、VQ-VAE、扩散模型DDPM、DETR到ViT、Swin transformer》的第二部分——扩散模型DDPM:先前向加噪后反向去噪从而建立噪声估计模型 - 反向过程
扩散模型被训练来执行反向过程,通过逐步去噪来学习数据。有几种方法可以做到这一点;在这项工作中,遵循Ho等人[2020]的方法,将方程中的高斯噪声ϵ建模为步骤t的累计噪声的代理「we follow the approach of Ho et al. [2020] and model the Gaussian noise ϵ in Equation 2 as a proxy for the cumulative noise at step t.」
具体来说,使用参数θ的模型被训练用来在给定噪声数据和时间步的情况下估计噪声ϵ。实际上,模型通常基于额外的上下文信息进行条件化,例如在生成图像时的标题
因此,通过最小化均方误差损失来优化噪声预测模型的参数
在噪声设计上,在创建带噪示例时,决定了时间步长的噪声方差。在本工作中,一般采用常用的余弦调度器Nichol andDhariwal[2021],该调度器在很大程度上遵循,并进行了一些调整
在推理上,解码是迭代完成的,在每一步中逐渐去除一些噪声。从纯高斯噪声开始,模型预测在时间步累积的噪声。预测的噪声根据噪声计划进行缩放,并从中移除相应比例的预测噪声以生成
在实践中,推理的时间步数少于训练。通常使用无分类器引导——CFG[Ho 和 Salimans, 2022] 来通过对比模型在上下文条件下的预测与无条件预测来改善生成,代价是计算量加倍
想深入了解更多细节的,可以参看此文《图像生成发展起源:从VAE、VQ-VAE、扩散模型DDPM、DETR到ViT、Swin transformer》
进一步,早期的扩散模型直接在像素空间中工作[Ho et al., 2020],但这被证明计算上很昂贵。变分自编码器(VAEs)[Kingma and Welling, 2013]可以通过将图像编码到低维潜在空间来节省计算
- 作为深度卷积神经网络(CNNs)实现,现代VAEs在重构损失和正则化损失的组合上进行训练[Esser et al., 2021],允许下游模型如潜在扩散模型(LDMs)[Rombachet al., 2022a]在紧凑的图像块嵌入上高效运行
例如,将每个8×8像素块表示为一个8维向量。对于自回归语言建模方法[Ramesh et al., 2021, Yu et al., 2022],图像必须被离散化 - 离散自编码器,如矢量量化VAE(VQ-VAE)[Van Den Oord et al., 2017],通过引入一个量化层(以及相关的正则化损失)将连续的潜在嵌入映射到离散的token来实现这一点
2.1.3 Transfusion的数据表示、模型架构、训练目标
Transfusion主要创新在于可以针对不同模式使用不同的损失函数——对文本使用语言建模,对图像使用扩散——在共享的数据和参数上进行训练
下图图1展示了Transfusion的过程
在数据表示上
作者在两种模态下进行数据实验:离散文本和连续图像。每个文本字符串被分词为一个固定词汇表中的离散token序列,其中每个token表示为一个整数
每个图像使用VAE编码为潜在patch,其中每个patch表示为一个连续向量;这些patch从左到右、从上到下排列,形成每个图像的patch向量序列
对于混合模态示例,作者在插入文本序列之前,用特殊的图像开始(BOI)和图像结束(EOI)token包围每个图像序列;因此,作者得到了一个可能同时包含离散元素(表示文本token的整数)和连续元素(表示图像patch的向量)的单一序列
在模型架构上
绝大多数模型的参数属于一个单一的transformer,无论模态如何,它都会处理每一个序列。transformer接收一个高维向量序列作为输入,并生成类似的向量作为输出
为了将作者的数据转换到这个空间中,作者使用轻量级的模态特定组件,这些组件的参数不共享
对于文本,这些组件是嵌入矩阵,将每个输入整数转换为向量空间,并将每个输出向量转换为词汇表上的离散分布
对于图像,作者尝试了两种替代方案,将k×k patch向量的局部窗口压缩成一个单一的transformer向量
- 一个简单的线性层
- U-Net的上下块[Nichol和Dhariwal,2021,Saharia等,2022]
总体架构如下图图3所示
进一步而言,语言模型通常使用因果掩码来有效地计算整个序列的损失和梯度,在一个前向-后向传递中不泄露未来token的信息
虽然文本本质上是顺序的,但图像不是,通常使用不受限制的——双向注意力进行建模
故,Transfusion通过对序列中的每个元素应用因果注意力,并在每个单独图像的元素内应用双向注意力来结合这两种注意力模式。这使得每个图像块可以关注同一图像中的其他块,但只能关注序列中先前出现的文本或其他图像的块「This allows every image patch to attend to every other patch with in the same image, but only attend to text or patches of other images that appeared previously in the sequence」。故作者发现,启用图像内注意力显著提升了模型性能
下图图4展示了一个Transfusion注意力掩码的例子
在训练目标上
为了训练模型,作者将语言建模目标应用于文本token的预测,将扩散目标应用于图像块的预测
LM 损失是按每个token计算的,而扩散损失是按每个图像计算的,这可能跨越序列中的多个元素(图像块)
具体来说,作者根据扩散过程向每个输入潜在图像 添加噪声 ϵ 以生成 ,然后在分块化之前计算图像级别的扩散损失
最终,作者通过简单地将每种模态计算的损失与平衡系数 λ 相加来结合这两种损失(离散分布损失与连续分布损失相结合以优化同一模型)
在推理上
类似训练目标,解码算法也在两种模式之间切换:LM 和扩散
- 在 LM模式下,遵循从预测分布中逐个采样token的标准做法
- 当采样到一个 BOI标记时,解码算法切换到扩散模式,在这种模式下,遵循从扩散模型解码的标准程序 具体来说,在输入序列中附加形式为 个图像块的纯噪声 (取决于所需的图像大小),并在 T 步内去噪。在每个步骤 t 中,获取噪声预测并使用它生成,然后覆盖序列中的 ;即模型始终以噪声图像的最后一个时间步为条件,不能关注之前的时间步「the model always conditions on the last timestep of the noised image and cannot attend to previous timesteps」
如下图所示,便是一步步去噪的过程:基于去噪 得到 一旦扩散过程结束,则在预测的图像中附加一个 EOI token,并切换回 LM 模式。此算法能够生成任何文本和图像模态的混合体
2.2 Playground v3
// 待更
第三部分 π之外,流匹配与修正流Rectified Flow在机器人领域的其他应用
关于什么是流匹配Flow Matching与修正流Rectified Flow,详见此文《文生图中从扩散模型到流匹配的演变:从SDXL到Stable Diffusion3(含Flow Matching和Rectified Flow的详解)》的第五部分
考虑到有朋友问:“感觉pi0特点是不是就是flow matching,有其他的论文也是这么做的吗”,SD3之类的我就不说了,我重点说下这两在机器人领域的其他应用
3.1 用于多支撑操控的流匹配模仿学习
3.1.1 Flow Matching Imitation Learningfor Multi-Support Manipulation
24年7月,来自法国国家信息与自动化研究所的研究者们提出了「用于多支撑操控的流匹配模仿学习」的方法,其对应的论文为《Flow Matching Imitation Learning for Multi-Support Manipulation》
3.1.2 相关工作与提出背景
传统的BC方法,如DMP[6]或ProMPs[7],在演示的状态空间分布内的简单任务中表现良好
- 但由于预测错误的积累可能导致状态发散和失败
为了解决这个问题,作者的策略预测动作轨迹,与最近的工作[9-即上文提到过的Diffusion Policy],[24-即上面提到过的ACT],[25-3D Diffusion Policy,详见此文《斯坦福iDP3——改进3D扩散策略以赋能人形机器人的训练:不再依赖相机校准和点云分割(含3D扩散策略DP3的详解)》的第一部分]一致,增强了时间一致性并减轻了错误累积 - BC的另一个限制是处理人类演示的多样性、空闲动作以及解决相同任务所使用的不同策略。这些演示形成了一个可以是非凸的多模态分布,使得数据平均可能导致任务失败
最近的方法通过将BC的策略重新表述为生成过程来解决这个问题。去噪扩散概率模型(DDPM)[10]作为一种新型生成模型,已经超越了以前的生成模型
DDPM逆转了一个扩散过程,该过程将噪声添加到干净样本中,直到它变成高斯噪声。通过求解随机微分方程,然后从这种噪声中生成干净样本
去噪扩散隐式模型(DDIM)[26]则将逆过程作为普通微分方程求解,减少了推理步骤以加快计算速度,但以牺牲质量为代价
总之,最近的工作[8-“Planning with diffusion for flexible behavior synthesis],[9-Diffusion Policy],[25-3D Diffusion Policy],[27-Diffusion models for reinforcement learning: A survey]已将这些最初用于图像生成的技术应用于强化和模仿学习
它们生成的动作轨迹模仿了基于任务状态的人类演示,有效地捕捉了高维概率分布,并处理具有多个模式的非凸、非连接分布
而流匹配[13]是一种基于最优传输理论[11-Stochastic interpolants: A unifying framework for
flows and diffusions],[12-Building normalizing flows with stochastic interpolants]的新型生成方法,与DDPM和DDIM在理论上有相似之处
- 它更简单,超参数更少,数值上比DDIM更稳定。流匹配在传输流中产生更直的路径,通过给定数量的积分步骤提高生成质量,或使用更少的步骤在相同质量下实现更快的推理,这对于实时机器人应用至关重要
- 与[28-RF-POLICY: Rectified flows are computation-adaptive decision makers]、[29- “AdaFlow: Imitation learning with variance-adaptive flow-basedpolicies]、[30-Riemannian flow matching policy for robot motion learning]一致,这些研究表明流在模拟机器人任务中比扩散有改进,作者研究了流匹配在机器人学中的应用,并将其部署在真实的人形机器人上
3.2 整体方法
作为一种从示范中学习的方法,为了使人形机器人能够执行多支撑操作任务,可以通过增加接触点和全身运动来增强操作能力
这些任务可以自主执行,也可以通过辅助共享自主性执行,在这种情况下,人类操作员部分控制机器人,而学习到的策略提供辅助和接触点放置
总之,作者强调了他们的方法如何处理接触转换并在真实硬件上控制由此产生的多接触运动
3.2.1 整体架构
作者设计了一个具有两个层级模块的架构(图2),以增强鲁棒性「系统架构使用三种不同的操作模式(右)作为高层控制器输出执行器命令。这些命令通过SEIKO Retargeting [31], [32] 和 SEIKO Controller [22] 在机器人上实现(左)」
- 基于模型的低级控制器解决全身优化、多接触力分布、接触切换和具有严格可行性约束的跟踪问题
A model-based low-levelcontroller addresses whole-body optimization, multi-contact force distribution, contact switching and tracking with strictfeasibility constraints. - 基于学习的高级控制器处理笛卡尔效应器命令、接触位置和排序
它在世界坐标系中输出一个笛卡尔姿态目标和每个效应器的接触切换命令
A learning-based high-level controllerhandles Cartesian effector commands, contact locations, andsequencing.
It outputs a Cartesian pose target in world frameand a contact switch command for each effector.
效应器可以固定在与环境接触的状态(启用状态),主动施加力以平衡机器人,或者不接触并自由移动(禁用状态)
接触切换命令是一个离散信号,触发低级控制器实施的启用和禁用状态之间的转换
Effectors caneither be fixed in contact with the environment (enabled state),actively applying forces to balance the robot, or not in contactand free to move (disabled state).
The contact switch commandis a discrete signal that triggers the transition between enabledand disabled states implemented by the low-level controller.
下图图2中的高级控制器在三种不同模式下运行,如下图右侧所示
- 远程操作模式用于创建数据记录效应器命令发送到低级控制器,并由机器人的头部摄像头检测到外部标记的姿势
The teleoperation mode is used to create a dataset recording effector commands sent to the low-level controllerand poses of external markers detected by the robot’s head camera.
人类操作员直接指挥机器人从随机初始状态解决任务或从手动选择的状态执行恢复动作,收集演示数据
The human operator directly commands the robot to collect demonstrations, solving the task from randomizedinitial states or performing recovery actions from manuallyselected states outside nominal execution. - 完全自主模式使用模仿收集的演示训练的策略来解决任务
- 辅助共享自主模式结合人类和策略命令来解决分布外任务
操作员指挥一个效应器,而策略自主管理其他效应器
策略在共享和完全自主模式下使用相同的输入和后处理「The operator commands one effector while the policy autonomously manages the others. The policyuses identical inputs and post-processing in both shared andfull autonomous modes.」
然而,在共享自主模式下,操作员的命令取代了他们控制的效应器的策略输出「However, in shared autonomy mode,the operator’s commands replace the policy’s output for the effector they control.」
尽管[9-DP],[25-DP3]表明基于扩散的模仿学习可以从原始图像或点云中学习,作者选择在这项工作中使用基准标记来监测任务的外部状态
这能够将注意力集中在与接触切换和多接触相关的挑战上。机器人头部的RGB-D相机在彩色图像中使用AprilTags系统[33]检测这些标记
标记在相机框架中的3D位置和方向是从点云中提取的。然后,这些坐标通过前向运动学模型转换到机器人的世界框架中
在人类专家演示期间,标记的姿态被记录在数据集中,并作为输入提供给自主策略
3.2.2 行为克隆策略与接触切换
// 待更
3.2.3 使用流匹配进行轨迹生成
将行为克隆策略构建为一个生成过程,该过程从数据中学习概率分布并从中采样新元素。结果策略是随机的,并采样模拟人类操作员在相同状态下演示的轨迹
具体而言,作者采用流匹配方法[13-Flow straight and fast: Learning to generate and transfer data with rectified flow],该方法构建了一个流向量场,将源概率分布连续地转换为目标分布
下图图1展示了一个流将一个可以轻松采样的一维简单源分布转换为一个更复杂的多峰分布的过程
- 流匹配,基于最优传输理论,可以被视为扩散方法[11]的确定性对应。在从源分布采样后,流的积分确定性地产生目标分布的样本,这与在传输过程中引入噪声的扩散[10]方法形成对比。流匹配通常产生更直的流,从而加快推理速度
- 流匹配的训练定义如下
// 待更
版权声明:本文标题:π0——用于通用机器人控制的VLA模型:一套框架控制7种机械臂(基于PaliGemma和流匹配的3B模型) 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1733977601h1650050.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论