Fork me on GitHub

上海睿纵时面试

上海睿纵时机器人实习生 面试

公司介绍

一个初创公司,人数十分少,主要做机器人相关的业务。

面试问题

面试没啥硬核的问题,主要就是问问简历情况。想看八股的可以直接叉掉了。

1. Q: 自我介绍(点我展开) A:
2. Q: 你们浙大有一个博士后,也是做海洋方向的,姓戚,你认识吗? A: 不认识
3. Q: 介绍你做过的项目? A: 对简历里的一篇论文(SAR + LiDAR,物理参数反演)、一个项目(某海域背景场全水深预报)进行介绍
4. Q: 你这个模型的输入是什么,是纯图像输入还是激光雷达也有输入? A: 既有图像像素值输入也有激光雷达计算得到的粗糙度,某个位置的粗糙度相当于图像上对应样本点的一个label
5. Q: 你的模型效果怎么样? A: 给面试官展示论文的真实性检验图
6. Q: 你的模型效果怎么样? A: 给面试官展示论文的真实性检验图
7. Q: 你的某海域背景场全水深预报这个项目是你导师指导你做的吗,还是你自己做的? A: 这个项目是导师给我做的,但他不怎么管我,都是我自己做的 Q:你这个项目是语言用的是python吧? A:是的,主要用python
8. Q: 你这个项目的输入数据是什么? A: 主要是下载了20年的海洋学里一个叫HYCOM的数值模式数据,它有时间、深度、经纬度四个维度,通过20年的数据去训练一个 SimVPv2 模型。
9. Q: 你这个专业(海洋技术与工程)主要是什么方向? A: 浙大这个专业很杂,有做物理海洋的、机械的、控制的,我主要是做装备方向的。 Q:你是地球科学学院的吗? A:我是海洋学院的。 Q:那怪不得你不认识博士后,他是地科院的。
10. Q: 你cpp熟练吗(简历上有些会cpp)? A:cpp还可以,cpp11之前的都比较熟练 Q:后面的一些特性就不怎么用了是吧 A:是的
11. Q: 你了解transformer吗? A:transformer 我之前看过它的论文,但是没有实现过self-attention机制 Q:简单介绍一下transformer模型架构 A:八股
12. Q: 语义分割方面的模型你有了解吗? A:我之前有魔改过U-Net模型,主要是参照李晓峰的论文改的 Q:介绍一下你是怎么魔改的 A:我在U-Net的每一层增加了SE模块,这个SE模块具体干嘛过了太久有点忘了
13. Q: 目标检测这块的模型比如yolo这类你有了解吗? A:有看过yolo目标检测相关的论文,结果挺好的但是这块模型的原理没怎么了解
14. Q: 你目前有空来实习吗,你学校里没事了吗? A:我目前小论文已经录用了,学校里也没啥事,主要就是看导师愿不愿意放我出来实习,大论文我可以后面慢慢写,我工作量是做够了。

反问环节

15. Q: 你们公司这边的工作时间情况?需要加班吗? A:早上9点到9点半上班,晚上6点到6点半下班,周末双休,一般不加班,加班一般也都在7-8点就结束了。
16. Q: 公司业务? A:公司主要是做机器人业务的,辅助行人和自动驾驶方向。业务主要是有三块:一块是BEV感知,一块是语义分割(这个产品主要是出海),还有一块是目标识别。 Q:这个出海的产品主要是做国外业务? A:是的,国内目前没有这种产品,但是国外有竞品,我可以把图发给你看看。 Q:这个东西是一个实物啊? A:是的,是一个实物,重量大约5kg左右,用于给老人和残疾人提供避障服务。目前只有概念图,实物的话现在还没做。这块可能跟你的简历也不太相关了,因为这个东西纯视觉的一个东西,也没有激光雷达啥的。 Q:我没有什么问题了

结果

直接offer了。

上海柏楚笔试题

上海柏楚感知算法实习生 笔试题

考试总共100分钟,17题,还是挺紧张的。

后续联系HR,得到可能同学方向和我们业务方向不够匹配,没法继续推进流程的回复,已凉凉。

1. 论述题 (14*3)

  1. 一个数组 [4, 8, 6, 2, 5, 9, 1, 7, 3, 10],用一个 1*5 的中值滤波器滤波后的结果(边界补0)。

