news 2026/10/17 2:24:19

Focal Loss原理与实现:解决目标检测类别不平衡与难样本加权

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Focal Loss原理与实现:解决目标检测类别不平衡与难样本加权

把 Focal Loss 论文重新翻出来读了一遍,距离第一次看已经有好几年。当年为了赶实验,只急着把它塞进检测代码里调参,后来手头项目一忙就放下了;这次趁着空闲把公式从头推了一遍,又对着论文里的实验表格逐行看,才发现很多当年踩过的坑,答案其实都写在论文的细节里,只是当时的自己读得太糙。这篇被广泛称作 RetinaNet 的论文,核心贡献可以拆成两件事:第一,用 Focal Loss 解决密集目标检测中极端类别不平衡的问题;第二,配合特征金字塔网络(FPN)把单阶段检测器的精度拉升了一个档次。如果你正在被正负样本比例失衡搞得训练不稳定,或者在目标检测、长尾分类的任务里琢磨怎么给难样本加权重,这篇学习笔记应该能给你一些落到实处的参考。我不只讲公式结论,还会把推导过程、实现细节、复现时容易踩的坑一并写出来。

1. 为什么密集检测器会被类别不平衡卡死

1.1 一阶段与两阶段检测器在样本分布上的差异

目标检测里"一阶段"和"两阶段"的争论,表面上是精度与速度的取舍,但本质差别在于拿到手的训练样本分布完全不同。

两阶段检测器(比如经典的"先提区域再分类"路线)在第一阶段用区域提案网络先把可能有目标的区域筛出来,第二阶段再对这些区域做精细分类和回归。这个流程里,第二阶段拿到的候选区域数量是可控的,常见做法是每张图采样 256 或 512 个 proposal,并且强制保证正负样本比例在 1:3 左右。也就是说,两阶段检测器在训练阶段已经把最难缠的"海量背景"问题压住了。

一阶段检测器就没有这个缓冲。它直接在整张图的密集网格上预测,以常见的 anchor 方式为例,输入一张 800 像素左右的图,经过多层特征金字塔后,产生的 anchor 数量经常是十万甚至更多。而一张图里的真实目标通常只有几个到几十个,算下来正负样本比例随便就达到 1:1000。你可以把训练过程想象成一场课堂考试:布置了一万道一眼就会的送分题,真正有区分度的难题只有几十道,如果总分主要由送分题决定,那无论你难题怎么答,最后排名都差不多。

如果这里只靠随机抽样把负样本数量压下来,场景会变好一些吗?有一定作用,但随即带来的问题是抽样不固定、模型对不同场景的负样本覆盖不充分,而且你没法保证抽出来的负样本就有代表性。论文作者当时盯住的就是这种结构性问题:一阶段想保持快速,就必须在密集预测的框架下找到一种让"大部分简单负样本不那么影响训练"的办法。

1.2 简单负样本才是真正的"梯度刺客"

很多人以为类别不平衡的麻烦主要来自正样本太少、负样本太多,于是第一时间想"给负样本降个权不就行了"。但 Focal Loss 论文里的分析更细一层:真正的问题不只是负样本数量多,而是负样本里有大量"已经被正确分类、且非常确信"的简单样本。

用交叉熵损失训练时,一个预测置信度很高的简单负样本(比如 p_t = 0.9),单个样本的 loss 只有 0.1 出头;但十万个这样的样本加起来,贡献出的梯度绝对量非常大。相比之下,一个真正难分的样本(比如 p_t = 0.5,模棱两可),单个 loss 是 0.69,数量又少。于是在最后一次梯度累加时,简单负样本的权重通过“数量优势”完全压制了难样本和正样本,模型就被带偏了。

这种"简单样本压制难样本"的现象,普通样本均衡的数据集里也有,但没那么致命。一旦到了密集目标检测这种极端不平衡场景,就变成主要矛盾。论文的高明之处在于:不抛弃任何样本,不显式采样,而是用一条连续的曲线把每个样本的贡献按"难度"重新分配——这正是 Focal Loss 的思路起点。

