被新公司逼着学机器学习后我悟了
上周五晚上十一点半,我盯着屏幕上跑飞了的loss曲线,第三次想砸键盘。
旁边工位的测试小哥探过头来:"哥,你这又炸了?"
我叹了口气,把脸埋进手里。来这家新公司才两个月,本以为凭着我这几年在DevOps和K8s上攒下的经验,能舒舒服服地搞搞自动化运维、写写CI/CD流水线,结果入职第二周,leader就笑眯眯地跟我说:"小陈啊,咱们团队最近在搞AI应用落地,你技术底子好,这块你也一起跟一下?"
我当时内心是崩溃的。我一个写YAML的,你让我搞机器学习?
但没办法,求职市场现在卷成啥样大家心里都有数。上个月面试的时候我就发现,稍微好点的岗位,JD里恨不得把"熟悉大模型微调"写进基本要求。与其被动挨打,不如主动学学。再说了,来都来了(经典四字真言)。
所以这两个月,我白天搞K8s集群维护、写Helm Chart,晚上就啃机器学习。今天这篇文章,算是我这两个月入门学习的一个阶段性总结。不讲那些高大上的数学推导,就聊聊一个运维老兵是怎么从零开始理解机器学习这玩意儿的。
先搞清楚:机器学习到底在干嘛
说实话,刚接触的时候我被各种名词搞晕了。什么监督学习、无监督学习、强化学习,什么损失函数、梯度下降、过拟合……每个字都认识,连一起就懵了。
后来我想明白了一件事:机器学习本质上就是在"找规律"。
你想想我们运维做故障排查是啥思路?线上告警了,CPU飙到90%,内存快满了,QPS突然掉了一半。我们根据经验判断:哦,可能是某个服务内存泄漏了,或者是下游数据库连接池打满了。这个"根据经验判断"的过程,其实就是人脑在做"模式识别"。
机器学习干的事情一样,只不过它不是靠人拍脑袋的经验,而是靠数据来"找规律"。
举个我工作中碰到的真实场景。我们K8s集群之前经常出OOM(Out of Memory),每次都是pod被kill掉,然后我们手动去调resources.limits。后来我就想,能不能根据历史监控数据,让模型预测哪些pod快要OOM了?
这就是一个典型的机器学习问题:
- 输入(特征):pod的内存使用率、增长趋势、历史OOM次数、运行时长等
- 输出(标签):未来1小时内是否会OOM(是/否)
- 模型:从历史数据中学习"什么样的特征组合意味着要OOM"
想通了这个,后面的概念就好理解了。
监督学习 vs 无监督学习
这俩区别用大白话说就是:
监督学习——老师告诉你答案,你照着学。比如我给你一万张猫狗图片,每张图片都标好了"这是猫""这是狗",你从中学习区分猫狗的特征。对应到运维场景,就是我有历史故障数据,每条数据都标好了故障原因,我让模型学习"什么症状对应什么故障"。
无监督学习——没有老师,你自己去发现数据里的规律。比如给你一堆用户行为数据,你不告诉模型这是什么意思,让它自己把相似的行为聚成几类。对应到运维场景,就是我从集群监控数据里自动发现异常模式,但我事先不告诉它"异常"长什么样。
入门阶段,先把监督学习搞明白就够了,因为大部分实际应用都是监督学习。
损失函数:模型是怎么"学习"的
这是我觉得最核心的一个概念。
模型"学习"的过程,说白了就是不断犯错、纠错、再犯错、再纠错的过程。那怎么衡量它犯了多少错呢?这就需要损失函数(Loss Function)。
损失函数就是一个数学公式,用来计算模型预测值和真实值之间的差距。差距越大,loss越高,说明模型越"蠢";差距越小,loss越低,说明模型越"聪明"。
最常见的损失函数:
| 场景 | 损失函数 | 大白话解释 |
|---|---|---|
| 回归问题(预测具体数值) | MSE(均方误差) | 预测值和真实值的差的平方,再求平均 |
| 二分类问题(是/否) | BCE(二元交叉熵) | 衡量预测概率和真实标签的"距离" |
| 多分类问题(多选一) | CE(交叉熵) | BCE的升级版,适用于多个类别 |
拿我前面说的OOM预测举例,这是一个二分类问题(会不会OOM),所以用BCE。模型输出一个0到1之间的概率值,比如0.8表示"80%的概率会OOM"。如果真实情况是确实OOM了(标签为1),那0.8这个预测就挺准的,loss就低;如果真实情况是没OOM(标签为0),那0.8就错得离谱,loss就高。
梯度下降就是让模型不断调整自己的参数,使得loss越来越小的过程。你可以想象成一个人蒙着眼睛在山谷里,想要走到最低点,他每走一步就用脚探探周围哪个方向是下坡,然后往那个方向走。这个"探方向"的过程就是计算梯度,"走一步"就是更新参数。
这里有个坑我踩过:学习率(learning rate)设太大了,就像步子迈太大,直接跨过山谷到对面山坡上了;设太小了,走一步挪一毫米,训练到天荒地老也收敛不了。我一开始设了0.1,loss直接炸了,后来调到1e-4才稳住。
# 一个简单的梯度下降示例
import torch
import torch.nn as nn
# 模拟数据:pod内存使用率 -> 是否OOM
X = torch.tensor([[0.3], [0.5], [0.7], [0.85], [0.92], [0.95]]) # 内存使用率
y = torch.tensor([[0.0], [0.0], [0.0], [1.0], [1.0], [1.0]]) # 1=OOM, 0=正常
# 简单线性模型
model = nn.Linear(1, 1)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01) # 学习率,别设太大!
criterion = nn.BCEWithLogitsLoss() # 二分类损失函数
for epoch in range(1000):
optimizer.zero_grad()
outputs = model(X)
loss = criterion(outputs, y)
loss.backward() # 计算梯度
optimizer.step() # 更新参数
if (epoch + 1) % 200 == 0:
print(f'Epoch [{epoch+1}/1000], Loss: {loss.item():.4f}')
过拟合:模型"死记硬背"了
这是新手最容易踩的坑,我也没逃过。
训练的时候loss一路狂降,我开心得不行,心想"稳了稳了"。结果拿到测试集上一跑,准确率惨不忍睹。这就是过拟合(Overfitting)——模型把训练数据"死记硬背"下来了,包括里面的噪声和特例,但完全没有学到通用规律。
打个比方,就像有个同学做数学题,不是学会了解题方法,而是把答案背下来了。换道题就不会了。
在运维场景里也有类似的问题。比如我用历史故障数据训练了一个模型,结果那段时间刚好赶上一次特殊的网络抖动,数据里有很多因为网络抖动导致的"假告警"。模型把这些假告警的模式也学进去了,结果上线后遇到类似的网络波动就疯狂误报。
解决过拟合的常用手段:
- 加正则化(Regularization):限制模型复杂度,不让它"想太多"。L1/L2正则化就是在loss函数里加一项惩罚,模型参数越大惩罚越重。
- Dropout:训练时随机"关掉"一部分神经元,强迫模型不要过度依赖某些特征。
- 早停(Early Stopping):训练过程中同时监控验证集的loss,一旦发现验证集loss开始上升(说明开始过拟合了),就停止训练。
- 增加数据量:数据越多,模型越难"背答案"。这也是为什么大厂都在拼命搞数据。
我最后是用早停+L2正则化搞定的,验证集准确率从68%拉到了82%,虽然不算特别高,但对于一个入门项目来说够用了。
从传统ML到大模型:Dify让我开了眼
学了一段时间传统机器学习(决策树、SVM、随机森林这些),我本来以为AI就是这些东西了。直到leader让我调研一下Dify。
说实话,第一次看到Dify的时候我惊了。这玩意儿的思路跟我之前学的传统ML完全不一样。
传统ML是你自己收集数据、选特征、选模型、调参数,整个过程需要大量领域知识和工程经验。而Dify走的是另一条路——它基于大语言模型(LLM),通过提示词工程(Prompt Engineering) 和工作流编排来构建AI应用。
简单说,你不需要自己训练模型,而是直接调用现成的大模型(GPT、Claude、开源模型等),通过设计提示词和工作流来实现业务需求。
我们团队用Dify做了个内部知识库问答机器人。把公司的运维文档、故障处理手册、K8s最佳实践都灌进去,然后用RAG(检索增强生成)的方式做问答。新来的运维同学遇到不懂的问题,直接问机器人就行,不用再翻wiki翻半天。
搭建过程其实不复杂,Dify的界面很友好,拖拖拽拽就能编排工作流。核心是几个关键点:
- 文档切片策略:文档怎么切块直接影响检索效果。我们试了几种方案,最后用按段落+重叠的方式效果最好。
- Embedding模型选择:用来把文本转成向量。中文场景下,bge-large-zh效果不错。
- Prompt设计:这个真的是门玄学。同样的问题,换个问法效果天差地别。我们迭代了十几版prompt才达到比较满意的效果。
# Dify工作流配置示例(简化版)
app:
name: "运维知识库问答"
mode: "chat"
workflow:
nodes:
- id: "start"
type: "start"
- id: "knowledge_retrieval"
type: "knowledge-retrieval"
config:
dataset_ids: ["运维文档库", "故障手册库"]
retrieval_mode: "semantic" # 语义检索
top_k: 5
- id: "llm"
type: "llm"
config:
model: "gpt-4o"
prompt: |
你是一个资深运维工程师。请根据以下知识库内容回答用户问题。
如果知识库中没有相关信息,请明确告知用户。
知识库内容:
{{knowledge_retrieval.output}}
用户问题:{{start.input}}
这个搞上线之后,团队里反馈还不错。至少新人onboarding的时间缩短了不少,不用再天天追着老员工问"这个报错啥意思"了。
聊聊DALL-E:当运维遇上AI绘图
说到AI应用,不得不提一下DALL-E。虽然这玩意跟我的本职工作关系不大,但上个月发生了一件有趣的事。
我们产品要做一个内部技术分享的海报,设计师排期排不上,产品经理急得跳脚。我当时正好在研究多模态模型,就试着用DALL-E生成了一张。
你别说,效果还真可以。我给的prompt是:"A futuristic data center with glowing Kubernetes pods floating in the air, cyberpunk style, dark background with neon blue lights",出来的图居然挺有赛博朋克那味儿的。
当然,DALL-E这种文生图模型跟我前面讲的机器学习入门不是一回事。它背后是扩散模型(Diffusion Model),原理复杂得多。但作为一个技术人,了解这些前沿应用还是很有必要的,毕竟技术视野不能太窄。
而且说真的,现在做技术分享、写博客、做PPT,有个能生成配图的AI工具太方便了。以前找图找到眼瞎,现在描述一下就能出来,效率提升不是一点半点。
一些实在的学习建议
最后,作为一个从运维转过来学ML的"半路出家"选手,分享几点我踩坑后总结的经验:
1. 别一上来就啃论文
我知道很多人(包括之前的我)觉得学AI就得从论文开始,什么Attention Is All You Need之类的。但对于入门来说,这太劝退了。建议先从实践入手,跑通几个demo,有了直观感受再去理解原理。
2. 用你熟悉的领域做项目
这是我觉得最重要的。如果你硬去做一个"猫狗分类器",学起来会很枯燥。但如果你用机器学习解决你工作中的实际问题,动力完全不一样。我就是用OOM预测这个项目入门的,因为我自己就深受其害,解决它的意愿特别强。
3. 先跑通,再优化
别一开始就追求SOTA(State of the Art)。先用最简单的模型、最少的特征跑通整个流程,确保数据流是通的,然后再逐步加复杂度。我第一版模型就是用最简单的逻辑回归,准确率75%,但流程是通的。后面换成XGBoost,加特征工程,才慢慢提到82%。
4. 善用工具,别重复造轮子
scikit-learn、XGBoost、PyTorch这些库已经非常成熟了,没必要自己手写算法。把精力放在理解问题、设计特征、评估效果上,而不是纠结实现细节。
5. 关注AI工程化,这是DevOps的优势
学了两个月我最大的感触是:现在AI领域最缺的不是算法科学家,而是能把模型落地成产品的工程师。模型训练好了,怎么部署?怎么做推理加速?怎么做监控和灰度?怎么做A/B测试?这些全是DevOps的强项。所以运维同学学AI,不是去跟算法工程师抢饭碗,而是在AI工程化这个方向上找到自己的差异化优势。
写在最后
写了这么多,其实就想表达一个观点:机器学习没有想象中那么神秘。它的核心思想很朴素——从数据中找规律。入门的门槛也没有那么高,关键是找到正确的学习路径和切入点。
我现在每天的状态就是:白天维护K8s集群、处理各种oncall,晚上抽两三个小时学ML。虽然累,但确实能感觉到自己在进步。上周leader还夸我那个OOM预测的小工具"有点东西",让我继续深挖。
至于求职嘛,现在简历上多了一项"机器学习项目经验",虽然不算深入,但至少面试的时候能聊两句了。在这个卷出天际的市场里,多一个技能点总没坏处。
对了,最近还在研究怎么用Dify搭一个自动化的故障诊断助手,把告警信息、日志、监控数据串起来,让大模型帮忙做初步的根因分析。如果有搞这块的朋友,欢迎交流。
不说了,线上又告警了,我去处理一下。希望今天不要加班到太晚,阿门。


评论 0