
tf.compat.v1 里“初始化”相关的东西主要分两类:会话中一次性执行的初始化器(返回一个 op,需要 sess.run),以及为变量提供初始值的“初始器”(传给 get_variable/Variable 的 initializer 参数)
会话级初始化器(运行一次以初始化图中的对象)
兼容别名(已弃用,但在 compat.v1 仍可用)
辅助检查
sess.run(tf.compat.v1.globalvariablesinitializer())
变量初始值“初始器”(传给变量创建时的 initializer)
方差缩放初始化,把权重按 fanin/fanout 计算出尺度,再用均匀或正态分布采样。它们的等价关系与公式如下(fanin=输入通道数,fanout=输出通道数;Dense 的 [in, out],Conv2D 的 [kh, kw, inC, outC] 则 fanin=khkwinC,fanout=khkwoutC)
选择建议:
tf.compat.v1.layers 是 TF1 的“简易层”API(已弃用,TF2 请用 tf.keras.layers)。里面主要是两类:函数式层(返回张量)和对应的层类
tf.keras.layers
核心与形状
卷积与转置卷积
池化
归一化与标准化
嵌入与注意力
序列与循环网络
合并/运算层
采样/几何变换/边界
预处理(可在模型内端到端使用)
https://huggingface.co/blog/zh/rlhf
过去几年里各种 LLM 根据人类输入提示 (prompt) 生成多样化文本的能力令人印象深刻。然而,对生成结果的评估是主观和依赖上下文的,例如,我们希望模型生成一个有创意的故事、一段真实的信息性文本,或者是可执行的代码片段,这些结果难以用现有的基于规则的文本生成指标 (如 BLEU 和 ROUGE) 来衡量。除了评估指标,现有的模型通常以预测下一个单词的方式和简单的损失函数 (如交叉熵) 来建模,没有显式地引入人的偏好和主观意见。
如果我们 用生成文本的人工反馈作为性能衡量标准,或者更进一步用该反馈作为损失来优化模型,那不是更好吗?这就是 RLHF 的思想:使用强化学习的方式直接优化带有人类反馈的语言模型。RLHF 使得在一般文本数据语料库上训练的语言模型能和复杂的人类价值观对齐
RLHF 是一项涉及多个模型和不同训练阶段的复杂概念,这里我们按三个步骤分解:
RLHF的训练分为两个关键阶段:
在这种背景下,RLHF有以下几个核心需求:
https://github.com/huggingface/trl
https://github.com/CarperAI/trlx
https://github.com/allenai/RL4LMs
https://github.com/facebookresearch/Pearl
https://github.com/BVLC/caffe https://caffe.berkeleyvision.org/
https://github.com/Farama-Foundation/Gymnasium
https://zhuanlan.zhihu.com/p/10791831521
DQN,
DQN适用于离散动作空间的强化学习问题,其目标是学习一个近似的Q值函数。Q值函数的更新公式为:
在DQN中,动作是离散的,通常使用-贪婪策略进行选择。然而,LLM(Large Language Models)的输出是连续概率分布,无法直接适配离散动作的Q学习方法。要应用DQN,需要对动作空间进行离散化,但这会引入近似误差,导致生成质量下降。
同时,DQN存在样本效率较低和收敛性不稳定的问题,在RLHF的大规模复杂任务中会放大这些缺点
PPO,
SAC Soft Actor-Critic
DDPG
PPO是一种基于信任区域的强化学习算法,它通过限制策略更新的幅度,在稳定性和效率之间找到了平衡。以下是PPO在RLHF中的核心优势:
MC、TD、SARSA、Q-learning、DQN、REINFORCE、PPO、SAC、TD3……这些名字听起来像是完全不同的东西。但其实,它们都在回答同一个问题:怎么让智能体学会做决策。
后来我发现,如果你用”三个问题”来看这些算法,它们就不再是一堆孤立的名字,而是有清晰脉络的一个体系:
https://github.com/thu-ml/tianshou
https://github.com/RLinf/RLinf/tree/main
https://github.com/huggingface/trl
精选博主: https://www.zhihu.com/people/yilan-zhong-shan-xiao-29-98/posts
现在的大模型在进行预训练时大部分都采用了GPT的预训练任务,即 Next token prediction。
在训练过程中,模型通过大量的文本数据来学习文本之间的模式和结构。例如,模型会看到成千上万次的“我爱X”这样的模式,其中X可以是各种不同的词。通过这样的训练,模型会学会哪些词最有可能出现在“我爱”之后。
要理解清楚这一训练过程,最主要的就是搞清楚预训练的数据怎么构造,数据怎么喂给模型,模型输出的是什么,以及如何计算loss。
假设现在有一个用来预训练的数据集
你知道什么是预训练吗?假设经过分词后
你: 9
知道: 3
什么: 6
是: 4
预训练: 2
吗: 1
?: 5原来的数据变为如下序列,后面补了三个0(假设我们希望最大序列长度是10)
9 3 6 4 2 1 5 0 0 0预测下一个token就类似于9预测3,93预测6,以此类推,但是如果这样拆成很多个数据段其实比较低效,因此就可以考虑移位来构造数据,即
9 3 6 4 2 1 5 0 0 03 6 4 2 1 5 0 0 0 0这样就可以一次性把整条序列喂给模型,计算一次就包含了个预测下一个token的损失了。注意这里模型的设计是有讲究的,我们不能让输入看到后面的词(如果看得到的话就没必要进行预测了),也就是“你”在模型内看不到“知道”,“你 知道”在模型内看不到“什么”,这个可以通过注意力机制实现,不是本文的关注点,这里就不展开了
现在模型的输入的维度为,第一维为batch_size,然后经过embedding层后变为,这里假设embedding的维度为768。
记住进入transfomer前后数据的维度不会发生变化,把transfomer当作一个黑盒,也就是transformer(X)的维度还是,接下来就是基于它来进行预测了,因为要预测哪个词,词的可能情况就是词表的大小,所以做的就是一个分类任务,预测下一个token是词表中的哪一个(词表中的每一个词当作一个类别)
为了完成分类任务,需要对transformer的输出做一个映射,映射到跟词表一样大,也就需要定义这样一个线性变换
output_layer = nn.Linear(768, vocab_size, bias=False)然后logits=output_layer(transformer(X))的维度就是(1,10,vocab_size),接下来就可以计算loss了,具体来说就是计算logits(模型预测)与targets(真实标签)之间的交叉熵损失,同时忽略了填充值对应的损失。
loss = F.cross_entropy(logits.view(-1, logits.size(-1)), targets.view(-1), ignore_index=0)Supervised fine-tuning
“有监督微调”意味着使用有标签的数据来调整一个已预训练好的语言模型(LLM),使其更适应某一特定任务。通常LLM的预训练是无监督的,但微调过程往往是有监督的
当进行有监督微调时,模型权重会根据与真实标签的差异进行调整。通过这个微调过程,模型能够捕捉到标签数据中特定于某一任务的模式和特点。使得模型更加精确,更好地适应某一特定任务。
以一个简单的例子来说,你有一个已经预训练好的LLM。当输入“我不能登录我的账号,我该怎么办?”时,它可能简单地回答:“尝试使用‘忘记密码’功能来重置你的密码。”
这个回答很直接,适用于一般问题,但如果是客服场景,可能就不太合适了。一个好的客服回答应该更有同情心,并且可能不会这么直接,甚至可能包含联系信息或其他细节。这时候,有监督微调就显得非常重要了。
经过有监督微调后,你的模型可以提供更加符合特定指导原则的答案。例如,经过一系列专业的培训示例后,你的模型可以更有同情心地回答客服问题。
接下来我们还是从数据到模型输出,计算loss的步骤来看看SFT的实现原理。
首先还是来看看数据怎么构造,SFT的每一条样本一般由两部分组成,也就是prompt(instruction)+ answer,比如:
翻译以下句子: What is pretrain什么是预训练也就是我们要给模型提供一些类似于问答形式的答案来学习,有了前面预训练的经验后,SFT其实就很好理解的,它本质上也在做next token prediction,只是我们更希望模型关注answer部分的预测,这可以通过生成一个mask向量来屏蔽不希望计算loss的部分,下面就是数据构造的一个示意:做的事情就是拼接prompt和answer,并在answer两侧添加一个开始和结束的符号,算一下prompt/instruction的长度,以及后面需要pad的长度,然后生成一个mask向量,answer部分为1,其他部分为0
input_id=prompt+[bos]+answer+[eos]
context_length = input_id.index(bos)
mask_position = context_length - 1
pad_len = max_length - len(input_id)
input_id = input_id + [pad] * pad_len
loss_mask = [0]*context_length+[1]*(len(input_id[mask_position+1:])) + [0]*pad_len构造好输入后,token转为embedding,经过transformer的过程跟之前预训练完全一样,也就是我们又得到了一个维度是(1,10,vocab_size)的输出logits=output_layer(transformer(X)),进一步就可以计算answer部分的loss了,其实就是通过mask把不希望考虑的地方乘以0,保留answer部分loss
loss = F.cross_entropy(logits.view(-1, logits.size(-1)), Y.view(-1), ignore_index=0,reduce=False)
loss_mask = loss_mask.view(-1)
loss = torch.sum(loss*loss_mask)/loss_mask.sum()有了loss,进行反向传播更新模型参数就OK啦
语言风格有要求 比如ai恋爱 ai面试
全模型微调(Full Fine-Tuning)
冻结部分参数微调(Partial Fine-Tuning / Layer Freezing)
轻量化微调(Parameter-Efficient Fine-Tuning, PEFT)
渐进微调(Progressive Fine-Tuning)
多任务微调(Multi-Task Fine-Tuning)
科研用1就行
https://github.com/huggingface/peft
from peft import PeftModel
device = torch.accelerator.current_accelerator().type if hasattr(torch, "accelerator") else "cuda"
model_id = "Qwen/Qwen2.5-3B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id, device_map=device)
model = PeftModel.from_pretrained(model, "qwen2.5-3b-lora")
inputs = tokenizer("Preheat the oven to 350 degrees and place the cookie dough", return_tensors="pt")
outputs = model.generate(**inputs.to(device), max_new_tokens=50)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))| 你的情况 | 推荐方法 | 理由 |
|---|---|---|
| 数据量小(<1k) | 冻结+LoRA | 防止过拟合,高效利用参数 |
| 数据量大(>10k) | 全微调或LoRA | 全微调效果最好,LoRA性价比高 |
| 计算资源有限 | QLoRA | 单卡微调大模型的唯一选择 |
| 需要多任务能力 | 多任务微调+LoRA | 共享表示,任务特定适配 |
| 快速实验迭代 | LoRA/Prompt Tuning | 训练快,切换方便 |
| 生产部署 | LoRA(合并后) | 无推理开销,性能接近全微调 |
目前各种Pretraining的Transformer模型层出不穷,虽然这些模型都有开源代码,但是它们的实现各不相同,我们在对比不同模型时也会很麻烦。Huggingface Transformer能够帮我们跟踪流行的新模型,并且提供统一的代码风格来使用BERT、XLNet和GPT等等各种不同的模型。而且它有一个模型仓库,所有常见的预训练模型和不同任务上fine-tuning的模型都可以在这里方便的下载。截止目前,最新的版本是4.5.0
Huggingface Transformer 4.5.0需要安装Tensorflow 2.0+ 或者 PyTorch 1.1.0+
Transformers的目的是为了:
使用预训练模型最简单的方法就是使用pipeline函数,它支持如下的任务:
https://fancyerii.github.io/2021/05/11/huggingface-transformers-1/
https://umi-gripper.github.io/
过去两年,机器人操作这条线有点像2020年之前的大模型世界:模型层面已经有了很强的模板(Diffusion Policy、各种VLA、RDT),真正卡住的反而是——怎么稳定、便宜、大规模地收"人类教机器"的数据。
传统两条路各有硬伤:
纯teleop路径:人在远程操控真实机械臂,优点是动作空间对齐、可直接部署,但缺点也很致命——硬件贵、搭建复杂、实时性差、难scale。一套双臂teleop系统动辄几十万美元,还需要专门的实验室空间。
纯人类视频路径:直接从YouTube、Ego4D这类视频里学,数据量巨大,但没有显式动作、形态差异大,embodiment gap和observation gap都很严重。机器人看着人类做饭的视频,根本不知道该输出什么动作指令。
UMI(Universal Manipulation Interface)本质上是在回答一个问题:能不能让"人类在真实世界随手做事"变成直接可用的机器人训练数据,同时又不用动真实机器人?
这条线从最初的UMI,演化出了Fast-UMI、MV-UMI、DexUMI、ActiveUMI一整个家族,基本把"手部操作"这块的数据接口打磨得很成熟了
UMI的核心设计可以概括成三句话:
第一,手持3D打印夹爪+GoPro。手里拿的是一个平行夹爪(软指尖),扳机控制开合,夹爪前面挂一台GoPro,配超广角鱼眼镜头,还在两边贴了物理小镜子,直接在一张图里搞出多视角"隐式双目"。整套东西完全可以装进背包,去哪儿都能收数据。
第二,只用"手腕相机"对齐人和机器人。人演示时是"GoPro+夹爪"的第一视角,真机部署时,在机器人末端挂同样的GoPro+夹爪,看出去的画面几乎一模一样。这就把人类和机器人统一到同一个观察空间,极大减小了embodiment gap。
第三,用Diffusion Policy学"相对轨迹+延迟补偿"。UMI把从视觉SLAM+IMU估出来的6DoF末端轨迹,转成"相对轨迹",不依赖绝对世界坐标,在训练和部署时都显式建模传感、推理、执行延迟,保证真实机器人动作和当时的视觉是对齐的。Policy本身用的是Diffusion Policy,一口气预测一个短时轨迹段,天然适合多模态的人类数据。
效果上,一代UMI已经能做到:动态、双臂、长时序的真实任务(比如倒饮料、切菜、复杂装配),只要换训练数据就能换任务,同一套数据可以零样本迁移到不同自由度的机械臂上,成功率在OOD环境里还能保持在70%左右
关键insight:UMI不是在做"更强的网络",而是把"人类如何用手和世界交互"这件事装进了一个高保真、低摩擦的接口里,再交给一个足够强的生成式policy去拟合。
3 工程化进阶:从实验室demo到数据工厂▸▸
一代UMI虽然好用,但在工程上还有两个痛点:依赖基于视频的SLAM+IMU,部署流程不够"傻瓜",只有手腕视角,复杂场景下的视觉上下文仍然有限。于是就有了两条演化支线。
Fast-UMI干的事情很直接:把UMI做成真正可扩散的工程系统。用更通用的跟踪模块和标定方式取代原来对特定相机/SLAM的依赖,明确把"人类手持设备"和"机器人端"全流程打通,做成硬件无关pipeline,顺带开源了一套包含多类任务的数据集,直接为VLA/Diffusion Policy提供训练燃料。
它的意义不在于提出新算法,而在于:把"UMI这种接口"从一篇论文demo,变成任何团队都能复现&改造&堆数据的基础设施。对于后续做manipulation foundation model的团队,这是非常关键的一步
MV-UMI(Multi-View UMI)解决的是另一个问题:Wrist-only视角对齐了人和机器人,但上下文严重受限。那能不能在不引入观察空间gap的前提下,再加一个环境视角?
它的做法很巧:人演示时,同时录制手腕视角(和UMI一样)和顶视/侧视第三人称相机,然后对第三人称视频做两件事——用SAM-2把人整块segment掉,用静态背景帧做inpainting,把人抹掉,只留下场景和被操作物体。训练时,policy输入的是"手腕视角+去人后的第三人称视角"。
这样一来,机器人部署时也可以用第三人称视角(甚至可以再做一次inpainting去掉机器人本体),两边视觉分布保持一致,但模型获得了远比wrist-only更完整的环境上下文,特别适合长时序、多物体任务。论文里在严重依赖上下文的任务上,性能提升可以做到接近50%量级
UMI系列最有意思的一支是DexUMI:直接把"人手"变成universal manipulation interface。
大致思路可以理解为:硬件侧,人戴一个手部外骨骼,一边做各种高自由度操作(抓、捏、转、拧),外骨骼实时测量每根手指的关节角,甚至还能提供一定的力反馈。软件侧,通过几何映射+约束优化,把人手的高维关节空间映射到机器人手(比如Allegro hand、其他五指手)的可行姿态,同时在视频层面做"手替换":对原始人手视频做inpainting,用高保真的机器人手渲染替换掉人手,避免视觉domain gap。
学习侧,在两套真实机器人手上做实验,任务包括旋转物体、精细抓取等高难度dexterous任务,实验里平均成功率能做到86%左右。
从设计哲学上看,DexUMI和一代UMI是同一种思路:把"人自然的控制通道"(这里是手)当成黄金标准,用一套硬件+软件把它映射进机器人可执行的动作空间。差别在于:UMI处理的是"平行夹爪+末端6DoF",更适合日常工具型操作,DexUMI直接打到高自由度dexterous hand,针对的是精细抓取和复杂操作。
这一支线给"通用手部操作基础模型"补上了最难的一块——精细接触操作的数据接口
ActiveUMI:告诉机器人"看哪里"和"怎么动手"一样重要▸▸
UMI系列还有一条非常符合直觉,但之前基本没人系统做好的方向:ActiveUMI。
问题非常朴素:人在做复杂任务时,手在动,头也在动。传统UMI只把"手"映射给机器人,忽略了"头怎么动"这个信号。
ActiveUMI就是在把这件事补上:数据采集用VR头显+双手控制器,人戴VR头显+手持控制器,在一个虚拟环境里操作"虚拟机械臂",系统同时记录双手控制器的6DoF轨迹(对应双机械臂末端)、头显的6DoF轨迹(对应机器人"头/摄像头"的pose)。
机器人侧,两只机械臂做双臂操作,第三只机械臂专门拿着"头部相机",训练出一个policy,不仅预测双臂动作,还预测"头往哪里看"。
学习到的是"注意力模式"。模型学到的不是一个固定相机,而是:"在人类做rope boxing/折衣服/关工具箱/放瓶子的过程中,头是怎么转的"。部署时,机器人可以主动移动视角去消除遮挡、检查抓取结果,真正具备了active perception。
实验结果很直观:同样一套任务,UMI(仅腕部摄像)平均成功率26%,加一个固定顶视摄像头42%,ActiveUMI(主动控制头部视角)能到~70%。换到新环境,ActiveUMI还能在OOD场景维持56%的成功率,而UMI baseline掉到6%。
更有意思的是数据混合实验:大量ActiveUMI数据+少量真实teleop轨迹(1%级别),在复杂的折衣服任务上,成功率可以从80%拉到95%。这基本说明了一件事:"廉价、可扩展"的UMI/ActiveUMI数据+"少量昂贵"的teleop数据,是一个非常稳的组合
如果把现在机器人界各种"数据接口"放在一起看,会发现一个清晰的谱系:手持接口(UMI/Fast-UMI/MV-UMI/ActiveUMI系列)、外骨骼接口(Airexo/Airexo-2/DexOp/Nuexo等上肢exoskeleton,用整条手臂甚至身体作为接口)、全身VR接口(TWIST/TWIST2、OmniH2O这类基于VR+全身追踪的人形数据采集系统)。
UMI系列的独特之处在于三点:
第一,完全robot-free的in-the-wild数据路径。手持设备本身就是一个"机器人末端代理",收数据时完全不需要真实机器人,极大降低了扩展成本。你可以带着UMI夹爪去厨房、去车库、去任何地方收集数据,而传统teleop必须在机器人旁边操作。
第二,观察/动作空间都是"机器人视角"。Wrist camera+末端6DoF/轨迹,天然容易映射到真实机械臂,这让它非常适合作为通用VLA/Diffusion Policy的data back-end。
第三,从"如何动手"逐步扩展到"如何看+如何动手"。MV-UMI引入了多视角静态上下文,ActiveUMI进一步引入了"人类头部运动"这一attention信号
https://zhuanlan.zhihu.com/p/1980925297101653137
机器人必须能够在广泛的现实场景中进行泛化一直是机器人领域的一个长期关注点。RT-X、RT-1、Octo、CrossFormer 这些都是在大量多样化机器人数据集训练的,明显提高了泛化能力
https://zhuanlan.zhihu.com/p/1943972298639013811
https://www.zhihu.com/tardis/zm/art/670907685?source_id=1003
uc伯克利有人在做 https://ecot-lite.github.io/。https://verityw.github.io/
Parquet 是一种开源的列式存储文件格式,用于高效存储和分析大数据。与传统的行式存储格式(如 CSV 或 JSON)不同,Parquet 将同一列的数据存储在一起,从而提高了查询性能,并能通过先进的压缩和编码技术降低存储成本。它在 Hadoop 生态系统中被广泛使用,并被 Apache Spark、Apache Hive 等多种大数据处理框架所支持和采用
随着大模型AI的进一步发展,我们需要存储和处理的数据量呈指数级增长,寻找存储各种数据风格的最佳方式依然是最大的挑战之一。
相信现在几乎已经没有人还会认为关系数据库是依然是唯一数据存储处理方式。
比如说抖音的视频和直播等信息,其原始数据通常是无法实现以传统(关系)数据库方式存储的,或者以传统方式存储它们需要大量的精力和时间,同时会增加总体数据的分析时间。
即使我们还在以某种方式坚持传统方法,结构化方式存储数据,但我们需要设计复杂且耗时的 ETL 工作负载来将这些数据移动到企业数据仓库中。
这种架构方式使得数据分析从业人员,可能被分为两类,一类人主要每天接触 Python负责处理转换数据到关系型数仓,一类主要接触SQL针对关系型数据库进行分析
可以说最近几年 Parquet 已经被认为是当今存储数据的事实上的标准了,它主要有以下几个优势:
我们已经提到过 Parquet 是一种基于列的存储格式。
然而,要了解使用 Parquet 文件格式的好处,我们首先需要区分基于行和基于列的数据存储方式。
在传统的基于行的存储中,数据存储为行序列
现在我们举例OLAP数据分析中的一个场景,用户可能会问的一些常见问题:
为了能够回答这些问题,引擎必须从头到尾扫描每一行!
因此,为了回答这个问题:有多少美国用户购买了 T 恤,引擎必须执行以下操作
本质上,我们只需要两列中的信息:产品(T 恤)和国家/地区(美国),但引擎将会扫描所有五列数据!
这不是我们想要的最有效的解决方案。
现在让我们看看列存储是如何工作的,是否如您可能猜想的那样
如上图所示,在这种情况下,每一列都是一个单独的实体 - 这意味着,每一列在物理上都与其他列分开的!
回到我们之前的业务问题:引擎现在可以只扫描查询所需的列(产品和国家/地区),同时跳过不必要扫描的列。
在大多数情况下,这种数据跳过应该会提高分析查询的性能。
好的,但在Parquet诞生之前,列式存储早已经出现
实际上我们在OLAP场景中,主要关心两个概念:
投影是指SQL 语言中的SELECT语句 - 查询需要哪些列。回到之前的示例,我们只需要“产品”和“国家/地区”列,因此引擎可以跳过扫描其余的列。
谓词是指SQL 语言中的WHERE子句 – 哪些行满足查询中定义的条件。在我们的例子中,我们只对 T 恤感兴趣,因此引擎可以完全跳过扫描第 2 行组,其中“产品”列中的所有值都等于袜子!
让我们暂停总结分析一下,因为我希望您认识到各种类型的存储在引擎需要执行的工作方面的差异:
显然,这是一个过于简化的示例,只有 6 行和 5 列,您绝对看不到这三种存储选项之间的性能差异。然而,在现实生活中,当您处理大量数据时,差异就会变得更加明显。
现在,最急切的问题是:Parquet 是如何“知道”要跳过/扫描哪个行组?
Parquet 文件包含元数据
这意味着,每个 Parquet 文件都包含“有关数据的数据”,例如特定行组内特定列中的最小值和最大值等信息。
此外,每个 Parquet 文件都包含一个页脚,其中保存有关格式版本、架构信息、列元数据等信息。您可以在此处找到有关 Parquet 元数据类型的更多详细信息。
为了优化性能并消除不必要的数据结构(行组和列),引擎首先需要“熟悉”数据,因此它首先读取元数据。
虽然这个操作不算慢,但还是需要一定的时间,因此,如果您从多个小型 Parquet 文件中查询数据,查询性能可能会降低,因为引擎必须从每个文件中读取元数据。
因此,您最好将多个较小的文件合并为一个较大的文件(但仍然不要太大)
那么什么是“大”,什么是“小”呢,这里没有单一的“黄金”数字,因为这和任务的处理瓶颈是相关的,一般我们建议单个 Parquet 文件的大小至少应为几百 MB。
当说数据湖文件组织格式所提供能力时,主要是 Parquet 文件的版本控制。它还存储事务日志,以便跟踪应用于 Parquet 文件的所有更改。这也称为ACID 兼容事务。
由于它不仅支持 ACID 事务,还支持时间旅行(回滚、审计跟踪等)和 DML(数据操作语言)语句,例如 INSERT、UPDATE 和 DELETE,等数据仓库的行为,所以又被叫做“data warehouse on the data lake”
https://zhuanlan.zhihu.com/p/680143641
cuda
CUDA(Compute Unified Device Architecture)是由NVIDIA推出的一种并行计算平台和编程模型。它允许开发者使用通用编程语言(如C、C++)来利用NVIDIA GPU进行并行计算。CUDA提供了一组库、编译器、运行时系统和开发工具,使开发者能够更轻松地利用GPU的计算能力
cuda-toolkit
CUDA Toolkit是用于CUDA开发的软件包,包括了CUDA编译器、运行时库、GPU驱动程序、开发工具等。CUDA Toolkit提供了一整套用于开发GPU加速应用程序的工具和库,以及与NVIDIA硬件和驱动程序的兼容性。
CUDA Toolkit 完整和不完整的区别:在安装了CUDA Toolkit (Pytorch)后,只要系统上存在与当前的 cudatoolkit 所兼容的 Nvidia 驱动,则已经编译好的 CUDA 相关的程序就可以直接运行,不需要重新进行编译过程。如需要为 Pytorch 框架添加 CUDA 相关的拓展时(Custom C++ and CUDA Extensions),需要对编写的 CUDA 相关的程序进行编译等操作,则需安装完整的 Nvidia 官方提供的 CUDA Toolkit
nvidia-driver(NVIDIA驱动程序)是操作系统与NVIDIA GPU硬件之间的软件接口。它负责管理GPU硬件的操作、资源分配、性能优化等任务。CUDA依赖于NVIDIA的驱动程序,因为它需要与GPU硬件进行通信以执行并行计算任务。在使用CUDA进行开发时,确保安装了与CUDA兼容的NVIDIA驱动程序是很重要的。
理解驱动的定义,有助于理解nvidia-driver
CuDNN(CUDA Deep Neural Network library)是NVIDIA提供的用于深度学习任务的GPU加速库。它是专门为使用CUDA(Compute Unified Device Architecture)平台的深度学习框架而设计的,旨在优化深度神经网络的计算性能。
CuDNN提供了一系列高度优化的基本操作和算法,例如卷积、池化、归一化等,这些操作是深度学习中常见的基本构建块。通过使用CuDNN,深度学习框架可以利用NVIDIA GPU的并行计算能力,加速神经网络的训练和推理过程。