我的答案:[4, 4, 5, 6, 5, 5, 5, 7, 7, 7]
gemini答案:[4, 4, 5, 6, 5, 5, 5, 7, 3, 3]
补0后的数组:[0, 0, 4, 8, 6, 2, 5, 9, 1, 7, 3, 10, 0, 0]

  1. 相机手眼标定

相机安装在机械臂末端,在机械臂移动过程中随着机械臂一起运动。
eye_in_hand
有以下几种坐标系:

  • B:机械臂基座坐标系
  • E:机械臂末端执行器坐标系
  • C:相机坐标系
  • M:标定板坐标系
    有已下几种变换矩阵:
  • $T_{BE}$:机械臂基座坐标系到机械臂末端执行器坐标系的变换矩阵(可以通过正运动学求解得到)
  • $T_{BM}$:机械臂基座坐标系到标定板坐标系的变换矩阵(这两个都不会动)
  • $T_{CM}$:相机坐标系到标定板坐标系的变换矩阵

求:

  • $X$:机械臂末端执行器坐标系到相机坐标系的变换矩阵(4分)
  • 求解 $AX = BX$,并给出 A 和 B 的计算方法(10分)

我的答案(只知道要用上这三个变换):

1
2
1. $T_{CE} = T_{BE} * T_{BM}^{-1} * T_{CM}$
2. 没写

标准答案直接参考解析:
相关解析:https://develop.realman-robotics.com/AI/developerGuide/hand/

  1. resnet 的残差连接 和 ViT 的位置编码的作用? 训练效率和数据需求方面有哪些差异?
    我的答案(大概):
1
2
3
4
1. 残差连接可以解决多层非线性模型难以学习线性关系的问题,残差连接公式 $ x = x + res(x)$ (这里当时想成代码实现逻辑了,不是数学公式)。
ViT 的位置编码来源于transformer模型,通过把embedding后的词向量加上不同频率的正余弦编码,使得不同位置信息流动路径复杂度 `O(1)`。(只回答了transformer的位置编码的作用,ViT不会捏)

2. resnet 一般层数与参数量比ViT少,较容易训练,收敛速度更快,数据需求相对较少。

gemini 答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
**1. ResNet 残差连接 (Residual Connection)**

* **作用**
* **解决梯度消失/爆炸**:在深层网络中,梯度反向传播时容易变得非常小(消失)或非常大(爆炸)。残差连接 $y = F(x) + x$ 允许梯度直接通过恒等映射(Identity Mapping)传导到浅层,相当于搭建了“高速公路”,使得训练深层网络(如上百甚至上千层)成为可能。
* **打破网络退化**:理论上深层网络不应比浅层差(至少可以学成恒等映射),但实际中深层网络往往更难优化。残差结构让模型更容易学习到恒等映射(只需让 $F(x) \rightarrow 0$),从而保证加深网络层数时性能不会下降。
* **集成学习视角**:残差网络可以看作是许多不同深度路径的浅层网络的集成(Ensemble),增强了模型的鲁棒性。

**2. ViT 位置编码 (Position Encoding)**

* **作用**
* **注入序列顺序信息**:Transformer 的核心 Self-Attention 机制具有排列不变性(Permutation Invariant),即打乱输入 token 的顺序,输出结果(除了顺序变化)数值上是一样的。对于图像 Patch 序列来说,空间位置关系至关重要。位置编码通过将位置信息(绝对位置或相对位置)加到(或拼接到)输入 Embedding 上,让模型能够区分不同 Patch 的空间位置。
* **保持空间结构**:帮助模型理解图像的 2D 结构(如左上角、右下角、相邻关系等),弥补了 CNN 固有的归纳偏置(Inductive Bias,如平移不变性和局部性)在 Transformer 中的缺失。

**3. 训练效率与数据需求的差异**

* **训练效率**
* **ResNet**:由于引入了归纳偏置(卷积核的局部感受野和权值共享),ResNet 收敛速度通常较快,优化难度相对较低,在中小规模数据集上也能快速达到较好的效果。
* **ViT**:由于缺乏归纳偏置,ViT 需要从头学习像素间的长距离依赖和空间关系,训练初期收敛较慢,且对优化器(如 AdamW)和超参数(如 Learning Rate Warmup)更敏感。
* **数据需求**
* **ResNet**:对数据量的依赖相对较小,在 ImageNet-1k(128万张图)甚至更小的数据集上就能训练得很好。
* **ViT**:通常被认为是“数据饥渴”的(Data Hungry)。在中小数据集上容易过拟合,性能往往不如 ResNet。只有在超大规模数据集(如 JFT-300M, ImageNet-21k)上预训练后,ViT 的性能优势才能充分体现,超越 ResNet。

