从房贷压力到CV实战:我在北京用算法给猫主子“上户口”

云端造物者
2026-06-03 05:42
阅读 1081

上周五晚上十点半,我一边啃着冷掉的黄焖鸡,一边盯着屏幕上又一个跑崩的训练任务。房东刚在微信里催了下季度房租,而我的银行卡余额连猫粮都快买不起了——但还是咬牙续了云服务器,因为这个计算机视觉项目,真可能成为我跳槽的敲门砖。

作为一名刚在北京背上30年房贷的北漂程序员,白天在一家中型电商公司维护祖传代码,晚上刷LeetCode、看论文、调模型,几乎成了我的生活常态。最近团队接了个“宠物识别”需求,说是为即将上线的宠物社区App打基础。产品经理画了个大饼:“用户上传猫狗照片,系统自动识别品种、年龄,甚至情绪!” 我当时就想问:您是不是觉得ResNet是万能胶水?

但转念一想,这不正是个绝佳的实战机会?既能摸鱼学CV,又能攒项目经验写进简历。于是,我主动揽下了这个活儿——现在回想起来,真是年轻气盛。

数据比算法更难搞

很多人以为CV项目最难的是调参和选模型,其实不然。真正的地狱,在数据准备阶段

公司压根没现成的宠物数据集。内部历史图片全是商品图,连只活猫都没有。无奈之下,我只能自己动手,丰衣足食。

我先是爬了Kaggle上的Oxford-IIIT Pet Dataset,又从GitHub上搜罗了几个开源项目的数据增强脚本。比如这个叫 pet-augment-toolkit 的仓库(虽然star只有27个,但作者注释写得挺细),帮我自动做了旋转、裁剪、亮度调整。

但问题来了:真实用户上传的照片千奇百怪——有逆光的、模糊的、猫脸只占画面5%的,甚至还有P成奥特曼的。而公开数据集里的猫,个个都是精修写真。

怎么办?我灵机一动,把公司测试同事家的猫“征用”了。连续三天蹲点拍照,还自掏腰包买了逗猫棒和零食贿赂。最终凑了200多张“野生”猫图,混入训练集。别笑,这招叫域适应(Domain Adaptation),听起来高大上,其实就是穷人的数据增强。

算法选型:别被SOTA迷惑双眼

一开始我热血上头,直接上了EfficientNet-B7,心想:反正GPU烧的是公司钱。结果训练一轮下来,准确率才78%,推理时间还贼慢,手机端根本跑不动。

后来冷静下来一想:我们的目标不是刷榜,而是在有限资源下达到可用效果。于是重新评估了几种轻量级模型:

模型 参数量 (M) Top-1 Acc (%) 推理延迟 (ms, on iPhone 12) 是否支持ONNX导出
MobileNetV2 3.4 72.1 45
EfficientNet-Lite0 4.7 76.8 68
ResNet-18 11.7 70.3 92
ConvNeXt-Tiny 28.0 79.5 110

虽然ConvNeXt准确率最高,但它导出ONNX会报错(试了三天都没搞定,差点砸键盘),而且延迟太高。最终我选了EfficientNet-Lite0——它专为移动端优化,Google官方维护,支持TensorFlow Lite无缝部署。

关键代码片段如下(已简化):

import tensorflow as tf
from tensorflow.keras.applications import EfficientNetLite0

# 加载预训练权重(ImageNet)
base_model = EfficientNetLite0(
    weights='imagenet',
    include_top=False,
    input_shape=(224, 224, 3)
)

# 冻结前几层,只微调顶层
base_model.trainable = False

model = tf.keras.Sequential([
    base_model,
    tf.keras.layers.GlobalAveragePooling2D(),
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(num_classes, activation='softmax')
])

model.compile(
    optimizer=tf.keras.optimizers.Adam(1e-4),
    loss='categorical_crossentropy',
    metrics=['accuracy']
)

这里有个坑:千万别一上来就全解冻训练!我第一次这么干,loss直接飞到3.0,模型彻底学废。后来采用“先冻结特征提取层,训练分类头;再解冻部分层微调”的两阶段策略,准确率稳稳提升到83%。

部署上线:运维同学差点把我拉黑

模型训好了,下一步就是上线。按照公司流程,得打包成Docker镜像,走CI/CD流水线。

但问题来了:我们后端用的是Go,而模型是TensorFlow。中间需要写个gRPC服务做桥接。我吭哧吭哧写了两天,结果测试环境一跑,内存泄漏!每请求一次,内存涨50MB。

查了半天,发现是TensorFlow的Session没正确复用。后来改成全局单例加载模型,问题解决。不过运维大哥在群里@我:“你这服务启动要30秒,内存吃2G,确定不是挖矿程序?”

为了减小体积,我又把模型转成TensorFlow Lite格式,体积从80MB压缩到22MB,加载时间也从12秒降到3秒。顺手把转换脚本传到了自己的GitHub仓库:cat-breed-tflite-exporter(名字随便起的,别当真)。

效果与反思:技术之外的东西更重要

上线两周后,后台数据显示:识别准确率81.2%,用户平均等待时间1.8秒。虽然离产品经理吹的“99%准确”差得远,但老板居然挺满意——因为留存率涨了5%。

这次项目让我深刻体会到:在工业界,算法只是拼图的一小块。数据质量、工程落地、用户体验,往往比模型本身更重要。

另外,GitHub真的是宝藏。从数据增强工具,到模型转换脚本,再到别人踩过的坑issue,省了我至少两周时间。强烈建议大家:不要重复造轮子,但一定要读懂轮子怎么转

现在,这个项目已经作为我简历里的“高亮项目”了。上周面试一家AI startup时,面试官看到GitHub链接,当场让我现场讲Loss曲线为什么在epoch 15那里震荡——还好我截图存了tensorboard记录,不然真答不上来。

房贷还在还,跳槽还在准备,但至少今晚,我可以安心给猫主子开罐头了。毕竟,它可是我数据集里的“首席模特”。


后记:如果你也在边工作边搞副业/学习,别焦虑。每个深夜debug的程序员,都在为更好的明天编译人生。共勉!

(项目核心代码已开源,欢迎Star/Fork/提Issue,地址:https://github.com/yourname/pet-vision-demo —— 当然,这只是示例链接,真实项目涉及公司数据,没法全放 😅)

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