2. 从交叉熵一步步走到 Focal Loss

2.1 交叉熵的符号问题与 p_t 的提法

为了把公式的来历讲清楚,先把二分类交叉熵写出来。对于一个真实标签 y(1 或 0),模型对正类的预测概率为 p,交叉熵可以写成:

CE(p, y) = -log(p),当 y=1
CE(p, y) = -log(1-p),当 y=0

在目标检测里,很多时候用 sigmoid 对每个 anchor 做独立二分类,也就是多标签的形式。为了方便统一,论文引入一个记号 p_t:

p_t = p,当 y=1 时
p_t = 1-p,当 y=0 时

这样一来,交叉熵就成了一句话:CE(p_t) = -log(p_t)。p_t 越接近 1,说明模型对这个样本越有把握,分类越"简单";p_t 越小,说明模型越犹豫或直接错了,样本越"难"。

我一开始不太习惯这个记号,总觉得它就是换了个写法。后来发现,p_t 是理解 Focal Loss 的一把钥匙,因为后面整个调制因子都建立在 p_t 之上,而不是建立在模型原始输出 p 上。如果你拿着 p 而不是 p_t 去算,很容易在正负样本上写出两个分支,公式就变得啰嗦。

2.2 关键一步:给每个样本加上难度调制因子

交叉熵的问题是"一视同仁":不管 p_t 是 0.9 还是 0.5,每个样本按自己的 loss 参与求和,简单样本靠数量获胜。Focal Loss 做的改动只有一处,却非常关键:在交叉熵前面乘一个调制因子:

FL(p_t) = -(1 - p_t)^γ * log(p_t)

这里 γ 是聚焦参数(focal parameter),通常取 2。拆开看这个调制因子 (1-p_t)^γ:

  • 当 p_t 很接近 1,比如 0.9,(1-0.9)^2 = 0.01,原来 0.1 的 loss 被压到 0.001。简单样本的贡献被大幅削减。
  • 当 p_t 在 0.5 附近,(1-0.5)^2 = 0.25,loss 从 0.69 变成约 0.17。中等难度的样本保留了一部分。
  • 当 p_t 很小,比如 0.1,也就是模型把正类分得很糟,(1-0.1)^2 = 0.81,loss 从 2.3 变成约 1.87。难样本几乎原样保留。

也就是说,这个因子像一个"难度筛子",自动把训练焦点从堆积如山的简单背景转移到少数难样本上。关键是这个筛子不是硬性的丢与不丢,而是连续且可微的,所以整个模型依然能用标准反向传播训练,不需要额外设计样本选择逻辑。

为什么 γ=2 而不是 γ=1 或者 γ=0?γ=0 时 Focal Loss 退化成普通交叉熵;γ 越大,简单样本被压得越狠,但难样本的权重并没有无限放大,因为 (1-p_t)^γ 对难样本趋近 1,只是保留,不放大。到 γ=5 的时候,作者观察到简单样本几乎不提供梯度,训练变得困难,AP 反而下降。你可以在自己的数据上从 γ=2 起步,然后往 1 和 3 两边试。

2.3 α-balanced 变体:把类别权重和难度权重解耦

只看调制因子的话,它只调整了难易程度,并没有处理正负类别数量本身的不平衡。Focal Loss 里还有一个经常被人忽略的配套项:α-balanced 版本:

FL(p_t) = -α_t * (1 - p_t)^γ * log(p_t)

其中 α_t 是一个与类别相关的权重:正样本用 α,负样本用 1-α。论文里建议 α=0.25、γ=2 组合效果最好。α 负责"正负类别的数量差异",γ 负责"简单难样本的权重差异",两个维度是正交的,最好不要混着说。

