0%

在 XGBoost 里,这两个公式其实都会出现,但取决于你说的 base_score 是“原始 margin”还是“概率形式的 base_score”
我帮你把内部机制讲清楚,你就不会再混淆了。


0. 问题:

xgboost内部是: margin = base_score + tree_1(x) + tree_2(x) + ... + tree_N(x) 还是 margin = logit(base_score) + tree_1(x) + tree_2(x) + ... + tree_N(x) ?

最终答案(最重要一句)

XGBoost 内部使用的是:

\[\text{margin} = \text{base\_margin} + \sum_{i=1}^N \text{tree}_i(x)\]

而默认的 base_score(配置项)会先被转换成 logit(base_score),作为初始的 base_margin

也就是说:

内部真正使用的是:

\[ \text{margin} = logit(\text{base\_score}) + \sum_{i=1}^N \text{tree}_i(x) \]

不是直接用 base_score。


✅ 为什么会这样?

1. XGBoost 的树输出的是 margin(logit 空间)

对于二分类(logistic loss),XGBoost 的树不是直接输出概率,而是输出 logit 空间的值

\[\text{margin} = \log \frac{p}{1-p}\]

最终概率是:

\[p = \sigma(\text{margin})\]


2. base_score 是概率,但内部需要 margin

XGBoost 的参数 base_score 默认是 0.5。
但 0.5 是概率,不是 margin。

内部会做:

\[\text{base\_margin} = logit(\text{base\_score})\]

例如:

  • base_score = 0.5
  • logit(0.5) = 0
  • 所以初始 margin = 0

✅ 因此两种写法的关系是:

✅ 用户看到的配置:

1
base_score = 0.5

✅ XGBoost 内部实际使用:

1
base_margin = logit(0.5) = 0

✅ 最终 margin 累加方式:

\[\text{margin} = logit(\text{base\_score}) + \sum \text{tree}_i(x)\]


✅ 总结一句话

XGBoost 内部始终在 margin(logit)空间工作,因此 base_score 会先被 logit 转换,然后再加上所有树的输出。


2. Logit

“logit”这个词听起来有点数学味道,但它本质上就是一种 把概率转换成“对数几率” 的方式。我们一步一步来,你会发现它其实很直观。


🌟 logit 的定义

如果一个事件的概率是 (p),那么它的 logit 定义为:

[ (p) = () ]

这里的
- (p) 是概率(0 到 1 之间)
- () 叫做 odds(几率)
- logit 就是 几率的对数


🌱 为什么要把概率变成 logit?

✅ 1. 概率范围有限(0 到 1),logit 范围无限(-() 到 +())

这对模型非常重要:

  • 概率不能小于 0 或大于 1
  • 但模型(比如线性模型、树模型)输出通常是任意实数

logit 就是一个“桥梁”:

[ p (0,1) (p) (-, +) ]

这样模型可以在实数空间里自由学习,最后再通过 sigmoid 把 logit 转回概率。


✅ 2. logit 是 logistic 回归、XGBoost(二分类)等模型的“内部语言”

这些模型内部都不是直接预测概率,而是预测 margin(logit 值)

最后再用 sigmoid 转成概率:

[ p = () = ]

所以 logit 是概率的“反 sigmoid”。


✅ 3. logit 让模型更容易学习

因为 logit 空间是线性的,概率空间是非线性的。
举个例子:

  • 概率从 0.01 → 0.02,看起来变化很小
  • 但 logit 会告诉你:这是一个很大的相对变化

这对模型训练非常有帮助。


🎯 直观理解(最重要)

你可以把 logit 理解成:

“这个事件发生的可能性比不发生的可能性强多少?”

  • 如果 logit > 0:事件更可能发生
  • 如果 logit = 0:概率 = 0.5
  • 如果 logit < 0:事件更可能不发生

✅ 小例子

概率 p odds = p/(1-p) logit(p) 含义
0.5 1 0 一半一半
0.8 4 1.386 发生的可能性是 4 倍
0.2 0.25 -1.386 不发生的可能性是 4 倍

你会看到 logit 是对称的、线性的,非常适合模型学习。


3. logit、sigmoid、margin、概率之间的完整

当然可以,我给你讲一个从 margin → logit → sigmoid → 概率 的完整闭环,让你彻底理解它们之间的关系。我们不用画图,我用一种“像图一样”的结构来呈现,你会一眼看懂。


整体流程图(最重要)

1
2
3
4
5
6
7
8
9
10
  (模型输出)


margin
(任意实数值)

│ sigmoid = 1 / (1 + e^-x)

probability
(0 到 1 之间的概率)

