搜广推校招面经七十五

发布于:2025-04-17 ⋅ 阅读:(26) ⋅ 点赞:(0)

字节推荐算法

一、SVM 原理与推导

1.1. 问题定义

给定训练集:
{ ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . , ( x n , y n ) } , x i ∈ R d , y i ∈ { − 1 , + 1 } \{(x_1, y_1), (x_2, y_2), ..., (x_n, y_n)\}, \quad x_i \in \mathbb{R}^d, \quad y_i \in \{-1, +1\} {(x1,y1),(x2,y2),...,(xn,yn)},xiRd,yi{1,+1}
目标是找到一个线性分类器:
f ( x ) = sign ( w T x + b ) f(x) = \text{sign}(w^T x + b) f(x)=sign(wTx+b)
使得所有样本被正确分类,且分类间隔最大。

1.2. 几何间隔与函数间隔

几何间隔定义为:
γ i = y i ( w T x i + b ) ∥ w ∥ \gamma_i = \frac{y_i (w^T x_i + b)}{\|w\|} γi=wyi(wTxi+b)

最大化几何间隔:
max ⁡ γ = min ⁡ i γ i \max \gamma = \min_i \gamma_i maxγ=iminγi

约定几何间隔为 1,转换为约束:
y i ( w T x i + b ) ≥ 1 y_i (w^T x_i + b) \geq 1 yi(wTxi+b)1

1.3. 原始优化问题(线性可分)

将最大间隔问题转化为优化问题:
min ⁡ w , b 1 2 ∥ w ∥ 2 subject to y i ( w T x i + b ) ≥ 1 , i = 1 , . . . , n \min_{w,b} \quad \frac{1}{2} \|w\|^2 \\ \text{subject to} \quad y_i (w^T x_i + b) \geq 1, \quad i = 1, ..., n w,bmin21w2subject toyi(wTxi+b)1,i=1,...,n

1.4. 对偶问题推导(拉格朗日乘子法)

构造拉格朗日函数:
L ( w , b , α ) = 1 2 ∥ w ∥ 2 − ∑ i = 1 n α i [ y i ( w T x i + b ) − 1 ] L(w, b, \alpha) = \frac{1}{2} \|w\|^2 - \sum_{i=1}^n \alpha_i [y_i (w^T x_i + b) - 1] L(w,b,α)=21w2i=1nαi[yi(wTxi+b)1]

w , b w, b w,b 求偏导并令其为 0:

  • ∂ L ∂ w = 0 ⇒ w = ∑ i α i y i x i \frac{\partial L}{\partial w} = 0 \Rightarrow w = \sum_i \alpha_i y_i x_i wL=0w=iαiyixi
  • ∂ L ∂ b = 0 ⇒ ∑ i α i y i = 0 \frac{\partial L}{\partial b} = 0 \Rightarrow \sum_i \alpha_i y_i = 0 bL=0iαiyi=0

代入得到对偶问题:
max ⁡ α ∑ i = 1 n α i − 1 2 ∑ i , j α i α j y i y j x i T x j subject to ∑ i = 1 n α i y i = 0 , α i ≥ 0 \max_\alpha \sum_{i=1}^n \alpha_i - \frac{1}{2} \sum_{i,j} \alpha_i \alpha_j y_i y_j x_i^T x_j \\ \text{subject to} \quad \sum_{i=1}^n \alpha_i y_i = 0, \quad \alpha_i \geq 0 αmaxi=1nαi21i,jαiαjyiyjxiTxjsubject toi=1nαiyi=0,αi0

1.5. 支持向量与决策函数

求得 α i \alpha_i αi 后,有些 α i > 0 \alpha_i > 0 αi>0 的样本为支持向量(support vectors)。

最终分类器为:
f ( x ) = sign ( ∑ i ∈ S V α i y i x i T x + b ) f(x) = \text{sign}\left(\sum_{i \in SV} \alpha_i y_i x_i^T x + b\right) f(x)=sign(iSVαiyixiTx+b)

1.6. 软间隔 SVM(线性不可分)

引入松弛变量 (\xi_i),允许部分样本被错分:
min ⁡ w , b , ξ 1 2 ∥ w ∥ 2 + C ∑ i = 1 n ξ i \min_{w,b,\xi} \quad \frac{1}{2} \|w\|^2 + C \sum_{i=1}^n \xi_i minw,b,ξ21w2+Ci=1nξi
subject to y i ( w T x i + b ) ≥ 1 − ξ i , ξ i ≥ 0 \text{subject to} \quad y_i (w^T x_i + b) \geq 1 - \xi_i, \quad \xi_i \geq 0 subject toyi(wTxi+b)1ξi,ξi0
其中 C C C 为惩罚因子,控制间隔与误差的权衡。

1.7. 核方法(非线性 SVM)

使用核函数将数据映射到高维空间,实现非线性可分的分类:
f ( x ) = sign ( ∑ i ∈ S V α i y i κ ( x i , x ) + b ) f(x) = \text{sign}\left(\sum_{i \in SV} \alpha_i y_i \kappa(x_i, x) + b\right) f(x)=sign(iSVαiyiκ(xi,x)+b)
常见核函数:

  • 线性核: κ ( x i , x j ) = x i T x j \kappa(x_i, x_j) = x_i^T x_j κ(xi,xj)=xiTxj
  • 多项式核: ( x i T x j + c ) d (x_i^T x_j + c)^d (xiTxj+c)d
  • RBF 核(高斯核): exp ⁡ ( − ∥ x i − x j ∥ 2 2 σ 2 ) \exp\left(-\frac{\|x_i - x_j\|^2}{2\sigma^2}\right) exp(2σ2xixj2)

