面试小米汽车大模型算法岗,最后把 offer 拒了。。。

节前,我们星球组织了一场算法岗技术&面试讨论会,邀请了一些互联网大厂朋友、参加社招和校招面试的同学,针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。


汇总合集:《大模型面试宝典》(2024版) 发布!


周五,一位星球成员向我咨询要不要去小米汽车,说自己有点犹豫,纠结点是每天几乎10点之后下班,说不太稳定。虽然拿到了小米汽车的offer,内心很纠结,最后这位同学拒了小米汽车的offer。

今天我把面试题总结一下分享出来。希望对大家有帮助,更多大厂面试题、参考答案,文末社群中获取,喜欢本文记得收藏、关注、点赞。

1. 自我介绍

在自我介绍环节,我清晰地阐述了个人基本信息、教育背景、工作经历和技能特长,展示了自信和沟通能力。

2. 技术问题

2.1 self-attention的计算方式?

微信截图_20240123195056.png)

2.2 说一下 transformer的模型架构和细节?

微信截图_20240123195332.png)

2.3 说一下大模型高校参数微调方式 p-tuning v2?

P-Tuning V2在P-Tuning V1的基础上进行了下述改进:

  • 在每一层都加入了Prompts tokens作为输入,而不是仅仅加在输入层,这与Prefix Tuning的做法相同。这样得到了更多可学习的参数,且更深层结构中的Prompt能给模型预测带来更直接的影响。

  • 去掉了重参数化的编码器。在 P-tuning v2 中,作者发现重参数化的改进很小,尤其是对于较小的模型,同时还会影响模型的表现。

  • 针对不同任务采用不同的提示长度。提示长度在提示优化方法的超参数搜索中起着核心作用。在实验中,我们发现不同的理解任务通常用不同的提示长度来实现其最佳性能,这与Prefix-Tuning中的发现一致,不同的文本生成任务可能有不同的最佳提示长度。

  • 可选的多任务学习。先在多任务的Prompt上进行预训练,然后再适配下游任务。一方面,连续提示的随机惯性给优化带来了困难,这可以通过更多的训练数据或与任务相关的无监督预训练来缓解;另一方面,连续提示是跨任务和数据集的特定任务知识的完美载体。

2.4 在 大模型任务中,你用到 LoRA,讲一下 LoRA 实现原理?

LoRA 的思想很简单:

  • 在原始 PLM (Pre-trained Language Model) 旁边增加一个旁路,做一个降维再升维的操作,来模拟所谓的intrinsic rank。

  • 训练的时候固定 PLM 的参数,只训练降维矩阵 A 与升维矩阵 B 。而模型的输入输出维度不变,输出时将 BA 与 PLM 的参数叠加。

  • 用随机高斯分布初始化 A ,用 0 矩阵初始化 B ,保证训练的开始此旁路矩阵依然是 0 矩阵。

2.5 你知道为什么现在的大语言模型都采用Decoder only架构么?

大模型从模型架构上主要分为三种:Only-encoder, Only-Decoder, Encoder-Decoder三种模型架构

  • Only-encoder:例如BERT,通过在大规模无标签文本上进行预训练,然后在下游任务上进行微调,具有强大的语言理解能力和表征能力。

  • Only-Decoder: 例如GPT,通过在大规模无标签文本上进行预训练,然后在特定任务上进行微调,具有很强的生成能力和语言理解能力。

  • Encoder-Decoder:例如T5(Text-to-Text Transfer Transformer)可以用于多种自然语言处理任务,如文本分类、机器翻译、问答等。

而LLM之所以主要都用Decoder-only架构,除了训练效率和工程实现上的优势外,在理论上是因为Encoder的双向注意力会存在低秩问题,这可能会削弱模型表达能力,就生成任务而言,引入双向注意力并无实质好处。而Encoder-Decoder架构之所以能够在某些场景下表现更好,大概只是因为它多了一倍参数。所以,在同等参数量、同等推理成本下,Decoder-only架构就是最优选择了。

2.6 为什么大模型进行SFT后,LLM不升反降呢?

SFT(Supervised Fine-Tuning)是一种常见的微调技术,它通过在特定任务的标注数据上进行训练来改进模型的性能。然而,SFT可能会导致模型的泛化能力下降,这是因为模型可能过度适应于微调数据,而忽视了预训练阶段学到的知识。这种现象被称为灾难性遗忘,可以使用一些策略,如:

  • 使用更小的学习率进行微调,以减少模型对预训练知识的遗忘。

  • 使用正则化技术,如权重衰减或者早停,以防止模型过度适应微调数据。

  • 使用Elastic Weight Consolidation(EWC)等技术,这些技术试图在微调过程中保留模型在预训练阶段学到的重要知识。