而 logit 是 sigmoid 的反函数:

1
2
probability  --logit-->  margin
margin --sigmoid--> probability

也就是说:

  • sigmoid:把 margin 转成概率
  • logit:把概率转回 margin

它们是一对互逆函数。


✅ 1. margin 是什么?

margin 是模型内部的“原始输出”,可以是任意实数:

  • 可能是线性模型的输出
  • 可能是 XGBoost 所有树的累加
  • 可能是神经网络最后一层的 logit

margin 没有概率意义,它只是一个“分数”。


✅ 2. logit 是什么?

logit 是把概率 (p) 转成 margin 的函数:

[ (p) = () ]

它把:

  • (p (0,1)) 映射到
  • margin ((-, +))

这是模型训练的空间。


✅ 3. sigmoid 是什么?

sigmoid 是 logit 的反函数:

[ p = () = ]

它把:

  • margin(任意实数)
  • 转成概率(0 到 1)

✅ 4. 它们之间的关系(像图一样)

我给你画一个“完整闭环”:

1
2
3
4
5
6
7
8
9
概率 p

│ logit(p) = log(p/(1-p))

margin(模型内部使用)

│ sigmoid(margin) = 1/(1+e^-margin)

概率 p

你会看到:

  • logit:概率 → margin
  • sigmoid:margin → 概率

它们互相反转。


✅ 5. 为什么模型要用 margin 而不是直接预测概率?

因为:

  • 概率只能在 0 到 1 之间
  • margin 可以是任意实数,更适合模型学习
  • sigmoid 可以把 margin 平滑地映射成概率
  • logit 可以把概率映射回 margin,方便计算梯度

这就是为什么:

  • 逻辑回归内部用 margin
  • XGBoost(二分类)内部用 margin
  • 神经网络最后一层输出 margin(logits)

✅ 6. 用一个例子串起来

假设模型输出 margin = 2:

1
2
margin = 2
prob = sigmoid(2) = 0.88

如果你反过来:

1
logit(0.88) = 2

完全对应。


✅ 总结一句话

margin 是模型的内部语言,sigmoid 和 logit 是 margin 与概率之间的翻译器。

这个问题问得特别关键,因为它触到了 XGBoost 的本质设计哲学
一句话先给你定个基调:

XGBoost 的树输出 margin(对数几率),而不是概率,是因为 margin 空间更适合做梯度优化、二阶近似和树的加法模型。

下面我把原因拆成几个层次,让你从直觉到数学都能完全理解。


✅ 1. 树模型是“加法模型”,概率不能直接相加

XGBoost 的模型结构是:

[ f(x) = _{k=1}^K f_k(x) ]

每棵树输出一个值,然后全部相加。

但概率不能相加:

  • 0.6 + 0.7 = 1.3(无意义)
  • 概率必须在 0 到 1 之间

margin(logit)可以是任意实数,非常适合做加法:

  • 1.2 + (-0.5) + 0.8 = 1.5(完全合法)

所以:

树必须输出 margin,因为 margin 是可加的。


✅ 2. logistic loss 的梯度和二阶导数是在 margin 空间定义的

二分类的损失函数是:

[ L = -[yp + (1-y)(1-p)] ]

但训练时不会直接对概率 (p) 求导,而是对 margin (z) 求导:

[ p = (z) ]

梯度和 Hessian 是:

[ g = p - y ] [ h = p(1-p) ]

这些都是 margin 的函数。

也就是说:

XGBoost 的优化过程完全发生在 margin 空间,而不是概率空间。

如果树输出概率,梯度和 Hessian 都没法正确计算。


✅ 3. margin 空间是线性的,概率空间是非线性的

sigmoid 是一个 S 型函数:

  • 中间变化快
  • 两端变化慢

如果直接在概率空间优化:

  • 梯度会在两端消失(梯度消失问题)
  • 模型难以学习

但 margin 空间是线性的:

  • 变化均匀
  • 梯度稳定
  • 更适合二阶优化(XGBoost 的核心)

所以:

margin 空间更适合优化,概率空间不适合。


✅ 4. margin + sigmoid = 概率(训练和预测分工明确)

训练阶段:

  • 树输出 margin
  • margin 用来计算梯度和 Hessian
  • margin 之间可以相加

预测阶段:

  • 最终 margin 通过 sigmoid 转成概率

[ p = () ]

这种分工非常清晰:

  • 训练:margin 空间(线性、可加、可优化)
  • 预测:概率空间(可解释)

✅ 5. 逻辑回归、神经网络也都输出 margin(logits)

