news 2026/10/23 10:20:42

VLA 系统学习第 13 课:Transformer 到底看到什么?——Sequence、Token、Embedding 和 Position

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
VLA 系统学习第 13 课:Transformer 到底看到什么?——Sequence、Token、Embedding 和 Position

第十二课标准答案

1. 为什么只看当前一帧 \(o_t\) 有时候无法判断运动趋势?

因为:

\[ o_t \]

只能描述“现在是什么样”,不一定包含“刚才是怎么变过来的”。

例如当前关节位置:

\[ q_t=0.5 \]

仅凭这一点无法判断它正在:

\[ 0.4\rightarrow0.5 \]

还是:

\[ 0.6\rightarrow0.5 \]

所以加入过去 Observation:

\[ [o_{t-1},o_t] \]

就能提供一定时间信息。


2. 什么叫 Observation History?

就是:

Policy 不只看当前 Observation,而是同时看过去若干个 Observation。

例如:

\[ T_o=3 \]

那么:

\[ [o_{t-2},o_{t-1},o_t] \]

就是一个长度为 3 的 Observation History。


3. Tensor

\[ [32,4,10] \]

分别是什么?

\[ 32=B \]

Batch Size,一次 32 个训练样本。

\[ 4=T \]

每个样本包含 4 个时间步。

\[ 10=D \]

每个时间步由 10 个特征描述。

所以应该读成:

32 个样本,每个样本有 4 个时间位置,每个时间位置是 10 维特征。


4. 图像 Tensor

\[ [16,3,3,224,224] \]

如果第一个 3 是时间长度,那么第二个 3 是什么?

第二个:

\[ 3 \]

表示 RGB Channel:

\[ R,G,B \]

所以:

\[ [B,T,C,H,W] \]

这里是:

\[ [16,3,3,224,224] \]

即:

16 个样本,每个样本有 3 帧,每帧 RGB 三通道,图片尺寸 224×224。


5. 什么叫 Single-step Action Prediction?

就是一次只预测:

\[ a_t \]

一个 Action。

形式:

\[ o_t\rightarrow a_t \]

执行后重新观察,再预测:

\[ o_{t+1}\rightarrow a_{t+1} \]


6. 什么叫 Action Chunk?

不是只预测一个 Action,而是一次预测一串未来 Action:

\[ A_t= [a_t,a_{t+1},\ldots,a_{t+K-1}] \]

这一小段连续 Action 就叫:

Action Chunk


7. 如果

\[ B=32,\quad K=20,\quad D_a=7 \]

Action Chunk Shape 是什么?

\[ \boxed{[32,20,7]} \]

含义:

  • 32 个 Sample;
  • 每个 Sample 预测 20 个未来 Action;
  • 每个 Action 是 7 维。

8. Observation Horizon 和 Prediction Horizon 为什么不是一个东西?

Observation Horizon 回答:

模型往过去看多久?

例如:

\[ T_o=3 \]

输入:

\[ [o_{t-2},o_{t-1},o_t] \]

Prediction Horizon 回答:

模型往未来预测多长?

例如:

\[ T_p=16 \]

输出:

\[ [a_t,a_{t+1},\ldots,a_{t+15}] \]

所以完全可以:

\[ T_o=2,\qquad T_p=16 \]

两者没有必须相等的关系。


9. 为什么预测 16 个 Action,不一定执行完 16 个?

因为真实环境会变化。

可以:

观察 ↓ 预测16步 ↓ 只执行前4步 ↓ 重新观察 ↓ 再预测16步

这样既保留一定动作连续性,又保持闭环反馈。


10. Episode 只剩 3 个 Action,但要求固定 10 个怎么办?

因为模型通常希望固定 Shape:

\[ [K,D_a] \]

如果:

\[ K=10 \]

但真实只剩:

\[ 3 \]

个 Action,就可能需要用 Padding 补齐剩下 7 个位置。


11. Padding 后为什么还需要 Mask?

因为模型必须知道:

哪些是真数据,哪些只是为了凑长度补出来的。

例如:

\[ mask= [1,1,1,0,0,0,0,0,0,0] \]

前 3 个有效,后面 7 个是 Padding。

否则 Loss 可能错误地把 Padding 当成真实动作训练。


12. 为什么[B,T,D]会自然把我们带向 Transformer?

因为:

\[ T \]

代表一个Sequence。

模型现在不只处理单个向量,而是:

\[ x_1,x_2,\ldots,x_T \]

这样一串位置。

于是问题变成:

