Jasaxion一只大雄

风打,碎琉璃; 打不碎的,是那阳光漫地。The wind strikes, shattering the glazed glass; Yet unbroken remains the sunlight spilling across the earth.

[2025|面经]商汤大模型见习研究员-offer

2025-03-01


起因

​ 哇啦啦啦,研一下一开学,乌拉拉的一片人去实习了,本来我的意愿也不是很浓的,但最后左思右想后,还是决定也去尝试找一下实习,工程实习宁可不做,希望可以有一些成果产出的,科研类型的实习肯定优先。

​ 一次偶然的机会刷到公众号提到商汤见习研究员的实习,听到这个名字就感觉应该很偏研究,我上午马上匆匆改完简历然后直接邮件联系,没想到下午就来电话问我有没有意愿来参与实习,简单介绍了一下他们做的内容,虽然跟我的研究内容估计只有 30% 的相似性,但我还是希望能够推我一下,很快就开始安排面试时间。

嘎嘎!没想到这么快!

好慌,我已经 N 久没刷过算法题了!!!然后对于简历上写的一些内容如机器学习等课程也很久没复习了,距离一面还剩 4 天,得努努力了。

image-20250306170755513

一轮面试

​ 首先一开始就是巴拉巴拉介绍自己的项目,面试官的水平我觉得还是挺高的,因为从我蹩脚的表述中,她都能详细地复述我所讲的项目细节,还好我对自己的项目和论文非常熟悉,所以可以轻松应对了。

面试官问得问题全是我项目和论文里面的细节,也没有问其他的,总共面试时长大约有1 个小时。

做了一道算法题「动态规划」

​ 算法题:找出连续的和最大且最长的子数组 (leetcode 的付费题) —>最后是做出来了。

大概如下,例如一个数组:2 -4 3 -1 2 -4 3,你需要返和最大的子数组

1
2
3
4
5
6
input: 

n = 7
[2 -4 3 -1 2 -4 3]

output:  [3, -1, 2] = 4

思路:

  1. 定义 dp 数组:dp[i]表示下标为 i的序列中的最大连续数组和;
  2. 状态转移:
    1. dp[i] = dp[i-1] + x[i] if x[i] + dp[i-1] > x[i] 表示加入这个元素,为最大
    2. else dp[i] = x[i] 表示忽略之前的元素最大
    3. 换句话说就是取当前位置的最大值,如果之前的序列有帮助则加入,没帮助则当前元素的值就是最大,忽略之前的数组
  3. 边界:dp[0] = x[0]
  4. 遍历顺序:0….n-1
  5. 答案 :max(dp[0…n-1])
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include<bits/stdc++.h>

using namespace std;
const int N = 10010;
int x[N];
int dp[N];
int ans = -9f9f9f9f;
int main(){
  int n;
  cin >> n;
  for(int i = 0; i < n; i ++){
    cin >> x[i];
  }
  dp[0] = x[0];
  for(int i = 1; i < n; i ++){
    dp[i] = max(dp[i-1] + x[i], x[i]);
    ans = max(ans, dp[i]);
  }
  return ans;
}

优化,可以发现dp数组只依赖于前一个状态的信息,可以优化存储空间为一个变量,存储之前的状态即可

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include<bits/stdc++.h>

using namespace std;
const int N = 10010;
int x[N];
int dp;
int ans = -9f9f9f9f;
int main(){
  int n;
  cin >> n;
  for(int i = 0; i < n; i ++){
    cin >> x[i];
  }
  dp = x[0];
  for(int i = 1; i < n; i ++){
    dp = max(dp + x[i], x[i]);
    ans = max(ans, dp);
  }
  return ans;
}

二轮面试

​ 首先又是个人项目和论文细节的介绍,这里不多提了。

