在这里插入图片描述

👨‍💻作者简介: CSDN、阿里云人工智能领域博客专家,新星计划计算机视觉导师,百度飞桨PPDE,专注大数据与AI知识分享。✨公众号:GoAI的学习小屋 ,免费分享书籍、简历、导图等,更有交流群分享宝藏资料,关注公众号回复“加群”或➡️点击链接 加群。

🎉AI学习星球推荐: GoAI的学习社区 知识星球是一个致力于提供《机器学习 | 深度学习 | CV | NLP | 大模型 | 多模态 | AIGC 》各个最新AI方向综述、论文等成体系的学习资料,配有全面而有深度的专栏内容,包括不限于 前沿论文解读、资料共享、行业最新动态以、实践教程、求职相关(简历撰写技巧、面经资料与心得)多方面综合学习平台,强烈推荐AI小白及AI爱好者学习。

💚AI面经专栏总结: 本专栏主要为总结各小中大厂的面经系列总结,内容涵盖了多个热门技术领域,包括但不限于算法、机器学习、CV、NLP、大模型、测开、大数据、数分等,内容包括问题及详细答案,此外金邀请了行业内经验丰富的技术专家和面试官,分享面试经验和技巧,帮助求职者顺利通关各类技术面试。

算法工程师面经系列

淘天阿里妈妈部门 内容风控算法工程师

一面 60min

1. Transformer

(1) 结构

整体结构: Transformer 主要由编码器(Encoder)和解码器(Decoder)两部分组成。
Encoder: N个编码器层堆叠,每层包括多头自注意力(Multi-Head Self-Attention)和前馈神经网络(Feed Forward Network),每个子层后有残差连接和LayerNorm。
Decoder: N个解码器层堆叠,每层包括掩码多头自注意力、编码器-解码器注意力、前馈网络,同样有残差和LayerNorm。
注意力机制: 核心是自注意力机制(Self-Attention),允许每个位置聚合全局信息。
输入嵌入与位置编码: 输入首先被嵌入(Embedding),然后加上位置编码(Positional Encoding)以注入序列顺序信息。

(2) 为什么它能处理多种模态,是怎么处理的

统一的结构: Transformer 的核心是处理“序列”数据,无论是文本、图像块、音频帧等都可以转化为向量序列输入。
多模态输入方式:
文本: 直接词嵌入+位置编码。
图像: 划分为patch(如ViT),每个patch展平成向量,相当于“词”,加上位置编码。
音频/视频: 分帧后转为向量序列,同理。
多模态融合: 可以对不同模态分别编码后,拼接或融合为统一的序列输入到Transformer中(如CLIP、VisualBERT等)。
灵活性: 结构不依赖于输入模态的具体特征,只依赖于序列建模能力,所以能处理多种模态。

(3) 它怎么用于图像分类,怎么处理图像的

ViT(Vision Transformer)为例:
图片切分: 将输入图片划分为固定大小的小块(如16x16),每个块展平成一维向量。
线性投影: 每个patch通过线性层映射到d维向量。
加位置编码: 给每个patch加上可学习的位置编码,保留空间信息。
序列输入: 类似文本序列一样,将这些patch embedding组成序列输入Transformer编码器。
分类Token: 通常在输入序列前加一个特殊的[CLS] token,最后用它的输出做分类。
输出层: Transformer输出后,提取[CLS] token的表征,送入MLP(全连接层)做分类。

(4) 他的解码器和编码器有什么不同

编码器(Encoder):
只包含自注意力(Self-Attention)机制,可全局访问整个输入序列。
输入是完整序列,无掩码。
解码器(Decoder):
第一层是带掩码的自注意力机制(Masked Self-Attention),防止当前时刻访问未来信息(保证自回归)。
第二层是编码器-解码器注意力(Encoder-Decoder Attention),解码时可关注编码器输出的全部信息。
解码器通常用于生成任务,比如机器翻译、文本生成等。
####(5) Mask编码
定义: Mask编码主要用于在Transformer解码器自注意力中,防止模型在生成时访问“未来”的token。
实现方式: 通过设置掩码矩阵,使得每个位置只能关注本身及之前的位置,未来位置注意力分数设为
−
∞
−∞(softmax后为0)。
作用: 保证解码器的自回归性质,实现一步步生成。

