news 2026/10/15 23:15:13

损失函数与优化器:从SVM到交叉熵的实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
损失函数与优化器:从SVM到交叉熵的实战指南

1. 从“打分”到“打分好不好”:损失函数到底在解决什么问题

很多人第一次接触图像分类任务时,会把注意力全放在网络结构上——卷积层怎么设计、池化怎么加、全连接层多少维。但真正跑过一轮完整训练的人都知道,模型能不能收敛、最终效果好不好,很大程度上取决于两件事:损失函数选得对不对,优化过程走得稳不稳。Lecture 3 这个部分,恰恰是把“模型输出一个分数”变成“模型知道自己错在哪、该往哪个方向改”的关键桥梁。

先把这个问题的背景说清楚。假设我们有一个图像分类任务,输入是一张图片,模型最终输出的是每个类别的得分。比如做十分类,模型对一张图输出十个数字,分别代表它认为这张图属于这十个类别的“信心分数”。但问题来了:这些分数本身只是数字,模型怎么知道自己当前的表现是好还是坏?如果预测错了,错得有多离谱?这就是损失函数要回答的问题。

用生活化的类比来说,损失函数就像一位严格的教练。运动员做完一套动作,教练不会只说“还行”或者“不行”,而是会给出一个具体的扣分:手抬高了扣0.5分,落地不稳扣1.2分。分数越高说明问题越大,运动员就知道下一步该重点改哪里。损失函数做的就是这件事——它把模型当前的预测结果和真实标签之间的差距,量化成一个数值。这个数值越大,说明模型错得越严重;数值越小,说明模型预测得越接近正确答案。

但这里有一个容易被忽略的细节:损失函数并不是直接衡量“准确率”的。准确率是一个离散的、不可导的指标——预测对了就是1,错了就是0。这种指标没法用来做梯度下降,因为它的导数几乎处处为零,没法告诉模型“往哪个方向微调参数能让结果变好”。所以我们需要设计一个连续可导的替代指标,这就是损失函数存在的根本原因。它本质上是一个代理指标:我们真正关心的是准确率,但我们优化的是损失函数,因为只有它才能提供有效的梯度信息。

Lecture 3 里重点讲了两类损失函数:多类支持向量机损失(Multiclass SVM Loss)和Softmax交叉熵损失(Softmax Cross-Entropy Loss)。这两者代表了两种不同的思路。SVM损失的核心思想是“只要正确类别的得分比错误类别高出一定边界,我就认为你预测对了,不再追究”。而交叉熵损失则更“贪心”——它不仅要求正确类别得分最高,还希望正确类别的概率尽可能接近1。这两种思路没有绝对的优劣,但在实际任务中表现出的特性差异很大,后面会详细展开。

还有一个关键点需要提前说清楚:损失函数通常由两部分组成——数据损失和正则化损失。数据损失衡量的是模型预测和训练数据的匹配程度,正则化损失则是对模型复杂度的惩罚。很多人调参时只盯着数据损失,忽略了正则化项的作用,结果模型在训练集上表现很好,一到测试集就崩了。这个坑在后面会专门展开讲。

2. 多类SVM损失:那个“够用就行”的边界哲学

2.1 从二分类到多分类的直觉迁移

理解多类SVM损失,最好先从二分类的直觉入手。在二分类任务里,我们通常希望正确类别的得分比错误类别高出至少一个边界值。比如设定边界为1,那么如果正确类别得分是3.2,错误类别得分是2.1,差值是1.1,超过了边界,我们就认为这个样本已经被正确分类了,不再产生损失。如果差值是0.5,没到边界,就产生1 - 0.5 = 0.5的损失。

多类SVM损失把这个思路推广到了多个类别。对于每一个样本,我们遍历所有“错误类别”,只要某个错误类别的得分加上边界值之后仍然大于正确类别的得分,就产生损失。用公式表达就是:

[ L_i = \sum_{j \neq y_i} \max(0, s_j - s_{y_i} + \Delta) ]

其中 ( s_j ) 是第 ( j ) 个类别的得分,( s_{y_i} ) 是正确类别的得分,( \Delta ) 是边界值,通常设为1。这个公式的核心逻辑是:只有当错误类别的得分“逼近”或“超过”正确类别得分时,才产生惩罚。如果正确类别已经遥遥领先,损失就是零。

