聊聊我在家撸Rust之余搞懂的机器学习那点事

向量数据库猫
2026-07-20 05:53
阅读 1099

早上八点钟,咖啡刚泡好,窗外鸟叫得挺欢。我坐在家里书房,打开Trae准备写点代码,结果发现昨晚跑的一个Rust小项目编译又报错了,满屏的lifetime错误看得我脑壳疼。索性先放一放,打开Moltbot跟它聊了两句,让它帮我理理思路。

聊着聊着就聊到了机器学习。说来也巧,最近公司有个新项目要上一个推荐模块,老板说"你顺便研究研究机器学习呗",得,又被安排了。其实我自己也一直想系统搞搞这块,毕竟现在不会点AI都不好意思说自己是搞技术的。

今天这篇文章,就跟大家聊聊我这段时间入门机器学习的一些心得。不讲太深的数学推导(那种东西看论文去),就聊聊基础概念,顺便对比对比各种算法的选型,给想入门的兄弟们一点参考。


先搞清楚:机器学习到底在干嘛

很多兄弟一听"机器学习"就觉得高深莫测,其实说白了就一句话:让程序自己从数据里找规律,而不是你手写规则

举个例子,你要做一个垃圾邮件过滤器。传统做法是你写一堆if-else:如果标题包含"中奖"就标记为垃圾邮件,如果发件人在黑名单里也标记……写到天荒地老也写不完。机器学习的思路是:我给你一堆已经标好"垃圾/正常"的邮件样本,你自己去学,学完了遇到新邮件你就知道该咋分了。

这里面有几个核心概念得先搞清楚:

概念 大白话解释 举个栗子
特征(Feature) 你用来判断的依据 邮件标题、发件人、正文关键词
标签(Label) 你要预测的目标 是不是垃圾邮件
模型(Model) 学到的规律 一套判断规则或函数
训练(Training) 让模型学习的过程 喂数据,调参数
过拟合(Overfitting) 学得太死了,换个数据就不行 做题只会背答案,换题型就懵

三大门派:监督、无监督、强化学习

机器学习算法大体上分三个门派,各有各的玩法:

监督学习(Supervised Learning) 是最常见的,就是你给数据打上标签,让模型学。分类问题(这是猫还是狗)和回归问题(明天股票多少钱)都属于这个门派。像线性回归、逻辑回归、决策树、SVM、随机森林这些都是。

无监督学习(Unsupervised Learning) 就比较野了,数据没标签,让模型自己去找结构。聚类(把相似的东西归到一堆)和降维(把高维数据压到低维还能保留主要信息)是典型代表。K-Means、DBSCAN、PCA这些是常用算法。

强化学习(Reinforcement Learning) 是另一个路子,模型通过不断试错来获取奖励,有点像训练小狗。AlphaGo就是这条路子的代表。这块水太深,入门阶段先不碰。

算法选型:到底该用哪个?

这才是大家最关心的问题。我最近做那个推荐模块的时候,也纠结了好久。下面是我整理的一个选型参考,结合了实际场景:

算法 适用场景 优点 缺点 上手难度
线性回归 连续值预测,特征和结果线性相关 简单、快、可解释 只能处理线性关系 ★☆☆☆☆
逻辑回归 二分类问题 简单、输出概率 同样只能线性 ★★☆☆☆
决策树 分类/回归,特征有明确阈值 可解释性强,不用特征缩放 容易过拟合 ★★☆☆☆
随机森林 分类/回归,通用 不容易过拟合,精度高 模型大,慢 ★★★☆☆
SVM 分类,特征维度高 小样本效果好 大数据集慢,调参痛苦 ★★★★☆
K-Means 聚类,数据量大 快,简单 要指定K值,对异常值敏感 ★★☆☆☆
XGBoost 表格数据,各种比赛 精度高,支持并行 调参是门玄学 ★★★★☆

说点实际的。如果你刚入门,数据量不大,特征也不多,随机森林基本是万金油,先跑一个baseline再说。别一上来就搞深度学习,杀鸡用牛刀不说,你还调不明白。

我之前有个同事,拿到一个二分类问题,上来就搭了个神经网络,调了三天参数,准确率还不如我跑了十分钟的XGBoost。当时他那个表情,我现在想起来还想笑。

实战踩坑:推荐模块的那些事

回到我那个推荐模块的项目。需求是这样的:根据用户的历史行为(浏览、点击、收藏、购买),预测用户对某个商品的点击概率。本质上是个二分类问题。

数据方面,我们有一份大概50万条的用户行为记录,特征包括用户年龄、性别、历史浏览品类、商品类目、价格区间、上架时间等等,大概二十来个特征。

第一步:数据预处理

这一步其实最耗时,也最重要。圈里有句话叫"数据和特征决定了机器学习的上限,模型和算法只是逼近这个上限"。

import pandas as pd
from sklearn.preprocessing import LabelEncoder, StandardScaler
from sklearn.model_selection import train_test_split

# 加载数据
df = pd.read_csv('user_behavior.csv')