2. BN(Batch Normalization)的作用和好处

作用:
对每一层的激活(feature map)做归一化(标准化),使其均值为0,方差为1,然后通过可学习的缩放和平移参数恢复表达能力。

好处:
缓解内部协变量偏移(Internal Covariate Shift): 输入分布更稳定。
加速模型收敛: 允许更大学习率,训练更快。
缓解梯度消失/爆炸: 使得梯度传递更平稳。
一定程度上有正则化效果: 训练时引入噪声,减轻过拟合。
减少对初始权重敏感度。

3. Dropout的好处

防止过拟合: 随机丢弃一部分神经元,使网络不能过度依赖某些特征,提高模型泛化能力。
等价集成多个子网络: 不同训练步对应不同子网络,共享权重,类似集成学习,提升鲁棒性。
简化网络: 随机删除神经元,使网络更简单,减少复杂度。
减少神经元间的共适应关系(co-adaptation): 强迫网络学习更有用的、分布式的特征。

4. 梯度消失的原因

激活函数饱和: 如sigmoid、tanh,在输入大/小时导数趋近于0,反向传播时多层相乘导致梯度迅速变小。
权重初始化不当: 权重过小,多层相乘造成梯度指数级缩小。
深层网络结构: 层数越深,梯度链式法则相乘,容易导致梯度消失。
归一化问题: 激活分布不稳定,进一步加剧梯度消失。

5. ResNet为什么能减缓梯度消失的原因

引入残差连接(Residual Connection):
每一层输出是 y=F(x)+x,即直接加上输入,信息可以直接传递。
反向传播时,梯度可以直接通过“捷径”流向前面层,不会因多次乘以小于1的数而迅速消失。

本质原因:
保证了梯度可以有效传回前层,避免被激活函数/权重缩小。
使网络更容易训练更深的结构(如50、101、152层)。

数学解释:
残差连接相当于提供了恒等映射的通道,梯度可以绕过非线性变换直接传递。
额外好处:
提升模型表达能力,解决深层网络“退化”问题(深层网络比浅层性能差)。

  1. 在nums寻找最小的连续子数组使得它们的和大于所给的targets
    法1: 前缀和+二分
def search(s, k, n, t):
    t > s[n]:
        return -1
    l, r = k, n 
    res = n
    while l < r:
        mid = (l + r) >> 1
        if s[mid] >= t:
            res = mid
            r = mid - 1
        else:
            l = mid + 1
    return res

def func(targets, nums):
    if targets < sum(nums):
        return 0
    n = len(nums)
    s = [0] * (n + 1)
    for i in range(1, n+1):
        s[i] = s[i - 1] + nums[i]
    res = n
    for i in range(1, n+1):
        t = targets + s[i - 1]
        d = search(s, i, n, t)
        if d > i and d - i + 1 < res:
            res = d - i + 1
    return res

target = 7
nums = [2,3,1,2,4,3]
print(func(target, nums))

法2: 双指针

二面 50-60min

  1. 介绍项目
  2. 说说对最近比较火的多模态 图像生成的了解
#求一个数的N次幂  

def pow(k, n):
    if k == 0 and n == 0:
        return None
    flag = 1
    if n < 0:
        flag = 0
    res = 1
    while n > 0:
        if n % 2 == 1:
            res = res * k 
        k *= k
        n //= 2
    if flag == 1:
        return res
    return 1.0 / res

#全排列 
# input 5,3
# [(1,2,3),(1,2,4),(1,2,5),(2,3,4),(2,3,5),(3,4,5),...]
import copy

def dfs(l, res, n, m, index, level, tmp):
    if level > m:
        return 
    if index >= n:
        return
    if level == m:
        t = copy.deepcopy(tmp)
        res.append(tuple(t))
        return 
    for i in range(index, n - m + level + 1): 
        tmp.append(res[i])
        dfs(l, res, n, m, i+1, level+1, tmp)
        tmp.pop()

def pailie(n, m):
    l = range(1, n+1)
    res = []
    tmp = []
    dfs(l, res, n, m, 0, 0, tmp)
	return res

更多推荐