ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

机器学习入门首选Scikit-learn:从环境搭建到完整项目实战指南

机器学习入门首选Scikit-learn:从环境搭建到完整项目实战指南 1. 为什么新手入门机器学习我首推Scikit-learn而不是TensorFlow经常有人跑来问我想学机器学习是不是直接上TensorFlow或者PyTorch我的回答通常都是先别急把Scikit-learn玩明白你才知道机器学习到底在干嘛。这不是说深度学习框架不好而是对于一个完全没有经验的人来说Scikit-learn的学习曲线要友好好几个量级。先说说Scikit-learn是什么。它是Python生态里最老牌、最稳定的传统机器学习库简称sklearn。从2007年发布到现在已经迭代了十几年功能覆盖了分类、回归、聚类、降维、数据预处理、模型评估、特征选择等几乎所有传统机器学习任务。你只需要会基本的Python语法就能用十来行代码构建一个逻辑回归、决策树、随机森林或者SVM模型然后完成对数据的预测。我见过太多一上来就学深度学习的同学结果卡在张量、梯度、反向传播这些概念上学了两三个月还在原地打转连一个能用的模型都跑不出来。但如果是先学Scikit-learn从拿到数据集、清洗数据、训练模型、评估效果到调参整个流程一两周就能理清楚。等你真正理解了机器学习的基本流程明白了模型训练、验证、过拟合、欠拟合这些概念再去玩深度学习框架会发现很多理念是相通的上手速度会快得多。而且Scikit-learn的应用场景远比很多人想象的广泛。虽然深度学习在图像识别、自然语言处理这些领域风头正劲但在日常的表格数据、业务数据、金融风控、用户画像、推荐系统、工业预测性维护等场景中传统机器学习依然是绝对主力。很多互联网公司的核心业务模型用的就是Scikit-learn里的逻辑回归、梯度提升树这些算法。自己动手搭建一个完整的机器学习项目从这个库入门是最好的选择。2. 万事开头难环境安装与Scikit-learn版本选择2.1 安装前的准备工作哪个Python版本最稳在装Scikit-learn之前你得先有一个能用的Python环境。我强烈建议不要直接去Python官网装一个原生Python然后配环境变量那样后面管理第三方包会很痛苦。我个人的推荐是装Anaconda。Anaconda是一个开源的Python发行版自带Python解释器和一大批数据科学常用的包包括NumPy、Pandas、Matplotlib、Jupyter Notebook这些更关键的是它自带conda包管理器可以很方便地创建独立的虚拟环境避免不同项目之间的依赖冲突。装好以后用conda创建一个独立环境然后激活它conda create -n sklearn_env python3.10 conda activate sklearn_env选择Python 3.10的原因是它是目前兼容性最稳的版本各个第三方库的适配都做得比较好。太新的Python版本有些库的预编译包还没跟上容易在安装时踩到编译报错的坑。2.2 正式安装Scikit-learnpip和conda两种方式对比环境准备完毕接下来就是装核心库。两条路可以走我用一个表格简单对比一下安装方式命令优点缺点pippip install scikit-learn安装快包通常比较新依赖管理不如conda严格偶尔会装到不兼容的依赖版本condaconda install scikit-learn依赖解析由conda统一管理很少出现依赖冲突默认源比较慢需要换国内镜像包更新可能略滞后我自己现在基本都是用pip因为pip配好国内镜像后速度很快而且Scikit-learn的依赖不算复杂一般就NumPy和SciPy这两个核心库冲突概率很低。如果你不是做非常复杂的环境管理直接pip就够用了。装完后验证一下版本python -c import sklearn; print(sklearn.__version__)看到类似“1.6.0”这样的输出版本号就说明装成功了。顺便看一下numpy和scipy的版本号确保它们也都是比较新的版本。2.3 现成数据集新手不需要自己找数据Scikit-learn自带了一组经典的数据集对新手来说这是天大的福音。你不需要上网到处找数据、下载数据、清洗数据直接就能拿来做练习。最常用的几个load_iris()鸢尾花数据集150条样本4个特征3个类别分类入门首选load_boston()波士顿房价数据集注意新版sklearn已经移除了这个数据集因为它的字段有伦理问题可以用fetch_california_housing()替代做回归练习load_digits()手写数字数据集1797张8x8的灰度图用来体验图像分类还有一个make_classification()函数可以按你的参数需求生成模拟数据我做演示的时候经常用。新手用自带数据集的好处是你可以把全部精力放在理解模型调用的逻辑上而不是被数据清洗绊住脚。3. 机器学习到底在做什么先把“特征、标签、训练、预测”这四个词彻底学透在跑代码之前我特别想把这一节单拎出来讲清楚因为太多人代码跑通了但心里其实完全不知道机器学习在干什么。如果你不理解这些核心概念后面所有代码都只是复制粘贴换个真实项目就抓瞎。3.1 训练一个模型本质上是在学一个函数我们小时候都学过函数给定一个x通过某种规则得到y。机器学习训练出来的模型本质上就是干这件事——它学着找到一个从x到y的映射关系。只不过这个函数太复杂不是用几行公式能表达出来的而是通过大量数据“算”出来的。举个例子你给一个系统输入一张猫的图片的数值化表示输出是一个标签“猫”或“狗”。在机器学习的世界里这个输入的数值化表示叫“特征向量”输出叫“标签”。模型的作用就是从大量已知特征和标签的对应关系中学到一个足够好的映射函数以至于下次看到一个从没见过的新样本也能大概率猜对标签。3.2 “特征”和“标签”是什么我用预测房价来说明白。假设你要用线性回归预测一套房子的价格。你手里有历史上1000套房子的成交记录。每条记录里有面积、卧室数量、所在楼层、房龄、以及最终成交价。这里“面积”、“卧室数”、“楼层”、“房龄”就是特征“成交价”就是标签。数据在交给模型之前通常要组织成一个二维表格的结构很像Excel表格。每一行是一个样本每一列是一个特征再加上一列标签。Scikit-learn的StandardScaler方法要求数据必须是这种结构——行是样本列是特征这是一个非常核心的规则。3.3 训练和预测的本质区别训练fit是让模型“看”数据“学”规律的过程预测predict是模型利用学到的规律去猜新样本答案的过程。选几行数据给模型看然后给它一叠没有答案的试卷让它自己批改这个过程在Scikit-learn里就是两行代码model.fit(X_train, y_train) predictions model.predict(X_test)在Scikit-learn中fit函数和predict函数几乎是所有模型类的统一接口这是这个库最让我喜欢的设计哲学——换一个算法调用方式一模一样重点全在你的数据上。这一点后面我会展开细讲。理解了这四个概念机器学习的第一步你就迈过去了。实际上大部分机器学习项目的失败都跟这些基础概念没吃透有关。比如有人把数据预处理做错把连续值当成离散值输入模型效果很差还找不到原因有人把整个数据集拿去训练没有留测试集结果评估出来分数高得离谱一看就是过拟合了。这些问题都会随着你对基础概念的理解深入而逐渐避免。4. 第一个完整项目实战用鸢尾花数据集跑通“训练-评估-预测”全流程光说不练假把式。在这个部分我把机器学习里最经典的“Hello World”项目拆开揉碎来讲——鸢尾花分类。我会走完从加载数据到模型评估的完整流程每一步都讲清楚到底在做什么、为什么这么做。4.1 加载数据下面的代码加载Scikit-learn自带的鸢尾花数据集from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split iris load_iris() X iris.data y iris.target print(特征矩阵形状:, X.shape) # (150, 4) print(标签数量:, len(y)) # 150 print(类别名称:, iris.target_names) # [setosa versicolor virginica]这里的X是150行4列的二维数组每一行是一朵鸢尾花的四个特征数值花萼长度、花萼宽度、花瓣长度、花瓣宽度。y是150个标签值0、1、2分别对应上面打印的三个品种名称。4.2 划分训练集和测试集拿到数据后第一件事不能是直接训练而是先把数据分成两份一份用于训练模型一份用于检验模型在“没见过”的数据上的表现。还有一个很容易被忽略的关键点划分数据之前要先把数据打乱shuffle。Scikit-learn的train_test_split函数很贴心它默认就会帮我们打乱数据再切分所以不太用担心这个问题。下面我们按7:3的比例划分# test_size0.3 表示拿出30%的数据做测试集 # random_state42 固定随机种子让每次运行结果一致便于复现 X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, random_state42 ) print(X_train.shape) # (105, 4) print(X_test.shape) # (45, 4)关于random_state我要多说两句。很多新手不明白为什么每次要设这个固定值。如果你不设每次运行程序划分出的训练集和测试集都不一样模型结果也会有波动。为了做实验对比不同的算法你就必须保证大家用同一份数据训练和测试。设置一个固定数值就好比给这次划分盖了个章之后任何人都可以复现你的结果。4.3 选择模型并训练接下来选择一个分类算法来训练。对于这种多分类、特征数量不多的小数据集逻辑回归是一个很好的起点。它的可解释性强、训练速度快而且作为最简单的线性分类器非常适合理解模型训练的过程。from sklearn.linear_model import LogisticRegression model LogisticRegression(max_iter1000) model.fit(X_train, y_train)我注意到很多第一次接触的同学会问fit到底是在干什么我们以前写代码都是在执行逻辑但fit是在“学习参数”。具体来说对于逻辑回归fit的过程就是通过一种叫梯度下降的优化方法不断调整模型内部的权重参数使得模型在训练数据上的预测结果和真实标签之间的差距越来越小。在没调整任何参数的情况下逻辑回归默认就能跑得很不错。但那行max_iter1000可能会让你踩到第一个坑如果不设置这个参数有时候会看到一条“ConvergenceWarning: Maximum iterations reached”的警告意思是模型在迭代到默认上限时还没收敛。这很常见于数据没有做标准化的情况为了不让训练过程因为迭代次数不够而半途而废我习惯显式地调大这个值。4.4 用测试集做预测模型训练完成之后最重要的环节来了——拿从来没有参与过训练的数据去考它看它能不能举一反三predictions model.predict(X_test) print(predictions[:10])这行代码输出的是测试集中前10个样本的预测结果可能是0或1或2。如果你想看模型预测的是每个类别的“置信度”也就是概率值还可以用predict_proba方法probabilities model.predict_proba(X_test[:3]) print(probabilities)输出的每一行是3个数字分别代表模型认为该样本属于类别0、1、2的概率。三个数加起来正好为1。4.5 评估模型准确率到底是什么意思评估分类模型最简单的指标就是准确率——预测正确的样本数除以总样本数。Scikit-learn里可以直接用一行代码算出来from sklearn.metrics import accuracy_score print(预测准确率:, accuracy_score(y_test, predictions))在我固定了random_state42的这套划分下这个模型通常能拿到0.9778的准确率。也就是说45个测试样本中模型只把1个样本的分类预测错了。对于一行机器学习代码都没写过的同学来说第一次看到这个数字会特别有成就感。这种感觉很重要它会成为你继续学下去的动力。不过我得提前打个预防针在真实项目中准确率并不是越高越好甚至有时候准确率高反而是个危险信号。比如一个99%样本都是正常用户的风控系统模型什么都不学全预测“正常用户”准确率就有99%。但真正的欺诈用户一个都抓不到这样的模型没有任何价值。这就引出了我们下一节要讲的更全面的评估方法。到这里你已经亲手完成了一个完整的机器学习项目全流程。整个过程其实就干了一件事——用历史数据训练一个函数然后拿新数据喂给这个函数得到预测结果。5. 别只盯着精确率Scikit-learn里更靠谱的模型评估指标和调参方法5.1 精确率、召回率和F1各自的适用场景上面说过只有准确率是远远不够的。在分类问题上Scikit-learn提供了更全面的评估工具。先说3个最核心的评估指标我用一个互联网公司识别垃圾邮件的场景来说明精确率Precision你从所有邮件里挑出10封预测为垃圾邮件其中7封确实是垃圾那么精确率就是70%。这个指标回答的是“你说是垃圾的到底有多少真是垃圾”。追求高精确率是为了减少误伤正常邮件。召回率Recall一共有100封真垃圾邮件你的模型只抓到了60封那召回率就是60%。这个指标关注的是“真的垃圾邮件你抓回了多少”。追求高召回率是为了尽量不漏掉每一封垃圾邮件。F1分数精确率和召回率的调和平均数。当这两个指标出现矛盾时F1就是一个平衡的折中值。如果你分类的目标是疾病筛查你可能要优先看召回率因为漏诊一个病人的代价远大于误诊如果你的目标是内容审核你可能更看重精确率因为误删用户正常内容会引发大量投诉。在Scikit-learn里这些指标全都有现成的函数from sklearn.metrics import classification_report print(classification_report(y_test, predictions))一行代码就能输出每个类别的精确率、召回率和F1分数以及各类别样本数。我几乎每个分类项目都会先跑一次这个函数快速判断模型在哪些类别上表现弱。在鸢尾花这个例子中你会发现三个类别的精确率都在0.96以上说明模型整体很均衡没有什么严重的偏向。5.2 把数据标准化为什么特征尺度不同会坑掉模型再往前推一步很多新手第一次训练完模型遇到训练不收敛、效果很差的问题十有八九是因为特征没有做标准化。我提前说一下这个问题等到你自己写项目时能少走弯路。先理解一下什么是“特征尺度不同”假设你在做一个房价预测面积这个特征的范围是30到200房龄的范围是1到50而小区评分是1到10。你会发现面积的数值普遍偏大在模型计算距离或者梯度时就会占据决定性地位其他特征几乎被“淹没”了。很多算法会因此对数据分布非常敏感。解决方案是缩放特征让它们的范围大致保持一致。Scikit-learn中最常用的是StandardScaler它会把每个特征变成均值为0、标准差为1的分布。一个很典型的流程是这样的from sklearn.preprocessing import StandardScaler scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train) X_test_scaled scaler.transform(X_test)注意这两个“坑”是非常重要的细节首先fit_transform需要用在训练集上而transform用在测试集上。原因是不允许让测试集的数据统计信息比如均值和标准差参与模型训练过程否则会发生信息泄露。还有一个是数据标准化本身就是为了让某些对尺度敏感的模型比如逻辑回归、SVM、KNN跑得更稳。但对决策树、随机森林这类基于划分的树模型有没有标准化影响不大因为它们不考虑特征之间的距离而是关注“怎么切”纯度增益。我第一次知道这个结论时感觉一下子明白了为什么有些项目几乎不用做数据预处理。5.3 交叉验证比一次性划分更靠谱的评估策略如果你足够细心可能会发现一个隐藏的问题前面我们划分了一次训练集和测试集这个划分是随机的那结果会不会因为这次偶然的划分而有失偏颇确实有这个问题。这就是为什么在实际项目中普遍会用交叉验证Cross-Validation来更稳定地评估模型的表现。交叉验证的思路非常直白把原始训练集切成K份每次拿出其中1份做验证剩下K-1份做训练轮流K次最终得到K个验证分数再取平均值。这样就大大降低了“这次碰巧划分得好”的运气成分模型评估结果更可信。Scikit-learn里的交叉验证简单到令人发指from sklearn.model_selection import cross_val_score scores cross_val_score(model, X_train, y_train, cv5) print(5折交叉验证得分:, scores) print(平均得分:, scores.mean())一般来说5折或10折是常用选择。如果数据量特别小也可以用留一法Leave-One-Out。新手在做模型对比时用cross_val_score而不是盲目相信单次准确率这是一个成熟的信号。5.4 用网格搜索调参的科学方法模型训练完后大家都会想一个问题能不能调一调参数让效果更好如果手动一个个去试效率太低。Scikit-learn提供了网格搜索GridSearchCV把参数组合自动排列好每组都做交叉验证最后告诉你哪组参数效果最好。比如对逻辑回归来说有一个重要的超参数是正则化强度C在小数据集上手动试5个值就够我倾向于取对数尺度上的几个点from sklearn.model_selection import GridSearchCV param_grid {C: [0.01, 0.1, 1, 10, 100]} grid_search GridSearchCV( LogisticRegression(max_iter1000), param_grid, cv5, scoringaccuracy ) grid_search.fit(X_train, y_train) # 找到的最优参数组合 print(最优参数:, grid_search.best_params_) # 对应的最优分数 print(最优交叉验证分数:, grid_search.best_score_)注意一点虽然GridSearchCV内部自己会交叉验证但网格搜索的分数是基于它内部的训练集和验证集评估出来的不是最终测试集分数。当你用这批“最优参数”重新训练最终模型后最后还是要拿最开始划分出来的那一份X_test做一次最终评估才算是诚实的结果。否则网格搜索会过拟合验证集导致你高估模型能力。6. 从Scikit-learn毕业之后新手的常见卡点与实际建议6.1 为什么代码跑通了却觉得没学到东西我观察到很多自学机器学习的同学出现的最典型的困惑是跑通了鸢尾花数据集代码一行一行理解也没问题接下来就不知道干嘛了。这就是“学了API却没有建立知识体系”的状态。我的个人建议是用一个自己熟悉领域的小数据集做一次完整的项目实践。比如你对电商感兴趣就用一份关于用户购买行为的数据去预测用户会不会复购。这样数据是你最熟悉不过的背景知识你很容易就能理解特征的含义和业务的合理性。从一卷自带数据集到自找数据这个过程会逼你去处理很多问题数据有缺失值怎么办、字符串特征怎么编码、样本严重失衡怎么办所有这些都会让你真正上一个台阶。Scikit-learn的文档是我见过所有开源库里写得最认真的之一每个模型都配有实际的例子和详细说明。遇到不熟悉的模型直接去找官方示例对着运行看效果比读一堆二手博客靠谱得多。官方还有一份备忘速查表专门帮你根据“我有多少标注数据”“数据是否带有标签”“需要解决什么问题”等维度快速定位合适的算法。6.2 常见坑位索引我整理的一份避坑清单坑位现象解决方案一次性把整个数据集拿来训练测试时分数虚高换到新数据上效果崩盘永远先切分出测试集只在训练集上做fit用fit_transform处理测试集导致信息泄露评估结果不可信训练集fit_transform测试集只transform忽略缺失值部分模型报警告或直接报错用SimpleImputer填充均值/中位数/众数把字符串类别直接喂给模型类型报错用OneHotEncoder或OrdinalEncoder编码不设置随机种子每次跑结果不一样无法复现统一设置random_state42所有特征不做标准化就训练SVM/KNN/逻辑回归训练不收敛效果差用StandardScaler预处理后再训练拿网格搜索的结果当作最终测试分数对模型能力盲目乐观网格搜索只在训练集内做最终保留测试集做验证这几个坑我基本都踩过一遍尤其是前两个几乎每隔一段时间就会看到有人犯同样的错误。信息泄露这件事特别隐蔽——表面上代码没报错评估指标也漂亮但模型其实已经被“剧透”了真实环境里根本达不到测试时的效果。6.3 学完传统机器学习下一步应该怎么办Scikit-learn入门以后回头看TensorFlow和PyTorch你会发现自己已经具备了理解机器学习全流程的知识框架。这时候再学深度学习其实就是在已有框架基础上换一种更“重型”的工具。你会发现整个流程还是那几步——数据处理、划分数据集、训练模型、评估效果、调参只是模型的内部结构变化了。大多数人的下一步方向取决于你想做什么对文本感兴趣可以尝试用Scikit-learn先做文本分类先掌握TF-IDF特征表示和朴素贝叶斯模型再逐步接触更复杂的神经网络文本模型。对推荐系统感兴趣可以先从协同过滤的思路出发用Scikit-learn里的最近邻算法做一个简单的“猜你喜欢”。对图像感兴趣可以先用load_digits()手写数字识别练手了解图像如何展平成一维向量再过渡到深度学习里的卷积神经网络。我给大多数新手的建议是一个月的时间把Scikit-learn核心用法掌握扎实一个月之后你再决定是深入研究传统机器学习算法还是转向深度学习。这个过程不只是学了一堆函数调用更是在帮你完成思维训练从“拿到数据一脸茫然”到“知道先看什么、后做什么、如何评估结果是否有价值”。有了这个基底后面你无论是继续学算法推导、学工程部署还是跳去学深度学习框架都会顺畅得多。机器学习这条路很长但Scikit-learn绝对是最好的第一个台阶。
返回列表