你会发现:

  • 逻辑回归输出 logit
  • 神经网络最后一层输出 logits
  • XGBoost 输出 margin

它们都遵循同一个原则:

模型内部在 logit 空间工作,最后用 sigmoid 转成概率。

这是整个机器学习领域的通用做法。


✅ 6. 一个直观例子让你彻底理解

假设模型已经训练了两棵树:

  • tree1 输出 0.8
  • tree2 输出 -0.3

margin = 0.5
prob = sigmoid(0.5) ≈ 0.62

如果树输出概率:

  • 0.7 + 0.8 = 1.5(无意义)
  • 你无法再用 sigmoid 转概率
  • 也无法计算梯度

所以树必须输出 margin。


✅ ✅ 总结一句话(最核心)

XGBoost 的树输出 margin,是因为 margin 是可加的、可优化的、梯度稳定的,而概率不是。


如果你愿意,我可以再帮你画一张 “XGBoost 二分类内部流程图”,把 base_score、logit、margin、树输出、sigmoid 全部串起来,会非常清晰。

residual explain

residual explain
some notes from this video

神经网络初始化时,权重是随机的 —— 每一层的权重矩阵都是随机生成的。
前向传播时,输入数据经过每一层都会被随机的权重矩阵变换,换句话说:输入信号在每一层都被“打乱”一次。
如果层数很深(比如几十层),输入数据就会被这些随机变换一遍又一遍,到了最后一层时,输出结果几乎不再携带原始输入的“有效信息” —— 变成了一堆“随机激活”(noise)。
这就像把一个信号通过几十个带随机旋转的transpose处理之后,最后剩下的根本不知道是什么。
我们可以说:原始输入被“扰乱”成了随机噪声。这种情况下,模型的输出和输入几乎没有实际联系。
训练时,我们计算 loss,并进行反向传播(backpropagation)以更新权重。
反向传播的梯度来源于输出误差,但如果输出本身已经是“随机激活”,那这个误差根本不能反映输入的真实特征,所以它对靠后的几层的更新意义也不大。
在反向传播过程中,每一层的梯度也会被它的权重矩阵(也就是在前向传播时使用的那个)反向变换。因为这些矩阵是随机的,所以:
梯度回传到早期层时,已经被多层的随机变换“扰乱”梯度本身也变得和数据无关了
后面的层(靠近输出)的输入是随机的,因此即使我们对它们做了梯度更新,也是在优化一些“无意义的东西”——所以这个更新 “不是很有意义”(not very meaningful)。
早期层的输入其实还比较接近原始输入,但 梯度本身已经被“污染”了,所以即使这些层“想学”,也无法从错误中获得有效信息。
这就解释了为什么深层网络在训练初期进展缓慢,甚至基本不学习 —— 因为梯度下降没有清晰的方向,就像“在黑夜里瞎走”。

  • 对于后面的层,它们的输入已经像噪声,所以即使 loss 传回来,更新的目标本身就没什么意义
  • 对于前面的层,它们的输入还比较“干净”,但传回来的梯度已经乱掉了,更新的方向也没有意义
  • 所以,这些更新不是完全错误,而是无效、低效、方向性差,因此叫 “not very meaningful”

gradient 和 weight的关系

在两层神经网络中,反向传播(Backpropagation) 的目的是计算损失函数关于每一层权重(weights)的梯度,用于更新权重。
下面步步说明梯度是如何与权重相关联的。

假设一个简单的两层神经网络结构:

网络结构:

输入 → 第一层(Linear + Activation) → 第二层(Linear) → 输出(Loss)

  • 输入:$\mathbf{x} \in \mathbb{R}^d$
  • 第一层权重:$\mathbf{W}_1 \in \mathbb{R}^{h \times d}$,偏置:$\mathbf{b}_1 \in \mathbb{R}^h$
  • 激活函数:ReLU 或 Sigmoid(记为 $f$)
  • 第二层权重:$\mathbf{W}_2 \in \mathbb{R}^{o \times h}$,偏置:$\mathbf{b}_2 \in \mathbb{R}^o$
  • 输出层无激活(或直接用 MSE)
Read more »

Bonus 架构图 (现代 Function Calling Agent 流程)

1
2
3
4
5
6
7
8
9
10
11
User Input

Embedding Model ───────→ 语义索引 (FAISS / Qdrant / Weaviate)

Top-K Function Candidates

Inject into Prompt as JSON Schema

LLM 生成 Function Call

调用工具 / API + 结构校验 + 反馈

MCP server 流程图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
               +-------------+
