news 2026/10/20 22:44:18

零基础机器学习入门:从Numpy到XGBoost的代码驱动学习路线

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
零基础机器学习入门:从Numpy到XGBoost的代码驱动学习路线

1. 为什么零基础学机器学习,最怕的就是“跳步”

很多人一上来就问:我想学机器学习,是不是得先把高等数学、线性代数、概率论全部啃一遍?这个问题我被人问过不下五十次。每次我的回答都一样:你如果真按那个顺序来,大概率三个月后就放弃了。不是因为数学不重要,而是因为脱离代码和实际数据的数学学习,对零基础的人来说几乎是无效的。

我自己当年入门的时候,走过一条非常蠢的弯路。先买了一本厚得能砸死人的统计学习教材,从第一章的期望、方差开始推公式,推了两周,连一行代码都没写过。后来一个做数据科学的朋友跟我说了一句话,把我点醒了:“你先用Numpy把数据读进来,用Pandas做个透视表,画几张图看看分布,再跑一个KNN分类器出来,你自然就知道自己缺什么数学了。”我照做了,三天之内跑通了第一个分类任务,那种“我真的让机器学会了一件事”的成就感,比推一百个公式都管用。

所以这篇内容的核心逻辑非常明确:以代码驱动学习,以项目串联知识点。整套路线按照“数据处理 → 可视化 → 经典算法 → 集成方法 → 无监督学习”的顺序展开,每一步都有可运行的代码和可解释的原理。你不需要先成为数学家,再成为程序员,最后才碰机器学习。你需要的是一条从零到能跑通完整项目的最短路径。

这条路径适合谁?适合完全没有机器学习基础、但有一点Python语法概念的人。如果你连变量、循环、函数都还没写过,建议先花一周把Python基础过一遍,不用深,能看懂列表推导和字典操作就够了。剩下的,交给Numpy、Pandas和Scikit-learn。

下面我会按照这条路线,把每个阶段的核心工具、关键操作、常见坑点和实操心得全部拆开讲。每一段都是我或者我身边人真实踩过的路,不是从文档里抄来的。

2. Numpy和Pandas:别急着建模,先把数据这关过了

2.1 Numpy的ndarray到底比Python列表强在哪

零基础的人第一个困惑往往是:Python已经有列表了,为什么还要学Numpy?我直接用列表存数据不行吗?行,但你会死得很惨。原因很简单:列表是通用容器,ndarray是数值计算专用容器。当你需要对一百万个数字做逐元素乘法时,列表需要写循环,ndarray一行代码搞定,而且底层是C实现的,速度快几十倍。

我做过一个简单的对比测试:对一个包含100万个浮点数的列表和ndarray分别做平方运算,列表耗时大约0.08秒,ndarray只要0.002秒。这还只是单次运算,如果在机器学习中要做几千次迭代,差距就是几分钟和几小时的差别。

Numpy的核心概念只有几个,但必须吃透:

  • shape:数组的形状,比如(1000, 5)表示1000行5列。这是最容易出错的地方,很多报错都是shape不匹配导致的。
  • dtype:数据类型,常见的有float64、int32、bool。机器学习中默认用float64,但有时候为了省内存可以转成float32。
  • 广播机制:不同shape的数组做运算时,Numpy会自动扩展维度。这个机制很方便,但也是bug的重灾区。

注意:广播机制虽然好用,但不要依赖它做复杂的维度变换。我见过太多人因为广播导致结果shape不对,排查半天。遇到不确定的情况,先用.reshape()把shape显式写清楚。

一个实操中非常常见的场景是:你从CSV读进来的数据,某一列本来是数字,但因为里面混了一个“未知”字符串,整列变成了object类型。这时候你用Numpy做运算就会报错。解决办法是用pd.to_numeric(errors='coerce')强制转换,把无法转换的变成NaN,然后再决定是填充还是删除。

2.2 Pandas的DataFrame:数据清洗的主战场

如果说Numpy是发动机,Pandas就是方向盘。真实项目里,80%的时间花在数据清洗上,而Pandas就是干这个的。零基础的人最容易犯的错误是:拿到数据直接往模型里塞,结果报了一堆错,然后开始怀疑人生。

