资讯动态

机器学习入门实战:回归、聚类、决策树、随机森林、神经网络与贝叶斯算法选型与Python实现

发布时间:2026/10/20 14:04:30 来源:尧图企业网站定制
机器学习入门这件事我见过太多人卡在同一个地方教程看了一堆公式推了一遍真拿到一份数据集却不知道从哪下手。这个项目标题里列了一长串——回归、聚类、决策树、随机森林、神经网络、贝叶斯看起来像是把整个算法图谱铺开了但真正有价值的问题不是这些算法分别是什么而是它们各自解决什么类型的问题什么时候该用哪个怎么用Python把它们串成一条完整的分析链路。这篇内容就是围绕这条主线展开的适合有一点Python基础、想系统建立机器学习实战能力的人也适合已经会调库但说不清原理的开发者拿来补课。1. 整体学习路径与算法选型逻辑1.1 为什么不能按算法清单逐个学很多人学机器学习的路径是这样的今天学线性回归明天学决策树后天啃神经网络每个算法都跑一遍sklearn的demo然后觉得自己学过了。但一到真实问题就懵了——因为真实问题不会告诉你请用随机森林解决它只会给你一张表或者一堆数据让你自己判断。我的建议是反过来先建立问题类型→算法族→具体算法的映射关系再往每个格子里填细节。机器学习要解决的问题本质上就几大类预测一个连续数值房价、销量、温度。这类问题归到回归算法族线性回归、多项式回归、正则化回归、回归树、随机森林回归都在这个族里。预测一个类别邮件是不是垃圾、用户会不会流失。这类问题归到分类算法族逻辑回归、决策树、随机森林、朴素贝叶斯、神经网络分类器都在这里。把相似的东西归堆用户分群、商品分组。这类问题归到聚类算法族K-Means、DBSCAN、层次聚类是主力。在少量标注下做判断文本分类、垃圾过滤。朴素贝叶斯在这种场景下往往出奇地好用。你看标题里那串算法名其实可以全部塞进这四个格子里。学的时候按格子学用的时候按格子找效率完全不一样。1.2 工具链选型为什么是Python scikit-learnPython在机器学习领域的地位不用多解释但具体到工具选型我想说清楚几个关键决策。scikit-learn是主力框架原因是它的API设计极其统一fit()训练、predict()预测、score()评估几乎所有算法都遵循这套接口。这意味着你学会了一个算法的调用方式换另一个算法只需要改类名和参数。对于入门阶段这种一致性比性能更重要。NumPy和Pandas是数据层的基础。NumPy负责数值计算Pandas负责表格数据处理。实际项目中数据清洗和特征工程的时间往往占整个流程的60%以上这两个库的熟练程度直接决定你的效率。Matplotlib和Seaborn负责可视化。不要跳过可视化它是你理解数据分布、发现异常值、验证模型效果的最直接手段。我见过太多人拿到数据直接往模型里灌结果模型效果差排查半天发现是某个特征的量纲差了三个数量级。深度学习部分用PyTorch还是TensorFlow对于入门阶段我倾向于先用scikit-learn的MLPClassifier理解神经网络的基本概念再过渡到PyTorch。原因是sklearn的神经网络封装屏蔽了太多细节适合理解神经网络是一个非线性分类器这个层面但真要理解反向传播、梯度下降、批次训练这些概念还是得用PyTorch手动写一遍训练循环。注意不要一上来就装一堆框架。入门阶段numpy、pandas、scikit-learn、matplotlib这四个就够了。装太多反而分散注意力。1.3 环境搭建的实操细节环境搭建看起来简单但踩坑的人不少。我用的是conda管理虚拟环境原因是它能同时管理Python版本和非Python依赖比如某些科学计算库的底层C库。conda create -n ml-basics python3.11 conda activate ml-basics pip install numpy pandas scikit-learn matplotlib seaborn jupyter版本选择上Python 3.10到3.12都是安全的scikit-learn建议1.3以上。不要用太新的版本有些库的兼容性还没跟上。Jupyter Notebook是入门阶段最好的实验工具因为它允许你分块运行代码、即时看到结果、随时修改。但要注意一点Notebook容易让人养成随手写、不整理的习惯。我的做法是在Notebook里做探索性分析一旦某个流程跑通了就把它整理成.py脚本文件方便复用和版本管理。2. 核心算法原理与关键细节拆解2.1 回归算法从最小二乘到正则化回归是机器学习里最直观的一类算法。线性回归的核心思想是找到一条直线或者超平面让所有数据点到这条线的距离平方和最小。这个距离平方和最小就是最小二乘法的目标函数。数学上对于 $y Xw b$最优的 $w$ 有解析解$w (X^TX)^{-1}X^Ty$。但在实际中我们很少直接用这个公式原因有两个一是矩阵求逆在特征多的时候计算量大二是当特征之间存在共线性时$X^TX$ 可能不可逆。所以实际中更常用的是梯度下降法来迭代求解。这里有一个关键参数学习率。学习率太大损失函数会震荡甚至发散学习率太小收敛速度慢得让人抓狂。我的经验是先用0.01试如果损失下降太慢就调到0.1如果震荡就降到0.001。正则化是回归算法里最容易被忽视但最重要的部分。L2正则化Ridge在损失函数里加上权重的平方和让权重趋向于小值L1正则化Lasso加上权重的绝对值之和会让部分权重直接变成零起到特征选择的作用。ElasticNet则是两者的混合。from sklearn.linear_model import Ridge, Lasso, ElasticNet from sklearn.preprocessing import StandardScaler from sklearn.pipeline import Pipeline # 正则化回归必须做标准化否则惩罚项对量纲大的特征不公平 ridge_pipe Pipeline([ (scaler, StandardScaler()), (model, Ridge(alpha1.0)) ])实操心得正则化回归之前一定要做标准化。因为惩罚项是对权重的大小进行约束如果某个特征的量纲是另一个的1000倍那它的权重自然就会很小惩罚项对它的约束就不公平了。我见过有人不做标准化直接用Ridge结果模型效果还不如普通线性回归。2.2 聚类算法K-Means的陷阱与DBSCAN的适用场景K-Means是最常用的聚类算法但它的局限性也很明显。它假设簇是球形的、大小相近的而且需要预先指定簇的数量K。实际数据往往不满足这些假设。K-Means的算法流程是随机选K个中心点把每个样本分配到最近的中心然后重新计算每个簇的中心重复直到收敛。这个过程本质上是在最小化簇内平方和WCSS。K值怎么选常用的方法是肘部法则画一条K从1到10的WCSS曲线找那个下降速度突然变缓的拐点。但这个方法的判断往往很主观。更客观的指标是轮廓系数Silhouette Score它同时考虑样本到本簇其他点的距离和到最近簇的距离取值范围是-1到1越接近1越好。from sklearn.cluster import KMeans from sklearn.metrics import silhouette_score scores [] for k in range(2, 11): km KMeans(n_clustersk, n_init10, random_state42) labels km.fit_predict(X_scaled) scores.append(silhouette_score(X_scaled, labels))注意n_init10这个参数。K-Means对初始中心点的选择很敏感不同的初始化可能得到完全不同的结果。n_init表示跑10次不同的初始化取最好的那次。在scikit-learn 1.4之后默认值从10改成了auto建议显式设置。DBSCAN是另一类聚类算法它不需要指定簇的数量而是基于密度来发现簇。它的两个核心参数是eps邻域半径和min_samples成为核心点所需的最小邻居数。DBSCAN能发现任意形状的簇还能识别噪声点这是K-Means做不到的。但DBSCAN的参数调起来比K-Means麻烦。eps太小大部分点都被当成噪声eps太大所有点都归成一个簇。我的做法是先画k-距离图每个点到第k个最近邻的距离排序图找拐点作为eps的参考值。2.3 决策树与随机森林从单棵树到集成学习决策树的核心是递归地选择最优特征进行分裂。什么是最优分类树用基尼系数或信息增益回归树用均方误差。基尼系数衡量的是节点的不纯度值越小说明节点里的样本越纯。决策树最大的问题是容易过拟合。一棵完全生长的树可以把训练集做到100%准确但泛化能力极差。解决办法是剪枝限制树的最大深度、最小叶节点样本数、最小分裂样本数等。from sklearn.tree import DecisionTreeClassifier dt DecisionTreeClassifier( max_depth5, # 限制深度 min_samples_leaf10, # 叶节点最少10个样本 min_samples_split20, # 分裂需要至少20个样本 random_state42 )随机森林是决策树的集成版本。它的核心思想是三个臭皮匠顶个诸葛亮训练多棵决策树每棵树用不同的数据子集Bootstrap采样和不同的特征子集最后投票决定结果。这样做的好处是降低了单棵树的过拟合风险同时保持了决策树的可解释性可以通过特征重要性来看哪些特征最重要。随机森林的关键参数是n_estimators树的数量和max_features每次分裂考虑的特征数。n_estimators一般设100到500就够了再多收益递减。max_features在分类任务中常用sqrt特征数的平方根回归任务中常用1.0全部特征或0.3。踩过的坑随机森林的feature_importances_属性给出的是基于不纯度减少的特征重要性当特征中存在类别数较多的分类特征时这个指标会偏向于这些特征。更可靠的做法是用permutation_importance它通过打乱特征值来观察模型性能的变化更接近真实的重要性。2.4 朴素贝叶斯为什么朴素反而好用朴素贝叶斯的核心是贝叶斯定理$P(y|X) P(X|y)P(y) / P(X)$。它假设所有特征在给定类别下相互独立——这就是朴素的来源。这个假设在现实中几乎从来不成立但朴素贝叶斯在文本分类等任务上表现却很好。原因在于分类任务只需要比较不同类别的后验概率大小不需要精确的概率值。即使独立性假设导致概率估计有偏差只要偏差不改变大小关系的排序分类结果就是对的。朴素贝叶斯有三种常见变体高斯朴素贝叶斯假设特征服从正态分布适合连续特征、多项式朴素贝叶斯适合计数特征如词频、伯努利朴素贝叶斯适合二值特征。文本分类中最常用的是多项式朴素贝叶斯。from sklearn.naive_bayes import MultinomialNB from sklearn.feature_extraction.text import TfidfVectorizer # 文本分类的经典组合 vectorizer TfidfVectorizer(max_features5000, stop_wordsenglish) X_train_vec vectorizer.fit_transform(X_train_text) nb MultinomialNB(alpha1.0) # alpha是平滑参数 nb.fit(X_train_vec, y_train)alpha是拉普拉斯平滑参数防止某个特征在某个类别中从未出现导致概率为零。一般设1.0就行如果数据量很大可以调小。2.5 神经网络从感知机到多层感知机神经网络的基本单元是神经元输入加权求和经过激活函数输出结果。单个神经元只能解决线性可分的问题这就是为什么需要多层网络和非线性激活函数。激活函数的选择很关键。Sigmoid函数在早期很流行但它有个致命问题当输入很大或很小时梯度接近零导致梯度消失深层网络训练不动。ReLURectified Linear Unit解决了这个问题它在正区间梯度恒为1计算也简单。但ReLU在负区间梯度为零可能导致神经元死亡。LeakyReLU和ELU是改进版本。from sklearn.neural_network import MLPClassifier mlp MLPClassifier( hidden_layer_sizes(128, 64, 32), # 三个隐藏层 activationrelu, solveradam, alpha0.001, # L2正则化 learning_rate_init0.001, max_iter500, early_stoppingTrue, # 验证集性能不提升就停 random_state42 )hidden_layer_sizes的设定没有固定公式。我的经验是先从一层开始神经元数量在输入特征数和输出类别数之间取一个值然后根据验证集表现调整。层数增加通常比单层神经元增加更有效但也不要超过3到4层否则训练困难和过拟合的风险都会上升。early_stoppingTrue是一个很实用的设置它自动从训练集里分出一部分做验证当验证集性能连续若干轮不提升就停止训练防止过拟合。3. 完整项目实战流程3.1 项目场景与数据准备我以一个模拟的用户行为预测项目为例走一遍完整流程。场景是根据用户的基本信息和历史行为预测用户是否会在一周内产生某类操作。这是一个二分类问题。数据方面我用sklearn.datasets里的make_classification生成模拟数据包含2000个样本、20个特征其中10个是有信息量的5个是冗余的。from sklearn.datasets import make_classification X, y make_classification( n_samples2000, n_features20, n_informative10, n_redundant5, n_classes2, random_state42 )真实项目中数据准备阶段要做的事情包括处理缺失值均值填充、中位数填充、或模型预测填充、处理异常值用IQR或Z-score识别、编码分类变量One-Hot或Label Encoding、特征缩放标准化或归一化。3.2 数据划分与交叉验证数据划分有一个铁律测试集只能在最后评估时用一次。如果在调参过程中反复用测试集评估就会造成信息泄露模型在测试集上的表现会虚高。from sklearn.model_selection import train_test_split, StratifiedKFold, cross_val_score X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42, stratifyy ) cv StratifiedKFold(n_splits5, shuffleTrue, random_state42)stratifyy保证训练集和测试集中正负样本的比例一致。对于类别不平衡的数据这个参数很重要。StratifiedKFold同理它保证每一折中类别比例一致。交叉验证的作用是更可靠地评估模型性能。5折交叉验证意味着把训练集分成5份每次用4份训练、1份验证重复5次取平均。这样得到的评估结果比单次划分更稳定。3.3 多模型对比与超参数调优我一般会先跑一个基线对比把几个候选算法都用默认参数跑一遍交叉验证看看哪个方向更有希望。from sklearn.linear_model import LogisticRegression from sklearn.tree import DecisionTreeClassifier from sklearn.ensemble import RandomForestClassifier from sklearn.naive_bayes import GaussianNB from sklearn.neural_network import MLPClassifier from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler models { LogisticRegression: Pipeline([ (scaler, StandardScaler()), (clf, LogisticRegression(max_iter1000)) ]), DecisionTree: DecisionTreeClassifier(random_state42), RandomForest: RandomForestClassifier(n_estimators100, random_state42), NaiveBayes: GaussianNB(), MLP: Pipeline([ (scaler, StandardScaler()), (clf, MLPClassifier(hidden_layer_sizes(64, 32), max_iter500, random_state42)) ]) } for name, model in models.items(): scores cross_val_score(model, X_train, y_train, cvcv, scoringf1) print(f{name}: F1 {scores.mean():.4f} (/- {scores.std():.4f}))评估指标的选择要看具体场景。对于类别平衡的问题准确率就够了对于类别不平衡的问题F1分数、AUC-ROC更合适。我在这里用F1因为它同时考虑精确率和召回率。基线跑完之后对表现最好的模型做超参数调优。GridSearchCV是暴力搜索适合参数空间小的情况RandomizedSearchCV随机采样适合参数空间大的情况。from sklearn.model_selection import GridSearchCV param_grid { n_estimators: [100, 200, 300], max_depth: [5, 10, 15, None], min_samples_leaf: [1, 5, 10], max_features: [sqrt, log2] } grid GridSearchCV( RandomForestClassifier(random_state42), param_grid, cvcv, scoringf1, n_jobs-1, verbose1 ) grid.fit(X_train, y_train) print(fBest params: {grid.best_params_}) print(fBest F1: {grid.best_score_:.4f})n_jobs-1表示用所有CPU核心并行计算能显著加快搜索速度。3.4 模型评估与结果解读调优完成后用最优模型在测试集上做最终评估。这一步要看的不仅是准确率还有混淆矩阵、分类报告、ROC曲线。from sklearn.metrics import classification_report, confusion_matrix, roc_auc_score best_model grid.best_estimator_ y_pred best_model.predict(X_test) y_prob best_model.predict_proba(X_test)[:, 1] print(confusion_matrix(y_test, y_pred)) print(classification_report(y_test, y_pred)) print(fAUC-ROC: {roc_auc_score(y_test, y_prob):.4f})混淆矩阵告诉你模型在哪些类别上容易犯错。如果假阳性高说明模型倾向于把负样本判成正样本如果假阴性高则相反。分类报告给出每个类别的精确率、召回率和F1。AUC-ROC衡量的是模型区分正负样本的能力不受分类阈值影响。特征重要性分析也是重要一环。随机森林的feature_importances_可以告诉你哪些特征对预测贡献最大这对业务理解和后续特征工程都有帮助。4. 常见问题与排查技巧实录4.1 模型效果差的排查思路模型效果差是最常见的问题排查要按顺序来不要跳步。排查步骤检查内容常见问题1. 数据质量缺失值、异常值、重复值缺失值填充方式不当异常值未处理2. 特征工程特征缩放、编码方式未标准化导致距离类算法失效3. 数据泄露训练集和测试集是否独立标准化在划分之前做了4. 模型选择算法是否适合问题类型用回归算法做分类5. 超参数是否调优默认参数不适合当前数据6. 评估指标指标是否合理类别不平衡时用准确率数据泄露是最隐蔽的问题。一个典型的错误是先对整个数据集做标准化再划分训练集和测试集。这样测试集的均值和方差信息就泄露到了训练过程中。正确的做法是用Pipeline把标准化和模型封装在一起在交叉验证的每一折内部单独做标准化。4.2 过拟合与欠拟合的判断与处理过拟合的表现是训练集表现很好验证集表现差很多。处理方法包括增加数据量、减少特征数、增加正则化强度、降低模型复杂度减少树深度、减少神经网络层数、使用Dropout神经网络、早停。欠拟合的表现是训练集和验证集表现都差。处理方法包括增加模型复杂度、增加特征、减少正则化、训练更长时间。判断过拟合和欠拟合的一个实用方法是画学习曲线横轴是训练样本数纵轴是性能指标分别画训练集和验证集的曲线。如果两条曲线收敛但都处于较低水平是欠拟合如果两条曲线之间有明显间隙是过拟合。4.3 类别不平衡的处理策略类别不平衡在实际项目中非常常见。比如欺诈检测中欺诈样本可能只占0.1%。这时候准确率就没有意义了——一个把所有样本都判为非欺诈的模型准确率是99.9%但毫无用处。处理方法有几种重采样对少数类过采样或对多数类欠采样、调整类别权重class_weightbalanced、更换评估指标用F1、AUC-ROC代替准确率、使用适合不平衡数据的算法如代价敏感学习。# 方法一调整类别权重 rf RandomForestClassifier(class_weightbalanced, random_state42) # 方法二SMOTE过采样需要安装imbalanced-learn from imblearn.over_sampling import SMOTE smote SMOTE(random_state42) X_resampled, y_resampled smote.fit_resample(X_train, y_train)注意重采样只能在训练集上做绝对不能在测试集上做。否则测试集里包含了合成样本评估结果不可信。4.4 神经网络训练不收敛的排查神经网络训练不收敛的原因通常有几个学习率太大导致震荡、学习率太小导致收敛慢、数据未标准化导致梯度不稳定、网络结构不合理、激活函数选择不当。我的排查顺序是先检查数据是否标准化再检查学习率然后检查网络结构。学习率可以从0.001开始试如果损失震荡就降到0.0001如果下降太慢就升到0.01。批量大小也会影响训练太小导致梯度噪声大太大导致内存不够且泛化可能变差一般32到256之间比较合适。5. 从入门到精通的进阶路线5.1 特征工程的进阶方向入门阶段用原始特征跑模型就够了但要提升效果特征工程是绕不开的。进阶方向包括特征交叉把两个特征组合成新特征、多项式特征、目标编码用目标变量的统计量编码分类特征、时间特征提取从时间戳中提取小时、星期、是否节假日等。特征选择也是重要一环。过滤法用方差、卡方、互信息筛选、包裹法递归特征消除RFE、嵌入法L1正则化、树模型的特征重要性各有适用场景。我一般先用过滤法快速筛掉明显无用的特征再用嵌入法做精细选择。5.2 模型融合与集成策略单个模型的效果总有上限模型融合往往能带来明显提升。常见策略有投票法分类、平均法回归、堆叠法用元学习器组合基模型、提升法AdaBoost、Gradient Boosting、XGBoost、LightGBM。对于表格数据梯度提升树尤其是LightGBM和XGBoost往往是效果最好的单模型。它们通过逐步添加弱学习器来修正前一步的错误在结构化数据上表现非常稳定。5.3 持续学习的建议机器学习领域更新很快但基础概念变化很慢。我的建议是把scikit-learn的官方文档通读一遍它写得非常清晰然后找几个真实数据集比如Kaggle上的入门竞赛完整走一遍流程最后再深入某个方向NLP、CV、推荐系统做专项学习。不要追求学完所有算法而是追求遇到问题知道往哪个方向找答案。工具和算法会变但分析问题的框架和解决问题的思路是通用的。我在实际项目中最深的体会是数据质量决定模型上限特征工程决定能否接近上限算法选择只是在上限附近做微调。很多人把大量时间花在换模型、调参数上却忽略了数据本身的清洗和特征的设计这是本末倒置。另外不要迷信复杂模型在很多业务场景下一个逻辑回归加上精心设计的特征效果不比深度学习差而且可解释性强得多上线和维护成本也低得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