如何从头开始使用Python实现堆栈泛化(Stacking)
【翻译自 : How to Implement Stacked Generalization (Stacking) From Scratch With Python】
【说明:Jason Brownlee PhD大神的文章个人很喜欢,所以闲暇时间里会做一点翻译和学习实践的工作,这里是相应工作的实践记录,希望能帮到有需要的人!】
集成方法是提高机器学习问题的预测性能的绝佳方法。堆叠概括或堆叠是一种集成技术,它使用新模型来学习如何最佳地组合来自数据集上训练的两个或多个模型的预测。
在本教程中,您将发现如何在Python中从头开始实现堆栈。完成本教程后,您将知道:
如何学习在数据集上组合来自多个模型的预测。
如何将堆叠泛化应用于现实世界的预测建模问题。
描述
本节简要概述了本教程中使用的Stacked Generalization算法和Sonar数据集。
堆叠泛化算法
堆叠泛化或堆叠是一种集成算法,其中训练了一个新模型,以结合来自两个或多个已经训练的模型或您的数据集中的预测。来自现有模型或子模型的预测使用新模型进行组合,因此,由于来自子模型的预测被混合在一起,因此通常将其称为混合。通常,使用简单的线性方法将子模型的预测(例如简单平均或投票)与使用线性回归或逻辑回归的加权总和相结合。结合了预测的模型必须具有解决问题的技能,但不必成为最佳模型。这意味着您无需专心调整子模型,只要模型相对于基线预测显示出某些优势即可。重要的是,子模型会产生不同的预测,即所谓的不相关预测。当合并的预测都是熟练的,但以不同的方式熟练时,堆叠的效果最佳。这可以通过使用使用非常不同的内部表示(与实例相比,树)和/或在训练数据的不同表示或投影上训练的模型的算法来实现。在本教程中,我们将研究两个非常不同且未调整的子模型,并将它们的预测与简单的逻辑回归算法结合起来。
声纳数据集
我们将在本教程中使用的数据集是Sonar数据集。这是一个描述声纳chi回波从不同表面弹起的数据集。 60个输入变量是不同角度的收益强度。这是一个二元分类问题,需要一个模型来区分岩石和金属圆柱体。有208个观察结果。
这是一个易于理解的数据集。所有变量都是连续的,通常在0到1的范围内。输出变量是字符串“ M”(对于矿井)和“ R”(对于岩石),需要将其转换为整数1和0。通过用数据集中(M或地雷)中观察次数最多的类别进行预测,零规则算法可以实现约53%的准确性。您可以在UCI机器学习存储库中了解有关此数据集的更多信息。免费下载数据集,并将其放置在文件名为sonar.all-data.csv的工作目录中。
教程
本教程分为3个步骤:
子模型和聚合器。
结合预测。
声纳数据集案例研究。
这些步骤提供了您需要了解和实现自己的预测建模问题的基础。
1.子模型和聚合器
我们将使用两个模型作为用于堆叠的子模型,并使用线性模型作为聚合器模型。
这部分分为3个部分:
子模型1:k个最近邻居。
子模型2:感知器。
聚集器模型:逻辑回归。
将根据用于训练模型的功能和用于进行预测的功能来描述每个模型。
1.1子模型1:k个近邻
k最近邻居算法或kNN使用整个训练数据集作为模型。因此,训练模型涉及保留训练数据集。 下面是一个名为knn_model()的函数。
# Prepare the kNN model
def knn_model(train):return train
进行预测涉及在训练数据集中找到k个最相似的记录,并选择最常见的班级值。 欧几里得距离函数用于计算新数据行与训练数据集中的行之间的相似度。 以下是涉及对kNN模型进行预测的这些辅助函数。 函数euclidean_distance()计算两行数据之间的距离,get_neighbors()在训练数据集中找到新数据行的所有邻居,而knn_predict()从邻居对新数据行进行预测。
# Calculate the Euclidean distance between two vectors
def euclidean_distance(row1, row2):distance = 0.0for i in range(len(row1)-1):distance += (row1[i] - row2[i])**2return sqrt(distance)# Locate neighbors for a new row
def get_neighbors(train, test_row, num_neighbors):distances = list()for train_row in train:dist = euclidean_distance(test_row, train_row)distances.append((train_row, dist))distances.sort(key=lambda tup: tup[1])neighbors = list()for i in range(num_neighbors):neighbors.append(distances[i][0])return neighbors# Make a prediction with kNN
def knn_predict(model, test_row, num_neighbors=2):neighbors = get_neighbors(model, test_row, num_neighbors)output_values = [row[-1] for row in neighbors]prediction = max(set(output_values), key=output_values.count)return prediction
您可以看到,邻居数(k)设置为2作为knn_predict()函数的默认参数。 选择此编号时需要经过反复尝试,并且尚未调整。 现在我们已经有了kNN模型的基础,让我们看一下Perceptron算法。
1.2子模型2:感知器
Perceptron算法的模型是从训练数据中学到的一组权重。为了训练权重,需要对训练数据进行许多预测以计算误差值。 因此,模型训练和预测都需要具有预测功能。以下是用于实现Perceptron算法的帮助函数。 perceptron_model()函数在训练数据集上训练Perceptron模型,perceptron_predict()用于对一行数据进行预测。
# Make a prediction with weights
def perceptron_predict(model, row):activation = model[0]for i in range(len(row)-1):activation += model[i + 1] * row[i]return 1.0 if activation >= 0.0 else 0.0# Estimate Perceptron weights using stochastic gradient descent
def perceptron_model(train, l_rate=0.01, n_epoch=5000):weights = [0.0 for i in range(len(train[0]))]for epoch in range(n_epoch):for row in train:prediction = perceptron_predict(weights, row)error = row[-1] - predictionweights[0] = weights[0] + l_rate * errorfor i in range(len(row)-1):weights[i + 1] = weights[i + 1] + l_rate * error * row[i]return weights
perceptron_model()模型将学习率和训练时期数都指定为默认参数。 同样,这些参数的选择是经过反复试验的,但并未在数据集中进行调整。 现在,我们有两个子模型的实现,让我们看一下实现聚合器模型的过程。
1.3聚集器模型:逻辑回归
像Perceptron算法一样,逻辑回归使用一组权重(称为系数)来表示模型。就像Perceptron算法一样,系数是通过迭代对训练数据进行预测并对其进行更新来学习的。以下是用于实现逻辑回归算法的辅助函数。 logistic_regression_model()函数用于在训练数据集上训练系数,而logistic_regression_predict()用于对一行数据进行预测。
# Make a prediction with coefficients
def logistic_regression_predict(model, row):yhat = model[0]for i in range(len(row)-1):yhat += model[i + 1] * row[i]return 1.0 / (1.0 + exp(-yhat))# Estimate logistic regression coefficients using stochastic gradient descent
def logistic_regression_model(train, l_rate=0.01, n_epoch=5000):coef = [0.0 for i in range(len(train[0]))]for epoch in range(n_epoch):for row in train:yhat = logistic_regression_predict(coef, row)error = row[-1] - yhatcoef[0] = coef[0] + l_rate * error * yhat * (1.0 - yhat)for i in range(len(row)-1):coef[i + 1] = coef[i + 1] + l_rate * error * yhat * (1.0 - yhat) * row[i]return coef
logistic_regression_model()将学习率和时期数定义为默认参数,并且与其他算法一样,这些参数经过反复试验后仍发现并且未优化。 现在,我们已经有了子模型和聚合器模型的实现,让我们看看如何将多个模型的预测结合起来。
2.结合预测
对于机器学习算法,学习如何组合预测与从训练数据集中学习非常相似。可以根据子模型的预测来构建新的训练数据集,如下所示:
每行代表训练数据集中的一行。
第一列包含由第一子模型(例如k最近邻居)在训练数据集中每一行的预测。
第二列包含第二个子模型(例如Perceptron算法)对训练数据集中的每一行的预测。
第三列包含训练数据集中该行的预期输出值。
下面是一个构造的堆叠数据集的人为示例:
kNN, Per, Y
0, 0 0
1, 0 1
0, 1 0
1, 1 1
0, 1 0
然后可以在此新数据集上训练机器学习算法,例如逻辑回归。 从本质上讲,这个新的元算法学习如何最佳地组合来自多个子模型的预测。
下面是一个名为to_stacked_row()的函数,该函数实现此过程以为此堆栈数据集创建新行。
该函数将模型列表作为输入,这些模型用于进行预测。 该函数还将函数列表作为输入,一个函数用于对每个模型进行预测。 最后,包括训练数据集中的一行。
一次将新行构造为一列。 使用每种模型和训练数据行来计算预测。 然后,将训练数据集行的预期输出值添加为该行的最后一列。
# Make predictions with sub-models and construct a new stacked row
def to_stacked_row(models, predict_list, row):stacked_row = list()for i in range(len(models)):prediction = predict_list[i](models[i], row)stacked_row.append(prediction)stacked_row.append(row[-1])return stacked_row
在某些预测性建模问题上,可以通过在训练行和子模型进行的预测两者上训练聚合模型来获得更大的提升。
此改进使聚合器模型同时具有训练行中所有数据的上下文,以帮助确定如何以及何时最佳地组合子模型的预测。
我们可以通过汇总训练行(减去最后一列)和上面创建的堆叠行来更新to_stacked_row()函数以包括此函数。
以下是实现此改进的to_stacked_row()函数的更新版本。
# Make predictions with sub-models and construct a new stacked row
def to_stacked_row(models, predict_list, row):stacked_row = list()for i in range(len(models)):prediction = predict_list[i](models[i], row)stacked_row.append(prediction)stacked_row.append(row[-1])return row[0:len(row)-1] + stacked_row
尝试对问题使用两种方法以查看哪种方法最好是一个好主意。 既然我们拥有用于堆叠概括的所有要素,我们就可以将其应用于实际问题。
3.声纳数据集案例研究
在本节中,我们将把Stacking算法应用于Sonar数据集。该示例假定数据集的CSV副本位于当前工作目录中,文件名为sonar.all-data.csv。首先加载数据集,将字符串值转换为数字,然后将输出列从字符串转换为0到1的整数。这可以通过辅助函数load_csv(),str_column_to_float()和str_column_to_int()来实现数据集。我们将使用k倍交叉验证来评估学习模型在看不见的数据上的性能。这意味着我们将构建和评估k个模型,并将性能评估为平均模型误差。分类准确性将用于评估模型。这些行为在cross_validation_split(),precision_metric()和valuate_algorithm()帮助函数中提供。
我们将使用上面实现的k最近邻,感知器和逻辑回归算法。我们还将使用我们的技术来创建上一步中定义的新的堆叠数据集。开发了一个新的函数名称stacking()。此功能执行4件事:
它首先训练模型列表(kNN和Perceptron)。
然后使用模型进行预测并创建一个新的堆叠数据集。
然后,在堆叠的数据集上训练聚合模型(逻辑回归)。
然后,它使用子模型和聚合器模型对测试数据集进行预测。
下面列出了完整的示例。
# Test stacking on the sonar dataset
from random import seed
from random import randrange
from csv import reader
from math import sqrt
from math import exp# Load a CSV file
def load_csv(filename):dataset = list()with open(filename, 'r') as file:csv_reader = reader(file)for row in csv_reader:if not row:continuedataset.append(row)return dataset# Convert string column to float
def str_column_to_float(dataset, column):for row in dataset:row[column] = float(row[column].strip())# Convert string column to integer
def str_column_to_int(dataset, column):class_values = [row[column] for row in dataset]unique = set(class_values)lookup = dict()for i, value in enumerate(unique):lookup[value] = ifor row in dataset:row[column] = lookup[row[column]]return lookup# Split a dataset into k folds
def cross_validation_split(dataset, n_folds):dataset_split = list()dataset_copy = list(dataset)fold_size = int(len(dataset) / n_folds)for i in range(n_folds):fold = list()while len(fold) < fold_size:index = randrange(len(dataset_copy))fold.append(dataset_copy.pop(index))dataset_split.append(fold)return dataset_split# Calculate accuracy percentage
def accuracy_metric(actual, predicted):correct = 0for i in range(len(actual)):if actual[i] == predicted[i]:correct += 1return correct / float(len(actual)) * 100.0# Evaluate an algorithm using a cross validation split
def evaluate_algorithm(dataset, algorithm, n_folds, *args):folds = cross_validation_split(dataset, n_folds)scores = list()for fold in folds:train_set = list(folds)train_set.remove(fold)train_set = sum(train_set, [])test_set = list()for row in fold:row_copy = list(row)test_set.append(row_copy)row_copy[-1] = Nonepredicted = algorithm(train_set, test_set, *args)actual = [row[-1] for row in fold]accuracy = accuracy_metric(actual, predicted)scores.append(accuracy)return scores# Calculate the Euclidean distance between two vectors
def euclidean_distance(row1, row2):distance = 0.0for i in range(len(row1)-1):distance += (row1[i] - row2[i])**2return sqrt(distance)# Locate neighbors for a new row
def get_neighbors(train, test_row, num_neighbors):distances = list()for train_row in train:dist = euclidean_distance(test_row, train_row)distances.append((train_row, dist))distances.sort(key=lambda tup: tup[1])neighbors = list()for i in range(num_neighbors):neighbors.append(distances[i][0])return neighbors# Make a prediction with kNN
def knn_predict(model, test_row, num_neighbors=2):neighbors = get_neighbors(model, test_row, num_neighbors)output_values = [row[-1] for row in neighbors]prediction = max(set(output_values), key=output_values.count)return prediction# Prepare the kNN model
def knn_model(train):return train# Make a prediction with weights
def perceptron_predict(model, row):activation = model[0]for i in range(len(row)-1):activation += model[i + 1] * row[i]return 1.0 if activation >= 0.0 else 0.0# Estimate Perceptron weights using stochastic gradient descent
def perceptron_model(train, l_rate=0.01, n_epoch=5000):weights = [0.0 for i in range(len(train[0]))]for epoch in range(n_epoch):for row in train:prediction = perceptron_predict(weights, row)error = row[-1] - predictionweights[0] = weights[0] + l_rate * errorfor i in range(len(row)-1):weights[i + 1] = weights[i + 1] + l_rate * error * row[i]return weights# Make a prediction with coefficients
def logistic_regression_predict(model, row):yhat = model[0]for i in range(len(row)-1):yhat += model[i + 1] * row[i]return 1.0 / (1.0 + exp(-yhat))# Estimate logistic regression coefficients using stochastic gradient descent
def logistic_regression_model(train, l_rate=0.01, n_epoch=5000):coef = [0.0 for i in range(len(train[0]))]for epoch in range(n_epoch):for row in train:yhat = logistic_regression_predict(coef, row)error = row[-1] - yhatcoef[0] = coef[0] + l_rate * error * yhat * (1.0 - yhat)for i in range(len(row)-1):coef[i + 1] = coef[i + 1] + l_rate * error * yhat * (1.0 - yhat) * row[i]return coef# Make predictions with sub-models and construct a new stacked row
def to_stacked_row(models, predict_list, row):stacked_row = list()for i in range(len(models)):prediction = predict_list[i](models[i], row)stacked_row.append(prediction)stacked_row.append(row[-1])return row[0:len(row)-1] + stacked_row# Stacked Generalization Algorithm
def stacking(train, test):model_list = [knn_model, perceptron_model]predict_list = [knn_predict, perceptron_predict]models = list()for i in range(len(model_list)):model = model_list[i](train)models.append(model)stacked_dataset = list()for row in train:stacked_row = to_stacked_row(models, predict_list, row)stacked_dataset.append(stacked_row)stacked_model = logistic_regression_model(stacked_dataset)predictions = list()for row in test:stacked_row = to_stacked_row(models, predict_list, row)stacked_dataset.append(stacked_row)prediction = logistic_regression_predict(stacked_model, stacked_row)prediction = round(prediction)predictions.append(prediction)return predictions# Test stacking on the sonar dataset
seed(1)
# load and prepare data
filename = 'sonar.all-data.csv'
dataset = load_csv(filename)
# convert string attributes to integers
for i in range(len(dataset[0])-1):str_column_to_float(dataset, i)
# convert class column to integers
str_column_to_int(dataset, len(dataset[0])-1)
n_folds = 3
scores = evaluate_algorithm(dataset, stacking, n_folds)
print('Scores: %s' % scores)
print('Mean Accuracy: %.3f%%' % (sum(scores)/float(len(scores))))
使用k值为3进行交叉验证,得出每个折叠208/3 = 69.3或略低于70条记录,以便在每次迭代时进行评估。 运行示例将打印最终配置的分数和分数平均值。
Scores: [78.26086956521739, 76.81159420289855, 69.56521739130434]
Mean Accuracy: 74.879%
如何从头开始使用Python实现堆栈泛化(Stacking)相关推荐
- 实现贝叶斯分类器_从头开始在Python中实现高斯朴素贝叶斯
Naive Bayes是一种非常方便,流行且重要的机器学习算法,尤其适用于文本分析和一般分类.在本文中,我将讨论高斯朴素贝叶斯:算法,其实现和应用于微型维基百科数据集(维基百科中给出的数据集). 算法 ...
- 从头开始学python教程_怎样开始自学Python?
Python是一个通用编程语言,并很快成为每个自重程序员宝库中的一个必需品. Python中有数不清的Web框架,从基本bai的微小架构到完整的架构,它们自有各自的优点.那么你准备使用它来做一些web ...
- GitHub热榜,获2400星!帮你免费从头开始学Python数据科学
点上方"菜鸟学Python",选择"星标" 共460篇原创干货,第一时间送达 机器之心报道 作者:魔王.陈萍 如何入门数据科学? 这个 GitHub 项目提供了 ...
- linux下java调用python脚本,java - 在Linux Terminal中以编程方式从Java调用python脚本 - 堆栈内存溢出...
我正在开发一个Java应用程序,用于检查源文件中的补丁程序(是否存在). 用于检测补丁程序更改的核心逻辑位于python脚本[titled'patch.py']中,并且我的Java应用程序与此Py ...
- python实现堆栈_Python堆栈实现计算器
原博文 2017-10-28 01:16 − 一.程序介绍 需求: 开发一个简单的python计算器 1.实现加减乘除及拓号优先级解析 2.用户输入 -1 - 2 *((-60+30+(-40/5)* ...
- 从头打造纯python的mud游戏-基于Evennia(1)
目录 Evennia概述 云服务器 安装python3.10+ 安装evennia包 示范程序 Evennia概述 Evennia是一个基于python的开源框架,代码库和服务器,用于使用现代技术和工 ...
- 从头开始学习python+pytest接口自动化测试(一)pytest的运行方式3.pytest.ini配置文件运行
[pytest] addopts = -vs testpaths = test_cases python_files = test_*.py python_classes = Test* python ...
- 堆叠泛化(Stacking Generalization)
Stacking是一种通用的通过训练学习器来结合个体学习器的方法,堆叠泛化是一种在集成学习中对数据从纵向进行划分的技术,一般称为SG技术,其一般用于最小化一个或多个泛化器的泛化误差率. 基本思想为:数 ...
- python stacking_详解 Stacking 的 python 实现
1. 什么是 stacking stacking 就是当用初始训练数据学习出若干个基学习器后,将这几个学习器的预测结果作为新的训练集,来学习一个新的学习器. 2. 代码: 例如我们用 RandomFo ...
- 基于Python的Stacking集成机器学习实践
[翻译自 : Stacking Ensemble Machine Learning With Python] [说明:Jason Brownlee PhD大神的文章个人很喜欢,所以闲暇时间里会做一点翻 ...
最新文章
- Java线性池的使用方式以及核心运行原理
- 浅谈java内存分析和垃圾收集器
- Numpy.random中shuffle与permutation的区别(转)
- 写一个脚本,判断下如果是阴历7月7日,在服务器上广播“七夕情人节快乐!”...
- jQuery1.4新特性
- mysql映射超_Hibernate的映射类型 hibernate mysql映射类型
- 在浏览器地址栏按回车、F5、Ctrl+F5刷新网页的区别
- android.graphics.Color 包含颜色值
- 不只有BERT!盘点2018年NLP令人激动的10大想法
- shell经典面试题根据文件创建用户名及密码(亲测)
- MantisBT安装部署(XAMPP)邮件配置 中文配置
- 关于信号系统的一些笔记
- 基础才是重中之重~LazyInitializer.EnsureInitialized对属性实现化的性能优化
- testlink界面优化_Testlink 太老了,测试用例管理有没有什么好工具推荐?
- 用系统工具sxstrace检查缺少的VC运行时组件
- python中什么是句柄_python中的句柄操作的方法示例
- RCC_APB2Periph_ALL 哪儿里去了?
- 京版国八条终于出来了——京十五条
- 漫谈云数据中心的前世今生
- Window10蓝牙无法连接的解决方案(已成功)
热门文章
- Deepin Linux 设置开机自动进入命令行模式
- HTML 5 会为 Flash 和 Silverlight 送终吗?
- 别被数据分析师骗了!用数据说谎的三种办法
- 国家建筑标准设计图集
- 前端向后台发送请求有几种方式?
- java生产环境增量发版陷阱【原】
- javaweb实现教师和教室管理系统 java jsp sqlserver
- 解决weblogic.net.http.SOAPHttpsURLConnection incompatible with javax.net.ssl.HttpsURLConnection
- ubuntu 运行级别initlevel
- Android_JarZip压缩和解压文件