我总结了一套数据清洗的固定流程,每次拿到新数据都按这个顺序走:

  1. 看形状和类型:df.shape和df.dtypes,先知道有多少行多少列,每列是什么类型。
  2. 看缺失值:df.isnull().sum(),统计每列缺失多少。如果某列缺失超过50%,考虑直接丢掉。
  3. 看分布:df.describe(),对数值列看均值、标准差、分位数。如果发现最大值是999999,大概率是异常值。
  4. 看类别:对分类列用df['col'].value_counts(),看看有没有类别极度不平衡。
  5. 处理缺失值:数值列用中位数填充,分类列用众数填充,或者直接删除缺失行。
  6. 处理异常值:用IQR方法或者3σ原则识别,然后决定是截断还是删除。

这套流程看起来简单,但每一步都有坑。比如中位数填充,很多人直接写df.fillna(df.median()),结果报错,因为中位数只能对数值列计算。正确的做法是分开处理:

# 数值列用中位数填充 num_cols = df.select_dtypes(include=['float64', 'int64']).columns df[num_cols] = df[num_cols].fillna(df[num_cols].median()) # 分类列用众数填充 cat_cols = df.select_dtypes(include=['object']).columns for col in cat_cols: df[col] = df[col].fillna(df[col].mode()[0])

还有一个经典坑:SettingWithCopyWarning。当你从一个大DataFrame切片出一个小DataFrame,然后试图修改小DataFrame时,Pandas会警告你可能修改的是视图而不是副本。解决办法是切片时显式加.copy():

subset = df[df['age'] > 30].copy() subset['new_col'] = subset['age'] * 2 # 这样就不会警告

这个警告不是小事,我见过有人因为没加.copy(),导致修改了一个子集,结果原始数据也被改了,整个分析结果全错。

2.3 可视化:不画图你永远不知道数据长什么样

很多人觉得可视化是“锦上添花”,不做也行。我的观点恰恰相反:可视化是数据理解的核心手段,不是装饰。你算出一列数据的均值是50,标准差是10,然后呢?你知道它是正态分布还是双峰分布吗?你知道有没有离群点吗?画个直方图,三秒钟就看明白了。

Matplotlib是基础,但说实话,它的默认样式不太好看,而且API有点啰嗦。我的建议是:入门用Matplotlib搞懂原理,实战用Seaborn提高效率。Seaborn封装了很多统计图形,一行代码就能画出带回归线的散点图、带分布的分组箱线图。

几个必会的图形和它们的用途:

图形用途关键参数
直方图看单变量分布bins控制柱子数量
箱线图看分布和离群点自动标记超过1.5倍IQR的点
散点图看两个变量的关系alpha控制透明度,避免重叠
热力图看相关系数矩阵annot=True显示数值
配对图看多变量两两关系适合特征不多时快速探索

提示:画散点图时一定要加alpha=0.5左右的透明度。否则数据点一多,图就是一团黑,什么都看不出来。这个技巧是我在画了几十张废图之后才养成的习惯。

还有一个实操心得:画图之前先采样。如果你的数据有几十万行,直接画散点图会卡死,而且点太密也看不出规律。随机采样5000行再画,效果一样,速度快十倍。

3. KNN和回归:从第一个分类器到第一个预测器

3.1 KNN的直觉:近朱者赤,近墨者黑

KNN(K近邻)是我推荐给零基础的人第一个上手的算法,原因很简单:它的思想可以用一句话说清楚。你要预测一个新样本的类别,就看它在特征空间里离哪些已知样本最近,然后让最近的K个样本投票决定。

这个算法没有训练过程,所有计算都发生在预测阶段。这既是优点也是缺点。优点是简单直观,缺点是预测慢,而且对特征尺度极其敏感。

我举个例子说明尺度敏感有多严重。假设你有两个特征:年龄(范围20-60)和年收入(范围2万-200万)。在计算距离时,收入的差异会完全主导结果,年龄的影响几乎可以忽略。解决办法是标准化,把所有特征缩放到同一量级。最常用的是Z-score标准化:

from sklearn.preprocessing import StandardScaler scaler = StandardScaler() X_scaled = scaler.fit_transform(X)

注意:fit_transform只能用在训练集上。测试集必须用训练集的scaler做transform,否则会数据泄露。这个坑我踩过,当时测试集准确率异常高,排查了半天才发现是标准化时把测试集的信息也带进去了。

K值的选择也有讲究。K太小,模型对噪声敏感,容易过拟合;K太大,模型过于平滑,容易欠拟合。一般从3开始试,然后5、7、9这样往上加。如果类别不平衡,K最好取奇数,避免投票平局。

还有一个实用技巧:用交叉验证选K。不要手动一个个试,写个循环:

from sklearn.model_selection import cross_val_score for k in [3, 5, 7, 9, 11]: knn = KNeighborsClassifier(n_neighbors=k) scores = cross_val_score(knn, X_scaled, y, cv=5) print(f"K={k}, 平均准确率={scores.mean():.4f}")

这样跑一遍,哪个K最好一目了然。

3.2 线性回归:不只是画一条直线

线性回归看起来简单,但它是理解所有机器学习模型的基础。它的核心思想是:找到一组权重,使得预测值和真实值的平方误差之和最小。这个“平方误差之和最小”就是最小二乘法。

零基础的人容易忽略的是:线性回归有很多假设。比如残差要服从正态分布、残差方差要恒定、特征之间不能有严重共线性。如果这些假设不满足,模型的结果就不可靠。

我一般会做几个诊断:

  • 残差图:横轴是预测值,纵轴是残差。如果呈现喇叭形,说明方差不齐。
  • Q-Q图:检查残差是否正态分布。
  • VIF:方差膨胀因子,大于10说明有严重共线性。
from statsmodels.stats.outliers_influence import variance_inflation_factor vif_data = pd.DataFrame() vif_data["feature"] = X.columns vif_data["VIF"] = [variance_inflation_factor(X.values, i) for i in range(X.shape[1])] print(vif_data)

如果VIF很高,解决办法有:删除相关特征、用PCA降维、或者改用正则化回归(Ridge或Lasso)。

说到正则化,这是线性回归必须掌握的进阶内容。Ridge回归加的是L2正则,会让权重变小但不为零;Lasso回归加的是L1正则,会把不重要的特征权重直接压到零,相当于自动做特征选择。实际项目中,如果特征很多且你怀疑大部分没用,先用Lasso筛一遍。

3.3 逻辑回归:名字叫回归,其实是分类

逻辑回归是我见过名字最误导人的算法。它叫“回归”,但干的是分类的活。它的核心是在线性回归的基础上加了一个Sigmoid函数,把输出压缩到0到1之间,表示属于某一类的概率。

为什么不用线性回归做分类?因为线性回归的输出可以是任意实数,没法直接解释为概率。而且平方误差损失对分类问题来说,梯度性质不好,容易陷入困境。逻辑回归用的是对数损失,梯度更稳定。

逻辑回归的可解释性很强,每个特征的权重可以理解为“该特征增加一个单位,对数几率增加多少”。这在风控、医疗等需要解释的场景中非常重要。

实操中,逻辑回归有几个关键参数:

  • penalty:正则化类型,l1或l2。
  • C:正则化强度的倒数,C越小正则化越强。
  • solver:优化算法,l1一般用liblinear或saga,l2用lbfgs。
from sklearn.linear_model import LogisticRegression lr = LogisticRegression(penalty='l2', C=1.0, solver='lbfgs', max_iter=1000) lr.fit(X_train_scaled, y_train)

注意:逻辑回归对特征尺度也敏感,尤其是用了正则化之后。所以标准化这一步不能省。我见过有人不做标准化直接跑,结果模型完全不收敛,还以为是数据有问题。

4. 决策树与集成学习:从单棵树到一片森林

4.1 决策树:最符合人类直觉的模型