第 1 个位置和第 5 个位置有什么关系?

哪个时间步对当前决策更重要?

不同位置之间的信息应该怎样交互?

这正是 Attention / Transformer 最擅长处理的问题。


VLA 系统学习第 13 课:Transformer 到底看到什么?——Sequence、Token、Embedding 和 Position

上一课我们已经自然得到:

\[ [B,T,D] \]

也就是说每个 Sample 不再只是一个向量,而是一个 Sequence:

\[ x_1,x_2,\ldots,x_T \]

接下来真正进入 Transformer 前,必须先解决一个很容易被讲模糊的问题:

Transformer 里的“Token”到底是什么?

因为后面一上来就会出现:

\[ X\in\mathbb R^{B\times T\times D} \]

然后:

\[ Q=XW_Q \]

如果现在连 \(X\) 里面装的是什么都不清楚,Q/K/V 很容易沦为背公式。


一、Sequence 不等于 Language

很多人第一次接触 Transformer,是从语言模型开始的。

于是容易形成:

Token = 单词

这种印象。

但严格来说不是。

Token 更准确的理解是:

Transformer Sequence 中的一个“位置单位”。

语言里,一个 Token 可以来自:

"pick" "up" "the" "block"

图像里,一个 Token 可以对应:

一块图像 Patch。

机器人状态里,一个 Token 可以对应:

某一个时间步经过编码后的 Robot State。

所以:

\[ \boxed{ Token不是某一种具体数据 } \]

而是:

Transformer 序列中的一个信息单元。


二、先看最熟悉的 Language Token

假设一句话:

pick up the red block

Tokenizer 处理以后,可能得到若干 Token。

为了教学,假设得到:

["pick", "up", "the", "red", "block"]

实际上现代 Tokenizer 往往还会进行 subword 切分,所以真实结果不一定正好等于单词。

然后每个 Token 会映射成一个 Token ID。

例如教学示意:

pick → 17 up → 52 the → 4 red → 91 block → 33

于是:

\[ tokens= [17,52,4,91,33] \]

Shape:

\[ [T] \]

其中:

\[ T=5 \]


三、为什么不能直接把 Token ID 喂进 Transformer?

因为:

\[ 17 \]

和:

\[ 52 \]

只是编号。

不能理解成:

52 比 17 大,所以"up"比"pick"多 35 个单位。

Token ID 没有这种连续数值意义。

它更像:

学生1号 学生17号 学生52号

编号只是身份标识。

因此需要把:

\[ Token\ ID \]

转换成一个向量:

\[ Embedding \]


四、Embedding 到底是什么?

假设:

\[ D=4 \]

每个 Token 被表示成 4 维向量。

例如:

\[ 17 \rightarrow [0.2,-0.4,0.8,0.1] \]\[ 52 \rightarrow [-0.5,0.3,0.1,0.9] \]

那么一句 5 Token 的话:

\[ [17,52,4,91,33] \]

经过 Embedding 以后就从:

\[ [5] \]

变成:

\[ [5,4] \]

也就是:

\[ [T,D] \]

加入 Batch:

\[ \boxed{ [B,T,D] } \]

看到没有?

这正好和上一课的 Sequence Tensor 接上了。


五、代码里 Embedding 长什么样?

PyTorch:

import torchimport torch.nn as nnembedding = nn.Embedding( num_embeddings=100, embedding_dim=4)

这里:

num_embeddings=100

意思是:

我的词表中有 100 个不同 Token ID。

而:

embedding_dim=4

表示:

每个 Token 最终变成一个 4 维向量。

现在输入:

token_ids = torch.tensor([ [17, 52, 4, 91, 33], [12, 8, 7, 31, 2]])

Shape:

\[ [2,5] \]

也就是:

  • Batch = 2;
  • 每句话 5 个 Token。

执行:

x = embedding(token_ids)

输出 Shape:

\[ [2,5,4] \]

所以代码链就是:

Token ID [B,T] ↓ nn.Embedding ↓ Token Embedding [B,T,D]

六、nn.Embedding本质上里面是什么?

它内部可以先理解成有一张大表:

\[ E\in\mathbb R^{V\times D} \]

其中:

\[ V \]

是 Vocabulary Size,

\[ D \]

是 Embedding Dimension。

例如:

\[ E:[100,4] \]

每一行对应一个 Token 的向量。

如果 Token ID:

\[ 17 \]

就取:

\[ E_{17} \]

这一行。

因此:

embedding(token_ids)

本质上是在:

