首页
友情链接
点点滴滴
关于本站
秋码记录
一个游离于山间之上的Java爱好者 | A Java lover living in the mountains
累计撰写
137
篇文章
累计创建
297
个标签
累计创建
45
个分类
栏目
首页
友情链接
点点滴滴
关于本站
搜索
包含标签
机器学习
错误分析 (Machine Learning 研习十九)
错误分析 您将探索数据准备选项,尝试多个模型,筛选出最佳模型,使用 Grid SearchCV微调其超参数,并尽可能实现自动化。在此,我们假设您已经找到了一个有前途的模型,并希望找到改进它的方法。其中一种方法就是分析它所犯的错误类型。 首先,查看混淆矩阵。为此,首先需要使用 cross_val_predict() 函数进行预测;然后可以像之前一样,将标签和预测值传递给 confusion_matrix()函数。不过,由于现在有 10 个类别而不是 2 个,混淆矩阵将包含大量数字,可能难以读取。 混淆矩阵的彩色图更容易分析。要绘制这样的图表,请使用ConfusionMatrixDisplay.from_predictions() 函数,如下所示: from sklearn.metrics import ConfusionMatrixDisplay y_train_pred = cross_val_predict(sgd_clf, X_train_scaled, y_train, cv=3) ConfusionMatrixDisplay.from_predictions(y_train, y_train_pred) plt.show() 这就产生了 图1 中的左图。这个混淆矩阵看起来相当不错:大多数图像都在主对角线上,这意味着它们被正确分类了。请注意,对角线上第 5 行第 5 列的单元格看起来比其他数字略暗。这可能是因为模型对 5 的错误较多,也可能是因为数据集中 5 的数量比其他数字少。这就是为什么要对混淆矩阵进行归一化处理,将每个值除以相应(真实)类别中的图像总数(即除以行的总和)。只需设置 normalize="true "即可。我们还可以指定 val ues_format=".0%"参数来显示不带小数点的百分比。下面的代码将生成 图1 右侧的图表: ConfusionMatrixDisplay.from_predictions(y_train, y_train_pred, normalize="true", values_format=".0%") plt.show() 现在我们不难发现,只有 82% 的 5 图像被正确分类。模型在处理 5 的图像时最常见的错误是将其误判为 8:在所有 5 的图像中,有 10%的图像被误判为 8。但只有 2% 的 8 被误判为 5;混淆矩阵通常不是对称的!如果你仔细观察,就会发现很多数字都被错误地分类为 8,但从这张图上并不能一眼看出。如果想让错误更明显,可以尝试将正确预测的权重设为零。下面的代码就是这样做的,并生成了图2 左侧的图表: sample_weight = (y_train_pred !
2024-04-10
[Machine Learning 人工智能]
多类别分类器(Machine Learning 研习十八)
多类别分类器 二元分类器可以区分两个类别,而多类别分类器(也称为多叉分类器)可以区分两个以上的类别。 一些 Scikit-Learn 分类器(如 LogisticRegression、RandomForestClassifier 和 GaussianNB)能够原生处理多个类别。其他分类器则是严格的二进制分类器(如 SGDClassifier 和 SVC)。不过,您可以使用多种策略来使用多个二进制分类器执行多类分类。 要创建一个能将数字图像分为 10 类(从 0 到 9)的系统,一种方法是训练 10 个二进制分类器,每个数字一个(0-检测器、1-检测器、2-检测器,以此类推)。然后,当您想对一幅图像进行分类时,您可以从每个分类器中得到该图像的判定分数,然后选择分类器输出分数最高的类别。这就是所谓的 “以一敌百”(OvR)策略,有时也称为 “以一敌众”(OvA)策略。 另一种策略是为每一对数字训练一个二元分类器:一个用于区分 0 和 1,另一个用于区分 0 和 2,还有一个用于区分 1 和 2,以此类推。这就是所谓的一对一(OvO)策略。如果有 N 个类别,则需要训练 N × (N - 1) / 2 个分类器。对于 MNIST 问题,这意味着要训练 45 个二进制分类器!当你想对一幅图像进行分类时,你必须让图像通过所有 45 个分类器,看看哪个分类器赢得了最多的对决。OvO 的主要优势在于,每个分类器只需在训练集中包含其必须区分的两个类别的部分进行训练。 有些算法(如支持向量机分类器)随训练集的大小而缩放,效果不佳。对于这些算法,OvO 是首选,因为在小训练集上训练多个分类器比在大训练集上训练少数分类器更快。不过,对于大多数二元分类算法来说,OvR 是首选。 Scikit-Learn 会检测你是否尝试在多分类任务中使用二元分类算法,并根据算法自动运行 OvR 或 OvO。让我们使用 sklearn.svm.SVC 类支持向量机分类器来尝试一下。我们只对前 2,000 张图像进行训练,否则会耗费很长时间: from sklearn.svm import SVC svm_clf = SVC(random_state=42) svm_clf.fit(X_train[:2000], y_train[:2000]) # y_train, not y_train_5 我们使用从 0 到 9 的原始目标类别(y_train),而不是 5 对其余目标类别(y_train_5)来训练 SVC。由于有 10 个类别(即多于 2 个),Scikit-Learn 使用 OvO 策略训练了 45 个二元分类器。现在,让我们对一幅图像进行预测:
2024-04-03
[Machine Learning 人工智能]
绘制特征曲线-ROC(Machine Learning 研习十七)
接收者操作特征曲线(ROC)是二元分类器的另一个常用工具。它与精确度/召回率曲线非常相似,但 ROC 曲线不是绘制精确度与召回率的关系曲线,而是绘制真阳性率(召回率的另一个名称)与假阳性率(FPR)的关系曲线。FPR(也称 “下降率”)是阴性实例被错误归类为阳性实例的比率。它等于 1 - 真阴性率 (TNR),即正确分类为阴性的阴性实例的比率。TNR 也称为特异性。因此,ROC 曲线是灵敏度(召回率)与 1 - 特异性的关系图 要绘制 ROC 曲线,首先要使用 roc_curve() 函数计算不同阈值的 TPR 和 FPR: from sklearn.metrics import roc_curve fpr, tpr, thresholds = roc_curve(y_train_5, y_scores) 然后可以使用 Matplotlib 绘制 FPR 与 TPR 的对比图。下面的代码可以绘制出 见下图 所示的图形。要找到与 90% 精度相对应的点,我们需要查找所需阈值的索引。由于在这种情况下阈值是按递减顺序排列的,因此我们在第一行使用 <= 而不是 >=: idx_for_threshold_at_90 = (thresholds <= threshold_for_90_precision).argmax() tpr_90, fpr_90 = tpr[idx_for_threshold_at_90], fpr[idx_for_threshold_at_90] plt.plot(fpr, tpr, linewidth=2, label="ROC curve") plt.plot([0, 1], [0, 1], 'k:', label="Random classifier's ROC curve") plt.plot([fpr_90], [tpr_90], "ko", label="Threshold for 90% precision") [.
2024-03-29
[Machine Learning 人工智能]
精确率(召回率)的权衡(Machine Learning 研习十六)
精确率(召回率)的权衡 为了理解这种权衡,让我们看看 SGDClassifier 如何做出分类决策。 对于每个实例,它根据决策函数计算分数。 如果该分数大于阈值,则将该实例分配给正类; 否则它会将其分配给负类。 图 3-4 显示了从左侧最低分数到右侧最高分数的几个数字。 假设决策阈值位于中心箭头(两个 5 之间):您会在该阈值右侧发现 4 个真阳性(实际为 5),以及 1 个假阳性(实际上为 6)。 因此,使用该阈值,精度为 80%(5 分之 4)。 但在 6 个实际的 5 中,分类器仅检测到 4 个,因此召回率为 67%(6 中的 4)。 如果提高阈值(将其移动到右侧的箭头),假阳性(6)会变成真阴性,从而提高精度(在本例中高达 100%),但一个真阳性会变成假阴性 ,将召回率降低至 50%。 相反,降低阈值会增加召回率并降低精确度。 Scikit-Learn 不允许您直接设置阈值,但它允许您访问它用于进行预测的决策分数。 您可以调用其decision_function()方法,而不是调用分类器的predict()方法,该方法返回每个实例的分数,然后使用您想要根据这些分数进行预测的任何阈值: SGDClassifier 使用等于 0 的阈值,因此前面的代码返回与 Predict() 方法相同的结果(即 True)。 让我们提高门槛: 这证实了提高阈值会降低召回率。 该图像实际上代表的是 5,当阈值为 0 时分类器会检测到它,但当阈值增加到 3,000 时分类器会错过它。 y_scores = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3, method="decision_function") 有了这些分数,使用 precision_recall_curve() 函数计算所有可能阈值的精度和召回率(该函数添加最后精度 0 和最后召回率 1,对应于无限阈值): from sklearn.
2024-03-21
[Machine Learning 人工智能]
对模型性能进行评估(Machine Learning 研习十五)
在上一篇我们已然训练了一个用于对数字图像识别的模型,但我们目前还不知道该模型在识别数字图像效率如何?所以,本文将对该模型进行评估。 使用交叉验证衡量准确性 评估模型的一个好方法是使用交叉验证,让我们使用cross_val_score()函数来评估我们的 SGDClassifier 模型,使用三折的 k 折交叉验证。k-fold 交叉验证意味着将训练集分成 k 个折叠(在本例中是三个),然后训练模型 k 次,每次取出一个不同的折叠进行评估: 当您看到这组数字,是不是感到很兴奋?毕竟所有交叉验证折叠的准确率(预测准确率)均超过了 95%。然而,在您兴奋于这组数字前,还是让我们来看看一个假分类器,它只是将每张图片归入最常见的类别,在本例中就是负类别(即非 5): from sklearn.dummy import DummyClassifier dummy_clf = DummyClassifier() dummy_clf.fit(X_train, y_train_5) print(any(dummy_clf.predict(X_train))) # prints False: no 5s detected 您能猜出这个模型的准确度吗?让我们一探究竟: 没错,它的准确率超过 90%!这只是因为只有大约 10% 的图片是 5,所以如果你总是猜测图片不是 5,你就会有大约 90% 的时间是正确的。比诺斯特拉达穆斯还准。 这说明了为什么准确率通常不是分类器的首选性能指标,尤其是在处理偏斜 数据集时(即某些类别的出现频率远高于其他类别)。评估分类器性能的更好方法是查看混淆矩阵(CM)。 实施交叉验证 与 Scikit-Learn 现成提供的功能相比,您有时需要对交叉验证过程进行更多控制。在这种情况下,你可以自己实现交叉验证。下面的代码与 Scikit-Learn 的 cross_val_score() 函数做了大致相同的事情,并会打印出相同的结果: from sklearn.model_selection import StratifiedKFold from sklearn.base import clone skfolds = StratifiedKFold(n_splits=3) # add shuffle=True if the dataset is # not already shuffled for train_index, test_index in skfolds.
2024-03-15
[Machine Learning 人工智能]
图像识别之入门案例之数字识别(Machine Learning 研习十四)
在前面的文章中,我们曾提到最为常见的监督学习任务是回归(预测价值)和分类(预测类别)。我们使用线性回归、决策树和随机森林等各种算法探讨了回归任务,即预测房屋价值。现在,我们将把注意力转向分类系统。 MNIST数据集 我们将使用 MNIST 数据集,这是一组由人类手写的 70,000 张小数字图像。每张图片都标注了所代表的数字。人们对这个数据集的研究非常深入,以至于它经常被称为机器学习的 “hello world”:每当人们提出一种新的分类算法时,他们都会好奇地想看看这种算法在 MNIST 上的表现如何,而且任何学习机器学习的人迟早都会用到这个数据集。 Scikit-Learn 提供了许多下载流行数据集的辅助函数。MNIST 就是其中之一。以下代码从 OpenML.org 获取 MNIST 数据集: from sklearn.datasets import fetch_openml mnist = fetch_openml('mnist_784', as_frame=False) sklearn.datasets 包主要包含三种类型的函数:fetch_* 函数(如 fetch_openml())用于下载现实生活中的数据集;load_* 函数用于加载 Scikit-Learn捆绑的小型玩具数据集(因此无需通过互联网下载);make_* 函数用于生成假数据集,对测试非常有用。生成的数据集通常以 (X, y) 元组的形式返回,其中包含输入数据和目标数据,两者都是 NumPy 数组。其他数据集以 sklearn.utils.Bunch 对象的形式返回,这是一个字典,其条目也可以作为属性访问。它们通常包含以下条目: “DESCR” 数据集描述 “data” 输入数据,通常为Numpy二维数组 “target” 标签,通常为Numpy一维数组 fetch_openml() 函数有点不寻常,因为默认情况下,它以 Pandas DataFrame 的形式返回输入,以 Pandas Series 的形式返回标签(除非数据集很稀疏)。但 MNIST 数据集包含图像,而 DataFrame 并不适合图像,因此最好设置 as_frame=False,以 NumPy 数组的形式获取数据。让我们来看看这些数组: 共有 70,000 幅图像,每幅图像有 784 个特征。这是因为每幅图像都是 28 × 28 像素,每个特征只代表一个像素的强度,从 0(白色)到 255(黑色)。让我们来看看数据集中的一个数字(图 3-1)。我们需要做的就是抓取一个实例的特征向量,将其重塑为 28 × 28 数组,然后使用 Matplotlib 的 imshow() 函数显示出来。我们使用 cmap="binary" 来获取灰度颜色图,其中 0 代表白色,255 代表黑色:
2024-03-15
[Machine Learning 人工智能]
微调模型——续(Machine Learning 研习之十三)
集成方法 微调系统的另一种方法是尝试组合性能最佳的模型。 群体(或“整体”)通常会比最好的单个模型表现得更好,就像随机森林比它们所依赖的单个决策树表现更好一样,特别是当各个模型犯下不同类型的错误时。 例如,您可以训练和微调 k 最近邻模型,然后创建一个仅预测随机森林预测和该模型预测的平均值的集成模型。 分析最佳模型及其错误 通过检查最佳模型,您通常会获得对问题的深入见解。 例如,RandomForestRegressor可以指示每个属性对于做出准确预测的相对重要性: 让我们按降序对这些重要性分数进行排序,并将它们显示在相应的属性名称旁边: 有了这些信息,您可能想尝试删除一些不太有用的功能(例如,显然只有一个ocean_proximity类别真正有用,因此您可以尝试删除其他功能)。 您还应该查看系统所犯的具体错误,然后尝试了解为什么会犯这些错误,以及如何解决问题:添加额外的功能或删除无信息的功能,清理异常值等。 现在也是一个好时机,可以确保您的模型不仅平均运行良好,而且适用于所有类别的地区,无论是农村还是城市、富裕还是贫穷、北部还是南部、少数民族还是非少数民族等。 每个类别的验证集需要一些工作,但这很重要:如果您的模型在整个地区类别上表现不佳,那么在问题解决之前可能不应该部署它,或者至少不应该使用它 对该类别进行预测,因为它可能弊大于利。 在测试集上评估您的系统 对模型进行一段时间的调整后,您最终会得到一个性能足够好的系统。 您已准备好在测试集上评估最终模型。 这个过程没有什么特别的; 只需从测试集中获取预测变量和标签并运行Final_model来转换数据并进行预测,然后评估这些预测: X_test = strat_test_set.drop("median_house_value", axis=1) y_test = strat_test_set["median_house_value"].copy() final_predictions = final_model.predict(X_test) final_rmse = mean_squared_error(y_test, final_predictions, squared=False) print(final_rmse) # prints 41424.40026462184 在某些情况下,这样的泛化误差点估计不足以说服您启动:如果它只比当前生产的模型好 0.1% 怎么办? 您可能想了解这个估计的精确度。 为此,您可以使用 scipy.stats.t.interval() 计算泛化误差的 95% 置信区间。 您会得到从 39,275 到 43,467 的相当大的区间,而您之前的点估计值 41,424 大致位于中间: 如果您进行了大量的超参数调整,性能通常会比使用交叉验证测量的性能稍差。 这是因为您的系统最终经过微调以在验证数据上表现良好,但在未知数据集上可能表现不佳。 本示例中的情况并非如此,因为测试 RMSE低于验证 RMSE,但当发生这种情况时,您必须抵制调整超参数以使数字在测试集上看起来不错的诱惑; 这些改进不太可能推广到新数据。 现在是项目预启动阶段:您需要展示您的解决方案(突出显示您所学到的内容、有效的内容和无效的内容、做出的假设以及系统的局限性),记录所有内容,并使用以下内容创建精美的演示文稿: 清晰的可视化和易于记忆的陈述(例如,“收入中位数是房价的第一预测指标”)。 在这个加州住房示例中,系统的最终性能并不比专家的价格估计好多少,专家的价格估计通常会下降 30%,但启动它可能仍然是一个好主意,特别是如果这样可以释放更多资金 给专家一些时间,以便他们可以从事更有趣、更有成效的任务。 启动、监控和维护您的系统 您现在需要准备好用于生产的解决方案(例如,完善代码、编写文档和测试等)。 然后您可以将模型部署到生产环境。 最基本的方法就是保存您训练的最佳模型,将文件传输到您的生产环境并加载它。 要保存模型,您可以使用 joblib 库,如下所示:
2024-03-09
[Machine Learning 人工智能]
微调模型(Machine Learning 研习之十二)
现在正处于百模乱战的时期,对于模型微调,想必您是有所了解了,毕竟国外的大语言模型一开源,国内便纷纷基于该模型进行微调,从而开始宣称领先于某某、超越了谁。可到头来,却让人发现他们套壳了国外大语言模型对外开放的API。 好了,我们不说国内各种大模型宣称超过了谁,毕竟,嘴巴长在别人脸上,我们管不了,也管不着,吹牛终将是会露馅的! 当我们需要对开源大模型进行微调时,看看有几种方法可以做到这一点的! 网格搜索 手动调整超参数,直到找到超参数值的完美组合。 这将是一项非常乏味的工作,而且您可能没有时间去探索多种组合。 相反,您可以使用 Scikit-Learn 的 GridSearchCV 类来搜索您。 您需要做的就是告诉它您希望它试验哪些超参数以及要尝试哪些值,它将使用交叉验证来评估超参数值的所有可能组合。 例如,以下代码搜索 RandomForestRegressor 的最佳超参数值组合: from sklearn.model_selection import GridSearchCV full_pipeline = Pipeline([ ("preprocessing", preprocessing), ("random_forest", RandomForestRegressor(random_state=42)), ]) param_grid = [{'preprocessing__geo__n_clusters': [5, 8, 10], 'random_forest__max_features': [4, 6, 8]}, {'preprocessing__geo__n_clusters': [10, 15], 'random_forest__max_features': [6, 8, 10]}, ] grid_search = GridSearchCV(full_pipeline, param_grid, cv=3, scoring='neg_root_mean_squared_error') grid_search.fit(housing, housing_labels) 请注意,您可以引用管道中任何估计器的任何超参数,即使该估计器嵌套在多个管道和列转换器的深处。 例如,当 Scikit-Learn 看到“preprocessing__geo__n_clusters”时,它会在双下划线处分割该字符串,然后在管道中查找名为“preprocessing”的估计器并找到预处理 ColumnTransformer。 接下来,它在此 ColumnTransformer 中查找名为“geo”的转换器,并找到我们在纬度和经度属性上使用的 ClusterSimilarity 转换器。 然后它找到该变压器的n_clusters超参数。 同样,random_forest__max_features指的是名为“random_forest”的估计器的max_features超参数,这当然是RandomForest模型。 这个param_grid中有两个字典,因此GridSearchCV将首先评估第一个字典中指定的n_clusters和max_features超参数值的所有3×3=9个组合,然后它将尝试第一个字典中指定的所有2×3=6个超参数值组合 第二个字典。 因此,网格搜索总共将探索 9 + 6 = 15 种超参数值组合,并且每个组合都会对管道进行 3 次训练,因为我们使用的是 3 折交叉验证。 这意味着总共将有 15 × 3 = 45 轮训练! 这可能需要一段时间,但是完成后您可以获得如下参数的最佳组合:
2024-03-09
[Machine Learning 人工智能]
选择和训练模型(Machine Learning 研习之十一)
当您看到本文标题时,不禁感叹,总算是到了训练模型这一节了。 是啊,在之前的文章中,我们对数据进行了探索,以及对一个训练集和一个测试集进行了采样,也编写了一个预处理管道来自动清理,准备您的数据用于机器学习算法,然而现在,我们可以选择并训练模型了。 训练集的训练与评估 我们从一个最基本的线性回归模型开始: from sklearn.linear_model import LinearRegression lin_reg = make_pipeline(preprocessing, LinearRegression()) lin_reg.fit(housing, housing_labels) 很好,至此,我们现在算是有了一个有效的线性回归模型,可以在训练集上试用它,查看前五个预测,并将它们与标签进行比较:: 第一个预测偏差很大(超过200,000美元!),而其他预测则更好,两个预测偏差约25%,还有两个预测 偏差不到10%。请记住,您选择使用RMSE作为性能测度,因此您希望使用Scikit-Learn的mean_squared_error()函数在整个训练集上测量该回归模型的RMSE,并将平方参数设置为False。 这总比没有好,但显然不是一个很好的分数,大多数地区的房屋价值中位数在120,000美元和26.5万美元之间,所以一个典型的68628美元的预测误差真的不是很令人满意。这是一个模型拟合训练数据不足的示例。当这种情况发生时,可能意味着这些特征没有提供足够的信息来做出好的预测,或者模型不够强大。 正如我们在上一章中看到的,修复欠拟合的主要方法是选择一个更强大的模型,为训练算法提供更好的特征,或者减少对模型的约束。这个模型没有正规化,这就排除了最后一个选项。您可以尝试添加更多功能,但首先您要尝试更复杂的模型,看看它是如何工作的。 您决定尝试DecisionTreeRegressor,因为这是一个相当强大的模型,能够在数据中找到复杂的非线性关系(后续篇章将更详细地介绍决策树): from sklearn.tree import DecisionTreeRegressor tree_reg = make_pipeline(preprocessing, DecisionTreeRegressor(random_state=42)) tree_reg.fit(housing, housing_labels) 现在模型已训练完毕,您可以在训练集中对其进行评估: 等等,难道这个模型真的很完美吗?当然咯,更有可能的是模型严重地过度拟合了数据。您怎么能确定正如你前面看到的,在您准备好启动一个您有信心的模型之前,您不想碰测试集,所以您需要使用一部分训练集进行训练,另一部分用于模型验证。 使用交叉验证进行更好的评估 评估决策树模型的一种方法是使用train_test_split()函数将训练集拆分为较小的训练集和验证集,然后针对较小的训练集训练您的模型,并针对验证集对其进行评估。这是一点努力,但没有太难,它会工作得相当不错。 一个很好的替代方法是使用Scikit-Learn的k_-fold交叉验证特性。下面的代码随机地将训练集分成10个不重叠的子集,称为fold,然后训练和评估决策树模型10次,每次选择不同的fold进行评估,并使用其他9个fold进行训练。结果是一个包含10个评价分数的数组: from sklearn.model_selection import cross_val_score tree_rmses = -cross_val_score(tree_reg, housing, housing_labels, scoring="neg_root_mean_squared_error", cv=10) ```Scikit-Learn```的交叉验证功能期望的是效用函数(越大越好)而不是成本函数(越低越好),所以评分函数实际上是RMSE的反面。它是一个负值,所以您需要切换输出的符号来获得RMSE分数。 让我们来看看结果吧: 现在决策树看起来不像以前那么好了。事实上,它的表现几乎和线性回归模型一样差!请注意,交叉验证不仅允许您获得模型性能的估计值,还允许您测量该估计值的精确度(即其标准差)。决策树的均方根误差约为66,868,标准差约为2,061。如果只使用一个验证集,则不会有此信息。但是交叉验证是以多次训练模型为代价的,所以它并不总是可行的。 如果您为线性回归模型计算相同的度量,您将发现平均RMSE为69,858,标准差为4,182。因此,决策树模型的性能似乎比线性模型稍微好一点,但由于严重的过拟合,差异很小。我们知道存在过拟合 问题,因为训练误差很低(实际上为零),而验证误差很高。 现在让我们尝试最后一个模型:随机森林调节器,随机森林的工作原理是在特征的随机子集上训练许多决策树,然后平均出它们的预测值。这样的模型组成的许多其他模型被称为合奏:他们能够提高性能基础模型(在本例中为决策树)。代码与前面的代码大同小异: from sklearn.ensemble import RandomForestRegressor forest_reg = make_pipeline(preprocessing, RandomForestRegressor(random_state=42)) forest_rmses = -cross_val_score(forest_reg, housing, housing_labels, scoring="neg_root_mean_squared_error", cv=10) 随机森林真的看起来非常有前途的任务!但是,如果您训练一个RandomForest并测量训练集上的RMSE,您将发现大约17,474:这要低得多,这意味着仍然存在大量的过度拟合。可能的解决方案是 简化模型,约束它(即,规则化它),或得到更多的训练数据。但是,在深入研究随机森林之前,您应该尝试来自各种类别机器学习算法的许多其他模型(例如,具有不同内核的多个支持向量机,可能还有一个神经网络),而无需花费太多时间调整超参数。目标是列出几个(两到五个)有前途的模型。
2024-01-14
[Machine Learning 人工智能]
机器学习中的 Transformation Pipelines(Machine Learning 研习之十)
Transformation Pipelines 有许多数据转换步骤需要以正确的顺序执行。幸运的是,Scikit-Learn提供了Pipeline类来帮助处理这样的转换序列。下面是一个用于数值属性的小管道,它首先对输入特性进行归并,然后对输入特性进行缩放: from sklearn.pipeline import Pipeline num_pipeline = Pipeline([ ("impute", SimpleImputer(strategy="median")), ("standardize", StandardScaler()), ]) Pipeline构造函数采用名称/估算器对(2元组)的列表,定义了一系列步骤。名称可以是您喜欢的任何名称,只要它们是唯一的,并且不包含双下划线(__)。以后我们讨论超参数调优时,它们会很有用。估计器必须都是转换器(即,它们必须有一个fit_transform()方法),除了最后一个,它可以是任何东西:转换器、预测器或任何其他类型的估计器。 如果你不想命名transformers你可以使用 make_pipeline() 函数; 它将transformers作为位置参数,并使用transformers类的名称(小写且不带下划线)创建管道(例如,“simpleimputer”): from sklearn.pipeline import make_pipeline num_pipeline = make_pipeline(SimpleImputer(strategy="median"), StandardScaler()) 如果多个transformers具有相同的名称,则会在其名称后附加索引(例如“foo-1”、“foo-2”等)。 当您调用管道的 fit() 方法时,它会在所有transformers上顺序调用 fit_transform(),将每个调用的输出作为参数传递给下一个调用,直到到达最终估计器,为此它只调用 fit() 方法。 该管道公开与最终估计器相同的方法。 在此示例中,最后一个估计器是 StandardScaler,它是一个transformers,因此管道也充当transformers。 如果您调用管道的transform()方法,它将按顺序将所有转换应用于数据。 如果最后一个估计器是预测器而不是变换器,那么管道将具有 Predict() 方法而不是 Transform() 方法。 调用它会按顺序将所有转换应用于数据并将结果传递给预测器的 Predict()方法 让我们调用管道的 fit_transform() 方法并查看输出的前两行,四舍五入到小数点后两位: 如前所述,如果要恢复一个漂亮的DataFrame,可以使用管道的get_feature_names_ out()方法: df_housing_num_prepared = pd.DataFrame( housing_num_prepared, columns=num_pipeline.get_feature_names_out(), index=housing_num.index) 管道支持索引;例如,管道[1]返回管道中的第二个估计值,管道[:-1]返回一个包含除最后一个估计值以外的所有估计值的管道对象。您还可以通过steps属性(它是名称/估算器对的列表)或named_steps字典属性(它将名称映射到估算器)访问估算器。例如,num_line[“ simpleimputer”]返回名为“simpleimputer”的估计器。 到目前为止,我们已经分别处理了分类列和数值列。如果有一个能够处理所有列的转换器,将适当的转换应用到每一列,那会更方便。为此,您可以使用olumnTransformer。例如,下面的ColumnTransformer将把num_pipeline(我们刚刚定义的那个)应用于数字属性,把cat_pipeline应用于类别属性: from sklearn.compose import ColumnTransformer num_attribs = ["longitude", "latitude", "housing_median_age", "total_rooms", "total_bedrooms", "population", "households", "median_income"] cat_attribs = ["ocean_proximity"] cat_pipeline = make_pipeline( SimpleImputer(strategy="most_frequent"), OneHotEncoder(handle_unknown="ignore")) preprocessing = ColumnTransformer([ ("num", num_pipeline, num_attribs), ("cat", cat_pipeline, cat_attribs), ]) 首先导入ColumnTransformer类,然后定义数字和分类列名的列表,并为分类属性构造一个简单的管道。最后,我们构造了一个列变换器。它的构造函数需要一个三元组(3-tuple)列表,每个三元组包含一个名称(必须是唯一的且不包含双下划线)、一个转换器和一个应该应用转换器的列的名称(或索引)列表。
2023-12-11
[Machine Learning 人工智能]
1
2