决策树是我最喜欢用来给零基础的人解释的模型,因为它完全模拟了人类的决策过程。你去看病,医生先问“发烧吗”,再问“咳嗽吗”,然后根据回答决定下一步。决策树就是这么干的:每个节点选一个特征,根据特征值把数据分成两拨,递归下去,直到满足停止条件。

决策树的核心是特征选择。ID3用信息增益,C4.5用信息增益率,CART用基尼系数。Scikit-learn用的是CART,所以默认是基尼系数。基尼系数的直观理解是:从数据集中随机抽两个样本,它们类别不一致的概率。概率越小,数据越纯。

决策树最大的优点是可解释性强,你可以直接把树画出来,给非技术人员看。但它的缺点也很致命:极其容易过拟合。如果不加限制,树可以一直长到每个叶子节点只有一个样本,在训练集上准确率100%,在测试集上可能只有60%。

控制过拟合的参数主要有:

  • max_depth:树的最大深度,最常用的参数。
  • min_samples_split:节点分裂所需的最小样本数。
  • min_samples_leaf:叶子节点的最小样本数。
  • max_features:每次分裂考虑的最大特征数。
from sklearn.tree import DecisionTreeClassifier dt = DecisionTreeClassifier( max_depth=5, min_samples_split=10, min_samples_leaf=5, random_state=42 )

我一般会先用默认参数跑一遍,看看树有多深,然后根据情况限制深度。如果树深度超过10,基本可以确定过拟合了。

还有一个实用技巧:用plot_tree把树画出来,直观看看哪些特征最重要。如果树的前几层用的都是同一个特征,说明这个特征很强。

4.2 随机森林:三个臭皮匠顶个诸葛亮

随机森林的思想非常朴素:既然一棵树容易过拟合,那我就种很多棵树,让它们投票。每棵树用不同的数据子集(Bootstrap采样)和不同的特征子集来训练,最后综合所有树的结果。

为什么随机森林有效?因为每棵树的偏差差不多,但方差可以通过平均来降低。这就像你问一个人问题可能不准,但问一百个人取平均,结果就靠谱多了。

随机森林的关键参数:

  • n_estimators:树的数量,一般100到500就够了,再多收益递减。
  • max_depth:每棵树的最大深度,通常不限制,让树充分生长。
  • max_features:每次分裂考虑的特征数,分类问题默认是sqrt(n_features)。
  • oob_score:是否用袋外样本评估模型,开启后可以不用单独划分验证集。
from sklearn.ensemble import RandomForestClassifier rf = RandomForestClassifier( n_estimators=200, max_depth=None, max_features='sqrt', oob_score=True, random_state=42, n_jobs=-1 ) rf.fit(X_train, y_train) print(f"袋外准确率: {rf.oob_score_:.4f}")

提示:n_jobs=-1表示用所有CPU核心并行训练,能显著加快速度。这个参数在数据量大、树多的时候特别有用。

随机森林还有一个非常好用的功能:特征重要性。训练完之后,rf.feature_importances_会给出每个特征的重要性分数。这个分数可以用来做特征选择,把重要性低的特征删掉,往往能提升模型效果。

4.3 梯度提升:从AdaBoost到XGBoost的进化

如果说随机森林是“并行种树”,那梯度提升就是“串行种树”。它的核心思想是:每一棵新树都去拟合前面所有树的残差,一步步把误差降下来。

梯度提升的经典代表是GBDT,后来进化出了XGBoost、LightGBM、CatBoost等高效实现。这些工具在结构化数据竞赛中几乎是无敌的存在。

XGBoost相比传统GBDT的改进主要有:

  • 二阶导数:用损失函数的二阶泰勒展开,收敛更快。
  • 正则化:在目标函数中加入了树复杂度的惩罚项,控制过拟合。
  • 并行化:特征粒度上的并行,训练速度大幅提升。
  • 缺失值处理:自动学习缺失值的分裂方向。
import xgboost as xgb model = xgb.XGBClassifier( n_estimators=300, learning_rate=0.05, max_depth=6, subsample=0.8, colsample_bytree=0.8, reg_alpha=0.1, reg_lambda=1.0, random_state=42 ) model.fit(X_train, y_train, eval_set=[(X_test, y_test)], early_stopping_rounds=20, verbose=False)