这个设计有一个很反直觉的地方:如果正确类别的得分已经足够高,损失函数就不再关心它到底有多高了。比如正确类别得分是10,错误类别最高得分是2,差值是8,远超边界1,损失为零。但如果正确类别得分是100,错误类别最高得分是2,差值98,损失依然是零。从损失函数的角度看,这两种情况没有区别。这就是SVM损失的“边界哲学”——只要跨过了边界,就不再追求更高的置信度。

2.2 边界值Δ到底该怎么理解

边界值 ( \Delta ) 是一个超参数,通常设为1。但很多人会问:为什么是1?设成2或者0.5会怎样?

从数学上看,( \Delta ) 的取值其实不影响最优解的方向,只影响损失函数的尺度。因为如果我们把所有权重参数 ( W ) 同时缩放一个因子 ( \lambda ),那么所有得分也会缩放同样的因子,损失函数中的差值也会缩放。所以 ( \Delta ) 和权重尺度之间存在一种“冗余”关系。换句话说,设 ( \Delta = 1 ) 并让权重自由学习,和设 ( \Delta = 2 ) 但限制权重范围,最终得到的分类边界是一样的。

但在实际操作中,( \Delta ) 的取值会影响优化的难易程度。如果 ( \Delta ) 设得太大,模型会拼命拉大正确类别和错误类别之间的差距,导致权重数值变得很大,容易过拟合。如果 ( \Delta ) 设得太小,模型可能学到一个“差不多就行”的解,泛化能力反而下降。所以实践中通常保持 ( \Delta = 1 ),然后通过正则化强度来控制权重的尺度。

注意:SVM损失中的边界值 ( \Delta ) 和正则化强度 ( \lambda ) 是一对“搭档”。调参时不要单独调其中一个,而要联合考虑。一个经验法则是:如果发现权重数值异常大,先检查正则化强度是否太小,而不是急着调 ( \Delta )。

2.3 一个具体的计算示例

假设我们有一个三分类任务,某个样本的正确类别是第2类(索引从0开始),模型输出的得分向量是 ( s = [3.2, 1.3, 2.2] ),边界值 ( \Delta = 1 )。

计算过程如下:

  • 对于错误类别0:( \max(0, 3.2 - 1.3 + 1) = \max(0, 2.9) = 2.9 )
  • 对于错误类别2:( \max(0, 2.2 - 1.3 + 1) = \max(0, 1.9) = 1.9 )
  • 总损失:( L_i = 2.9 + 1.9 = 4.8 )

这个结果说明模型当前的表现很差——正确类别的得分(1.3)不仅没有领先,反而被两个错误类别都超过了。损失值4.8会通过反向传播告诉模型:你需要大幅调整参数,让正确类别的得分升上去,同时把错误类别的得分压下来。

如果换个场景,得分向量变成 ( s = [0.5, 4.0, 1.2] ),正确类别还是第2类:

  • 对于错误类别0:( \max(0, 0.5 - 4.0 + 1) = \max(0, -2.5) = 0 )
  • 对于错误类别2:( \max(0, 1.2 - 4.0 + 1) = \max(0, -1.8) = 0 )
  • 总损失:( L_i = 0 )

这时候正确类别得分4.0远超其他类别,损失为零。模型不会再对这个样本产生任何梯度更新。

2.4 为什么SVM损失在实际中仍然有用

虽然现在大多数图像分类任务都用交叉熵损失,但SVM损失在某些场景下仍然有优势。它的一个显著特点是对“已经分对”的样本不再产生梯度,这意味着模型会把注意力集中在那些还没分对的“困难样本”上。这种特性在某些类别不平衡的数据集上反而有帮助——因为多数类样本很快就会被分对,损失降为零,模型会更多地关注少数类。

但SVM损失也有一个明显的缺点:它不提供概率输出。在很多需要置信度估计的任务中(比如医疗诊断、自动驾驶),我们不仅要知道模型预测了什么,还要知道它有多确信。SVM损失只给出得分,不给出概率,这就限制了它的应用范围。

3. Softmax交叉熵损失:从得分到概率的转换

3.1 Softmax函数到底做了什么

Softmax函数的作用是把一组任意实数得分转换成概率分布。它的公式是:

[ P(y = k | x) = \frac{e^{s_k}}{\sum_j e^{s_j}} ]

这个公式的核心操作是:先对每个得分取指数,然后归一化。取指数的目的是保证所有输出为正数,同时放大得分之间的差异。比如得分是[3.2, 1.3, 2.2],取指数后变成[e^3.2, e^1.3, e^2.2] ≈ [24.5, 3.7, 9.0],归一化后得到[0.66, 0.10, 0.24]。可以看到,原本得分最高的类别0,经过Softmax后概率被进一步放大到了0.66。

