1. 梯度下降的几种变体及其优缺点 梯度下降(Gradient Descent)是机器学习中一种基础且有效的优化算法,其核心思想是通过迭代更新模型参数来逼近损失函数的最小值。在深度学习中,梯度下降的几种常见形式包括批量梯度下降(BGD)、随机梯度下降(SGD)和Mini-batch梯度下降(MBGD)。每种方法都有其独特的优点和局限性。
  • 批量梯度下降(BGD):每次更新使用全部训练数据计算梯度。这种方法的优势在于梯度方向准确,收敛稳定;然而,由于需要对所有样本进行计算,因此在数据量大时计算开销巨大,不适用于大规模数据集。
  • 随机梯度下降(SGD):每次只用一个样本计算梯度。这种方法的优势在于更新快,能逃离局部最优;但其缺点是梯度方向噪声大,收敛路径震荡明显,需要精细调节学习率。
  • Mini-batch 梯度下降(MBGD):折中方案,每次用小批量数据(如32、64或128条数据)计算梯度。目前深度学习训练的标准方法,兼顾了计算效率和梯度稳定性。
  • Adam(Adaptive Moment Estimation):结合了动量(Momentum)和RMSProp两者的优点:
  • 维护梯度的一阶矩(均值)和二阶矩(未中心化方差)的指数移动平均;
  • 对每个参数独立调整学习率;
  • 在大多数任务上收敛快、调参容忍度高。 实践建议:默认使用Adam(lr=1e-3, β1=0.9, β2=0.999),如果追求极致泛化性能(如ImageNet benchmark)可切换到带动量的SGD,需要更精细地调学习率。
  1. Transformer的注意力机制是如何工作的? Transformer 是一种重要的序列到序列模型结构,其注意力机制允许模型在处理输入序列时关注到不同位置的重要性,从而能够更好地理解文本内容。
  • Self-Attention 计算流程:Q/K/V矩阵 → 点积 → Scale → Softmax → 加权求和。
  • Q、K、V分别为Query、Key、Value矩阵,这些矩阵的大小通常相同且形状为[d_k, d_k]。
  • 点积操作用于计算Q和K的点积,结果再除以√d_k以防止点积结果过大导致Softmax梯度消失。
  • Scale操作是为了将点积的结果缩放到合理的范围,防止Softmax输出的梯度过大。
  • 最后通过Softmax函数得到加权求和的结果,即每个Token的最终权重。
  • Multi-Head 的作用:Multi-Head允许模型在不同子空间学习不同的维度注意力关系。这意味着模型可以同时关注序列中的多个位置,从而提高模型对长距离依赖关系的捕捉能力。
  • 与 RNN 的核心区别:与循环神经网络(RNN)相比,Transformer的最大区别在于其并行计算能力和全局依赖性。RNN依赖于序列的特定顺序,而Transformer则不受序列长度的限制,能够处理任何长度的输入序列。此外,Transformer的并行计算能力也使得其在处理大规模数据时更加高效。 内容重构: 在机器学习中,特别是在处理序列数据如文本、语音等时,类别不平衡是一个常见的挑战。这种不平衡意味着某一类别的样本数量远多于其他类别,这会导致模型对少数类的预测更加准确,而对多数类的预测则可能产生偏差。为了解决这一问题,可以采取以下策略:
  1. 数据层面
  • 过采样(SMOTE):通过在少数类样本之间进行插值生成新样本,来增加这些样本的数量。这种方法比简单地复制少数类样本更为有效。
  • 欠采样:随机去除部分多数类样本,适用于数据量较大时使用,但会损失信息。
  • 负采样:在深度学习场景中常用,以固定比例(如1:4)随机保留负样本,同时用sample_weight修正偏差。
  1. 算法层面
  • class_weight:在损失函数中设置类别权重,自动加大少数类样本的梯度贡献,从而减少模型对少数类的误判。
  • Focal Loss:引入一个非零的正系数,使得模型在处理少数类时,其对正确分类的贡献被放大,从而平衡了模型对不同类别的偏好。
  1. 评估层面
  • 不应仅依赖准确率作为评估指标,还应考虑AUC/F1/精确率召回率曲线等多维度评估方法,以全面反映模型的性能。
  1. 业务层面
  • 根据误报的代价调整决策阈值,例如,如果误报的代价很高,那么在模型输出为正时,应降低阈值以避免过多的误判。 以上策略的综合应用,可以有效地解决机器学习中的类别不平衡问题,提高模型的整体性能和泛化能力。 我的毕业设计是一个中文医疗问答系统,任务是对患者提问做意图识别(分为问药、问症状、问医院等 8 个类别)。 模型选择:最初,我选择了TextCNN模型,其F1值大约为82%。然而,在经过一系列的实验和对比后,我发现BERT-base-chinese模型在迁移学习后能够显著提升F1值至91.3%,这让我意识到了预训练模型的重要性。 遇到的挑战:尽管BERT-base-chinese提升了F1值,但计算延迟问题仍然存在。当使用BERT进行推理时,响应时间高达230ms/条,这对于实时应用来说是一个重大的限制。 解决方案:为了解决这个延迟问题,我采用了知识蒸馏技术,将BERT压缩到6层,并命名为DistilBERT。通过这种方式,推理速度从原来的230ms/条降低到了75ms,同时保持了90.5%的F1值。 领域词汇缺失:由于医疗专业术语的特殊性,通用BERT模型无法很好地处理这些词汇。为了解决这个问题,我在词表中增加了医疗术语,并利用CHIP数据集对BERT进行了额外的预训练。 数据不平衡:在8个意图类别中,样本量差异很大,最多的类别只有500条样本,而最少的类别有10000条样本。为了解决这个问题,我使用了Focal Loss算法和back-translation数据增强方法来平衡各类别的F1值。 为什么想来百度?我对百度文心大模型的了解主要在于它的ERNIE系列技术和知识增强能力。百度文心大模型不仅支持多模态输入和输出,还具备强大的知识理解和生成能力,这使我看到了与百度技术战略相匹配的方向。 文心大模型基于ERNIE(Enhanced Representation through kNowledge IntEgration)系列,从早期的ERNIE 1.0通过知识图谱增强预训练,到文心3.54.0引入RLHF人类反馈对齐,在中文理解和生成任务上有明显的本地化优势,尤其在中文逻辑推理和文化常识上表现优于部分通用英文模型。 产品层面,我深度使用过文心一言,感受最深的是它对中文语境的理解比较自然,在诗歌创作、商业文案等中文生成任务上有差异化竞争力。百度将大模型能力直接嵌入搜索结果,形成“搜索+生成”的新范式,这是其他模型公司暂时无法复制的流量入口优势。 个人契合方面,我在毕设中做的医疗NLP工作让我对大模型的垂直领域适配有一定实践积累,百度在医疗AI方向的布局(灵医智惠)与我的研究方向高度契合,希望加入后能在大模型的领域精调和知识增强方向做出贡献。 什么是过拟合?如何防止过拟合? 机器学习基础题,百度算法岗几乎必问,要覆盖从数据、模型、训练三个层面的完整防过拟合策略。 什么是过拟合:训练误差持续下降但验证误差反而上升,模型记住了噪声而非规律。 数据层面:数据增强、更多训练数据。 模型层面:减少参数量、使用正则化(L1/L2/Dropout)、集成学习(Bagging)。 训练层面:Early Stopping、交叉验证。 回答示例: 过拟合的本质是模型复杂度超过了数据所能支撑的复杂度——模型不仅学习了数据中的真实规律,还把噪声(偶然出现的个别样本的特征)也记住了。 防止过拟合的方法: 数据增强:在图像任务中对图像做旋转/翻转/裁剪/颜色抖动;在NLP中对文本做同义词替换、回译(中文→英文→中文)等,增加训练样本多样性,让模型学到真正的pattern而不是个别样本。 正则化: L1正则(Lasso):在损失函数中加入|w|项,会将部分权重置零(特征选择),适合特征稀疏的场景; L2正则(Ridge):在损失函数中加入w²项,让权重趋近于0但不等于0,适合特征之间存在多重共线性的场景; Dropout:训练时随机丢弃一定比例(如20%-50%)的神经元,强迫网络不依赖特定神经元,从而学到更鲁棒的表征。 回答思路 在处理海量数据时,我们面临内存限制的挑战,需要设计算法来高效地处理和筛选出最大的K个数。针对这个问题,我们提出了两种策略:小数据量下,直接对数据进行排序取前K;大数据量下,采用分治加堆的算法;而当单机内存不足以存储全部数据时,则采用分布式计算框架如MapReduce。 卷积层(Convolutional Layer) : 卷积层通过滑动卷积核的方式,在输入特征图上进行局部内积运算,提取出局部的特征信息。每个卷积核只与上一层的局部区域相连,模拟人类视觉皮层的局部感知特性,从而实现参数共享,大幅减少模型参数的数量。 池化层(Pooling Layer) : 池化层通过对特征图进行降采样操作,常用的有最大池化(Max Pooling)和平均池化(Average Pooling),目的是降低特征图的尺寸,减少后续层的计算负担。 全连接层(Fully Connected Layer) : 全连接层将分布式特征映射到样本标记空间,完成最后的分类或回归任务,是深度学习模型中负责输出结果的关键部分。 现代趋势 随着技术的发展,CNN的组件也在逐步演变。例如,用Global Average Pooling替代传统的FC(Fully Connected)层以减少过拟合现象,以及Vision Transformer等新型模型逐渐取代传统的CNN结构。 在深度学习模型中,尤其是大型语言模型(LLMs),幻觉问题是一个常见的挑战。幻觉指的是模型生成的内容虽然看似合理,但实际上包含错误或无中生有的信息。这种现象的根源在于LLM的本质是“高级的概率补全器”,它生成的是最像真话的内容,而非事实上的真话。幻觉产生的原因包括知识陈旧、长尾知识缺失以及概率采样的随机性。为了缓解这些问题,百度采用了结合百度搜索/百科知识库的RAG路线,并辅以事实链验证链(CoT+Fact Check)和减少Temperature/Top-p等方法。 首先,幻觉的根源在于LLM的本质。作为一个高级的概率补全器,LLM生成的内容旨在提供最接近真实答案的回答。然而,由于训练数据可能存在截止日期,导致模型无法完全掌握最新的信息;此外,长尾知识领域,如医学和法律,由于其复杂性和专业性,模型在这些领域的学习可能不够深入,容易产生误导性的结论。同时,概率采样过程中,即使正确答案被选中,高温度参数的调整也可能导致错误的选择。 为了解决这些问题,百度的实践包括结合百度搜索/百科知识库的RAG路线。这种方法通过检索相关的知识内容作为输入给模型,迫使模型“照着证据说话”,而不是凭空生成内容。此外,百度还采用事实链验证链(CoT+Fact Check)的方法,通过分步骤推理和要求模型标注每个陈述的置信度和依据,对低置信度段落进行进一步的验证和检索。最后,百度还通过减少Temperature/Top-p等参数来降低过拟合的风险,从而减少幻觉的产生。 总之,大模型幻觉问题的缓解需要从多个方面入手,包括更新训练数据、优化模型结构和参数设置、引入额外的验证机制等。百度在这方面的实践为其他研究者提供了有益的参考。 在需要支持带parent指针的二叉树时,递归法的实现可以稍微复杂一些。首先,我们需要定义一个辅助函数来处理带parent指针的情况。这个辅助函数会检查当前节点是否为p或q,如果是,则返回当前节点;否则,它会递归地调用自身来查找左右子树。 然后,主函数lowestCommonAncestor的实现可以稍作修改,以便在找到目标节点或到达空节点时返回父节点。这样,我们就可以在递归过程中同时考虑父节点的信息了。 示例代码如下:
// 递归法,时间复杂度 O(n),每个节点最多访问一次
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
// 递归终止条件:找到目标节点或到达空节点
if (root == null || root == p || root == q) return root;
// 在左右子树中分别查找
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
// 左右子树都有返回值,说明p和q分别在左右子树,当前节点是LCA
if (left != null && right != null) return root;
// 只有一边有返回值,说明p和q都在这一侧
return left != null ? left : right;
}

在这个版本的算法中,我们使用了两个辅助函数,一个用于处理带parent指针的情况,另一个用于递归地查找左右子树。这样,我们就能够在找到目标节点或到达空节点时返回父节点,从而简化了代码并提高了效率。

public TreeNode lowestCommonAncestorWithParent(TreeNode p, TreeNode q) {
Set<TreeNode> path = new HashSet<>(); // p向上遍历,记录所有祖先
while (p != null) {
path.add(p);
p = p.parent;
}
// q向上遍历,第一个已在path中的节点就是LCA
while (q != null) {
if (path.contains(q)) return q;
q = q.parent;
}
return null;
}