early_stopping_rounds是一个非常重要的参数。它表示如果验证集上的指标连续20轮没有提升,就停止训练。这能有效防止过拟合,同时节省训练时间。

LightGBM是微软出的,比XGBoost更快,内存占用更少。它的核心改进是直方图算法和Leaf-wise生长策略。直方图算法把连续特征离散化成桶,大大减少了分裂点的搜索次数。Leaf-wise策略每次选增益最大的叶子分裂,而不是像XGBoost那样按层分裂,所以树更深、更不平衡,但精度往往更高。

import lightgbm as lgb model = lgb.LGBMClassifier( n_estimators=500, learning_rate=0.05, num_leaves=31, max_depth=-1, subsample=0.8, colsample_bytree=0.8, random_state=42 )

num_leaves是LightGBM最重要的参数,它控制树的复杂度。一般设置为2^max_depth以下,比如max_depth=6时,num_leaves不要超过64。

5. 聚类:没有标签时怎么发现数据里的结构

5.1 K-Means:简单但需要动脑子

K-Means是最常用的聚类算法,没有之一。它的流程极其简单:随机选K个中心点,把每个样本分配给最近的中心,然后重新计算中心,重复直到中心不再变化。

但简单不代表好用。K-Means有几个硬伤:

  • 需要预先指定K:你不知道数据该分几类,它不会告诉你。
  • 对初始中心敏感:不同的初始化可能得到完全不同的结果。
  • 只能发现球形簇:如果数据是环形或者月牙形,K-Means完全无能为力。
  • 对离群点敏感:一个极端值可以把中心拉偏很多。

针对这些问题,实操中有几个应对策略:

选K:用肘部法或轮廓系数。肘部法是画K和 inertia(簇内平方和)的关系图,找拐点。轮廓系数是衡量簇内紧密度和簇间分离度的指标,越接近1越好。

from sklearn.cluster import KMeans from sklearn.metrics import silhouette_score inertias = [] silhouettes = [] for k in range(2, 11): km = KMeans(n_clusters=k, n_init=10, random_state=42) labels = km.fit_predict(X_scaled) inertias.append(km.inertia_) silhouettes.append(silhouette_score(X_scaled, labels))

初始化:用n_init=10,让算法跑10次不同初始化,取最好的结果。Scikit-learn新版本默认就是10,但老版本是1,要注意。

数据预处理:K-Means基于距离,所以必须标准化。而且如果数据有离群点,先用IQR方法处理掉。

注意:K-Means的标签是没有顺序的。第一次跑出来“簇0”可能对应第二次的“簇2”。如果你需要稳定的标签,要么固定random_state,要么用聚类结果做后续分析时不要依赖标签编号。

5.2 DBSCAN:能发现任意形状的簇

DBSCAN是我个人非常喜欢的聚类算法,因为它解决了K-Means的两个核心痛点:不需要指定K,能发现任意形状的簇。

它的核心概念只有两个:

  • eps:邻域半径。
  • min_samples:成为核心点所需的最小邻居数。

根据这两个参数,样本被分为三类:核心点(邻域内样本数≥min_samples)、边界点(在核心点邻域内但自己不是核心点)、噪声点(既不是核心点也不是边界点)。

DBSCAN的调参比K-Means更棘手。eps太小,大部分点都是噪声;eps太大,所有点都聚成一团。我的经验是:先用KNN找eps的参考值。计算每个点到第min_samples个最近邻的距离,排序后画图,找拐点。

from sklearn.neighbors import NearestNeighbors from sklearn.cluster import DBSCAN # 找eps参考值 nbrs = NearestNeighbors(n_neighbors=5).fit(X_scaled) distances, indices = nbrs.kneighbors(X_scaled) distances = np.sort(distances[:, -1]) # 画图找拐点,拐点对应的距离就是eps的参考值 db = DBSCAN(eps=0.5, min_samples=5) labels = db.fit_predict(X_scaled)

DBSCAN还有一个好处:能识别噪声点。标签为-1的样本就是噪声。这在异常检测场景中非常有用。