2. 选择题 (4*2 + 2*10)

  1. 下列关于数据结构的说法中,正确的是( )多选
    A. 数组随机访问复杂度 O(1)
    B. 二叉搜索树中序遍历的时间复杂度为 O(n)
    C. 忘了
    D. 哈希表的查找复杂度为 O(log n)
    我的答案:ABC(应该是对的)
    gemini答案:AB

  2. RANSAC 算法的说法中,正确的是( )单选
    A. 采样的次数越多,模型越准确
    B. 阈值
    C. 每次迭代都使用最小点集来拟合模型
    D. 单次拟合可以拟合出多个平面
    我的答案:A
    gemini答案:C

  3. 88 正方体 由若干11 正方体构成 表面涂色的块数( )单选
    A. 296
    剩下忘了都是300+
    我的答案:A
    gemini答案:A

  4. 仓库运来含水量为90%的一种水果100千克.一星期后再测,发现含水量降低到80%.现在这批水果的质量是__千克 单选
    A. 40kg
    B. 50kg
    C. 80kg
    D. 90kg
    我的答案:B
    gemini答案:B
    相关解析:https://qb.zuoyebang.com/xfe-question/question/a78e2d0d714e35752ef11d225e11166f.html

  5. 1000瓶饮料,3个瓶子可以再换一瓶,一共可以喝多少瓶?(不能另外再借瓶子) 单选
    A. 1333
    B. 1494
    C. 1499
    D. 1500
    我的答案:C
    gemini答案:C
    相关解析:https://www.nowcoder.com/questionTerminal/2569018b80044c4fab95b4d6752fbccf

  6. 12*5 = 61 在几进制下成立( )单选
    A. 7进制
    B. 8进制
    C. 9进制
    D. 10进制
    我的答案:C
    gemini答案:C

  7. 200个数冒泡排序200ms, 800ms 能排多少数?单选
    A. 200
    B. 400
    C. 600
    D. 800
    我的答案:B
    gemini答案:B

  8. 4对(), 能组成多少对字符串() 单选
    A. 5
    B. 10
    C. 12
    D. 14
    我的答案:B(简单枚举了一下)
    gemini答案:D

  9. 一个圆随机画两条弦,求两条弦相交的概率 单选
    A. 1/2
    B. 1/3
    C. 1/4
    D. 1/6
    我的答案:A(随便选了,来不及算)
    gemini答案:B
    https://blog.csdn.net/wwxy1995/article/details/108206111

  10. 彼此痛恨的甲、乙、丙三个枪手准备决斗。甲枪法最好,十发八中;乙枪法次之,十发六中;丙枪法最差,十发四中。如果三人同时开枪,并且每人只发一枪;谁活下来的机会大一些? 单选
    A. 甲
    B. 乙
    C. 丙
    D. 三人机会相等
    我的答案:D
    gemini答案:C
    https://blog.csdn.net/raojunyang/article/details/82291975

  11. 某家饭店中,一桌人边用餐边谈生意其中,一个人是哈尔滨人,两个人是北方人,一 个人是广东人,两个人只做电脑生意,三个人只做服装生意。如果以上介绍涉及餐桌上所有 的人,那么这一桌最少可能是几个人?最多可能是几个人?
    A.最少可能是 3 人;最多可能是 8 人。
    B.最少可能是 5 人,最多可能是 8 人。
    C.最少可能是 5 人,最多可能是 9 人。
    D.最少可能是 3 人,最多能是 9 人。
    我的答案:B
    gemini答案:B
    相关解析:https://wenku.baidu.com/view/7e6a22d60d22590102020740be1e650e52eacfd1.html?_wkts_=1766941582650

  12. 给甲、乙、丙三人各发一个正整数,并告诉他们他们三人的数字之和为14。
    甲对乙和丙说:我知道你们两人的数字一定不相等。
    乙想了想,对甲说:我们两人的数字之差一定比丙大。
    丙听完甲和乙的话后,依旧沉默不语。
    若甲乙丙三人都很聪明,且只要他们能推断出三人的数字分别是什么,那个人会在第一时间说出。(不考虑甲、乙见到丙沉默之后是否知晓)
    那么,丙的数字是多少? () 单选
    A. 1
    B. 2
    C. 3
    D. 4
    我的答案:A
    gemini答案:A
    相关解析:https://www.33iq.com/question/92507.html