为什么有了 γ 还需要 α?因为调制因子只改变难易样本之间的相对权重,没有改变正负类别之间的总体比例。同一难度下,负样本基数依然可能是正样本的上百倍;不引入 α 的话,整体梯度依然会偏向负样本方向。论文实验里只调 γ 不调 α,或者只调 α 不调 γ,效果都不如两个一起用。这一点我在复现的时候也验证过,单独把 γ 拉到 2 不加 α 时,检测 AP 会低一些,尤其是小物体那一栏掉得明显。

2.4 看一个数值例子就全明白了

口说无凭,我列一个简单的数值表,假设 γ=2、α=1,也就是先不看 α 的版本:

样本类型p_t 值CE 损失调制因子 (1-p_t)^2Focal Loss 值直观结论
简单背景0.90.1050.010.001损失被压到几乎不贡献
中等样本0.50.6930.250.173损失保留约 25%
困难正样本0.12.3030.811.865损失几乎原样保留

看到这个表就明白 Focal Loss 为什么能稳定压制简单负样本了:它不是把负样本删掉,而是让它们在梯度求和里的发言权指数级下降。这样即使负样本数量是正样本的几百倍,只要大部分负样本已经学得好、p_t 高,它们就不会再继续霸占梯度。

反过来也说明一个实际问题:如果训练初期所有样本都还没分好,p_t 普遍不高,那 Focal Loss 的压制效应还体现不出来,loss 会显得很高。这不是 bug,而是因为调制因子的目标是"学得好的别再抢戏",而不是"一开始就把总 loss 压低"。很多第一次用的人看训练曲线大跌眼镜,以为模型坏了,其实是没理解这个动态特性。

2.5 手写一个 PyTorch 实现

理解了公式之后,写实现就是水到渠成的事。下面是一个贴合论文公式的 PyTorch 版本,我习惯把它封装成函数,方便在训练循环里直接调用:

import torch import torch.nn.functional as F def focal_loss(logits, targets, alpha=0.25, gamma=2.0): # logits: [N, num_classes],targets: one-hot 或 float 标签 [N, num_classes] ce = F.binary_cross_entropy_with_logits(logits, targets, reduction="none") p = torch.sigmoid(logits) # p_t: 正样本取 p,负样本取 1-p p_t = p * targets + (1 - p) * (1 - targets) # alpha_t: 正样本用 alpha,负样本用 1-alpha alpha_t = alpha * targets + (1 - alpha) * (1 - targets) # focal weight focal_weight = (1 - p_t) ** gamma loss = alpha_t * focal_weight * ce return loss.mean()

有几个实现细节说明一下:这里用binary_cross_entropy_with_logits,因为分类子网络输出的是未过 sigmoid 的 logits,直接在 loss 里做 sigmoid 更稳定。targets我传的是与 logits 形状一致的 one-hot 浮点数,因为检测任务中一个 anchor 只分配一个类别,但训练时也可以用多标签。真正要小心的是 loss 的归一化:很多开源实现不会直接把所有样本的 focal loss 求平均,而是只除以正样本的数量,这样能避免负样本数量影响 loss 的绝对值尺度。上面的代码为了演示简洁用了 mean,实际项目里建议参考检测框架的归一化方式,按正样本数归一化。

3. RetinaNet 里那些容易忽略的实现细节

3.1 架构:FPN 负责定位"在哪里看",分类子网络负责"看到什么"

Focal Loss 不是一个孤立技巧,它是嵌在 RetinaNet 整个框架里起作用的。RetinaNet 的结构可以拆成三块:一个主干网络提取特征,一个特征金字塔网络(FPN)输出多层不同尺度的特征图,两个任务子网络分别做分类和回归。

FPN 在这里很重要,因为密集检测要在多种尺度下进行。RetinaNet 用 P3 到 P7 五层金字塔,每层 anchor 的尺度从 32×32 到 512×512,基本覆盖了从小到大各种目标。如果没有 FPN,只靠最后一层高层特征做检测,小目标定位信息早就被下采样丢光了,Focal Loss 再厉害也救不回来。

