从零搞懂机器学习算法:一个被产品经理“逼”出来的入门指南

Dev工程师
2026-02-15 03:08
阅读 2601

上周五晚上十一点半,我正窝在沙发上用 Cursor 写一个数据预处理脚本,突然钉钉弹出一条消息——产品经理发来一张模糊不清的手绘草图,配文:“这个推荐逻辑能不能下周上线?用户都等不及了。”

我当时差点把 MacBook 合上扔进垃圾桶。

作为一个靠 GitHub 开源项目养活自己的远程打工人,我平时写代码讲究可读性、模块化、文档齐全,结果现在要我去搞一个“模糊手绘 + 紧急上线”的推荐功能?更离谱的是,他连数据都没给全,只甩了一句:“你不是会 AI 吗?AI 能不能自己猜用户喜欢啥?”

行吧。既然躲不过,那就硬刚。

但问题是,我虽然天天用 Cursor 辅助写代码,对机器学习也只是“能跑通 demo”的水平。于是,我决定趁这个机会,彻底搞明白那些听起来高大上的“算法”到底是个啥。本文就是我在踩坑、翻论文、扒 GitHub、调 Trae(我们内部的 MLOps 平台)之后的血泪总结。


为什么“算法”听起来很玄,其实没那么可怕?

很多程序员(包括曾经的我)一听到“机器学习算法”,脑子里立刻浮现出一堆公式、梯度下降、损失函数……然后直接劝退。但说实话,算法本质上就是一套解决问题的规则,和你写个排序函数、设计个缓存策略没啥本质区别。

举个例子:你想让系统自动识别用户会不会点击某个商品。最朴素的想法是——如果用户过去点过类似的东西,那这次也可能点。这其实就是一个“基于历史行为的规则”,而机器学习干的事,就是把这种规则自动化、泛化、量化

所以别怕。咱们今天不讲数学推导,就聊清楚几个核心概念,再结合实际场景跑一遍流程,你就能上手。


核心三件套:模型、特征、目标

在我开始折腾之前,先理清三个关键词:

  1. 模型(Model):就是那个“猜你喜欢”的黑盒子。它可以很简单(比如线性回归),也可以很复杂(比如深度神经网络)。
  2. 特征(Features):喂给模型的数据原料。比如用户年龄、浏览时长、点击次数、设备类型……这些叫“输入特征”。
  3. 目标(Target / Label):你想预测的结果。比如“是否点击”(0/1)、“预计停留时长”(数值)等。

🚨 注意:垃圾特征进,垃圾预测出。再牛的算法也救不了乱七八糟的特征工程。

我们产品的需求是“预测用户是否会点击新上架的商品”。那目标就很明确:二分类问题(点击 or 不点击)。接下来就是找特征。


特征怎么搞?别闭门造车!

一开始我想直接拿用户 ID 和商品 ID 做 one-hot 编码,结果 Trae 上训练直接 OOM(内存溢出)。运维同事在群里幽幽地说:“兄弟,你这是要把 Redis 当特征库用?”

痛定思痛,我翻了翻 GitHub 上几个热门推荐系统项目(比如 lightfmimplicit),发现大家普遍采用交叉特征 + 嵌入向量(Embedding) 的方式。

于是我把原始数据做了如下处理:

  • 用户侧:最近7天点击次数、平均停留时长、活跃天数
  • 商品侧:类目、价格区间、上架时间
  • 交叉特征:用户对该类目的历史点击率、用户与该价格区间的互动频率

这些特征既能反映用户偏好,又不会爆炸式增长维度。用 Pandas 处理完后,输出一个干净的 CSV,丢给 Trae 训练。

# 示例:构造交叉特征
df['user_category_ctr'] = df.groupby(['user_id', 'category'])['clicked'].transform('mean')
df['user_price_bin_clicks'] = df.groupby(['user_id', 'price_bin'])['clicked'].transform('count')

💡 小技巧:用 transform 而不是 merge,避免数据膨胀。这是我在看 Airbnb 的开源特征工程库时学到的。


算法选型:别一上来就上 Transformer

很多人觉得“不用深度学习就不够酷”,但现实是——简单模型往往更稳、更快、更好解释

我们的场景数据量不大(日活几万),标签稀疏(点击率不到 2%),所以我试了三种算法:

算法 训练时间 AUC 可解释性 是否上线
Logistic Regression 8s 0.72 ⭐⭐⭐⭐⭐
Random Forest 45s 0.75 ⭐⭐⭐ ✅(备用)
XGBoost 60s 0.76 ⭐⭐ ❌(太慢)

AUC 是评估分类模型好坏的关键指标(越接近 1 越好)。虽然 XGBoost 略高一点,但它每次训练要一分钟,Trae 上资源紧张,测试环境排队排到第二天。而 LR 跑得飞快,还能直接看每个特征的权重——产品经理问“为啥推荐这个?”我能直接回答:“因为您昨天看了三次同类商品。”

最终我们上了 LR + 特征交叉的组合。上线后 CTR 提升了 12%,虽然不算惊艳,但胜在稳定、可控、可回滚。


GitHub 上的宝藏:别重复造轮子