2.7 Transformer为何使用多头注意力机制

多头保证了transformer可以注意到不同子空间的信息,捕捉到更加丰富的特征信息。

2.8 lora的矩阵怎么初始化?为什么要初始化为全0?

初始化时,矩阵 A 随机高斯初始化,矩阵 B 初始化为0。 之所以要这样初始化的原因是,在初始阶段这两个矩阵相乘为0,可以保证在初始阶段时,只有左边的主干生效。 然后 BA 还会乘以一个缩放因子 frac {alpha} {r} , alpha 也由我们自己指定。

2.9 ZeRO,零冗余优化器的三个阶段?

将优化器状态分割到不同设备上,减少内存占用;除了优化器状态,还将模型参数分割到不同设备上;将梯度和优化器状态也分割到不同设备上,实现最大的内存节省。

2.8 介绍一下stable diffusion的原理

Stable Diffusion 总共包含三个主要的组件,其中每个组件都拥有一个独立的神经网络:

  1. Clip Text 用于文本编码。 输入:文本 输出:77 个 token 嵌入向量,其中每个向量包含 768 个维度

  2. UNet + Scheduler 在信息(潜)空间中逐步处理 / 扩散信息。 输入:文本嵌入和一个由噪声组成的初始多维数组(结构化的数字列表,也叫张量 tensor)。 输出:一个经过处理的信息阵列

  3. 自编码解码器(Autoencoder Decoder),使用处理过的信息矩阵绘制最终图像的解码器。 输入:处理过的信息矩阵,维度为(4, 64, 64) 输出:结果图像,各维度为(3,512,512)

2.9 Stable Diffusion里是如何用文本来控制生成的?

Stable Diffusion是一种潜在扩散模型,主要通过自动编码器(VAE),U-Net以及文本编码器三个核心组件完成用文本来控制生成的图像。Unet的Attention模块Latent Feature和Context Embedding作为输入,将两者进行Cross Attenetion操作,将图像信息和文本信息进行了融合,整体上是一个经典的Transformer流程。

2.10 Stable Diffusion相比Diffusion主要解决的问题是什么?

Diffusion的缺点是在反向扩散过程中需要把完整尺寸的图片输入到U-Net,这使得当图片尺寸以及time step t足够大时,Diffusion会非常的慢。

2.11 介绍一下 CLIP

对比学习训练:一个batch的N张图片和文本进行对比;首先分别进行编码->再投影到相同特征维度->计算相似度;对角线为标签,计算交叉熵损失

2.12 VAE和VQ-VAE的区别

2.13 VAE公式推导了解吗

2.14 对比损失怎么计算的?

3. Leetcode 题

具体题意记不清了,但是类似 【215. 数组中的第K个最大元素】

  • 题目内容

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:

输入: [3,2,1,5,6,4], k = 2
输出: 5
示例 2:

输入: [3,2,3,1,2,4,5,5,6], k = 4
输出: 4
  • 提示:

  • 1 <= k <= nums.length <= 105

  • -104 <= nums[i] <= 104

  • 题目解答

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        nums_len = len(nums)
        # 1.构建大顶堆
        for i in range(math.floor(nums_len/2),-1,-1):
            # 从第一个非叶子结点从下至上,从右至左调整结构
            self.adjustHeap(nums,i,nums_len)
        # 2.调整堆结构+交换堆顶元素与末尾元素
        for i in range(nums_len-1,nums_len-1-k,-1):
            # 将堆顶元素与末尾元素进行交换
            self.swap(nums,0,i)
            # 重新对堆进行调整
            self.adjustHeap(nums,0,i)
        return nums[-k]
    
    def adjustHeap(self,nums,i,nums_len):
        '''
            功能:交调整大顶堆(仅是调整过程,建立在大顶堆已构建的基础上)
            @param nums        List 数组
            @param i           int  索引1
            @param nums_len    int  长度 
            @retusn
        '''
        left = 2*i+1    # i 的 左节点
        right = 2*i+2   # i 的 右节点
        largest = i     # 用于标记当前最大的节点值得索引,先取出当前元素i
        # 比较 左节点 和 当前节点 的值
        if left < nums_len and nums[left] > nums[largest]:
            largest = left
        # 比较 左节点 和 当前节点 的值
        if right<nums_len and nums[right]>nums[largest]:
            largest = right
        # 将 当前节点 和 最大节点 交换,然后重新构建 堆
        if largest!=i:
            self.swap(nums,i,largest)
            self.adjustHeap(nums,largest,nums_len)
        
    def swap(self,nums,a,b):
        '''
            功能:交换元素
            @param nums List 数组
            @param a    int  索引1
            @param b    int  索引2 
            @retusn
        '''
        nums[a],nums[b] = nums[b],nums[a]
  • 32
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值