根据 Token ID,从 Embedding Table 里查对应的向量。

所以 Embedding 很像:

\[ \boxed{ ID\rightarrow Vector } \]


七、Embedding 也是可训练 Parameter

这点很重要。

nn.Embedding(100, 4)

内部的 Embedding Table 不是固定死的。

它也是:

\[ Parameter \]

训练时:

loss.backward()

可以计算:

\[ \frac{\partial L}{\partial E} \]

Optimizer 再更新它。

所以最开始:

"red"

对应的向量可能是随机的。

训练以后,模型会逐渐学习:

哪种向量表示更有利于当前任务。

这和我们前面学习:

\[ W,b \]

完全是一回事。


八、那 Robot State 怎么变成 Token?

语言有 Token ID,可以查 Embedding Table。

Robot State 不一样。

假设某个时间步:

\[ s_t\in\mathbb R^{10} \]

它本身已经是连续数值:

\[ [0.1,-0.3,0.8,\ldots] \]

所以通常不需要:

State → Token ID → Embedding Table

更自然的做法是用 Linear Projection:

\[ s_t\in\mathbb R^{10} \]

映射到 Transformer 使用的:

\[ D=64 \]

维度:

\[ e_t=W_ss_t+b_s \]

于是:

\[ [10]\rightarrow[64] \]

这个:

\[ [64] \]

就可以作为一个 Robot State Token。


九、代码里 Robot State Token 怎么做?

例如:

state_encoder = nn.Linear(10, 64)

现在 Batch 中有:

\[ state:[32,4,10] \]

其中:

  • 32 个 Sample;
  • 4 个时间步;
  • 每个 State 10 维。

直接:

state_tokens = state_encoder(state)

nn.Linear会作用在最后一个维度。

所以:

\[ [32,4,10] \rightarrow [32,4,64] \]

也就是:

\[ [B,T,D_s] \rightarrow [B,T,D_{model}] \]

现在每个时间步:

\[ [10] \]

变成:

\[ [64] \]

于是 Transformer 可以把它理解成:

长度为 4 的 Robot State Token Sequence。


十、为什么nn.Linear(10,64)能直接处理[32,4,10]?

这是非常重要的 PyTorch Shape 规则。

我们以前一直用:

\[ [32,10] \]

输入:

nn.Linear(10,64)

得到:

\[ [32,64] \]

实际上nn.Linear主要要求:

输入最后一个维度必须等于in_features。

所以:

nn.Linear(10, 64)

可以处理:

\[ [32,4,10] \]

因为最后一维是:

\[ 10 \]

它会把每一个:

\[ [10] \]

向量分别变成:

\[ [64] \]

所以:

\[ [32,4,10] \rightarrow [32,4,64] \]

前面的:

\[ 32,4 \]

都保留。

以后这一点非常有用。


十一、Language 和 Robot State 为什么最后都能变成[B,T,D]?

语言:

Token IDs ↓ Embedding

变成:

\[ [B,T_l,D] \]

Robot State:

Continuous State ↓ Linear Projection

变成:

\[ [B,T_s,D] \]

关键在于:

虽然原始数据形式完全不同,但最后都被编码成 D 维 Token。

比如:

\[ D=64 \]

那么:

Language Token → [64] Robot State Token → [64]

这就给后面的统一 Sequence Modeling 创造了条件。


十二、那 Image 怎么变成 Token?

现在是第三种模态。

一张图:

\[ I\in\mathbb R^{3\times224\times224} \]

Transformer 不适合直接把:

\[ 224\times224 \]

每个像素都当一个 Token。

一种常见思想是:

把图片切成很多小 Patch。

例如 Patch Size:

\[ 16\times16 \]

那么:

\[ 224/16=14 \]

横向 14 个 Patch,

纵向 14 个 Patch。

一共:

\[ 14\times14=196 \]

个 Patch。

于是图片变成:

\[ 196 \]

个视觉位置。


十三、一个 Patch 里面有多少原始数字?

一个 RGB Patch:

\[ 16\times16 \]

每个像素 3 个 Channel。

所以:

\[ 16\times16\times3=768 \]

个数字。

即一个 Patch 原始可以看成:

\[ [768] \]

然后再通过 Linear Projection:

\[ [768]\rightarrow[D] \]

例如:

\[ [768]\rightarrow[64] \]

于是每个 Patch 就变成一个:

\[ [64] \]

Visual Token。

最终:

\[ 196 \]

个 Patch:

\[ [196,64] \]

加入 Batch:

\[ [B,196,64] \]