说到这儿必须安利几个 GitHub 项目,它们帮我省了至少三天时间:

  • scikit-learn:经典中的经典。LR、RF、SVM 全都有,API 统一,文档清晰。
  • feature-engine:专门做特征工程的库,自动处理缺失值、编码、分箱,比手写 pandas 稳得多。
  • mlflow:实验跟踪神器。我用它记录每次 Trae 上跑的不同参数组合,再也不用靠脑子记“AUC=0.75那次用了啥特征”。

特别是 feature-engine,一行代码搞定类别变量编码:

from feature_engine.encoding import OneHotEncoder
encoder = OneHotEncoder(variables=['category', 'device_type'])
df_encoded = encoder.fit_transform(df)

对比我自己写的 pd.get_dummies(),它还能自动处理训练/测试集的不一致问题(比如测试集出现新类目),简直救命。


Trae:我们的内部 MLOps 平台,爱恨交织

Trae 是我们公司自研的机器学习平台,名字取自“Train & Serve”的缩写。它集成了数据预览、模型训练、AB 测试、监控告警等功能。

但说实话,初期用它简直像在玩扫雷——文档少、报错信息谜语人、GPU 队列永远满。

有一次我提交了一个训练任务,等了两小时,结果报错:

Error: NaN in loss during epoch 3

我当场懵了。查了半天才发现是某个特征有极端异常值(有个用户停留时长显示为 999999 秒——明显是前端埋点 bug)。Trae 没做自动清洗,直接把 NaN 传给了模型。

从此以后,我在预处理阶段加了双重校验:

# 清洗极端值
df = df[(df['dwell_time'] >= 0) & (df['dwell_time'] <= 3600)]  # 最多1小时
# 检查 NaN
assert not df.isnull().any().any(), "存在缺失值!"

现在 Trae 已经成了我的日常工具。每天早上第一件事:看 Trae 监控面板,确认模型预测分布是否漂移(比如某天突然全是 0.9+ 的高分,可能数据管道出问题了)。


代码可读性:别让队友骂你祖宗

作为注重代码可维护性的老码农,我坚决反对“能跑就行”的炼丹式写法。我的训练脚本结构如下:

ml_pipeline/
├── config/
│   └── model_config.yaml
├── data/
│   ├── raw/
│   └── processed/
├── features/
│   └── build_features.py
├── models/
│   └── train_lr.py
└── utils/
    └── logger.py

关键原则:

  • 配置外置:超参、路径、特征列表全放 YAML,改参数不用动代码。
  • 函数单一职责build_features.py 只负责特征生成,不掺杂训练逻辑。
  • 日志清晰:每一步都打 log,方便 Trae 上排查。

比如 train_lr.py

def train_model(X_train, y_train, config):
    """训练逻辑回归模型"""
    logger.info(f"使用正则化参数 C={config['C']}")
    model = LogisticRegression(C=config['C'], max_iter=1000)
    model.fit(X_train, y_train)
    logger.info("模型训练完成")
    return model

这样即使半年后回头看,也能秒懂。而且 Cursor 能完美理解这种结构,补全建议特别准——这才是 AI 编程的正确打开方式。


效果评估:别只看准确率!

上线前,测试同学问我:“准确率多少?”我反问:“你希望模型把所有人都预测成‘不点击’吗?”

在点击率这种极度不平衡的场景下,准确率(Accuracy)毫无意义。比如 98% 的样本是 0(不点击),模型全猜 0,准确率 98%,但实际 useless。

所以我们重点看:

  • AUC:衡量模型区分正负样本的能力。
  • Precision@K:Top K 推荐中有多少是真的被点击了。
  • Recall:所有真实点击中,有多少被模型覆盖了。

在 Trae 的 AB 测试中,我们对比了新旧策略:

指标 旧规则 新模型 提升
AUC 0.65 0.72 +10.8%
Precision@10 8.2% 11.5% +40%
日均点击量 1200 1344 +12%

虽然 AUC 提升看起来不多,但 Precision@10 的暴涨说明高质量推荐变多了——这正是产品想要的。


写在最后:算法不是魔法,而是工程

折腾完这一轮,我终于理解了:机器学习不是靠几个 fancy 的算法名词唬人,而是扎实的数据、合理的特征、稳健的工程和持续的迭代

现在产品经理再发手绘图,我会回一句:“行,但得先给我三天做特征分析和基线测试。”——他居然同意了!看来效果说话真的有用。

如果你也像我一样,被业务需求“赶鸭子上架”去搞 ML,别慌。从 GitHub 找个靠谱项目 fork 下来,用 Trae(或你司的类似平台)跑起来,一点点调,慢慢就熟了。

毕竟,代码写多了,AI 用顺了,连算法都能变成你的“副驾驶”。

对了,我所有的实验代码都整理好了,准备开源到 GitHub。等哪天不加班了就 push —— 希望别等到明年双11。


作者碎碎念:本文所有代码均在 Cursor 辅助下完成。没有它,我可能还在手动调试第 37 个 NaN。感谢 AI,让我从“调参民工”升级为“特征架构师”(自封的)。

评论 0

最热最新
暂无评论
Dev工程师Lv.1
0
影响力
0
文章
0
粉丝