5.3 聚类结果的评估与业务解释

聚类和分类不一样,没有真实标签,所以评估更主观。常用的内部指标有:

指标含义取值范围越大越好?
轮廓系数簇内紧密 vs 簇间分离-1到1是
Calinski-Harabasz簇间方差/簇内方差0到正无穷是
Davies-Bouldin簇内散度/簇间距离0到正无穷否

但我要说的是:内部指标只能作为参考,最终还是要看业务解释。你聚出来的簇,如果业务方看不懂、用不上,那指标再高也没意义。

我一般会做一件事:对每个簇计算特征均值,然后对比整体均值。比如电商用户聚类,如果某个簇的“购买频率”远高于整体,“客单价”也高,那这个簇就是高价值用户。如果某个簇的“最近购买时间”很久远,“购买频率”很低,那就是流失用户。这样一解释,业务方立刻就能理解。

# 对每个簇计算特征均值 cluster_profile = df.groupby('cluster').mean() # 对比整体均值 overall_mean = df.mean() diff = cluster_profile - overall_mean print(diff)

这个差异表是聚类分析中最有价值的输出之一。它直接告诉你每个簇的“性格”。

6. 把整条链路串起来:一个完整项目的实操节奏

6.1 项目流程的固定节奏

学完所有算法之后,最重要的是把它们串起来。一个完整的机器学习项目,节奏应该是这样的:

  1. 明确问题:是分类、回归还是聚类?评估指标是什么?
  2. 获取数据:从数据库、CSV、API等来源拿到原始数据。
  3. 数据探索:用Pandas和可视化工具了解数据的基本情况。
  4. 数据清洗:处理缺失值、异常值、重复值、类型转换。
  5. 特征工程:构造新特征、编码分类变量、标准化数值变量。
  6. 划分数据:训练集、验证集、测试集,或者用交叉验证。
  7. 基线模型:先用最简单的模型跑一个基线,比如逻辑回归或决策树。
  8. 模型迭代:尝试更复杂的模型,调参,集成。
  9. 模型评估:在测试集上评估,看是否达到业务要求。
  10. 结果解释:特征重要性、聚类画像、预测结果分析。
  11. 部署上线:保存模型,写预测接口,监控效果。

这个流程看起来线性,但实际中经常要回退。比如特征工程做完发现模型效果不好,可能要回到数据清洗阶段重新处理。

6.2 特征工程:决定模型上限的关键步骤

有一句话在圈内流传很广:数据和特征决定了机器学习的上限,模型和算法只是逼近这个上限。我深以为然。

特征工程包括几个方面:

数值特征处理:

  • 标准化:Z-score,适合大多数算法。
  • 归一化:Min-Max,适合神经网络和KNN。
  • 分箱:把连续值离散化,比如年龄分成青年、中年、老年。
  • 对数变换:处理右偏分布,比如收入。

分类特征处理:

  • One-Hot编码:适合类别数少的特征。
  • Label编码:适合有序分类,比如低、中、高。
  • Target编码:用目标变量的均值编码,适合高基数特征,但要小心数据泄露。

时间特征处理:

  • 提取年、月、日、星期、小时。
  • 计算时间差,比如“距离上次购买多少天”。
  • 滑动窗口统计,比如“过去7天平均消费”。

交互特征:

  • 两个特征的乘积、比值、差值。
  • 比如“收入/年龄”可能比单独的收入或年龄更有预测力。
# 一个实用的特征工程示例 df['age_income_ratio'] = df['income'] / (df['age'] + 1) df['purchase_per_day'] = df['total_purchases'] / (df['days_since_first_purchase'] + 1) df['is_weekend'] = df['purchase_date'].dt.dayofweek.isin([5, 6]).astype(int)

提示:特征工程不要一次加太多,容易过拟合。每次加几个,用交叉验证看效果。如果没提升甚至下降,果断删掉。

6.3 模型评估:准确率不是唯一标准

零基础的人最容易犯的错就是只看准确率。在类别不平衡的场景下,准确率极具误导性。比如一个二分类问题,99%的样本是负类,1%是正类。你什么都不做,全预测负类,准确率就有99%。但这个模型毫无价值。