这里有一个重要的细节:Softmax函数的输出之和恒为1,这正好符合概率分布的定义。而且Softmax是单调的——得分越高的类别,概率也越高。但它不是线性的,得分之间的微小差异经过指数放大后,可能会变成概率上的巨大差异。

3.2 交叉熵损失为什么是“正确类别的负对数”

交叉熵损失的公式看起来很简单:

[ L_i = -\log P(y_i | x_i) ]

其中 ( P(y_i | x_i) ) 是模型预测正确类别的概率。这个公式的直觉是:如果模型预测正确类别的概率是1,损失就是 ( -\log(1) = 0 );如果预测概率是0.5,损失是 ( -\log(0.5) ≈ 0.693 );如果预测概率是0.1,损失是 ( -\log(0.1) ≈ 2.303 )。概率越低,损失越大,而且增长是指数级的。

这个设计有一个很好的性质:当模型预测正确类别的概率很低时,损失会非常大,梯度也会非常大,这会迫使模型快速调整参数。相比之下,SVM损失在预测错误时产生的梯度是恒定的(等于边界值),不会因为错得越离谱而给出越大的惩罚。这是两种损失函数在优化动态上的一个关键差异。

3.3 数值稳定性:那个容易被忽略的坑

在实际实现Softmax时,有一个非常经典的坑:指数运算容易溢出。如果得分是[1000, 1001, 1002],直接取指数会得到天文数字,计算机浮点数根本存不下,结果就是inf或者nan。解决办法是在取指数之前,先减去得分中的最大值:

[ P(y = k | x) = \frac{e^{s_k - \max(s)}}{\sum_j e^{s_j - \max(s)}} ]

这个操作在数学上是等价的,因为分子分母同时乘以了一个常数 ( e^{-\max(s)} ),不改变最终结果。但在数值上,它把最大的指数变成了 ( e^0 = 1 ),其他指数都变成了负数,不会溢出。

提示:这个技巧在几乎所有深度学习框架的Softmax实现中都已经内置了,但如果你自己手写损失函数,一定要记得加上这个操作。我见过不少人在调试时发现损失变成nan,排查半天才发现是忘了做数值稳定处理。

3.4 SVM损失和交叉熵损失的对比

对比维度多类SVM损失Softmax交叉熵损失
输出含义得分,无概率解释概率分布
对已分对样本的处理损失为零,不再产生梯度仍然产生梯度,追求更高置信度
梯度特性恒定梯度(边界值)梯度随预测概率变化
数值稳定性无特殊要求需要做最大值减法
适用场景类别不平衡、只需分类结果需要概率输出、置信度估计

从实际使用经验来看,交叉熵损失在大多数图像分类任务中表现更好,因为它提供了更平滑的优化曲面和更丰富的梯度信息。但SVM损失在某些特定场景下(比如需要快速训练、对概率输出没有要求)仍然是一个不错的选择。

4. 正则化:那个让模型“别太自信”的约束项

4.1 为什么需要正则化

损失函数的数据部分只关心模型在训练集上的表现。如果只看数据损失,模型会倾向于尽可能完美地拟合每一个训练样本,包括那些噪声和异常点。结果就是模型在训练集上准确率很高,但在测试集上表现很差——这就是过拟合。

正则化的作用就是给模型加一个“约束”,让它不要为了拟合训练数据而把参数调得太极端。最常见的正则化是L2正则化:

[ R(W) = \sum_k \sum_l W_{k,l}^2 ]

它把所有参数的平方和加到总损失中。这样,如果模型想把某个参数调得很大,就会受到惩罚。最终的总损失是:

[ L = \frac{1}{N} \sum_i L_i + \lambda R(W) ]

其中 ( \lambda ) 是正则化强度,控制惩罚的力度。

4.2 L2正则化为什么能防止过拟合

从直观上理解,L2正则化倾向于让所有参数都接近零,但不会让它们完全等于零。这意味着模型不会过度依赖某一个特征或某一个输入维度,而是会把权重分散到多个特征上。这种“分散”的特性让模型对输入的微小变化不那么敏感,从而提高了泛化能力。

从数学上看,L2正则化等价于在参数空间上施加了一个高斯先验,让参数倾向于取较小的值。而L1正则化则等价于拉普拉斯先验,倾向于让参数变得稀疏(很多参数正好等于零)。在图像分类任务中,L2正则化更常用,因为它产生的解更平滑,优化也更稳定。