面试官很无奈地说:这个跟我们的研究的内容有什么关系?(我巴拉巴拉硬扯上关系了)把什么检索增强还有什么大模型 LLM 进行数据生成等都杂糅在一起。(企图蒙混过关,啊,其实已经尽力了

二面是主管面试,主管水平很高,首先看起来似乎对我的论文和科研能力首先表示了赞同,但也对我产生了诸多质疑,包括研究方向匹配度还不高,你自己的研究怎么办?达到了毕业要求吗?老师知道吗?很多问题,可以看出来面试官关心很多,考虑也非常多,在打消了老师的一些顾虑之后,问了几个问题。

大部分都是个人简历和项目论文经历的问题,下面是两个通用的问题:

  1. 手写自己最熟悉的排序算法,任何排序算法都可以,说出时间复杂度

我直接蹦出一个快速排序,虽然感觉用很简单的插入排序、选择、冒泡应该都无所谓

下面抛出当时写的冒泡排序算法「因为本地没有 cpp 编译器,于是老师给了个 onlinejudge 网站,哈哈,二面用的是一个奇怪的视频面试软件,我找了老半天才找到聊天窗口」

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <bits/stdc++.h>

using namespace std;
int n = 5;
int x[5] = {5,-2,3,1,-10};

int get_participant(int low, int high){
	int pivot = x[high]; //选择最后一个元素为基准
  int i = low - 1; //i 是<= pivot 元素的边界
  
  for(int j = low; j < high; j ++){
    if(x[j] <= pivot){ //如果当前元素小于基准值
      i ++ ;
      swap(x[i], x[j]); //将元素移动到左边
    }
  }
  swap(x[i+1], x[high]); //将 pivot 放在中间
  return i + 1; //返回 pivot 的位置
}

void quick_sort(int low, int high){
  if(low < high){
    int pi = get_participant(low, high);
    
    //递归操作
    quick_sort(low, pi-1);
    quick_sort(pi+1,high);
  }
  
}

int main(){
  quick_sort(0,n-1);
  for(int i = 0; i < n; i ++){
    cout << x[i] << " ";
  }
  return 0;
}

最好的情况 O(n),最坏的情况O(n^2),平均时间复杂度O(nlogn)

出乎意外,还好很简单,小菜一碟

  1. 给出一个实际场景,要我任意建模机器学习模型
1
2
3
4
任意选择机器学习模型,你认为简单的都可以
数据如下:
|体重|身高|性别|年龄|社交媒体评论|
要求从数据处理开始,逐步构建机器学习模型,根据后面的列值来预测体重。

插曲:太久没看机器学习,我知道这个是个回归问题,没想到脑子一热直接说出个逻辑回归,救命,短路了。不过在面试官的提醒下,马上改口。

我的回答:

首先肯定是对数据进行清洗,清洗包括冗余数据、错误数据、离群数据进行清理,完成数据清理后,这是一个连续值的预测任务,我会选择采用多元线性回归模型,首先对于性别,需要将其转化为 0 和 1 的值,其次,对于社交媒体评论,我会选择采用 word embedding 将其转化为向量,然后求该向量的平均值作为该特征值,至此,所有的特征都转化为了数值。

对于多元线性回归的参数求解,第一种比较暴力的方法是采用网格搜索不断地迭代搜索以找到最合适的参数点,另外一种直接求解的方法需要使用到数学方法,使用数学求解多元线性回归,可以采用高斯消元等方法来直接求解。

最后我们可以根据 rmse 或 mae 来对模型进行评估,训练过程中可以关注模型的 loss 值的变化,以防止训练过程中失误。

HR面

​ 简单打了个电话,让我选择一个到岗时间,然后加了 HR 微信,然后就结束了,效率很快。

总结

​ 其实经过面试后,我也学习到了很多,能感受到面试官的学识真的很丰富,水平真的很高,(巧思)最后反问希望面试官能够给我自己提一些建议,我觉得受益匪浅。

​ 如果未来就业的话,实习经历还是很重要的,如果继续深造读博的话(感觉不继续深造也要),要经常去更新自己的知识储备,要多去 follow 一些当前流行的技术,然后了解和参与一些开源项目,来扩大自己的影响力。

终身学习,谨记于心🌸。

坐等审批完成,来入职链接!