从零开始做AI:我在实际项目中入门Python机器学习的那些事儿
开篇:为什么我想写这篇文章?

记得去年刚开始接触机器学习的时候,我也是一个纯纯的小白。作为一个全栈开发出身的程序员,原本以为自己对编程、系统、架构这些都挺熟了,搞个“机器学习”应该也不在话下吧?结果现实啪啪打脸。
当时我们团队接了一个数据分析相关的项目,客户希望根据历史订单数据预测未来几周的销售量,从而更好地安排采购和库存管理。这个需求其实听起来不复杂,就是典型的预测问题嘛。但真到了实操阶段才发现,这背后涉及的东西远比我想象的多得多。
于是我开始了边学边做的旅程,一路踩坑、不断优化,最终交付了一个还算能用的模型。今天我就想结合那个项目的经历,分享一下我是怎么从一个门外汉一步步走进机器学习世界的真实过程。如果你也刚入门,或者准备入门,那希望这篇接地气的经验分享对你有些帮助。
项目背景:小电商平台的销量预测需求

我们合作的是一家区域性的小型电商平台,他们主要卖家居用品,用户群体集中在南方几个省份。平台已经运营了两年多,积累了不少数据,但他们现在的运营还是靠经验拍脑袋决定库存量。
他们的核心痛点是:
- 容易出现爆款缺货的情况
- 长尾商品又经常积压,导致资金周转慢
- 缺乏数据驱动决策的能力
所以我们的任务是基于过去两年的历史销售数据,构建一个可以预测未来四周每周销量的模型,让他们能提前安排采购和仓储计划。
挑战一箩筐:真实业务场景中的各种难题

刚开始拿到数据一看,心里有点慌。数据看起来很多,但结构很混乱,字段含义也不明确。比如:
- “下单时间”有文本格式也有日期格式混在一起
- 有些商品ID是空值或重复的
- 同一个商品在不同渠道上的SKU编号不一致
- 缺少一些关键的特征信息,比如节假日、促销活动等
更头疼的是,客户没有专门的数据科学家,整个技术团队只有我和另一个前端工程师加一个产品经理,资源非常有限。
而且我之前对机器学习的认知,基本来自于网上的教程文章,什么“鸢尾花分类”、“泰坦尼克号生存率预测”这些玩具级项目,真正遇到真实业务场景的数据时才发现,根本不是一回事儿。
解决思路:从小处着手,逐步推进

考虑到资源和时间限制,我决定先用最简单的线性回归做个实验,看能不能跑出个靠谱的结果。如果行得通,再慢慢迭代到更复杂的模型;如果不行,至少也能了解问题出在哪。
整个流程大致分为以下几个步骤:
- 数据清洗与预处理
- 特征工程
- 模型训练与评估
- 模型部署与调用
整个过程中,我一直在用Python + Scikit-learn这套工具链,偶尔也会配合Pandas、Numpy和Matplotlib做一些探索分析。毕竟我们团队人不多,工具链不能太复杂。
接下来我会详细讲讲每个环节是怎么做的。
数据清洗与预处理:痛苦而必须的过程
数据质量差几乎是所有真实项目里的常态。我花了将近一周的时间清理数据,才得到一个相对干净的数据集。
举几个典型的清洗例子:
- 把
order_time字段统一转成datetime64类型,然后提取年/月/日作为新特征 - 对于缺失的商品类目(category_id),根据同品类商品补全
- 使用正则表达式清洗掉价格字段中多余的空格和单位(例如"¥599" -> "599")
- 给每天的销售记录进行汇总,生成每个SKU的日销量表
import pandas as pd
# 读取原始数据
df = pd.read_csv('raw_sales_data.csv')
# 清洗下单时间
df['order_time'] = pd.to_datetime(df['order_time'], errors='coerce')
df['date'] = df['order_time'].dt.date
df['year'] = df['order_time'].dt.year
df['month'] = df['order_time'].dt.month
df['dayofweek'] = df['order_time'].dt.dayofweek
# 处理缺失类目
df['category_id'] = df.groupby('product_name')['category_id'].transform(lambda x: x.fillna(x.mode()[0] if not x.mode().empty else 'UNKNOWN'))
# 转换价格为浮点数
df['price'] = df['price'].str.replace(r'[^\d.]', '', regex=True).astype(float)
# 汇总每日销量
daily_sales = df.groupby(['sku', 'date'])['quantity'].sum().reset_index()
这一阶段虽然繁琐,但真的非常重要。很多时候模型效果不好,不是因为算法不够先进,而是数据本身就有问题。
特征工程:让数据更有“价值”