4.3 正则化强度λ的调参经验

( \lambda ) 是训练过程中最重要的超参数之一。设得太小,正则化效果不明显,模型容易过拟合;设得太大,模型会被过度约束,连训练集都拟合不好,出现欠拟合。

在实际调参时,我通常从 ( \lambda = 1e-4 ) 开始尝试,然后按对数尺度搜索(比如 ( 1e-5, 1e-4, 1e-3, 1e-2 ))。判断标准是看验证集上的准确率:如果训练集准确率远高于验证集,说明过拟合,需要增大 ( \lambda );如果训练集准确率本身就很低,说明欠拟合,需要减小 ( \lambda )。

注意:正则化强度 ( \lambda ) 和边界值 ( \Delta ) 之间存在耦合关系。在SVM损失中,增大 ( \lambda ) 会抑制权重尺度,从而间接影响得分差距。所以调参时不要同时大幅调整这两个参数,否则很难判断是哪个因素在起作用。

5. 优化:从随机猜测到逐步逼近最优解

5.1 梯度下降的三种变体

有了损失函数,接下来的问题就是如何找到让损失最小的参数。最基础的方法是批量梯度下降(Batch Gradient Descent):每次用全部训练数据计算损失和梯度,然后更新参数。这种方法计算量大,但梯度方向准确。

随机梯度下降(SGD)每次只用一个样本计算梯度并更新参数。计算量小,但梯度方向噪声大,更新过程震荡严重。

小批量梯度下降(Mini-batch SGD)折中了两者:每次用一小批样本(比如32、64、128个)计算梯度。这样既保证了计算效率,又让梯度方向相对稳定。这也是实际中最常用的方法。

5.2 学习率:那个最需要“手感”的超参数

学习率控制每次参数更新的步长。设得太小,收敛速度慢,训练时间长得让人抓狂;设得太大,损失可能震荡甚至发散。

我个人的经验是:先用一个较大的学习率(比如0.1)跑几百次迭代,观察损失曲线。如果损失在震荡但不下降,说明学习率太大,需要减小;如果损失下降得非常慢,说明学习率太小,需要增大。找到一个大致的范围后,再用学习率衰减策略(比如每过几个epoch乘以0.1)来精细调整。

还有一个常用的技巧是学习率预热(Warmup):在训练初期用很小的学习率,然后逐渐增大到设定值。这样做可以避免训练初期因为参数随机初始化导致的梯度爆炸问题。

5.3 动量:让优化过程“记住”之前的梯度方向

标准SGD的一个问题是:在损失曲面的某些方向上,梯度可能来回震荡,导致收敛缓慢。动量法通过引入一个“速度”变量来解决这个问题:

[ v = \rho v - \alpha \nabla L ] [ W = W + v ]

其中 ( \rho ) 是动量系数(通常设为0.9),( \alpha ) 是学习率。动量法的核心思想是:如果某个方向的梯度一直指向同一个方向,那么速度会累积,更新步长会越来越大;如果梯度方向来回变化,速度会相互抵消,更新步长会减小。这样就能加速收敛并减少震荡。

5.4 自适应学习率方法:Adam和它的朋友们

除了SGD和动量法,还有一类自适应学习率方法,比如Adam、RMSProp、Adagrad。这些方法的核心思想是:为每个参数单独调整学习率,根据该参数历史梯度的大小来决定当前步长。

Adam是目前最常用的自适应方法之一。它结合了动量和RMSProp的思想,同时估计梯度的一阶矩和二阶矩。在实际使用中,Adam通常能更快地收敛,而且对学习率的初始值不那么敏感。但也有一些研究表明,在某些任务上,精心调参的SGD+动量法最终能达到更好的泛化性能。

提示:如果你刚开始做图像分类任务,建议先用Adam快速跑通流程,确认模型结构和数据管道没有问题。然后再切换到SGD+动量法进行精细调参,追求更高的最终精度。

6. 从损失函数到实际训练:那些文档里不会写的经验

6.1 损失曲线到底该怎么看

训练过程中,损失曲线的形状能告诉你很多信息。如果损失下降得很平滑,说明学习率合适、数据管道没有问题。如果损失剧烈震荡,可能是学习率太大或者批量太小。如果损失下降一段时间后突然飙升,可能是遇到了异常样本或者梯度爆炸。