分类子网络的设计也值得留意:它不是把特征图拉平后过一个全连接,而是用一组小卷积,一层一层把语义信息抽出来。具体来说,分类塔用 4 个 3×3 卷积,输出通道保持 256,最后再用一个 3×3 卷积输出 K×A 个分数,K 是类别数,A 是每个位置的 anchor 数量。论文里所有分类都用 sigmoid,不用 softmax。我一开始觉得奇怪:常规分类不都应该 softmax 吗?但在密集检测的多标签场景下,sigmoid 更合理,因为一个位置上的几个 anchor 可能属于不同类别,而且 sigmoid 对每个类别独立建模,训练效率也更高。

3.2 分类分支的 bias 初始化,其实比想象中重要

这是我复现时吃了大亏的一个细节。论文里专门提了一句:分类子网络的最后一层卷积,bias 要初始化成:

b = -log((1 - π) / π)

其中 π = 0.01。算一下就知道 b 大概是 -4.595。这么做的目的是让训练刚开始的每个 anchor 都被预测为"背景"的概率接近 0.99,也就是 p_t 接近 0.99,Focal Loss 的调制因子一开始就处于强压低状态。

如果不做这个初始化,训练第一个 step 的损失可能高到离谱,梯度从一堆还没分清的样本上涌入,前几百步训练会非常不稳定。我踩过的坑是:当时偷懒没设置 bias,结果 loss 前期震荡剧烈,后来 AP 一直上不去。最初我还以为是学习率的问题,后来对照论文才发现是分类头初始预测置信度太中立,导致每一轮都有海量背景样本参与梯度计算,把优化方向搅乱了。

这个初始化技巧其实暴露了 Focal Loss 的一个特性:它是一个"训练动态相关"的损失。样本权重不是固定的,而是随着模型当前置信度变化。因此初始化状态会影响后续所有样本的权重分配,不能只顾着把网络结构搭出来,分类分支的起点也要符合整体设计。

3.3 Anchor 与匹配规则

RetinaNet 的 anchor 设计是:金字塔的每一层都使用 9 个 anchor,即 3 个尺度(scale)乘以 3 个长宽比(ratio),长宽比通常取 1:2、1:1、2:1。不同金字塔层级对应不同基础尺度,这样同一张图的候选框能够覆盖各种大小的目标。

正负样本的分配规则在论文里用的是 IoU 阈值:和某个真实目标 IoU 超过 0.5 的 anchor 算正样本;与所有真实目标 IoU 都低于 0.4 的算负样本;落在 0.4 到 0.5 之间的不参与训练。这个“灰色地带”很关键,因为这些 anchor 说它是正也不是、说负也不是,强行分配只会给训练塞噪声。很多复现效果差的代码库就是没有仔细处理这个区间,把 0.4-0.5 都当负样本来算,结果引入大量边界模糊样本,Focal Loss 反而被这些难样本带偏。

与两阶段检测器不同,RetinaNet 不会强制限制每张图正负样本的比例,而是靠 Focal Loss 来自动调节贡献。所以 anchor 匹配规则对最终效果的影响比想象中更大:正样本太苛刻,就会造成匹配不上的目标对模型完全不可见;负样本太宽,又会让灰色地带的难样本大量涌入。建议复现时先按论文的 0.5/0.4 来,不要凭感觉改。

3.4 训练超参和实验效果

论文里的实验配置大致是这样的:主干网络用 ResNet-50 或 ResNet-101,前面接 FPN;输入图像缩放到最短边 800、最长边不超过 1333;SGD 优化器,momentum 0.9,weight decay 0.0001,初始学习率 0.01,batch size 16 左右,训练步数在 90k 步上下。分类和回归两个子网络共享 FPN 特征,但各自保持独立权重。