这就是:

\[ [B,T,D] \]

结构。

只是这里:

\[ T=196 \]

不是时间步,而是:

Visual Patch Sequence Length。


十四、这里非常关键:\(T\) 不一定表示“时间”

上一课我们用:

\[ T \]

表示时间长度。

进入 Transformer 以后,更广义地应该理解成:

Sequence Length

例如 Language:

\[ T=句子Token数 \]

Robot History:

\[ T=时间步数量 \]

Image:

\[ T=Patch数量 \]

所以以后看到:

\[ [B,T,D] \]

不能机械翻译成:

Batch × Time × Dimension。

更准确的是:

\[ \boxed{ Batch \times Sequence \times Feature/Embedding } \]

至于 Sequence 到底是:

  • 时间;
  • 文字;
  • Patch;
  • Action Query;

要根据上下文判断。


十五、图片 Patch 化在代码里可以怎么理解?

教学上可以用 Conv2d 很方便地做 Patch Embedding:

patch_embed = nn.Conv2d( in_channels=3, out_channels=64, kernel_size=16, stride=16)

输入:

\[ image:[B,3,224,224] \]

经过:

x = patch_embed(image)

得到:

\[ [B,64,14,14] \]

为什么?

因为:

\[ 224/16=14 \]

每个 Patch 被映射成 64 维 Feature。

但 Transformer 想要:

\[ [B,T,D] \]

所以还需要把:

\[ 14\times14 \]

展平。

例如:

x = x.flatten(2)

变成:

\[ [B,64,196] \]

再:

x = x.transpose(1, 2)

变成:

\[ [B,196,64] \]

于是:

Image [B,3,224,224] ↓ Patch Embedding [B,64,14,14] ↓ Flatten [B,64,196] ↓ Transpose [B,196,64]

现在:

\[ 196 \]

就是 Visual Token 数量,

\[ 64 \]

就是 Embedding Dimension。


十六、为什么这里要transpose(1,2)?

因为Conv2d输出习惯是:

\[ [B,C,H,W] \]

Patch Embedding 后:

\[ [B,D,H_p,W_p] \]

展平空间后:

\[ [B,D,T] \]

但是 Transformer 常见输入更希望:

\[ [B,T,D] \]

所以需要把第 1 和第 2 维互换:

\[ [B,D,T] \rightarrow [B,T,D] \]

代码:

x = x.transpose(1, 2)

这就是 Tensor Shape 真正服务代码理解的地方。


十七、所以三种完全不同的数据,最后居然能统一

现在我们有:

Language

\[ [B,T_l,D] \]

Robot State

\[ [B,T_s,D] \]

Visual Tokens

\[ [B,T_v,D] \]

注意最后一维全部是:

\[ D \]

于是理论上可以进一步组织成统一 Token Sequence。

例如概念上:

[Visual Token 1] [Visual Token 2] ... [Language Token 1] [Language Token 2] ... [State Token 1] [State Token 2] ...

最后形成:

\[ X\in\mathbb R^{B\times T_{total}\times D} \]

其中:

\[ T_{total} = T_v+T_l+T_s \]

实际模型到底是否这样直接拼接,要看具体架构,不能一概而论。

但是这个思想非常重要:

Transformer 不需要原始输入都是同一种模态,它需要的是这些模态最后都能变成某种 Token Representation。


十八、这就是 Multimodal Transformer 的一个基础思想

原始输入:

Image Language Robot State

差异巨大。

但经过各自 Encoder / Projection:

Image ↓ Visual Tokens Language ↓ Language Tokens Robot State ↓ State Tokens

最后都变成:

\[ D\text{维向量} \]

于是 Transformer 可以对它们进行统一的信息交互。

这也是为什么 VLA 中会频繁看到:

Vision Encoder Language Encoder State Projection Transformer Action Head

十九、但是现在出现一个严重问题:Transformer 怎么知道顺序?

假设两个 Token Sequence:

\[ [A,B,C] \]

和:

\[ [C,B,A] \]

如果每个 Token 只有自己的 Embedding:

A → vector_A B → vector_B C → vector_C

那么模型还缺一个信息:

A 是第 1 个还是第 3 个?

Sequence 的顺序没有自动写在向量里。

所以需要:

Position Information

位置编码。


二十、为什么 Robot Sequence 更需要 Position?

例如:

\[ [s_{t-2},s_{t-1},s_t] \]

如果模型不知道位置,那么:

最早的状态 当前状态 中间状态

之间的时间顺序可能不明确。

