从厨房到Kaggle:全职妈妈的计算机视觉实战突围记
上周四凌晨两点半,我一边给哭醒的娃换尿布,一边在MacBook上盯着训练loss曲线。咖啡早就凉了,头发乱得像鸡窝,心里却只有一个念头:这破模型再不收敛,我就要被产品经理挂墙上当装饰画了。
大家好,我是小林,一个坐标北京、每天通勤一小时、白天带娃晚上debug的全职妈妈。别误会,我说的“全职”是字面意思——孩子上托班那几个小时,我就是个正经码农;其余时间,我的IDE是婴儿车+尿布台组合套装。不过说实话,这种“双线程”生活虽然累成狗,但反而让我对代码可读性和工程效率格外敏感——毕竟,谁有时间去维护一堆自己都看不懂的屎山代码啊?
项目起因:老板说要“智能识别”
事情得从去年底说起。我们组接了个内部创新项目:用手机拍一张货架照片,自动识别商品种类和摆放状态。听起来是不是很像超市巡检系统?没错!但问题是,留给我们的训练数据只有200张标注图片,还全是模糊不清的手机随手拍。产品经理一脸无辜地说:“技术不是万能的吗?Fine-tuning一下不就好了?”
Fine-tuning?Fine你个头!我当时差点把保温杯砸他脸上。不过转念一想,这倒是个练手的好机会——毕竟,作为一个常年混迹技术分享会的老油条(虽然现在参会前得先找好托管阿姨),我早就想试试Kimi和LangChain在CV领域的骚操作了。
别被名字骗了:Kimi不是那个AI助手
先澄清一下,这里的Kimi不是月之暗面那个聊天机器人,而是我们内部一个轻量级CV框架的代号(老板非说叫“Kimi”显得可爱,行吧)。它基于PyTorch Lightning封装,主打一个“妈妈也能快速上手”——当然,这是理想状态。
我们的baseline选了ResNet50,预训练权重用ImageNet。但很快发现:通用分类模型面对“歪斜的薯片袋”和“半遮挡的饮料瓶”直接傻眼。准确率卡在68%,而业务要求至少90%。
这时候,Fine-tuning就不是可选项,而是救命稻草了。但怎么调?我试了三种策略:
- 全参数微调:效果最好,但200张图根本撑不住,过拟合快得像我家娃学骂人。
- 冻结backbone只训分类头:稳是稳了,但精度上不去,72%就到顶。
- 分层学习率 + Layer-wise LR decay:终于找到甜点!靠近输入层的学习率设为1e-5,越往后越大,最后分类头用1e-3。
# 分层学习率配置示例(Kimi框架内置)
optimizer = torch.optim.AdamW([
{'params': model.backbone.layer1.parameters(), 'lr': 1e-5},
{'params': model.backbone.layer2.parameters(), 'lr': 3e-5},
{'required_grad': True, 'lr': 1e-3} # 分类头
])
这个方案最终把验证集准确率干到了89.7%,离90%就差一口气。但你知道最气人的是什么吗?测试时发现,模型对“蓝色包装”特别敏感——因为训练集里80%的饮料都是蓝色的!典型的数据偏差陷阱,差点让我白忙活。
LangChain?CV项目也能玩?
这时候我想起了最近在技术会上听到的LangChain。等等,那不是搞大模型Agent的吗?跟图像识别有啥关系?
灵光一闪:用LangChain做后处理逻辑编排啊!
具体来说,我把CV模型输出的概率分布喂给一个轻量级LLM(其实就用了TinyLlama),让它结合上下文规则做二次判断。比如:
- 如果检测到“饮料”但旁边有“纸巾”,且置信度<0.8 → 可能是误检,建议人工复核
- 如果同一区域连续三帧都报“缺货” → 触发告警
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
prompt = PromptTemplate.from_template(
"根据CV模型输出:{detections},结合货架规则,判断是否需人工复核?"
)
chain = LLMChain(llm=tiny_llm, prompt=prompt)
result = chain.run(detections=cv_output)
别笑,这招居然把线上误报率降了40%!而且因为LangChain的链式结构清晰,连实习生都能看懂逻辑流——要知道,我们组新来的实习生以为Docker是某种海鲜,你能指望他读懂复杂的if-else嵌套?
踩坑实录:那些让我想删库跑路的瞬间
坑1:数据增强翻车现场
为了让200张图“看起来更多”,我上了全套augmentation:旋转、裁剪、色彩抖动……结果模型学会了把倒置的可乐罐当成“新品”。后来才明白,零售场景的图像增强不能太野——商品方向是有物理意义的!
解决方案:只保留平移、轻微缩放和亮度调整,放弃几何变换。血泪教训:数据增强不是越多越好,而是要符合业务物理约束。
坑2:部署时的“环境玄学”
本地跑得好好的模型,一上服务器就崩。日志显示:
CUDA error: out of memory
但服务器显存明明比我的MacBook Pro大十倍!查了半天才发现:运维大哥把Docker容器的GPU内存限制设成了2GB,而我的batch_size=8……
最终妥协方案:动态batch size + 梯度累积。虽然训练慢了点,但至少不用半夜被PagerDuty叫醒。
坑3:产品经理的“小小需求”
上线前一天,产品突然说:“能不能顺便识别商品价格标签?”
我:“……那是OCR任务,兄弟。”
产品:“但你们不是AI团队吗?”
最后靠Tesseract + OpenCV硬凑了个方案,准确率勉强及格。但这次经历让我深刻体会到:明确问题边界,比写代码更重要。
效果与反思:妈妈程序员的独特优势?
经过三轮迭代,系统最终在试点门店上线。关键指标如下:
| 指标 | Baseline (ResNet50) | Fine-tuned + LangChain后处理 |
|---|---|---|
| 准确率 | 68.2% | 91.5% |
| 误报率 | 22.7% | 13.1% |
| 单图推理耗时 | 0.8s | 1.1s (含LLM后处理) |
虽然推理慢了0.3秒,但业务方表示“完全可接受”——毕竟,省下的人工巡检成本够买一百台服务器了。
回头看这段经历,我反而觉得“带娃写代码”的身份给了我独特视角:
- 耐心:调参像哄睡,急不得
- 简化思维:屎山代码?没时间维护!必须一次写清楚
- 多任务并行:一边回工作消息一边冲奶粉,GPU训练时正好叠衣服
上周技术分享会上,我讲完这个项目,有位爸爸工程师感慨:“原来妈妈程序员才是真正的超人。” 我笑笑没说话——哪有什么超人,不过是把崩溃藏在深夜,把bug留在明天。
如果你也在带娃的同时搞技术,记住:你不是一个人在战斗。下次遇到模型不收敛,不妨想想——至少你的代码不会半夜哭着要喝奶。
(完)
后记:本文所有代码已脱敏开源,欢迎Star。另外,求推荐靠谱的周末托管班,北京海淀的优先!

评论 0