关于实验结果,我记得读论文时对比表里印象最深的一组:当时的单阶段检测器在公开检测数据集上的 AP 普遍在 30 上下,而 RetinaNet 用 ResNet-101 当骨干时,AP 能到 39 附近,跨过了一段不小的精度鸿沟,甚至能跟许多两阶段检测器打平或更好。这里不要拿我记忆里的数字当标准答案,不同输入尺度和训练设置下会有浮动,但趋势是确定的:引入 Focal Loss 之后,单阶段检测器从"速度快但精度差"变成了"速度和精度都能打"。

3.5 γ 的选择:效果最好的是 2,不是 5

论文里专门做了 γ 的消融实验,从 0 扫到 5,结论是 γ=2 时 AP 最高。γ=0 就是普通的 α-balanced 交叉熵,相当于没加调制因子;γ=1 能压低一部分简单样本,但对那些已经很确信的背景样本压得不到位;γ=5 时简单样本几乎完全不贡献梯度,好处是难样本主导训练,坏处是模型容易被个别标注错误或者极其难分的样本牵着走,AP 反而下降。

这个趋势在不同数据集上会有细微差异,但我建议调参时把 γ 当作“注意力强度”来理解:太小,模型注意力分散,简单背景仍然参与度高;太大,注意力过于集中,模型可能钻牛角尖。我自己试下来,γ=2 对大多数检测任务都是个稳定起点,α 可以优先试 0.25,然后根据结果微调。

4. Focal Loss 与其他困难样本方法的关系

4.1 OHEM 是硬挖,Focal Loss 是软加权

在读 Focal Loss 论文之前,我最熟悉的困难样本处理方法是 OHEM(在线困难样本挖掘)。OHEM 的思路很直接:计算完一轮 loss 之后,把所有样本按 loss 从大到小排序,只挑出 loss 最高的那部分样本做反向传播,其余样本的梯度直接置零。这样模型每轮都只看最难的样本。

OHEM 和 Focal Loss 的目的一致,但实现哲学完全不同。OHEM 是一个离散的选择过程:样本要么被选中、梯度完整计算,要么被丢弃、梯度为零。Focal Loss 则是连续的:每个样本都保留,只是根据难度乘上一个 0 到 1 之间的系数。换句话说,Focal Loss 可以看作 OHEM 的一个光滑近似,它把"前 k 个"的硬阈值换成了"按难度衰减"的软权重。

这种连续性带来的好处是训练过程平稳。OHEM 在样本排序边界附近会有突然的梯度跳变,而且一旦某一轮选中的难样本存在标注噪声,整个更新方向很容易被带歪。Focal Loss 给难样本的权重虽然大,但不是非 0 即 1,对噪声的耐受性要好一些。论文里对比过这种做法在密集检测框架里的效果,OHEM 在区域提案式的检测器里有效,但直接搬到密集预测框架里,AP 提升有限,Focal Loss 提升明显得多。

4.2 与常规类别加权、负样本降采样的区别

还有一种常见的做法是给正负样本分配不同权重,比如正样本权重设为负样本的 3 倍。这解决的是类别数量不平衡,但解决不了简单样本数量优势的问题。你可以做这样一个思想实验:即使把负样本总权重压到和正样本一个量级,这堆权重还是会被几万个简单负样本瓜分,每个简单负样本依然分到一点梯度;模型觉得"反正我大体分对了,没必要专门去改那些少数难样本"。

负样本随机降采样也有类似局限。降采样把负样本总数砍下来之后,难样本占比会相对提高,但采样的随机性意味着很多有难度的负样本可能压根没被采到,模型没见过,自然学不好。Focal Loss 不采样,它让全部样本都参与前向计算,只是反向传播时给梯度按难度重新分配。听起来是一个很小的差别,实际操作上却省去了很多调采样比例的麻烦。

4.3 出了目标检测,它还能用在哪