正确的评估方式是根据业务场景选指标:

场景推荐指标原因
类别平衡准确率、F1简单直观
类别不平衡AUC、召回率、精确率不受类别比例影响
代价敏感自定义代价矩阵不同错误的代价不同
排序问题NDCG、MAP关注排序质量

混淆矩阵是理解这些指标的基础:

from sklearn.metrics import confusion_matrix, classification_report print(confusion_matrix(y_test, y_pred)) print(classification_report(y_test, y_pred))

classification_report会输出每个类别的精确率、召回率、F1和样本数。我一般会重点看宏平均F1和加权平均F1。如果两者差距大,说明类别不平衡严重。

还有一个非常重要的概念:交叉验证。不要只做一次训练集/测试集划分,因为划分本身有随机性。用5折或10折交叉验证,看平均分和标准差。如果标准差很大,说明模型不稳定,需要检查数据或调整参数。

from sklearn.model_selection import cross_val_score scores = cross_val_score(model, X, y, cv=5, scoring='f1_macro') print(f"F1: {scores.mean():.4f} (+/- {scores.std():.4f})")

6.4 调参:网格搜索和随机搜索怎么选

调参是模型优化的最后一步,但很多人把它当成第一步。我的建议是:先把数据和特征搞好,再调参。数据质量差,调参调到天荒地老也没用。

网格搜索(GridSearchCV)是穷举所有参数组合,适合参数少、范围小的情况。随机搜索(RandomizedSearchCV)是随机采样参数组合,适合参数多、范围大的情况。贝叶斯优化(如Optuna)是更高级的方法,用概率模型指导搜索,效率更高。

from sklearn.model_selection import GridSearchCV, RandomizedSearchCV from scipy.stats import randint, uniform # 网格搜索 param_grid = { 'max_depth': [3, 5, 7, 9], 'min_samples_split': [2, 5, 10], 'min_samples_leaf': [1, 2, 4] } grid = GridSearchCV(DecisionTreeClassifier(), param_grid, cv=5, scoring='f1_macro', n_jobs=-1) grid.fit(X_train, y_train) print(grid.best_params_) # 随机搜索 param_dist = { 'n_estimators': randint(100, 500), 'max_depth': randint(3, 15), 'learning_rate': uniform(0.01, 0.3) } random = RandomizedSearchCV(XGBClassifier(), param_dist, n_iter=50, cv=5, scoring='f1_macro', n_jobs=-1) random.fit(X_train, y_train)

注意:调参时一定要用交叉验证,不要用测试集。测试集只能用一次,就是最终评估的时候。如果你用测试集调参,那测试集就变成了验证集,最终评估结果会偏乐观。

7. 零基础学习路上最容易踩的五个坑

7.1 坑一:只看视频不动手

这是零基础的人最大的坑。看视频的时候觉得什么都懂,一写代码就懵。机器学习是练出来的,不是看出来的。我的建议是:看一个知识点,立刻找一份数据跑一遍。哪怕只是把示例代码抄一遍,然后改几个参数看结果变化,也比光看强十倍。

7.2 坑二:追求最新最复杂的模型

很多人一上来就想学深度学习、Transformer。但结构化数据上,XGBoost和LightGBM往往比深度学习效果更好,而且训练快、可解释。先把经典算法吃透,再考虑深度学习。我见过太多人用神经网络做表格数据,效果还不如随机森林。

7.3 坑三:不做数据探索直接建模

拿到数据直接fit,然后抱怨效果差。数据探索是建模的前提。你不了解数据的分布、缺失、异常,怎么可能选对模型和参数?我每次拿到新数据,至少花30%的时间在探索和清洗上。

7.4 坑四:用测试集调参

前面说过,测试集只能用一次。但很多人忍不住,调一次参看一次测试集,调着调着测试集就变成了验证集。正确的做法是:训练集训练,验证集调参,测试集只在最后评估一次。

7.5 坑五:忽略业务解释