还有一个常见的现象是损失下降但准确率不升。这通常发生在类别不平衡的数据集上——模型学会了把所有样本都预测为多数类,损失确实在下降,但准确率没有实质提升。这时候需要检查数据分布,考虑使用加权损失或者重采样。

6.2 梯度检查:那个救命的调试步骤

在实现自己的损失函数时,梯度检查(Gradient Check)是一个必不可少的步骤。它的原理很简单:用数值方法近似计算梯度,然后和解析方法计算的梯度对比。如果两者差异很大,说明解析梯度实现有误。

数值梯度的计算公式是:

[ \frac{\partial L}{\partial W} \approx \frac{L(W + h) - L(W - h)}{2h} ]

其中 ( h ) 是一个很小的数(比如1e-5)。这个方法的计算量很大,所以只在小规模数据上做检查。但一旦发现梯度实现有误,它能帮你节省大量的调试时间。

6.3 超参数搜索的策略

损失函数和优化器涉及的超参数很多:学习率、正则化强度、批量大小、动量系数、学习率衰减策略等。手动调参费时费力,而且容易陷入局部最优。

常用的策略是网格搜索(Grid Search)和随机搜索(Random Search)。网格搜索在参数空间上均匀采样,适合参数维度较低的情况。随机搜索在参数空间上随机采样,在参数维度较高时更高效——因为不是所有参数都同等重要,随机搜索更容易找到关键参数的好值。

还有一种更高级的方法是贝叶斯优化,它根据历史评估结果来指导下一步的采样位置。这种方法在计算资源有限时特别有用,但实现起来也更复杂。

6.4 一个完整的训练流程示例

下面是一个简化的训练流程,展示了损失函数和优化器如何配合工作:

# 初始化参数 W = np.random.randn(D, C) * 0.001 learning_rate = 1e-3 reg_lambda = 1e-4 momentum = 0.9 v = np.zeros_like(W) for epoch in range(num_epochs): # 小批量采样 batch_indices = np.random.choice(N, batch_size) X_batch = X[batch_indices] y_batch = y[batch_indices] # 前向传播计算得分 scores = X_batch.dot(W) # 计算损失 data_loss, grad_scores = softmax_loss(scores, y_batch) reg_loss = 0.5 * reg_lambda * np.sum(W * W) total_loss = data_loss + reg_loss # 反向传播计算梯度 grad_W = X_batch.T.dot(grad_scores) + reg_lambda * W # 动量更新 v = momentum * v - learning_rate * grad_W W += v # 打印训练信息 if epoch % 100 == 0: print(f"Epoch {epoch}, Loss: {total_loss:.4f}")

这个流程虽然简单,但涵盖了训练的核心步骤:前向传播、损失计算、反向传播、参数更新。实际项目中还需要加入验证集评估、学习率衰减、模型保存等环节。

6.5 那些年我踩过的坑

第一个坑是忘记除以批量大小。在计算数据损失时,需要对批量中所有样本的损失求平均,而不是求和。如果忘记除以批量大小,损失值会随着批量大小变化,导致学习率需要重新调整。

第二个坑是正则化项重复计算。有些实现会在每个样本的损失中都加上正则化项,导致正则化被放大了批量大小倍。正确的做法是只在总损失中加一次正则化项。

第三个坑是Softmax数值溢出。前面已经提到过,但值得再强调一次:一定要在取指数之前减去最大值。这个操作在数学上等价,但在数值上能避免inf和nan。

第四个坑是学习率没有随批量大小调整。如果批量大小增大,梯度估计的方差会减小,理论上可以使用更大的学习率。一个经验法则是:批量大小翻倍,学习率也翻倍。但这个规则不是绝对的,需要根据实际情况调整。

7. 损失函数和优化器的选择框架

7.1 什么任务用什么损失

图像分类任务中,交叉熵损失是默认选择。但如果任务有特殊需求,比如需要处理类别不平衡,可以考虑加权交叉熵——给少数类更高的权重,让模型更关注它们。如果任务需要模型输出校准良好的概率,可以考虑标签平滑(Label Smoothing)——把硬标签变成软标签,避免模型过度自信。

对于回归任务,常用的损失是均方误差(MSE)和平均绝对误差(MAE)。MSE对大误差更敏感,MAE对小误差更鲁棒。选择哪个取决于你对异常值的容忍程度。

7.2 什么任务用什么优化器