gemini解析:

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
*正确答案应该是 A。**

以下是详细的逻辑推导过程:

**1. 分析甲(A)的话:**
* **条件**:$a + b + c = 14$,且 $a, b, c$ 都是正整数。
* **甲说**:“我知道你们两人的数字一定不相等。” ($b \neq c$)
* **推断**:甲知道 $a$,也就知道 $b+c = 14-a$。如果 $14-a$ 是偶数,那么 $b$ 和 $c$ 有可能相等(例如 $14-a=12$,则可能 $b=c=6$)。甲既然**敢肯定** $b \neq c$,说明 $b=c$ 的情况根本不可能发生。这意味着 $b+c$ 必须是奇数。
* **结论 1**:$14-a$ 是奇数 $\Rightarrow$ **$a$ 必须是奇数** ($1, 3, 5, 7, 9, 11$)。

**2. 分析乙(B)的话:**
* **乙说**:“我们两人的数字之差一定比丙大。” ($|a - b| > c$)
* **推断**:乙听了甲的话,知道 $a$ 是奇数。乙知道自己的数 $b$。乙敢肯定 $|a-b| > c$,说明对于**所有**满足条件的奇数 $a$,这个不等式都成立。
* 代入 $c = 14 - a - b$,不等式变为 $|a - b| > 14 - a - b$。
* 我们来测试 $b$ 的可能值(已知 $a$ 为奇数):
* 若 $b=7$:$a=1 \Rightarrow c=6, |1-7|=6 \ngtr 6$ (不成立)。
* 若 $b=8$:
* $a=1 \Rightarrow c=5, |1-8|=7 > 5$ (成立)
* $a=3 \Rightarrow c=3, |3-8|=5 > 3$ (成立)
* $a=5 \Rightarrow c=1, |5-8|=3 > 1$ (成立)
* (注意 $a$ 不能是 7,因为 $a$ 是奇数且 $a+b<14$)。
* 所以 $b=8$ 是可能的。
* 同理验证,$b=9, 10$ 也是可能的。
* 若 $b=11$:$a$ 只能是 1 ($c=2$)。此时乙能直接推断出 $a=1, c=2$。根据题目“只要他们能推断出...会在第一时间说出”,乙应该直接说“我知道了”,而不是说“差比丙大”。所以 $b \neq 11$。同理 $b \neq 12$。
* **结论 2****$b$ 的值只能是 8, 9, 10**

**3. 分析丙(C)的沉默:**
* **现象**:丙听完后依旧沉默。
* **推断**:丙知道 $c$,也知道 $a$ 是奇数,$b \in \{8, 9, 10\}$。如果丙能根据自己的 $c$ 唯一确定一组 $(a, b)$,他就会说话。**丙沉默说明对于他的 $c$,至少有两组 $(a, b)$ 符合条件。**

**4. 验证选项:**

* **选项 B ($c=2$):**
* 已知 $a+b = 12$。
* 限制条件:$a$ 是奇数,$b \in \{8, 9, 10\}$。
* 可能的组合:
* 若 $b=8 \Rightarrow a=4$ (偶数,不符)
* 若 $b=9 \Rightarrow a=3$ (奇数,符合) $\rightarrow$ 组合 $(3, 9, 2)$
* 若 $b=10 \Rightarrow a=2$ (偶数,不符)
* **结果**:如果 $c=2$,只有唯一解 $(3, 9, 2)$。丙会立即知道答案并说出来。**但这与“丙沉默”矛盾。所以 $c \neq 2$。**

* **选项 A ($c=1$):**
* 已知 $a+b = 13$。
* 限制条件:$a$ 是奇数,$b \in \{8, 9, 10\}$。
* 可能的组合:
* 若 $b=8 \Rightarrow a=5$ (奇数,符合) $\rightarrow$ 组合 $(5, 8, 1)$
* 若 $b=9 \Rightarrow a=4$ (偶数,不符)
* 若 $b=10 \Rightarrow a=3$ (奇数,符合) $\rightarrow$ 组合 $(3, 10, 1)$
* **结果**:如果 $c=1$,存在两组解 $(5, 8, 1)$ 和 $(3, 10, 1)$。丙无法区分是哪一组,所以会保持沉默。**这与题目描述相符。**