Focal Loss 的设计并不绑定目标检测,只要任务面临"极度不平衡 + 大量简单样本"就可以尝试。比如长尾图像分类里,头部类别样本多、尾部类别样本少,直接用交叉熵训练很容易让尾部类别被忽略,这时候给每个样本按置信度加调制因子,模型就会把注意力往尾部类别转移。

语义分割里也有类似的例子:图像中一个小目标区域可能只占几个像素,但背景像素占了绝大部分。把 Focal Loss 用在分割的像素级分类头上,能让模型更关注那些难分的边缘像素和稀少类别。我在自己的模拟实验里也验证过,Focal Loss 对识别小目标的 recall 提升立竿见影,但也要注意它会让错误标注的样本权重变大,标注质量差的数据集上要谨慎。

5. 复现过程中的常见问题与排查心得

5.1 如果损失贴地但 AP 上不去,先看 bias 初始化

复现 Focal Loss 时最诡异的现象之一是:训练 loss 收敛得很漂亮,曲线一路下降,但验证集 AP 就是上不去。这种情况多半不是 Focal Loss 本身的问题,而是分类分支的初始化或正负样本匹配有问题。

先说 bias 初始化。如果没有把分类头的 bias 设成 -log((1-0.01)/0.01),训练初期模型对所有 anchor 的初始置信度就是 0.5 上下,Focal Loss 的调制因子都是 0.25 左右的中间值,简单背景和难样本权重没有拉开,等于 Focal Loss 没有进入预期的“压制简单样本”状态。虽然训练后期模型自己也会慢慢调整,但前期优化轨迹已经偏了,最终 AP 会差一截。

再说 anchor 匹配。检查一下你的代码里,灰色地带(IoU 在 0.4 到 0.5 之间)的 anchor 是被正确忽略了,还是被错误地归为负样本。如果错误归为负样本,这些既有点目标影子又算背景的 anchor 一开始 p_t 就低,Focal Loss 会给它们很大的权重,模型花大量精力去学这些模糊样本,干净的正样本反而被冷落。这两处是我最常踩的坑。

5.2 γ 和 α 的手感:我调参的一些经验

先记住一个原则:γ 调难度权重,α 调类别权重,不要同时大改。我一般先固定 γ=2、α=0.25 复现出论文量级的基线,然后再单变量地去调。

如果 γ 调大后发现 loss 曲线波动剧烈,就看是不是难样本里有太多标注噪声。因为 γ 越大,模型越盯着 p_t 小的样本,而这些样本里很可能混着边界模糊的 anchor。一个可行的缓解方式是把 γ 退回 1.5 或者搭配更严格的 anchor 匹配阈值,把模糊负样本挡在训练之外。

α 的手感更直接:如果检测结果里漏检多(正样本拉不起来),试着把 α 从 0.25 调向 0.5,给正样本更高权重;如果误检多(负样本压制不住),就调向 0.1 或 0.15。但注意 α 和 γ 有轻微耦合,α=0.25 之所以是论文推荐值,是因为它在公开的密集检测场景下平衡得比较好,你的数据分布跟它差别大时,最好做个小网格搜索。

5.3 有关 Loss 数值和收敛曲线的几个盲区

用 Focal Loss 之后,训练 loss 的绝对数值会比交叉熵低很多,这是正常的,别一看到 loss 变低就觉得模型变好。因为调制因子把大量简单样本的贡献压到了 0.001 量级,总 loss 自然好看,但你要关注的是验证集上的 AP 或精确率召回率,而不是 loss 大小。

还有一个盲区是:Focal Loss 对正样本的贡献几乎是“全程保护”的,但正样本数量太少的时候,即便权重很高,梯度也扛不住海量负样本的总体量。这时候除了调 α,还要检查是不是 anchor 匹配阈值太严、正样本太少,或者 FPN 某些层没有分配到正样本(常见于小物体层)。我习惯在训练时打印每个金字塔层级的正样本数量,一旦发现某层长期为 0,首先怀疑 anchor 尺度设置和真实目标尺寸分布不匹配。