特征工程是我花时间最多的部分之一。这里有个小插曲:最初只用了时间序列上的滑动窗口统计,比如最近7天/30天的平均销量、最大销量之类的,但模型表现一般。后来我意识到,影响销量的因素不止历史趋势,还有其他外部因素。
所以我额外收集了一些数据源:
- 历史节假日(通过第三方API获取)
- 是否参与促销活动(需要产品同学手动标注)
- 每周天气(通过城市天气数据粗略估计)
把这些信息整合进数据集中后,模型性能明显提升。
比如,我们可以构造如下特征:
# 添加是否为周末
daily_sales['is_weekend'] = daily_sales['dayofweek'].isin([5,6]).astype(int)
# 添加是否为节假日(假设 holidays 是一个已知的日期列表)
daily_sales['is_holiday'] = daily_sales['date'].isin(holidays).astype(int)
# 过去7天、30天的平均销量
daily_sales['avg_7_days'] = daily_sales.groupby('sku')['quantity'].transform(lambda x: x.rolling(window=7).mean())
daily_sales['avg_30_days'] = daily_sales.groupby('sku')['quantity'].transform(lambda x: x.rolling(window=30).mean())
这部分其实没有固定模式,更多的是根据经验和数据表现来调整。有时候你会觉得某些特征很重要,但模型训练出来发现它并不显著;有时候一个不起眼的小特征反而能让精度提高不少。
模型训练与调优:从线性回归到LightGBM
第一轮训练我使用了LinearRegression,但效果只能说将就,R²大概在0.6左右,MAE(平均绝对误差)达到了12件——这意味着你预测某商品下周会卖出50件,实际可能是38~62之间,这对于进货来说误差太大。
于是开始尝试更复杂的模型,比如随机森林(RandomForestRegressor)和梯度提升树(GradientBoostingRegressor)。最后选择了LightGBM,因为它在中小规模数据集上训练速度快,调参相对灵活,而且支持早停机制,适合我们这种时间紧任务重的项目。
以下是训练的一个片段:
from sklearn.model_selection import train_test_split
from lightgbm import LGBMRegressor
from sklearn.metrics import mean_absolute_error
# 准备特征和目标变量
X = daily_sales.drop(columns=['quantity'])
y = daily_sales['quantity']
# 分割训练测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 训练模型
model = LGBMRegressor(n_estimators=200, learning_rate=0.1, max_depth=5, random_state=42)
model.fit(X_train, y_train)
# 评估
preds = model.predict(X_test)
mae = mean_absolute_error(y_test, preds)
print(f"MAE: {mae:.2f}")
经过多次调参(learning_rate、num_leaves、max_depth等),最终MAE降到了5.2,R²达到了0.83,算是一个能接受的结果。
不过我也试过XGBoost,效果差不多,只是训练速度稍慢一些。大家可以根据自己的需求选择。
踩坑经验:都是泪啊
在这趟旅程中,踩过的坑可不止一两个。总结几点印象深刻的经历:
坑1:盲目追“高大上”的模型
一开始听说Transformer特别火,就想试试能不能用来预测销量。结果呢?不仅没法收敛,还耗费大量时间在调参和环境搭建上。后来才知道,Transformer这类深度学习模型适合大规模、高维的数据,而我们这种小样本数据根本不合适。
教训:别一上来就追求最先进的模型,选适合当前问题和数据规模的才是王道。
坑2:忽视时间序列特性
最开始没把“时间维度”当回事,简单地按随机方式划分训练集和测试集,结果模型在测试集上表现很好,上线后却频繁出错。后来改成按时间顺序划分后,准确率立刻下降一大截,但也更贴近真实情况。
教训:对于时间序列问题,一定要注意数据的时序性,测试集应该是未来的数据!
坑3:过度拟合
有一段时间模型训练出来的R²很高,但在验证集上却差很多,明显过拟合。后来发现是因为加入了太多历史滑动窗口特征,模型记住了过去的噪声。
解决方法:
- 减少特征数量
- 增加L1/L2正则项
- 使用交叉验证
效果落地:模型终于能干活了
项目上线后,我们做了三个月的A/B测试,对照组继续采用人工判断,对照组使用我们的预测建议。
结果如下:
- 库存缺货率下降了23%
- 积压库存减少约18%
- 整体周转效率提升了12%
虽然数字不算惊艳,但对于一个初创团队来说,已经是不小的进步了。
客户反馈说:“虽然预测不一定每次都准,但比之前强太多了,现在买手开会都有依据了。”
我的一些心得体会
如果你也打算入门机器学习,不妨听听我的建议:
✅ 从实际问题出发,不要死磕理论
与其花一个月时间啃《机器学习》这本书,不如直接拿一个小项目练手。动手的过程中自然会碰到各种问题,再去查资料、学原理,这样理解更深、记忆更牢。
✅ 工具链越简单越好
尤其初期,推荐使用Scikit-learn + Jupyter Notebook这种组合,轻量高效,调试方便。别一开始就整什么Docker+TensorFlow Serving那一套,容易把自己绕进去。
✅ 多和同事、导师交流
我在这个项目里最大的收获之一,是学会了如何跟产品经理沟通数据需求。很多时候不是你不会建模,而是不知道哪些特征是有意义的。从业务角度理解问题,往往比数学知识更重要。
✅ 不要怕犯错
我前几次提交的版本MAE都在20以上,一度怀疑自己是不是不适合搞机器学习。后来慢慢调整,才一点点优化上来。机器学习本就是一个试错+迭代的过程。
写在最后:机器学习是工具,不是终点
很多人以为搞AI就得懂多少算法、会不会调参、要不要卷模型,其实不然。在我这个项目里,真正起决定作用的并不是模型本身,而是对业务的理解和对数据的洞察力。
机器学习只是解决问题的一种手段,而不是目的。它本质上是一个“从历史中寻找规律,并用于未来预测”的工具。掌握了这一点,才能更好地驾驭它。
如果你正在路上,别怕难,坚持走下去,哪怕一次只进步1%,一年下来也是不可忽视的成长。
结语

这篇文章写了好几天,几乎把我去年的心路历程都梳理了一遍。希望你能从中看到的不是一个冷冰冰的技术文档,而是一个开发者在实战中摸爬滚打的真实经历。
如果你也在做类似的项目,或者刚入门机器学习,欢迎留言交流。一起成长的路上,不孤单。

评论 0