**结论:**
根据严格的逻辑推理,**正确答案应该是 A (1)**

3. lc算法题(15*2)

  1. 压缩字符串
    参数给的是字符串类型的,返回也要求字符串类型。
    题目要求返回压缩后的字符串,没法压缩的返回原字符串。但没给数据量的范围。。。
    面试官要求必须用cpp解决,不能自行添加测试样例,但允许调试代码
    (测试框架用的googleTest,cout的输出在终端好像也看不见。。)

case1 input:

1
aaacbb

output:

1
a3c1b2

赛场代码 感觉加一个特判就能解决?也是傻逼了,过了2/3个hidden case:

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
39
class Solution {
public:
string compressString(string arg1)
{
string ans = "";
char x = arg1[0];
int cnt = 1;
bool hasCompressed = false;
for(int i = 1; i < arg1.size(); i++)
{
if(arg1[i] == x)
{
cnt++;
}
else
{
ans += x;
// 这里当时写了一个while循环处理了多位数,不知道测评是什么环境不敢用to_string
// string num = "";
// while(cnt > 0)
// {
// num = (char)(cnt % 10 + '0') + num;
// cnt /= 10;
// }
// ans = ans + num;
ans += to_string(cnt);

x = arg1[i];
cnt = 1;
}
}
if(cnt > 0)
{
ans += x;
ans += to_string(cnt);
}
return ans;
}
};

标准答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
string compressString(string arg1) {
string compressed = "";
int count = 1;
bool hasCompression = false;
for (int i = 1; i <= arg1.size(); ++i) {
if (i < arg1.size() && arg1[i] == arg1[i - 1]) {
count++;
hasCompression = true;
} else {
compressed += arg1[i - 1];
compressed += to_string(count);
count = 1;
}
}
return hasCompression ? compressed : arg1;
}
};
  1. 稀疏向量的点积

需要写完整的程序,包括输入输出。输入都给cpp了,肯定就得写cpp了。
只给了一个案例的输入:

1
2
vector<pair<int, double> > v1 = {{0, 1.0}, {2, 2.0}, {4, 3.0}};
vector<pair<int, double> > v2 = {{1, 4.0}, {2, 3.0}, {4, 4.0}};

需要实现的函数:

1
double sparseVectorDotProduct(vector<pair<int, double>> v1, vector<pair<int, double>>v2);

初始框架:

1
2
3
4
5
6
7
8
9
#include <iostream>
#include <vector>
#include <utility>
using namespace std;

int main()
{
return 0;
}

赛场代码(双指针,写的复杂了点):

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
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include <vector>
#include <utility>
using namespace std;

typedef vector<pair<int, double>> vpid;

double sparseVectorDotProduct(vpid v1, vpid v2) {
double result = 0.0;
if (v1.empty() || v2.empty())
return result;
int v1_ptr = 0, v2_ptr = 0;
int pos1, pos2;
while (v1_ptr < v1.size() && v2_ptr < v2.size()) {
if(pos1 == v1.size())
pos1 = -1;
else
pos1 = v1[v1_ptr].first;
if(pos2 == v2.size())
pos2 = -1;
else
pos2 = v2[v2_ptr].first;

if (pos1 == pos2) {
result += v1[v1_ptr].second * v2[v2_ptr].second;
v1_ptr++; // 这里之前差点忘记加了,导致程序一直卡在这
// v2_ptr++; // 这里赛场上没有加,其实可以加
} else if (pos1 < pos2) {
v1_ptr++;
} else {
v2_ptr++;
}
}
return result;
}

int main()
{
frepoen("input.txt", "r", stdin);
int n, m;
cin >> n >> m;
// 提前初始化,防止segmentation fault
vector<pair<int, double> > v1(n), v2(m);
for(int i = 0; i < n; i++)
cin >> v1[i].first >> v1[i].second;
for(int i = 0; i < m; i++)
cin >> v2[i].first >> v2[i].second;
double result = sparseVectorDotProduct(v1, v2);
cout << result << endl;
return 0;
}

双指针精简版:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
double sparseVectorDotProduct(vpid v1, vpid v2) {
double result = 0.0;
int i = 0, j = 0;
while (i < v1.size() && j < v2.size()) {
if (v1[i].first == v2[j].first) {
result += v1[i].second * v2[j].second;
i++;
j++;
} else if (v1[i].first < v2[j].first) {
i++;
} else {
j++;
}
}
return result;
}