如果追求快速收敛和易用性,Adam是首选。如果追求最终精度和泛化性能,SGD+动量通常更好,但需要更精细的学习率调参。如果训练数据非常大,Adagrad或RMSProp可能更合适,因为它们能自适应地调整每个参数的学习率。

在实际项目中,我通常先用Adam快速验证模型结构和数据管道,然后再切换到SGD+动量进行精细调参。这样既能快速发现问题,又能在最后阶段榨取更高的精度。

7.3 一个实用的调参顺序

根据我的经验,调参应该按照以下顺序进行:

  1. 先调学习率:这是最重要的超参数,其他参数的效果很大程度上取决于学习率是否合适。
  2. 再调正则化强度:在找到合适的学习率后,调整正则化强度来控制过拟合。
  3. 然后调批量大小:批量大小影响梯度估计的方差和训练速度。
  4. 最后调动量系数和学习率衰减策略:这些参数对最终精度的影响相对较小,但能帮助模型更稳定地收敛。

这个顺序不是绝对的,但遵循它能让调参过程更有条理,避免在多个参数之间来回折腾。

8. 从Lecture 3延伸出去:那些值得深入的方向

损失函数和优化是深度学习的核心,但Lecture 3只是一个起点。沿着这个方向,还有很多值得深入的内容。比如二阶优化方法(如牛顿法、L-BFGS)利用损失曲面的二阶信息来加速收敛,但计算量大,在深度学习中不常用。分布式优化把梯度计算和参数更新分散到多台机器上,能大幅加速大规模训练。元学习则尝试让模型学会如何学习,自动调整优化策略。

还有一个很有意思的方向是损失函数的设计。除了标准的交叉熵和SVM损失,研究者们提出了很多针对特定任务的损失函数,比如焦点损失(Focal Loss)用于处理极端类别不平衡,对比损失(Contrastive Loss)用于学习有区分度的特征表示。这些损失函数在特定场景下能显著提升效果,值得在实际项目中尝试。

从我个人经验来看,理解损失函数和优化器的工作原理,比记住具体的公式更重要。因为在实际项目中,你面对的数据和任务千变万化,只有理解了背后的原理,才能灵活地调整和设计适合当前任务的损失函数和优化策略。Lecture 3 提供的正是这样一个基础框架,让你在后续的学习和实践中能有的放矢。

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

C++11可变参数模板全解析:参数包、递归展开与完美转发

这个标题我一看就有冲动坐下来好好聊聊。可变参数模板(variadic templates)是C11引入的一组语法特性里,最容易被低估、却最能改变代码结构设计方式的能力之一。如果你还在用重载函数一个个手写参数组合,或者用va_list硬头皮处理不…

作者头像 李华
网站建设 2026/10/15 23:14:32

Java集合工具类CollectionUtils全解析:判空、集合运算与避坑指南

都说 Java 业务开发就是写 CRUD、处理集合,这话不夸张。我接手过的很多代码里,最脏最乱的部分往往不是复杂的业务逻辑,而是到处裸写的 for 循环、层层嵌套的 if 判空,以及一想到就头疼的“集合为空怎么处理”。CollectionUtils就是…

作者头像 李华
网站建设 2026/10/15 23:13:09

Ubuntu 上安装 Codex 并接入 DeepSeek API:TaoToken 统一 Key 配置实战

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

作者头像 李华
网站建设 2026/10/15 23:12:40

大模型 context-mode 工程实践:缓存、摘要与检索优化

很多人第一次听到 context-mode 这个词,多半是在把大模型接进业务系统的时候。我这边接手过一个客服问答项目,最初的模型应答质量其实不错,但一旦多轮对话超过三轮,模型就开始犯迷糊,要么把上一轮的用户意图记成当前轮…

作者头像 李华
网站建设 2026/10/15 23:11:44

O2O优惠券核销预测:分段轻量化建模实战

1. 项目概述:一张优惠券背后的“行为预判力”“O2O优惠券使用预测”这八个字,乍看是电商或本地生活平台后台的一个常规模型任务,但真正把它从需求文档落到生产环境、跑出可解释的业务价值,我前后踩过三轮坑——第一轮以为只是调个…

作者头像 李华
网站建设 2026/10/15 23:11:24

中老年垂直社交应用架构:从低端机、弱网到信任安全的技术取舍

我前几天在一个家庭聚会上,帮我爸清理手机里的App,发现他手机上装了三四个社交软件,最后只留了一个。我问他为什么,他说:别的不是不好,就是“字太小”、“点了没反应”、“老是弹窗让我清理内存&#xff0c…

作者头像 李华