如何使用堆栈选择最佳的算法?
每当您偶然发现具有数千个功能的海量数据时,您都会想知道哪种算法是对这些数据进行准确预测的最佳算法,以及是否使用所有功能或减少功能空间。通过该博客,我将带您逐步进行以下工作:通过套索回归找到良好的功能,并通过称为堆栈的技术获得正确的算法。
选择最佳算法
堆叠是指加入
机器学习模型的方法,类似于在餐厅布置一堆盘子。它结合了许多模型的输出。堆栈的性能通常接近最佳模型,有时它的性能可能会超出每个模型的预测性能。
目的是获得具有最相关的解释变量的目标变量的准确预测。我们将通过应用机器学习模型(例如Random Forest,Lasso回归和Gradient Boosting)来做到这一点,然后让我们堆叠这些单独模型的输出并将其传递给ridge回归器以计算最终预测。堆叠通过将每个模型的输出用作最终模型的输入来利用其强度。
我们将堆叠回归器的性能与各个模型的性能进行比较。堆栈的性能通常接近最佳模型,有时它的性能可能会超出每个模型的预测性能。本文末尾的图显示了给定数据集上各个回归变量和堆叠回归变量的性能。
选择最佳功能
变量的选择带来许多好处。该模型变得更简单,减少了用于错误处理的代码,并减少了拟合的机会,并最大程度地减少了错误的引入。减少了模型的执行时间和内存消耗。
在机器学习术语中,最小绝对收缩和选择算子(Lasso)是一种回归分析方法,可以完成变量选择和正则化,从而提高模型的预测准确性和可解释性。它会更改模型拟合过程,并仅选择协变量的一个子集。它通过强制将某些系数设置为零来实现此目的,并在构建模型时删除这些系数。
实作
对于实施,我们将使用该kaggle页面上可用的房价数据集。向下滚动到页面底部,然后单击链接“ train.csv”,然后单击屏幕右侧的“下载”蓝色按钮,以下载数据集。在这里,该文件被重命名为“ houseprice.csv”。我们基于描述这些房屋各个方面的不同解释变量,构建了一个机器学习模型来预测房屋的销售价格。我们的目标是使实际价格与模型估算的价格之间的差异最小。
因此,我们将使用
由Lasso回归模型选择的最有趣的功能,并分别检查
每个模型的性能和堆栈性能。跟着。
步骤1:导入所有库
#让我们导入所有库
#处理数据集
将熊猫作为pd导入
将numpy导入为np
#绘图
导入matplotlib.pyplot作为plt
#划分训练和测试集
从sklearn.model_selection导入train_test_split
#功能缩放
从sklearn.preprocessing导入MinMaxScaler
#到buid模型
从sklearn.linear_model导入套索
从sklearn.feature_selection导入SelectFromModel
#堆叠模型
从sklearn.ensemble导入GradientBoostingRegressor
从sklearn.ensemble导入RandomForestRegressor
从sklearn.ensemble导入StackingRegressor
从sklearn.linear_model导入LassoCV
从sklearn.linear_model导入RidgeCV
#评估模型
从sklearn.metrics导入mean_squared_log_error
从sklearn.metrics导入mean_squared_error,r2_score
导入数学
#查找模型的训练时间
导入时间
#可视化数据框中的所有列
pd.pandas.set_option('display.max_columns',无)
进口警告
warnings.simplefilter(action ='ignore')
步骤2:载入资料集
房价数据集包含1460行(即房屋)和81列(即变量)。
#加载数据集
数据= pd.read_csv('houseprice.csv')
打印(data.shape)
data.head()
步骤3:资料工程
数据需要经过处理才能处理:
对待缺失的价值观
分类变量:删除稀有标签
分类变量编码
工程师时间变量
处理非高斯分布变量
功能缩放
在开始设计功能之前,我们将数据分为训练和测试集。因为当我们设计功能时,某些技术会从数据中学习参数。重要的是仅从火车上学习这些参数,以免过度拟合。此外,我们需要在期望随机性的任何地方设置种子。
#让我们分为训练和测试集
#记住要设置种子(此sklearn函数的random_state)
X_train,X_test,y_train,y_test = train_test_split(data,data ['SalePrice'],test_size = 0.25,
random_state = 0)
X_train.shape,X_test.shape
处理缺失值
我们将在数值变量中找到缺失的值,并将其替换为模式。
用模式替换缺失值
#列出包含缺失值的数字变量
vars_with_na = [如果X_train [var] .isnull()。sum()> 0且X_train [var] .dtypes!='O',则data.columns中的var变量)
对于vars_with_na中的var:
#使用火车设置来计算模式
mode_val = X_train [var] .mode()[0]
#用模式替换缺失值
#(在训练和测试中)
X_train [var] = X_train [var] .fillna(mode_val)
X_test [var] = X_test [var] .fillna(mode_val)
列出包含缺失值的分类变量的列表,并将其替换为标签“缺少”
#列出包含缺失值的分类变量的列表
vars_with_na = [如果X_train [var] .isnull()。sum()> 0且X_train [var] .dtypes =='O',则data.columns中的var变量)
#用新标签“ Missing”替换缺失值
X_train [vars_with_na] = X_train [vars_with_na] .fillna('Missing')
X_test [vars_with_na] = X_test [vars_with_na] .fillna('Missing')
分类删除稀有标签
首先,我们将那些类别中的那些类别隔离在少于1%的观测值中。也就是说,少于1%的房屋所共有的分类变量的所有值都将被称为“稀有”。
#让我们捕获列表中的分类变量
cat_vars = [如果X_train [var] .dtype =='O',则X_train.columns中的var变量]
def find_frequent_labels(df,var,rare_perc):
#find_frequent_labels函数查找由多个对象共享的标签
#数据集中一定百分比的房屋
df = df.copy()
tmp = df.groupby(var)['SalePrice']。count()/ len(df)
返回tmp [tmp>罕见的perc] .index
对于cat_vars中的var:
#查找常见类别
quent_ls = find_frequent_labels(X_train,var,0.01)
#用字符串“ Rare”替换稀有类别
X_train [var] = np.where(X_train [var] .isin(frequent_ls),X_train [var],'Rare')
X_test [var] = np.where(X_test [var] .isin(frequent_ls),X_test [var],'Rare')
? ategorical可变编码
接下来,我们将编写一个小函数,该函数将离散值分配给变量的字符串。例如,较小的值对应于显示较小平均房屋销售价格的类别。
def replace_categories(训练,测试,变量,目标):
#将类别从最低的变量开始排序
#房屋出售价格,以最高的价格
ordered_labels = train.groupby([var])[target] .mean()。sort_values()。index
#创建一个有序类别到整数值的字典
ordinal_label = {k:i代表i,k枚举(ordered_labels,0)}
#使用字典将整数字符串替换为整数
train [var] = train [var] .map(ordinal_label)
test [var] = test [var] .map(ordinal_label)
对于cat_vars中的var:
replace_categories(X_train,X_test,var,'SalePrice')
工程师时间变量
有4个变量表示房屋或车库的建造或改建年份。我们将捕获这些变量与房屋销售年份之间经过的时间:
def elapsed_years(df,var):
#捕获年份变量之间的差异
#和房屋出售的年份
df [var] = df ['YrSold']-df [var]
返回df
对于['YearBuilt','YearRemodAdd','GarageYrBlt']中的var:
X_train =经过的年(X_train,var)
X_test = elapsed_years(X_test,var)
处理非高斯分布变量
一些变量显示偏斜分布。我们将对正数值变量进行对数转换,以获得更类似于高斯的分布。这将有助于线性机器学习模型。
对于['LotFrontage','LotArea','1stFlrSF','GrLivArea','SalePrice']中的var:
X_train [var] = np.log(X_train [var])
X_test [var] = np.log(X_test [var])
功能缩放
为了在线性模型中使用,需要对特征进行缩放或标准化。我们将要素缩放到最小值和最大值。
#捕获列表中的所有变量
#除了目标和ID
train_vars = [如果var不在['Id','SalePrice']中,则var为X_train.columns中的var]
#创建缩放器
缩放器= MinMaxScaler()
#将洁牙机安装到火车上
scaler.fit(X_train [train_vars])
#转换训练和测试集
X_train [train_vars] = scaler.transform(X_train [train_vars])
X_test [train_vars] = scaler.transform(X_test [train_vars])
打印(X_train.isnull()。sum()。any(),X_test.isnull()。sum()。any())
我们完成了正式的要素工程步骤。您可以扩展这些功能工程步骤。例如删除异常值等。
步骤4:功能选择
我们将使用Lasso回归选择变量:Lasso具有将非信息量变量的系数设置为零的属性。这样,我们可以识别这些变量并将其从最终模型中删除。在以下单元格中,我们将选择一组最具预测性的变量来构建我们的机器学习模型。
#捕获目标(注意该目标是日志转换的)
y_train = X_train ['SalePrice']
y_test = X_test ['SalePrice']
#从我们的训练和测试集中删除不必要的变量
X_train.drop([['Id','SalePrice'],axis = 1,inplace = True)
X_test.drop([['Id','SalePrice'],axis = 1,inplace = True)
让我们继续并选择最具预测性的功能的子集。拉索回归中有一个随机元素,所以要记住设置种子,选择一个合适的阿尔法(相当于罚分),阿尔法越大,选择的特征数量就越少。
sel_ = SelectFromModel(套索(alpha = 0.005,random_state = 0))
#训练套索模型并选择功能
sel_.fit(X_train,y_train)
#让我们打印总数和选定功能的数量
selected_feats = X_train.columns [(sel_.get_support())]
#让我们打印一些统计数据
print('总特征:{}'。format((X_train.shape [1])))
print(''selected features:{}'。format(len(selected_feats)))
print('系数缩小到零的特征:{}'。format(np.sum(sel_.estimator_.coef _ == 0)))
从79个功能中选择了25个。让我们看一下重要功能。
#让我们看一下功能的重要性
重要性= pd.Series(np.abs(lin_model.coef_.ravel()))
重要性。索引= selected_feats
Important.sort_values(inplace = True,ascending = False)
Important.plot.bar(figsize =(10
plt.ylabel('套索系数')
plt.title(“功能重要性”)
步骤5:建立模型
提取选定的特征。
X_train = X_train [selected_feats]
X_test = X_test [selected_feats]
打印(X_train.shape,X_test.shape)
我们将定义模型。
在堆栈中添加模型没有限制。
#模型内部的参数可以改变
参数= {'n_estimators':500,
'max_depth':4,
'min_samples_split':5
'learning_rate':0.01,
'loss':'ls'}
GB_model = GradientBoostingRegressor(**参数)
lin_model =套索(alpha = 0.005,random_state = 0)
RF_model = RandomForestRegressor(n_estimators = 400,random_state = 0)
#在列表中获取这些模型
估算器= [('Random Forest',RF_model),
(“套索”,lin_model),
(“梯度提升”,GB_model)]
#将这些模型与StackingRegressor堆叠在一起
stacking_regressor = StackingRegressor(estimators = estimators,
final_estimator = RidgeCV())
步骤6:比较效果
我们将借助散点图比较性能
def plot_regression_results(ax,y_true,y_pred,标题,分数,经过时间):
“”“预测目标与真实目标的散点图。”“”
ax.plot([y_true.min(),y_true.max()],
[y_true.min(),y_true.max()],
'--r',线宽= 2)
ax.scatter(y_true,y_pred,alpha = 0.2)
ax.spines ['top']。set_visible(False)
ax.spines ['right']。set_visible(False)
ax.get_xaxis()。tick_bottom()
ax.get_yaxis()。tick_left()
ax.spines ['left']。set_position(('outward',10))
ax.spines ['bottom']。set_position(('outward',10))
ax.set_xlim([y_true.min(),y_true.max()])
ax.set_ylim([y_true.min(),y_true.max()])
ax.set_xlabel('True_Price')
ax.set_ylabel('Predicted_Price')
extra = plt.Rectangle((0,0),0,0,fc =“ w”,fill = False,
edgecolor ='none',linewidth = 0)
ax.legend([extra],[scores],loc ='左上')
title =标题+'n以{:.2f}秒为单位的评估值。'。format(elapsed_time)
ax.set_title(标题)
无花果,斧头= plt.subplots(2,2, figsize =(9,7))
轴= np.ravel(轴)
errors_list = []
表示zip(axs ,estimators + [('Stacking Regressor',
stacking_regressor)]):
start_time = time.time()
模型= est.fit(X_train,y_ train)
elapsed_time = time.time()-s tart_time
pred = model.predict(X_test)
错误= y_test-model.predic t(X_test)
errors_list.append(错误)
test_r2 = r2_score(np.exp(y_ test),np.exp(pred))
test_rmsle = math.sqrt(平均值_平方_对数错误(y_test,pred))
plot_regression_results(ax,y_ test,pred,name,(r'$ R ^ 2 = {:. 3f} $ '+'\ n'+
r'$ RMSLE = {:. 3f} $')。format(test _r2,test_rmsle),lapsed_time)
plt.tight_layout()
plt.subplots_adjust(top = 0.9)
plt.show()
堆放
通过查看这些图,我们观察到梯度增强模型的性能良好,并且堆栈回归器在性能上更接近于梯度增强模型。
让我们看看每个模型的误差分布。
标题= ['Random_Forest','Lasso','Gradient_boosting','Stacked_regressor']
f,a = plt.subplots(2
a = a.ravel()
对于idx,枚举(a)中的ax:
ax.hist(errors_list [idx])
ax.set_title(titles [idx])
plt.tight_layout()
堆放
#让我们看一下功能的重要性
重要性= pd.Series(np.abs(lin_model.coef_.ravel()))Important.index
= selected_专长
重要度.sort_values(inplace = True,ascending = False)
Important.plot.bar(figsize =(1 0
plt.ylabel('套索系数')
plt.title(“功能重要性”)
误差的分布非常接近高斯分布。这表明我们的模型在做出预测方面做得很好。
题库