通过自定义域名中转api

1. 域名准备

通过 https://dash.domain.digitalplat.org/ 网站获取一个免费自定义域名
(注意最好申请 .dpdns.org 结尾的,.us.kg 结尾的需要key,而这个key是要钱的)

注意自定义域名需要设置dns解析服务器,这里以cloudflare dns解析服务器为例进行配置:
域名DNS解析服务器设置

申请好后可以把域名托管到 cloudflare上,具体操作如下:

  • 登录 cloudflare 账号,点击 onboard domain
    onboard domain
  • 填入申请好的域名后,剩下全默认,continue
    filling domain
  • 收费计划选择免费即可
    free plan

2. 启动中转项目

中转项目 fork到你个人的仓库,然后部署到vercel上
(注意不要部署到cloudflare上,否则会被分配到香港的边缘节点,无法访问gemini)

在 Cloudflare 的 DNS记录 中添加vercel提供的DNS记录:

vercel dns record

过几分钟访问你申请的域名,看到proxy成功启动说明部署成功。

proxy success

3. 在前端平台上使用

可以在 lobechat 平台上部署你的域名。

lobe chat

lobe setting

免费服务器的选择

深度学习模型的训练和部署通常需要强大的计算资源,尤其是GPU加速。对于个人用户或小型项目来说,购买高性能服务器可能成本较高,因此选择免费的服务器资源成为一个不错的选择。以下是我用过的一些免费服务器选项:

1. 启智协作平台

启智协作平台 是一个提供免费GPU、NPU等计算资源的平台。平台支持多种深度学习框架,如TensorFlow和PyTorch。注册后,用户可以获得50个积分的免费额度,用于租用如GPU、NPU等计算资源。

1.1 创建任务

首先先需要创建数据集和项目,然后才能创建云脑任务。创建数据集和项目流程略。

创建数据集示例

任务主要分为四种类型:

  • 调试任务(最多运行4小时)
  • 训练任务(适合长期训练,但不会返回运行时出现的错误)
  • 推理任务
  • 通用任务(需要审批)

下面以训练任务为例介绍如何创建任务:

训练任务

基本信息这边根据个人情况选择即可,建议选择NPU,不仅显存、内存、CPU核数比传统GPU高,并且消耗积分也更少。

镜像的话可以选择一个别人用的镜像(最好带cann),也可以把自己调试任务的环境保存成镜像。启动文件的话选择自己训练主程序入口(路径不要带点,如./examples/myexp_NPU.py,否则运行出错)。

1.2 tricks

  • 每天可以通过创建数据集、创建项目仓库等方式获取积分。
  • 还可以通过每日运行一次任务获得10个积分。
  • 任务终止后只有 work 路径下的文件会被保存,其他路径下的文件还有已经配好的环境都会丢失,建议把结果保存到 work 路径下,并且在主程序里添加pip下载依赖的代码。
1
2
import os
os.system('pip install numpy hickle lightning torch==2.1.0 torchvision xarray fvcore lpips pandas scikit-image timm tqdm einops PyWavelets')
  • 如果检测不到 NPU,可以在终端输入以下命令:
1
source /usr/local/Ascend/ascend-toolkit/set_env.sh
  • GPU 训练的代码可以通过torch_npu框架的代码转换直接在 NPU 上运行,代码转换代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
try:
import torch_npu
from torch_npu.contrib import transfer_to_npu

# 1. 修复 get_device_capability 返回 None 的问题
# NPU 不支持这个概念,我们伪造一个返回值 (比如 8.0,代表 Ampere 架构,骗过 Lightning)
if not hasattr(torch.cuda, 'get_device_capability'):
torch.cuda.get_device_capability = lambda device=None: (8, 0)
else:
# 如果已经存在但返回 None (transfer_to_npu 的副作用),则覆盖它
original_get_cap = torch.cuda.get_device_capability
def patched_get_cap(device=None):
cap = original_get_cap(device)
if cap is None:
return (8, 0) # 伪造一个支持 TF32 的架构
return cap
torch.cuda.get_device_capability = patched_get_cap
print("Info: 成功启用 NPU 自动迁移 (transfer_to_npu)。")
# 2. 禁用 Lightning 的 TF32 精度检查 (NPU 不需要这个)
torch.set_float32_matmul_precision('medium')
except ImportError:
print("Info: 未检测到 torch_npu,将使用标准 CPU/GPU 模式。")