# 处理缺失值 - 这里我用了填充,有时候直接删也行
df['age'].fillna(df['age'].median(), inplace=True)
df['price'].fillna(0, inplace=True)

# 类别特征编码
label_encoders = {}
for col in ['gender', 'category', 'price_range']:
    le = LabelEncoder()
    df[col] = le.fit_transform(df[col].astype(str))
    label_encoders[col] = le

# 特征缩放 - SVM和神经网络对缩放敏感,树模型倒无所谓
scaler = StandardScaler()
numeric_cols = ['age', 'price', 'browse_count']
df[numeric_cols] = scaler.fit_transform(df[numeric_cols])

# 划分训练集和测试集
X = df.drop('is_clicked', axis=1)
y = df['is_clicked']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

这里有个坑:一开始我没做特征缩放,直接跑SVM,效果奇差。后来加了StandardScaler,准确率直接涨了8个点。树模型虽然不怕这个,但如果你后面要对比多个模型,统一做一下缩放省事。

第二步:模型训练和对比

from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, roc_auc_score, classification_report
import xgboost as xgb

models = {
    'LogisticRegression': LogisticRegression(max_iter=1000),
    'RandomForest': RandomForestClassifier(n_estimators=100, random_state=42),
    'XGBoost': xgb.XGBClassifier(n_estimators=100, learning_rate=0.1, random_state=42)
}

results = {}
for name, model in models.items():
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)
    y_prob = model.predict_proba(X_test)[:, 1]
    
    acc = accuracy_score(y_test, y_pred)
    auc = roc_auc_score(y_test, y_prob)
    results[name] = {'accuracy': acc, 'auc': auc}
    print(f"{name}: Accuracy={acc:.4f}, AUC={auc:.4f}")

跑出来的结果:

模型 Accuracy AUC 训练耗时
LogisticRegression 0.7231 0.7102 0.3s
RandomForest 0.7856 0.8023 2.1s
XGBoost 0.8102 0.8341 1.8s

XGBoost赢了,但也没赢太多。这里有个经验:别只看准确率,分类问题一定要看AUC。特别是正负样本不平衡的时候(我们这个数据集点击率只有12%),准确率会骗人的。你全预测为"不点击",准确率都有88%,但那有啥用?

第三步:调参

XGBoost的调参确实是个玄学。我当时的策略是先粗调再细调:

from sklearn.model_selection import GridSearchCV

param_grid = {
    'n_estimators': [50, 100, 200],
    'max_depth': [3, 5, 7],
    'learning_rate': [0.01, 0.05, 0.1],
    'subsample': [0.8, 1.0],
    'colsample_bytree': [0.8, 1.0]
}

grid_search = GridSearchCV(
    xgb.XGBClassifier(random_state=42),
    param_grid,
    cv=5,
    scoring='roc_auc',
    n_jobs=-1
)
grid_search.fit(X_train, y_train)

print(f"Best params: {grid_search.best_params_}")
print(f"Best AUC: {grid_search.best_score_:.4f}")

GridSearch跑了大概二十分钟,最终最优参数是 n_estimators=200, max_depth=5, learning_rate=0.05, subsample=0.8, colsample_bytree=0.8,AUC提升到了0.8456。

这里说个教训:一开始我max_depth设了10,训练集上AUC飙到0.95,测试集只有0.78,典型的过拟合。后来把深度降下来,加了subsample和colsample_bytree做随机采样,泛化能力才上来。

一些碎碎念的心得

搞了这段时间机器学习,有几点感受想跟大家分享:

1. 数据比算法重要一万倍。 你花80%的时间在清洗数据、构造特征上,这很正常。别觉得这是脏活累活就不愿意干,特征工程做好了,简单模型也能出好效果。

2. 先跑baseline,再优化。 别一上来就追求极致,先用最简单的模型跑个baseline,心里有个底。很多时候你会发现,逻辑回归就能解决80%的问题。

3. 评估指标要选对。 分类问题看AUC、F1-score,回归问题看RMSE、MAE。别只看准确率,特别是样本不平衡的时候。

4. 工具很重要。 我最近用Trae写代码,体验确实不错,自动补全很智能,写Python和Rust都挺顺手。另外我建了个知识库,把看过的论文笔记、踩过的坑都丢进去,用的时候直接问Moltbot,省得翻来翻去。说到这个,最近改简历的时候也把这段机器学习的经历加上了,毕竟现在面试不问点AI相关的都不好意思。

5. 别怕数学,但也别死磕数学。 入门阶段理解直觉就够了,知道这个算法在干嘛、适合什么场景。等你用熟了,再回头补数学,那时候理解会深很多。


好了,咖啡喝完了,Rust的编译错误还等着我呢。今天先聊到这,希望这篇入门指南对想学机器学习的兄弟有点帮助。

有什么想聊的,评论区见。我一般早上八点到晚上都在,远程办公嘛,时间比较自由。要是聊Rust的就更好了,最近被borrow checker折磨得够呛,急需同病相怜的兄弟一起吐槽。

Peace out ✌️

评论 0

最热最新
暂无评论
向量数据库猫Lv.1
0
影响力
0
文章
0
粉丝