二、XGBoost 和 LightGBM 中的树构建与加速机制详解

2.1. 最优分裂节点的选择

2.1.1 分裂点选择目标

目标是最大化增益(Gain):
Gain = 1 2 [ G L 2 H L + λ + G R 2 H R + λ − ( G L + G R ) 2 H L + H R + λ ] − γ \text{Gain} = \frac{1}{2} \left[ \frac{G_L^2}{H_L + \lambda} + \frac{G_R^2}{H_R + \lambda} - \frac{(G_L + G_R)^2}{H_L + H_R + \lambda} \right] - \gamma Gain=21[HL+λGL2+HR+λGR2HL+HR+λ(GL+GR)2]γ
其中:

  • G L , H L G_L, H_L GL,HL:左子树的梯度和 Hessian
  • G R , H R G_R, H_R GR,HR:右子树的梯度和 Hessian
  • λ \lambda λ:正则项
  • γ \gamma γ:分裂代价

遍历每一个特征的候选划分点,计算 Gain,选择最大 Gain 的分裂点。

2.2. 加速技巧对比

项目 XGBoost LightGBM
分裂方式 预排序(pre-sorted)、近似算法(histogram) 直方图 (histogram)
特点 精度高但计算慢 速度快,内存友好
增益计算 精确计算梯度与 Hessian 离散 bin 上聚合统计量估算

2.2.1. 预排序(Pre-sorted)机制(XGBoost 早期)

原理(排序耗时,缓存效率差):
  • 每个特征提前对样本排序(一次性预处理)。
  • 每次分裂时只需线性扫一遍候选点,计算增益。

2.2.2. 直方图优化(Histogram-based)(LGB)

原理:
  • 将连续特征离散为有限数量的 bins(桶)。
  • 在每个 bin 上统计梯度和 Hessian 累加值。
  • 枚举 bins 而不是每个样本,提高效率。
  • XGBoost 中的 tree_method=hist
  • LightGBM 默认使用 histogram 构建

2.3. 缺失值处理

(1)训练时的处理方式:

1. XGBoost 的做法:
  • 在每个特征分裂时,尝试将缺失值分到左或右子树两种情况,计算哪种情况下 Gain 更高。
  • 将缺失值统一分到“默认方向”。
2. LightGBM 的做法:
  • 将缺失值看成一个独立的 bin,参与增益比较。
  • 根据缺失值所在 bin 的增益选择其应去的方向。

(2)预测时的处理:

  • XGB:根据训练中学到的“缺失值默认方向”将缺失样本分配下去。所以预测时无需补全缺失值。
  • LGB:仍然看作独立的bin

三、有了解过设计模式吗?

设计模式大致分为 三大类,共23 种经典模式

3.1. 创建型模式(Creational Patterns)- 解决“对象如何创建”的问题

模式名称 作用
Singleton(单例) 保证一个类只有一个实例
Factory Method(工厂方法) 把实例化交给子类
Abstract Factory(抽象工厂) 创建一系列相关或相互依赖的对象
Builder(建造者) 分步骤构建复杂对象
Prototype(原型) 通过拷贝已有实例创建新对象

3.2. 结构型模式(Structural Patterns)- 解决“类或对象如何组合”的问题

模式名称 作用
Adapter(适配器) 连接接口不兼容的类
Bridge(桥接) 分离抽象和实现,使其独立变化
Composite(组合) 统一处理部分和整体对象
Decorator(装饰器) 动态添加功能,不改变结构
Facade(外观) 提供统一接口,简化子系统使用
Flyweight(享元) 共享对象,减少内存使用
Proxy(代理) 控制对目标对象的访问

3.3. 行为型模式(Behavioral Patterns)- 解决“对象间如何通信、如何协作”的问题

模式名称 作用
Strategy(策略) 封装可互换的算法
Observer(观察者) 实现一对多的通知机制
Command(命令) 封装请求为对象
Chain of Responsibility(责任链) 顺序传递请求直到被处理
State(状态) 状态转换由对象自己控制
Template Method(模板方法) 父类定义算法骨架,子类实现细节
Iterator(迭代器) 顺序访问聚合对象元素
Mediator(中介者) 降低对象间耦合,由中介协调通信
Memento(备忘录) 保存和恢复对象状态
Visitor(访问者) 在不修改类的情况下添加操作
Interpreter(解释器) 定义语言语法,构建解释器解释表达式

四、解释装饰器模式(Decorator Pattern)

装饰器模式是一种结构型设计模式,允许在不改变原有类结构的情况下,动态地给对象添加功能。它通过将原始对象包装在装饰器对象中,达到扩展功能的目的。

本质:使用“对象包装”替代“类继承”来扩展功能。

4.1. 实际中的应用

场景 应用方式
Python 函数装饰器 @decorator 语法,动态增强函数功能
Java I/O 流体系 BufferedReader 包装 InputStreamReader
日志记录 在函数执行前后加日志
权限控制 在执行逻辑前检查权限
缓存机制 给函数增加缓存能力

五、46. 全排列

在这里插入图片描述

  • 代码:
    按照答案每个位置该选的位置。
class Solution:
    def permute(self, nums):
        n = len(nums)
        ans = []
        path = [0] * n  # 所有的排列长度都是一样的
        def dfs(i, s):  # 从答案的角度,第i个位置该从剩余s中选择哪一个
            if i == n:
                ans.append(path.copy())
                return
            for x in s:
                path[i] = x
                dfs(i+1, s-{x})
        dfs(0, set(nums))
        return ans

网站公告

今日签到

点亮在社区的每一天
去签到