2. Kaggle

Kaggle 是一个数据科学竞赛平台,提供免费的GPU资源(NVIDIA Tesla P100)。用户可以创建Notebook并使用这些资源进行深度学习模型的训练和测试。Kaggle 每周提供30小时的GPU使用时间,适合中小型项目,且使用方便。

2.1 创建Notebook

在Kaggle主页,点击右上角的“New Notebook”按钮,选择“Notebook”选项。然后在Notebook界面,点击右侧的“Settings”图标,选择“Accelerator”为GPU。注意需要手机验证后才能使用GPU资源。

2.2 tricks

  • Kaggle的GPU资源是按周计算的,每周六重置30小时的使用时间。
  • 需要预先把数据上传到 input 里面,模型默认保存在 output 路径下
  • 如果在本地已经写好了训练代码,可以先上传到input,通过以下代码拷贝到工作区
1
2
3
4
5
6
7
import shutil

src_dir = '/kaggle/input/openstl-hycom-code'
dst_dir = '/kaggle/working/openstl-hycom-code'

# 如果目标文件夹已存在,需先删除或用 dirs_exist_ok=True(Python 3.8+)
shutil.copytree(src_dir, dst_dir, dirs_exist_ok=True)
  • 通过下面这个魔术命令可以修改在 kaggle路径下的代码内容:
1
2
3
4
%%writefile /kaggle/working/path/to/yourcode/myexp.py

import os
# ..new code..
  • Notebook中代码在docker容器中运行,每次运行前都需要配置环境,配置环境代码如下所示:
1
2
3
# 在训练代码入口添加
import os
os.system('pip install numpy')
  • Notebook运行结束后,可以从 output 路径下下载所需模型文件
  • 默认工作路径 /kaggle/working 限制大小为20G,可以考虑把模型工作路径迁移到 /kaggle/tmp 文件夹下:
1
2
3
# notebook的魔术命令
!mkdir /kaggle/tmp
%cd /kaggle/tmp
  • 可以把模型和训练日志等上传到模型托管平台(如huggingface(可免费存100G)),上传代码如下所示:
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
class HuggingFaceSyncCallback(Callback):
def __init__(self, repo_id, token, src_dir, log_dir):
super().__init__()
self.repo_id = repo_id
self.token = token
self.src_dir = src_dir
self.log_dir = log_dir
self.api = HfApi(token=token)
self.current_epoch = 0

def on_train_epoch_end(self, trainer, pl_module):
self.current_epoch = trainer.current_epoch
self._upload()

def _upload(self):
try:
# 上传整个 checkpoints 文件夹
self.api.upload_large_folder(
folder_path=self.src_dir,
repo_id=self.repo_id,
repo_type="model",
# path_in_repo="checkpoints", # 在仓库中的路径
# commit_message=f"Upload checkpoints epoch {self.current_epoch}",
num_workers=4, # 并发上传数
print_report=True,
print_report_every=60, # 每60秒打印进度
)

self.api.upload_folder(
folder_path=self.log_dir,
repo_id=self.repo_id,
repo_type="model",
path_in_repo="lightning_logs", # 在仓库中的路径
commit_message=f"Upload logs epoch {self.current_epoch}"
)
print("Successfully uploaded checkpoints to HuggingFace Hub")
except Exception as e:
print(f"Upload failed: {e}")
  • 可以从huggingface下载最新的checkpoint再次训练,代码如下:
1
2
3
4
5
6
7
8
from huggingface_hub import hf_hub_download

# 下载 last.ckpt 到本地
model_path = hf_hub_download(
repo_id="marinerubbish/openstl-hycom-model",
filename="./last.ckpt",
local_dir="." # 下载到哪个文件夹
)

第4节-数据类型

1. 数值类型

整形分为 TINYINTSMALLINTMEDIUMINTINTBIGINT 四种类型,
大小分别为 1-4byte 和 8byte。

浮点型分为 FLOATDOUBLEDECIMAL。前两种大小与C语言的float和double相同。
DECIMAL 大小由长度M(精度) 和 小数点后位数d(标度) 决定。

比如要存储分数字段,因为最高分为100.0,有四位数、一位小数。
因此用 DECIMAL(4,1) 作为其数据类型。

2. 字符串类型

  • Copyrights © 2022-2026 CPY
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信