5.4 一个建议的调试清单

我把排查经验整理成一张表,方便你对照:

现象优先检查项建议动作
训练初期 loss 爆炸或震荡分类头 bias 初始化b = -log((1-0.01)/0.01)
loss 很低但 AP 不高anchor 匹配阈值、灰色地带处理确认 IoU>0.5 为正,<0.4 为负,中间忽略
漏检严重α 过小、正样本太少α 从 0.25 上调,检查每层正样本数
误检严重α 过大、γ 过小α 下调,γ 上调到 2 左右
某个尺度目标检测很差FPN 对应层 anchor 尺度不匹配调整该层 anchor 基础尺度
难样本噪声干扰γ 过大γ 退回 1.5,复查标注质量

这份清单不是银弹,每条都需要结合你自己的数据显示来验证。但按照这个顺序查,能省下不少“对着空气调参”的时间。

最后我再说说个人体会。把 Focal Loss 论文从头到尾推一遍之后,我最大的感触是:它真正的贡献不是发明了一个 loss 公式,而是把一个训练动态问题显式地建模进了目标函数。你在读的时候,光背结论不够,最好自己把 p_t 的定义、调制因子的梯度行为、bias 初始化的数值影响都手推一遍。哪怕只是对着公式算三分钟,后面调参手感都不一样。如果你正准备在项目里用它,建议先不要急着换大模型大框架,而是用一个小数据集,把 γ=2、α=0.25 的基线跑通,再逐步试 1、3 和 0.1、0.5。这样踩过一轮坑之后,你对 Focal Loss 的每个旋钮都会有自己的直觉。

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

springboot演唱会票务服务平台14749-计算机课程设计/毕业设计

前言 &#x1f4cc;博主介绍&#xff1a;一线全栈工程师&#xff0c;毕设实战引路人。技术栈覆盖Java、Python、C#、PHP、Node.js及UniApp跨端开发&#xff0c;擅长多语言项目落地与架构设计。持续分享毕设源码、开题报告、技术选型心得与职场踩坑经验。用工程化思维写代码&am…

作者头像 李华
网站建设 2026/10/17 2:18:12

HITSZ‘s End-To-End Speech Translation Systems Combining Sequence-to-Sequence Auto Speech Recognit...

文章主要内容总结 本文介绍了哈尔滨工业大学(深圳)(HITSZ)为IWSLT 2025 Indic赛道提交的语音到文本翻译(ST)系统,聚焦英语与印度语言(印地语、孟加拉语、泰米尔语)的双向翻译任务。针对低资源语言对的翻译质量提升问题,研究团队提出了一种端到端系统,将预训练的Whi…

作者头像 李华
网站建设 2026/10/17 2:18:09

终端AI编程助手Super Code:命令行里的结对编程新范式

终端里敲几行命令&#xff0c;AI 就能把整个文件改了、测试跑了、commit 写了&#xff0c;这事放两年前想都不敢想。但 Super Code 就是这么干的——它是一个跑在终端里的 AI 编程助手&#xff0c;不依赖 IDE&#xff0c;不抢编辑器&#xff0c;装上就能在命令行里和你对话、读…

作者头像 李华
网站建设 2026/10/17 2:18:06

《驾驭你的AI同事:WorkBuddy深度精通》011:3.3 调试与本地测试 Skill

《驾驭你的AI同事:WorkBuddy深度精通》011:3.3 调试与本地测试 Skill 本文是《唤醒你的 AI 同事:WorkBuddy 全栈指南》系列 卷二(深度精通) 的 第 11 篇。卷一带你"上手",卷二带你"看穿"——这一篇,我们补齐 Skill 开发最后一块拼图:在发布前,怎么…

作者头像 李华
网站建设 2026/10/17 2:17:19

两节串联电池组被动均衡实战:MP2642GR-Z与STM32L162ZE方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华