但是对 Robot Policy 来说:

\[ s_{t-2}\rightarrow s_{t-1}\rightarrow s_t \]

和:

\[ s_t\rightarrow s_{t-1}\rightarrow s_{t-2} \]

含义完全不同。

所以必须告诉模型:

这是第几个位置。


二十一、最简单的位置 Embedding 思想

假设:

\[ X:[B,T,D] \]

我们准备:

\[ P:[T,D] \]

其中每个位置都有一个 Position Vector:

\[ p_1,p_2,\ldots,p_T \]

然后:

\[ X'=X+P \]

也就是说 Token 自己的内容:

\[ x_t \]

加上:

\[ p_t \]

得到:

\[ x'_t=x_t+p_t \]

于是一个 Token 同时包含:

我是谁? + 我在第几个位置?

二十二、代码里最简单可以怎么写?

例如:

class SimpleSequenceEncoder(nn.Module): def __init__(self, input_dim, d_model, max_len): super().__init__() self.input_proj = nn.Linear(input_dim, d_model) self.pos_embedding = nn.Parameter( torch.randn(max_len, d_model) ) def forward(self, x): x = self.input_proj(x) T = x.shape[1] x = x + self.pos_embedding[:T] return x

假设输入:

\[ x:[32,4,10] \]

第一步:

x = self.input_proj(x)

得到:

\[ [32,4,64] \]

然后:

T = x.shape[1]

此时:

\[ T=4 \]

取:

self.pos_embedding[:4]

Shape:

\[ [4,64] \]

然后:

x = x + self.pos_embedding[:T]

这里利用了 PyTorch Broadcasting:

\[ [32,4,64] + [4,64] \]

得到:

\[ [32,4,64] \]

每个 Batch 都加上同样的位置向量。


二十三、这里第一次自然遇到 Broadcasting

不用展开成 NumPy 大课。

这里只需要理解:

\[ [32,4,64] + [4,64] \]

PyTorch 会把:

\[ [4,64] \]

视为:

对 32 个 Batch 都使用同样的位置编码。

所以不用手工复制 32 份。

最终 Shape 仍然:

\[ [32,4,64] \]


二十四、Position Embedding 是固定的吗?

不一定。

常见方案很多,例如:

  • fixed positional encoding;
  • learned positional embedding;
  • rotary position embedding;
  • relative positional information。

现在不要往旁支扩。

我们当前只需要掌握核心原因:

\[ \boxed{ Transformer本身需要额外获得位置/顺序信息 } \]

具体模型采用哪种 Position Encoding,以后读真实代码再查。


二十五、Token 和 Embedding 最容易混淆在哪里?

必须严格区分:

Token

表示一个序列位置上的“信息单位”。

例如:

一个词片段 一个图像Patch 一个时间步State

Token ID

语言中经常存在。

例如:

\[ 17 \]

只是词表索引。


Embedding

Token 被编码后真正送入 Transformer 的向量:

\[ e_t\in\mathbb R^D \]

所以 Language 中:

\[ Token \rightarrow Token\ ID \rightarrow Embedding \]

而 Robot State 可能直接:

\[ Continuous\ State \rightarrow Linear\ Projection \rightarrow Embedding \]

不一定存在 Token ID。

这一点要分清。


二十六、现在终于可以解释后面 Attention 里的 \(X\)

以后会看到:

\[ Q=XW_Q \]\[ K=XW_K \]\[ V=XW_V \]

那么这里:

\[ X \]

不应该再是一个抽象字母。

它通常可以理解成:

一批已经变成统一 Embedding Dimension 的 Token Sequence。

例如:

\[ X:[B,T,D] \]

其中:

\[ B \]

Batch Size,

\[ T \]

Token / Sequence Length,

\[ D \]

Embedding Dimension。

例如:

\[ X:[32,16,64] \]

意思:

32 个 Sample,每个 Sample 有 16 个 Token,每个 Token 是 64 维向量。

下一课的 Q/K/V 全部从这里出发。


二十七、代码里一个最小“进入 Attention 前”的数据流

现在可以组合成:

class RobotTokenEncoder(nn.Module): def __init__(self): super().__init__() self.state_proj = nn.Linear(10, 64) self.pos_embedding = nn.Parameter( torch.randn(16, 64) ) def forward(self, state): x = self.state_proj(state) T = x.shape[1] x = x + self.pos_embedding[:T] return x

假设:

state.shape

是:

\[ [32,4,10] \]

经过:

x = self.state_proj(state)

得到:

\[ [32,4,64] \]

再加 Position:

\[ [32,4,64] \]

Shape 不变。

于是:

x = encoder(state)

最终:

\[ X:[32,4,64] \]

这已经是一个非常标准的 Transformer Sequence Representation。

下一步就可以:

\[ X \rightarrow Q,K,V \]


二十八、这一课和 ACT 已经有什么联系?

ACT 后面会处理:

  • Robot State;
  • Image Feature;
  • Action Sequence;
  • Transformer;
  • Query;
  • Position Embedding。

如果现在没有建立:

\[ [B,T,D] \]

以及:

\[ Token \rightarrow Embedding \]

和:

\[ Position \]

这些概念,

以后看到 ACT 代码中的:

query_embed pos_embed encoder decoder

就很容易全部混成名词。

所以这一课真正是在给 ACT 搭最后的 Transformer 地基。


第十三课整章链路回看

上一课我们已经得到:

\[ Sequence \]

这一课进一步回答:

Sequence 中每个位置到底用什么形式进入 Transformer?

答案是:

\[ \boxed{ Token\ Representation } \]

语言:

\[ Token\ ID \rightarrow Embedding \]

Robot State:

\[ State \rightarrow Linear\ Projection \]

Image:

\[ Image \rightarrow Patch \rightarrow Visual\ Embedding \]

最终统一得到:

\[ X:[B,T,D] \]

再加入:

\[ Position\ Information \]

告诉模型:

每个 Token 在 Sequence 的哪个位置。

因此下一课终于可以正式开始:

\[ \boxed{ X \rightarrow Q,K,V \rightarrow Attention } \]


第十三课自测

  1. Token 为什么不能简单等同于“单词”?

  2. Language Token ID 为什么不能直接当连续数值输入神经网络?

  3. nn.Embedding(100,64)中的 100 和 64 分别是什么?

  4. 输入 Token ID Shape:

\[ [32,20] \]

经过nn.Embedding(1000,64)后 Shape 是什么?

  1. Robot State:

\[ [32,4,10] \]

经过:

nn.Linear(10,64)

为什么会得到:

\[ [32,4,64] \]

?

  1. 一张:

\[ [3,224,224] \]

图片,如果 Patch Size = 16×16,一共有多少 Patch?

  1. 为什么 Visual Patch 也可以称为 Token?

  2. [B,T,D]中的 \(T\) 为什么不一定表示时间?

  3. 为什么 Transformer 需要 Position Information?

  4. 下面:

x = x + pos_embedding[:T]

为什么通常不会改变:

\[ [B,T,D] \]

的 Shape?

  1. Language、Image、Robot State 原始形式完全不同,为什么最后有可能被同一个 Transformer 处理?

  2. 当下一课写:

\[ Q=XW_Q \]

时,这里的:

\[ X \]

现在应该怎样解释?

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 19:59:56

含电转气、碳捕集与垃圾焚烧的虚拟电厂优化调度MATLAB实现

虚拟电厂优化调度不是新话题,但把电转气、碳捕集和垃圾焚烧放在一起之后,模型的复杂度完全不一样。这段时间我在MATLAB里复现了一套这样的日前优化调度程序,用YALMIP建模、调用MILP求解器求解,今天把建模思路、代码结构和仿真结果…

作者头像 李华
网站建设 2026/10/20 19:59:57

30天速通Linux 第八章多线程编程

学习资料https://pan.baidu.com/s/1NZpC4NyH0OHGOPPbO9J10g?pwdh9m2 提取码: h9m2 一. 多线程概念 进程是资源分配单位,线程是 CPU 调度单位,又叫轻量级进程。同一进程的线程共享地址空间、文件描述符、信号处理等,切换代价远小于进程。Linu…

作者头像 李华
网站建设 2026/10/20 19:59:58

模板代码调试技巧:从行号错位到严格模式完整指南

模板这玩意儿,写得顺手时行云流水,一旦坏掉,很多人当场破防。模板代码调试技巧,我早些年是被行号错位坑到怀疑人生,后来才慢慢摸出一条能复用的路子。这篇文章想把我在实际项目里总结出来的模板调试方法完整讲一遍&…

作者头像 李华
网站建设 2026/10/20 22:08:15

Dos day7

ForeWordHello, everyone. I again meet you in this article, you neednt wait I upgrade passages. In fact, you could study for yourself. And I think you will do better than me. Now!! we start the new war travel!!At First LABEL、MODE、DISKPART、SYSTEMINFO、GPR…

作者头像 李华