模型准确率再高,如果业务方看不懂、用不上,就是废的。可解释性和业务价值同样重要。决策树、逻辑回归、特征重要性、聚类画像,这些都是让业务方理解模型的工具。不要只丢一个准确率数字过去。

8. 从入门到能干活,接下来该练什么

学完上面这些,你已经具备了机器学习的基础能力。但距离“能干活”还有一段距离。接下来我建议做三件事:

第一,找真实数据集练手。Kaggle上的Titanic、House Prices是经典入门赛,但太简单了。可以找一些更有挑战的,比如带时间序列的销售预测、带文本的评论分类、带图像的商品识别。真实数据的脏乱差,是课本数据给不了的。

第二,完整走一遍项目流程。从数据获取到模型部署,全部自己来。不要只做建模那一步。数据清洗、特征工程、模型评估、结果可视化,每一步都要亲手做。做完一个完整项目,比做十个半截项目收获大得多。

第三,学会读文档和源码。Scikit-learn、XGBoost、LightGBM的文档写得非常好,每个参数都有详细解释。遇到不懂的,先查文档,再查源码。这个习惯会让你受益终身。

我自己的经验是:入门阶段最重要的是建立信心和兴趣。不要一上来就啃最难的部分,先从能跑通、能看到结果的小项目开始。每跑通一个,信心就增加一分。等信心足够了,再去挑战更复杂的内容。

机器学习这个领域,入门不难,难的是持续深入。但只要你保持“用代码解决问题”的习惯,每一步都会走得很踏实。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 22:42:34

存储接口、总线与协议三者关系详解:从物理连接到数据传输逻辑

1. 这不是“背概念”,而是搞懂数据怎么从硬盘跑到你手机屏幕上的你有没有想过,当你在手机上点开一张照片,或者在电脑里双击一个视频文件,背后到底发生了什么?那张照片不是凭空出现的——它得先从硬盘(或SSD…

作者头像 李华
网站建设 2026/10/20 22:38:23

Wireshark抓包实战:解剖TCP三次握手与四次挥手的真实流量

1. 为什么抓包看三次握手比背定义管用十倍我带过不少刚学网络的新人,发现一个特别普遍的现象:他们能把TCP三次握手的SYN、SYN-ACK、ACK背得滚瓜烂熟,也能默写出四次挥手的FIN、ACK、FIN、ACK顺序,但一遇到线上服务连接超时、接口偶…

作者头像 李华
网站建设 2026/10/20 22:37:41

深度学习数学基础:梯度下降、Adam、熵与归一化层全解析

做深度学习做到一定阶段,大家都会开始回补数学基础。标题里这几个词——Adam优化器、梯度下降、熵、过拟合、LN和BN——几乎每一次真实训练都会碰到,但很多人一开始只是死记公式,等模型训不动了才回头补课。这篇文章想把笔记重新整理一遍&…

作者头像 李华
网站建设 2026/10/20 22:34:31

Transformer架构深度解析:从注意力机制到训练避坑实战

1. 为什么这篇论文值得反复读如果你关注自然语言处理或者大模型,Transformer 这个词你应该不陌生。从 BERT 到 GPT 系列,几乎所有主流语言模型都建立在 Transformer 架构之上。而这一切的源头,就是 2017 年那篇《Attention Is All You Need》…

作者头像 李华
网站建设 2026/10/20 22:32:05

信创环境下数据库与中间件监控体系搭建实战复盘

最近我们团队接手了一个典型的信创环境改造项目,要把原来跑在商业数据库和商业中间件上的业务系统,整体迁移到国产数据库和国产中间件上。迁移本身倒还好,真正让我头疼的是监控体系:以前靠现成管理工具能看到的那些指标&#xff0…

作者头像 李华
网站建设 2026/10/20 22:31:03

抖店开放平台签名机制详解:从sign not match到完整接入

做电商ERP或者订单管理的朋友,第一次调抖店开放平台接口时,撞见的第一个报错十有八九是签名错误: sign not match 、验签失败、参数签名错误……原因很简单,抖店API的每个请求都必须携带一个由业务参数和密钥计算出来的签名&…

作者头像 李华