| MCP Client |
+------+-----+
|
| submit task / query result
v
+------+------+
| MCP Server |
+------+------+
|
+--------------+---------------+
| |
v v
+-------------+ +---------------+
| Agent 1 | | Agent 2 |
+-------------+ +---------------+
| ^ | ^
| | Task Execution | | Task Execution
+---+--------------------------+---+

build GPT from scratch

cross_entropy 损失函数估计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class BigramLanguageModel(nn.Module):
……
def forward(self, idx, targets=None):
B, T, C = logits.shape
logits = logits.view(B*T, C)
targets = targets.view(B*T)
loss = F.cross_entropy(logits, targets)

m = BigramLanguageModel(vocab_size)
logits, loss = m(xb, yb)
print(logits.shape)
print(loss)

# output
torch.Size([32, 65])
tensor(4.8786, grad_fn=<NllLossBackward0>)
1
loss = F.cross_entropy(logits, targets)

其实计算的是

其中:

$p$ 是 softmax 后的概率分布
$y$ 是 ground-truth label (目标token)
$p_y$ 是对应ground-truth 类别的概率

对于这个Loss如果我们想估计一下是什么水平,那就对比随机猜的情况,,这个可以作为baseline

Read more »

Layer Normalization

验证LayerNorm的,通过使用torch.mean和torch.var复现的时候发现不一致
LayerNorm默认使用的是bias的整体方差, divided by N
torch.var默认使用的是无bias的样本方差, devided by N-1

对于每一个样本的特征向量 $x \in \mathbb{R}^d$ ,LayerNorm 执行以下操作:

  • $\mu, \sigma^2$ :当前样本的均值和方差(仅用于归一化)
  • $\gamma$ :可学习的缩放参数(scale,类似于权重)
  • $\beta$ :可学习的偏移参数(bias,偏置)

LayerNomr

Read more »

linear regession 或者mpl 会涉及到weight decay, 提及整数解的问题:
k个变量,d阶的项一共有多少种?

问题描述
我们有 $ k $ 个变量 $ x_1, x_2, \ldots, x_k $,要求它们的和等于 $ d $,即:

$ x_1 + x_2 + \cdots + x_k = d $

自然数解

从 ( d - 1 ) 个位置中选择 ( k - 1 ) 个位置放置隔板,其余的位置放置星星。

这可以用组合数表示为:

$ \binom{d - 1}{k - 1} = \frac{(d - 1)!}{(k - 1)! \cdot (d - k)!} $

非负整数解

在这个问题中,每个变量 $ x_i $ 可以取0。这意味着在分配过程中,某些变量可能不会获得任何单位。因此,为了表示这种情况,我们需要在星(单位)之间允许隔板(分隔符)彼此相邻,甚至位于首尾位置。这就增加了排列组合的灵活性。

Read more »

通过pandas 的compare function, 可以对比两个csv 文件
用途,例如升级或修改code之后,输出是csv文本文件,对于同样input的数据,预期应该一样
input -> program -> output
input -> program(optimize) -> output_new
expect output == output_new

Read more »

安装

64-bit镜像:
https://downloads.raspberrypi.org/raspios_lite_arm64/images/raspios_lite_arm64-2021-05-28/

获取树莓派ip

树莓派在接入路由器后是动态分配的,需要使用路由器的管理界面查看链接设备的MAC和ip地址
另外一种方式是扫描当前局域网的设备信息,比如可以使用IOS的Fing App去发现当前连接设备,一般树莓派的设备名称是Raspberry开头的

挂载移动硬盘

https://shumeipai.nxez.com/2013/09/08/raspberry-pi-to-mount-the-removable-hard-disk.html

1
sudo mount -o uid=pi,gid=pi /dev/sda1 /mnt/1GB_USB_flash
Read more »

YOLO

1. YOLO 损失函数第二部分

对于width, height的loss, 作者在论文中说明使用square root的原因:

Our error metric should reflect that small deviations in large boxes matter less than in small boxes. To partially address this we predict the square root of the bounding box width and height instead of the width and height directly.
经过实际计算演示如下:

1
2
3
4
5
6
def width_height_loss(w, h, error_shift=30):
return math.pow((math.sqrt(w)-math.sqrt(w-erro_shift)),2) + math.pow((math.sqrt(h)-math.sqrt(h+erro_shift)),2)
print(width_height_loss(300,500))
print(width_height_loss(100,150))
>> 1.22700707099
>> 4.03446019009

可以发现如此设计后,确实能起到如其所说loss对小的bbox比较敏感,惩罚度较大,而对大bbbox则反之。
究其原因,需要画一下此函数的曲线:

从曲线可以直观的看到单调性

Read more »