1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > kaggle赛事学习——house-prices-advanced-regression-technique(房价预测)

kaggle赛事学习——house-prices-advanced-regression-technique(房价预测)

时间:2019-05-06 09:12:04

相关推荐

kaggle赛事学习——house-prices-advanced-regression-technique(房价预测)

尝试计划

目前是定下了两个目标

通过看自己以前的代码,先搞出来一个简单的答案,不管准确率多少。得到惨不忍睹的结果后,再去看论坛上大佬的方法。看csdn这篇文章: link,能不能用他的TPOT方法找到最合适的模型来得到结果。

我打乱顺序,先将第三个事情做了的。但是,突然发现最根本的问题——不是找不到最合适的方法,而是这个数据集的特征太多了。

70+特征,这我要训练到什么时候去?

所以现在准备老老实实的,先从头搞起,先确定哪些特征有用,或者使用什么方法将特征重新聚合调整(果然走捷径要不得orz)。

开始学习

阶段一:初步训练

from sklearn.model_selection import train_test_splittrain_data = pd.read_csv('../input/house-prices-advanced-regression-techniques/train.csv', index_col='Id')test_data = pd.read_csv('../input/house-prices-advanced-regression-techniques/test.csv', index_col='Id')# 处理缺失值train_data.dropna(axis=0, subset=['SalePrice'], inplace=True) # 【删除空值】找到特定列中未缺失的行,并修改原数据y = train_data.SalePricetrain_data.drop(['SalePrice'], axis=1, inplace=True) # 删除列【删除】x_train, x_valid, y_train, y_valid = train_test_split(train_data, y, test_size=0.2, random_state=0) # "Cardinality"表示一列中唯一值的数量# 选择基数相对较低的分类列(方便但随意)# 这里保证一列中不同数据数小于10,且是文字(数字差异大有多种很正常)categorical_cols = [cname for cname in train_data.columns if train_data[cname].nunique()<10 and train_data[cname].dtype == "object"]# 挑选数字列numerical_cols = [cname for cname in train_data.columns if train_data[cname].dtype in ['int64', 'float64']]# 只留下挑选出来的列my_cols = categorical_cols + numerical_colsX_train = x_train[my_cols].copy()X_valid = x_valid[my_cols].copy()X_test = test_data[my_cols].copy()# X_train.head()

random_state——简单来说,它是随机种子,因此如果给了一个固定的值,就可以保证每次的分割数据结果相同。这样的话,就不会产生每次运行结果不一致的问题,方便调参。

from pose import ColumnTransformerfrom sklearn.pipeline import Pipelinefrom sklearn.impute import SimpleImputerfrom sklearn.preprocessing import OneHotEncoderfrom sklearn.ensemble import RandomForestRegressorfrom sklearn.metrics import mean_absolute_error# 数值数据预处理numerical_transformer = SimpleImputer(strategy='constant') # 将空值填充为自定义的值# 分类数据预处理categorical_transformer = Pipeline(steps = [('imputer', SimpleImputer(strategy='constant')), # 填补空值('onehot', OneHotEncoder(handle_unknown='ignore')) # 编码])# 数值数据和分类数据集合预处理(将处理方式运用上)preprocessor = ColumnTransformer(transformers = [('nums', numerical_transformer, numerical_cols),('cat', categorical_transformer, categorical_cols)])# 定义模型model = RandomForestRegressor(n_estimators=100, random_state=0)# 整合模型和预处理数据clf = Pipeline(steps=[('preprocessor', preprocessor),('model', model)])# 预处理训练数据,训练模型clf.fit(X_train, y_train)# 预处理验证数据,获得预测preds = clf.predict(X_valid)print('MAE:', mean_absolute_error(y_valid, preds))

①SimpleImputer——缺失值处理。strategy为空值填充的策略,其中mean表示该列的缺失值由该列的均值填充。median为中位数,most_frequent为众数。constant表示将空值填充为自定义的值,但这个自定义的值要通过fill_value来定义。

②Pipeline——模型的组件构成流程。

③onehot——编码分类变量。

④ColumnTransformer——选择地进行数据转换。必须指定一个转换器列表。每个转换器是一个三元素元组,用于定义转换器的名称,要应用的转换以及要应用于其的列索引,例如:(名称‘num-数值’,对象‘numerical_transformer-转换工具’,列‘numerical_cols-需转换数据’)

⑤RandomForestRegressor——随机森林。n_estimators为弱学习器的最大迭代次数

⑥mean_absolute_error——计算模型输出的显著性图谱与Ground-truth 之间的平均绝对误差,即计算平均绝对误差。

预测该代码产生的平均绝对误差(MAE)值约为17621。这个误差过大了,还需采取方法优化。

阶段二:优化代码

其实这里有多种方法,比如说多个模型堆叠使用,或者说使用数据分析的方法对特征值进行判断,处理并减少特征值的数量。

因为我的主要目的是为了学习机器学习,所以在此参考了一个使用7种模型集成学习建模方法大佬的代码进行学习。

以下代码为转载,作者:KeithFish; GitHub:KeithFish 链接: link

#导入计算模块,对模块大致功能注解:#numpy支持矩阵运算#pandas用来做数据清洗,像是python中的excel(支持将数据以.csv格式输出至本地)#sklearn用来进一步制作数据集(支持数据的导入和数据的导出),含有SVM支持向量机、DT决策树、KNN近邻、LR逻辑回归等封装好的模型,支持对数据进行交叉验证以调参。#mlxtend用来实现集成学习:bagging, boosting, stacking#lightgbm内有boosting tree(相比xgboost,改进了生成节点的方式)#xgboost内有boosting tree#os用来读取文件import numpy as np # linear algebraimport pandas as pd #from datetime import datetimefrom scipy.stats import skew # for some statisticsfrom scipy.special import boxcox1pfrom scipy.stats import boxcox_normmaxfrom sklearn.linear_model import ElasticNetCV, LassoCV, RidgeCVfrom sklearn.ensemble import GradientBoostingRegressorfrom sklearn.svm import SVRfrom sklearn.pipeline import make_pipelinefrom sklearn.preprocessing import RobustScalerfrom sklearn.model_selection import KFold, cross_val_scorefrom sklearn.metrics import mean_squared_errorfrom mlxtend.regressor import StackingCVRegressorfrom xgboost import XGBRegressorfrom lightgbm import LGBMRegressorimport os#######################################################数据导入和特征提取-【开始】#################################################################################显示当前编译器的Draft Environment下的文件;将文件夹下的对应名称csv文件储存为矩阵对象。print(os.listdir("../input"))train = pd.read_csv('../input/house-prices-advanced-regression-techniques/train.csv')test = pd.read_csv('../input/house-prices-advanced-regression-techniques/test.csv')#显示矩阵对象的维数,核查是否导入成功print("Train set size:", train.shape)print("Test set size:", test.shape)#记录运算开始的时间print('START data processing', datetime.now(), )#取出train矩阵(或者称之为“数据帧”dataframe)中title为'Id'的列,赋值给train_ID。所以train_ID是一维列向量了。test_ID类似。#train_ID和test_ID根本就没有使用,完全可以删除。#train_ID = train['Id']#test_ID = test['Id']##################删除训练集和测试集中的标签列-【开始】##################将train矩阵中的'Id'列删除(原地删除,故将inplace设为true),因为原始数据中的数据索引和预测模型的构建没有关系。#test矩阵类似。train.drop(['Id'], axis=1, inplace=True)test.drop(['Id'], axis=1, inplace=True)##################删除训练集和测试集中的标签列-【结束】################################删除训练集中的极端值和进行数据index更新-【开始】##########使用条件筛选操作,通过覆值的方式剔除原始数据train矩阵中的极端值(极端值也被称为outliers),帮助预防房价预测模型出现过拟合。剔除操作也可以视为前剪枝。train = train[train.GrLivArea < 4500]#由于删去了部分行,故此时train矩阵中的index列并不连续。使用reset_index命令,在固定非index数据的顺序的前提下(inplace=True),重新对index编号(drop=True)。train.reset_index(drop=True, inplace=True)###############删除训练集中的极端值和进行数据index更新-【结束】###################对预测目标数值进行对数变换和特征矩阵对象的创建-【开始】######## log1p就是log(1+x),用来对房价数据进行数据预处理,它的好处是转化后的数据更加服从高斯分布,有利于后续的分类结果。# 需要注意,最后需要将预测出的平滑数据还原,而还原过程就是log1p的逆运算expm1。train["SalePrice"] = np.log1p(train["SalePrice"])#单独取出训练数据中的房价列信息,存入y对象。#y = train.SalePrice.reset_index(drop=True) #.reset_index(drop=True)方法:在原有的索引列重置索引,不再另外添加新列。有必要使用reset_index吗?有必要的,不这样做y将有两套index,作为df的y将有两列。y = train['SalePrice'].reset_index(drop=True) #对上式的改写#沿着水平的方向寻找列名为'SalePrice'的列(们),把它们对应的列统统删掉。得到了单纯的特征矩阵,存入train_features对象中。train_features = train.drop(['SalePrice'], axis=1)#test本来就没有房价列,所以它本来就是单纯的特征矩阵。test_features = test##########对预测目标数值进行对数变换和特征矩阵对象的创建-【结束】#########合并训练数据特征矩阵与测试数据特征矩阵,以便统一进行特征处理-【开始】###将训练数据中的特征矩阵和测试数据中的特征矩阵合并(.concat[矩阵1,矩阵2]),并对合并后的矩阵index重新编号(.reset_index(drop=True))。features = pd.concat([train_features, test_features]).reset_index(drop=True)#检查合并后的矩阵的维数,核查合并结果。print("剔除训练数据中的极端值后,将其特征矩阵和测试数据中的特征矩阵合并,维度为:",features.shape)##合并训练数据特征矩阵与测试数据特征矩阵,以便统一进行特征处理-【结束】#########################################################数据导入和特征提取-【结束】##############################################################################################################################################特征处理-【开始】####################################################################################对于列名为'MSSubClass'、'YrSold'、'MoSold'的特征列,将列中的数据类型转化为string格式。features['MSSubClass'] = features['MSSubClass'].apply(str)features['YrSold'] = features['YrSold'].astype(str)features['MoSold'] = features['MoSold'].astype(str)###############################填充空值-【开始】###########################按照以下各个特征列的实际情况,依次处理各个特征列中的空值(.fillna()方法)features['Functional'] = features['Functional'].fillna('Typ') #空值填充为str型数据'Typ'features['Electrical'] = features['Electrical'].fillna("SBrkr") #空值填充为str型数据"SBrkr"features['KitchenQual'] = features['KitchenQual'].fillna("TA") #空值填充为str型数据"TA"features["PoolQC"] = features["PoolQC"].fillna("None") #空值填充为str型数据"None"#对于列名为'Exterior1st'、'Exterior2nd'、'SaleType'的特征列,使用列中的众数填充空值。#1.先查找数据列中的众数:使用df.mode()[]方法# 解释:df.mode(0或1,0表示对列查找,1表示对行查找)[需要查找众数的df列的index(就是df中的第几列)],将返回数据列中的众数#2.使用.fillna()方法进行填充features['Exterior1st'] = features['Exterior1st'].fillna(features['Exterior1st'].mode()[0]) features['Exterior2nd'] = features['Exterior2nd'].fillna(features['Exterior2nd'].mode()[0])features['SaleType'] = features['SaleType'].fillna(features['SaleType'].mode()[0])#对于列名为'GarageYrBlt', 'GarageArea', 'GarageCars'的特征列,使用0填充空值。for col in ('GarageYrBlt', 'GarageArea', 'GarageCars'):features[col] = features[col].fillna(0)#对于列名为'GarageType', 'GarageFinish', 'GarageQual', 'GarageCond'的特征列,使用字符串'None'填充空值。for col in ['GarageType', 'GarageFinish', 'GarageQual', 'GarageCond']:features[col] = features[col].fillna('None')#对于列名为'BsmtQual', 'BsmtCond', 'BsmtExposure', 'BsmtFinType1', 'BsmtFinType2'的特征列,使用字符串'None'填充空值。for col in ('BsmtQual', 'BsmtCond', 'BsmtExposure', 'BsmtFinType1', 'BsmtFinType2'):features[col] = features[col].fillna('None')#聚合函数(按某一列关键字分组)groupby,它的特点是:将返回与传入方法的矩阵维度相同的单个序列。#transform是与groupby(pandas中最有用的操作之一)通常组合使用,它对传入方法的矩阵进行维度不变的变换。具体变换方法写在括号中,通常会使用匿名函数,对传入矩阵的所有元素进行操作。#对于features矩阵,按照'MSSubClass'列中的元素分布进行分组,被分组的数据列是'MSZoning'列。feature.groupby(被作为索引的列的名称)[被分组的数据列的名称]#features.groupby('MSSubClass')['MSZoning']后,得到的是一个以'MSSubClass'为索引,以'MSZoning'为数据列的矩阵。#.transform()方法将对'MSZoning'数据列进行()内的变换,它将返回和传入矩阵同样维度的矩阵。#括号内是匿名函数,将对传入矩阵中的空值进行填充,使用的填充元素是传入矩阵中的众数。features['MSZoning'] = features.groupby('MSSubClass')['MSZoning'].transform(lambda x: x.fillna(x.mode()[0]))#判断出features矩阵中列为对象的列,将列名存入objects叔祖。对于features矩阵中的各个列对象,将其列中的空值填充为'None'objects = []for i in features.columns:if features[i].dtype == object:objects.append(i)features.update(features[objects].fillna('None'))#使用传入矩阵('LotFrontage'列)的中位数对传入矩阵中的空值进行填充。#先以'Neighborhood'为标签,以'LotFrontage'为被汇总序列。然后使用被汇总序列中的中位数,对原始矩阵'LotFrontage'列中的空值进行填充。#transform的特性是同维操作,最后输出结果的顺序和原始数据在序号上完全匹配。features['LotFrontage'] = features.groupby('Neighborhood')['LotFrontage'].transform(lambda x: x.fillna(x.median()))#对于整型和浮点型数据列,使用0填充其中的空值。numeric_dtypes = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']numerics = []for i in features.columns:if features[i].dtype in numeric_dtypes:numerics.append(i)features.update(features[numerics].fillna(0))###############################填充空值-【结束】################################################数字型数据列偏度校正-【开始】########################使用skew()方法,计算所有整型和浮点型数据列中,数据分布的偏度(skewness)。#偏度是统计数据分布偏斜方向和程度的度量,是统计数据分布非对称程度的数字特征。亦称偏态、偏态系数。 numeric_dtypes = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']numerics2 = []for i in features.columns:if features[i].dtype in numeric_dtypes:numerics2.append(i)skew_features = features[numerics2].apply(lambda x: skew(x)).sort_values(ascending=False)#以0.5作为基准,统计偏度超过此数值的高偏度分布数据列,获取这些数据列的index。high_skew = skew_features[skew_features > 0.5]skew_index = high_skew.index#对高偏度数据进行处理,将其转化为正态分布。#Box和Cox提出的变换可以使线性回归模型满足线性性、独立性、方差齐次以及正态性的同时,又不丢失信息。for i in skew_index:features[i] = boxcox1p(features[i], boxcox_normmax(features[i] + 1))#这是boxcox1p的使用方法,参数的具体意义暂时不解释######################数字型数据列偏度校正-【结束】#############################################特征删除和融合创建新特征-【开始】####################删除一些特征。df.drop(‘列名’, axis=1)代表将‘列名’对应的列标签(们)沿着水平的方向依次删掉。features = features.drop(['Utilities', 'Street', 'PoolQC',], axis=1)#融合多个特征,生成新特征。features['YrBltAndRemod']=features['YearBuilt']+features['YearRemodAdd']features['TotalSF']=features['TotalBsmtSF'] + features['1stFlrSF'] + features['2ndFlrSF']features['Total_sqr_footage'] = (features['BsmtFinSF1'] + features['BsmtFinSF2'] +features['1stFlrSF'] + features['2ndFlrSF'])features['Total_Bathrooms'] = (features['FullBath'] + (0.5 * features['HalfBath']) +features['BsmtFullBath'] + (0.5 * features['BsmtHalfBath']))features['Total_porch_sf'] = (features['OpenPorchSF'] + features['3SsnPorch'] +features['EnclosedPorch'] + features['ScreenPorch'] +features['WoodDeckSF'])#简化特征。对于某些分布单调(比如100个数据中有99个的数值是0.9,另1个是0.1)的数字型数据列,进行01取值处理。features['haspool'] = features['PoolArea'].apply(lambda x: 1 if x > 0 else 0)features['has2ndfloor'] = features['2ndFlrSF'].apply(lambda x: 1 if x > 0 else 0)features['hasgarage'] = features['GarageArea'].apply(lambda x: 1 if x > 0 else 0)features['hasbsmt'] = features['TotalBsmtSF'].apply(lambda x: 1 if x > 0 else 0)features['hasfireplace'] = features['Fireplaces'].apply(lambda x: 1 if x > 0 else 0)#检查特征处理后,特征矩阵的维数,核查特征处理结果。print("删除了3个特征,又融合创建了10个新特征,处理之后的特征矩阵维度为:",features.shape)######################特征删除和融合创建新特征-【结束】#######################################特征投影、特征矩阵拆解和截取-【开始】##################使用.get_dummies()方法对特征矩阵进行类似“坐标投影”操作。获得在新空间下的特征表达。final_features = pd.get_dummies(features).reset_index(drop=True)#打印新空间下的特征维数,也是新空间的维数。print("使用get_dummies()方法“投影”特征矩阵,即分解出更多特征,得到更多列。投影后的特征矩阵维度为:",final_features.shape)#进行特征空间降阶。截取前len(y)行,存入X阵(因为之前进行了训练数据和测试数据的合并,所以从合并矩阵中取出前len(y)行,就得到了训练数据集的处理后的特征矩阵)。#截取剩余部分,即从序号为len(y)的行开始,至矩阵结尾的各行,存入X_sub阵。此为完成特征变换后的测试集特征矩阵。#注:len(df)是行计数方法X = final_features.iloc[:len(y), :]#y是列向量,存储了训练数据中的房价列信息。截取后得到的X阵的维度是len(y)*(final_features的列数)。X_sub = final_features.iloc[len(y):, :]#使用len命令,求矩阵X的长度,得到的是矩阵对象的长度,即有矩阵中有多少列,而不是每列上有多少行。print("删除了3个特征,又融合创建了10个新特征,处理之后的特征矩阵维度为:",'X', X.shape, 'y', y.shape, 'X_sub', X_sub.shape)#在新生特征空间中,剔除X阵和y阵中有着极端值的各行数据(因为X和y阵在水平方向上是一致的,所以要一起删除同样的行)。outliers数值中给出了极端值的列序号。#df.drop(df.index[序号])将删除指定序号的各行。再使用=对df覆值。outliers = [30, 88, 462, 631, 1322]X = X.drop(X.index[outliers])#因为X阵是经过对特征矩阵进行类似“坐标投影”操作后得到的,列向量y中的行号对应着X阵中的列号。y = y.drop(y.index[outliers])####################特征投影、特征矩阵拆解和截取-【结束】#######################################消除截取后特征矩阵的过拟合-【开始】####################### 这一步的目的是处理X阵和X_sub阵。#在新生特征空间中,删除将产生过拟合的数据列。#这种数据列具有如下特征:overfit = []#用来记录产生过拟合的数据列的序号for i in X.columns:#遍历截取后特征矩阵的每一列counts = X[i].value_counts()#使用.value_counts()方法,查看在X矩阵的第i列中,不同的取值分别出现了多少次,默认按次数最高到最低做降序排列。返回一个df。zeros = counts.iloc[0]#通过行号索引行数据,取出counts列中第一个元素,即出现次数最多的取值到底是出现了多少次,存入zerosif zeros / len(X) * 100 > 99.94:#判断某一列是否将产生过拟合的条件:#截取后的特征矩阵有len(X)列,如果某一列中的某个值出现的次数除以特征矩阵的列数超过99.94%,即其几乎在被投影的各个维度上都有着同样的取值,并不具有“主成分”的性质,则记为过拟合列。overfit.append(i)#找到将产生过拟合的数据列的位置后,在特征矩阵中进行删除操作。overfit = list(overfit)#overfit.append('MSZoning_C (all)')#这条语句有用吗?是要把训练数据特征矩阵X中的列标签为'MSZoning_C (all)'的列也删除吗?但是训练数据中并没有任何一个列标签名称为MSZoning_C (all)。X = X.drop(overfit, axis=1)#.copy()#删除截取后特征矩阵X中的过拟合列。因为drop并不影响原数据,所以使用copy。直接覆值应该也可以。X_sub = X_sub.drop(overfit, axis=1)#.copy()######################消除截取后特征矩阵的过拟合-【结束】#######################print("删除极端值及过拟合列后,训练数据特征矩阵的维数为,特征:",'X', X.shape, '对应于特征的对数变换后的房价y', y.shape, '测试数据的特征矩阵(它应该在行、列上未被删减)X_sub', X_sub.shape)##############################################################特征处理-【结束】#################################################################################################################################################机器学习-【开始】###################################################################################print('特征处理已经完成。开始对训练数据进行机器学习', datetime.now())#设置k折交叉验证的参数。kfolds = KFold(n_splits=10, shuffle=True, random_state=42)#定义均方根对数误差(Root Mean Squared Logarithmic Error ,RMSLE)def rmsle(y, y_pred):return np.sqrt(mean_squared_error(y, y_pred))#创建模型评分函数,根据不同模型的表现打分#cv表示Cross-validation,交叉验证的意思。def cv_rmse(model, X=X):rmse = np.sqrt(-cross_val_score(model, X, y, scoring="neg_mean_squared_error", cv=kfolds))return (rmse)#############个体机器学习模型的创建(即模型声明和参数设置)-【开始】############alphas_alt = [14.5, 14.6, 14.7, 14.8, 14.9, 15, 15.1, 15.2, 15.3, 15.4, 15.5]alphas2 = [5e-05, 0.0001, 0.0002, 0.0003, 0.0004, 0.0005, 0.0006, 0.0007, 0.0008]e_alphas = [0.0001, 0.0002, 0.0003, 0.0004, 0.0005, 0.0006, 0.0007]e_l1ratio = [0.8, 0.85, 0.9, 0.95, 0.99, 1]#定义ridge岭回归模型(使用二范数作为正则化项。不论是使用一范数还是二范数,正则化项的引入均是为了降低过拟合风险。)#注:正则化项如果使用二范数,那么对于任何需要寻优的参数值,在寻优终止时,它都无法将某些参数值变为严格的0,尽管某些参数估计值变得非常小以至于可以忽略。即使用二范数会保留变量的所有信息,不会进行类似PCA的变量凸显。#注:正则化项如果使用一范数,它比L2范数更易于获得“稀疏(sparse)”解,即它的求解结果会有更多的零分量。ridge = make_pipeline(RobustScaler(), RidgeCV(alphas=alphas_alt, cv=kfolds))#定义LASSO收缩模型(使用L1范数作为正则化项)(由于对目标函数的求解结果中将得到很多的零分量,它也被称为收缩模型。)#注:正则化项如果使用二范数,那么对于任何需要寻优的参数值,在寻优终止时,它都无法将某些参数值变为严格的0,尽管某些参数估计值变得非常小以至于可以忽略。即使用二范数会保留变量的所有信息,不会进行类似PCA的变量凸显。#注:正则化项如果使用一范数,它比L2范数更易于获得“稀疏(sparse)”解,即它的求解结果会有更多的零分量。lasso = make_pipeline(RobustScaler(), LassoCV(max_iter=1e7, alphas=alphas2, random_state=42, cv=kfolds))#定义elastic net弹性网络模型(弹性网络实际上是结合了岭回归和lasso的特点,同时使用了L1和L2作为正则化项。)elasticnet = make_pipeline(RobustScaler(), ElasticNetCV(max_iter=1e7, alphas=e_alphas, cv=kfolds, l1_ratio=e_l1ratio))#定义SVM支持向量机模型 svr = make_pipeline(RobustScaler(), SVR(C= 20, epsilon= 0.008, gamma=0.0003,))#定义GB梯度提升模型(展开到一阶导数)gbr = GradientBoostingRegressor(n_estimators=3000, learning_rate=0.05, max_depth=4, max_features='sqrt', min_samples_leaf=15, min_samples_split=10, loss='huber', random_state =42) #定义lightgbm模型lightgbm = LGBMRegressor(objective='regression', num_leaves=4,learning_rate=0.01, n_estimators=5000,max_bin=200, bagging_fraction=0.75,bagging_freq=5, bagging_seed=7,feature_fraction=0.2,feature_fraction_seed=7,verbose=-1,#min_data_in_leaf=2,#min_sum_hessian_in_leaf=11)#定义xgboost模型(展开到二阶导数) xgboost = XGBRegressor(learning_rate=0.01, n_estimators=3460,max_depth=3, min_child_weight=0,gamma=0, subsample=0.7,colsample_bytree=0.7,objective='reg:linear', nthread=-1,scale_pos_weight=1, seed=27,reg_alpha=0.00006)#############个体机器学习模型的创建(即模型声明和参数设置)-【结束】#######################################集成多个个体学习器-【开始】#############################!!!!!!!!!!!!###!!!!!!!!!!!!###!!!regressors=(...)中并没有纳入前面的svr模型,怎么回事?###!!!!!!!!!!!!###!!!!!!!!!!!!stack_gen = StackingCVRegressor(regressors=(ridge, lasso, elasticnet, gbr, xgboost, lightgbm),meta_regressor=xgboost,use_features_in_secondary=True)#regressors=(...)中并没有纳入前面的svr模型###########################集成多个个体学习器-【结束】########################## ############################进行交叉验证打分-【开始】############################进行交叉验证,并对不同模型的表现打分#(由于是交叉验证,将使用不同的数据集对同一模型进行评分,故每个模型对应一个得分序列。展示模型得分序列的平均分、标准差)print('进行交叉验证,计算不同模型的得分TEST score on CV')#打印二范数rideg岭回归模型的得分score = cv_rmse(ridge)print("二范数rideg岭回归模型的得分: {:.4f} ({:.4f})\n".format(score.mean(), score.std()), datetime.now(), )#打印一范数LASSO收缩模型的得分score = cv_rmse(lasso)print("一范数LASSO收缩模型的得分: {:.4f} ({:.4f})\n".format(score.mean(), score.std()), datetime.now(), )#打印elastic net弹性网络模型的得分score = cv_rmse(elasticnet)print("elastic net弹性网络模型的得分: {:.4f} ({:.4f})\n".format(score.mean(), score.std()), datetime.now(), )#打印SVR支持向量机模型的得分score = cv_rmse(svr)print("SVR支持向量机模型的得分: {:.4f} ({:.4f})\n".format(score.mean(), score.std()), datetime.now(), )#打印lightgbm轻梯度提升模型的得分score = cv_rmse(lightgbm)print("lightgbm轻梯度提升模型的得分: {:.4f} ({:.4f})\n".format(score.mean(), score.std()), datetime.now(), )#打印gbr梯度提升回归模型的得分score = cv_rmse(gbr)print("gbr梯度提升回归模型的得分: {:.4f} ({:.4f})\n".format(score.mean(), score.std()), datetime.now(), )#打印xgboost模型的得分score = cv_rmse(xgboost)print("xgboost模型的得分: {:.4f} ({:.4f})\n".format(score.mean(), score.std()), datetime.now(), )############################进行交叉验证打分-【结束】####################################使用训练数据特征矩阵作为输入,训练数据对数处理后的预测房价作为输出,进行各个模型的训练-【开始】##########开始集合所有模型,使用stacking方法print('进行模型参数训练 START Fit')print(datetime.now(), '对stack_gen集成器模型进行参数训练')stack_gen_model = stack_gen.fit(np.array(X), np.array(y))print(datetime.now(), '对elasticnet弹性网络模型进行参数训练')elastic_model_full_data = elasticnet.fit(X, y)print(datetime.now(), '对一范数lasso收缩模型进行参数训练')lasso_model_full_data = lasso.fit(X, y)print(datetime.now(), '对二范数ridge岭回归模型进行参数训练')ridge_model_full_data = ridge.fit(X, y)print(datetime.now(), '对svr支持向量机模型进行参数训练')svr_model_full_data = svr.fit(X, y)print(datetime.now(), '对GradientBoosting梯度提升模型进行参数训练')gbr_model_full_data = gbr.fit(X, y)print(datetime.now(), '对xgboost二阶梯度提升模型进行参数训练')xgb_model_full_data = xgboost.fit(X, y)print(datetime.now(), '对lightgbm轻梯度提升模型进行参数训练')lgb_model_full_data = lightgbm.fit(X, y)#########使用训练数据特征矩阵作为输入,训练数据对数处理后的预测房价作为输出,进行各个模型的训练-【结束】#####################################进行交叉验证打分-【结束】###################################定义个体学习器的预测值融合函数,检测预测值融合策略的效果-【开始】########综合多个模型产生的预测值,作为多模型组合学习器的预测值def blend_models_predict(X):return ((0.1 * elastic_model_full_data.predict(X)) + \(0.05 * lasso_model_full_data.predict(X)) + \(0.1 * ridge_model_full_data.predict(X)) + \(0.1 * svr_model_full_data.predict(X)) + \(0.1 * gbr_model_full_data.predict(X)) + \(0.15 * xgb_model_full_data.predict(X)) + \(0.1 * lgb_model_full_data.predict(X)) + \(0.3 * stack_gen_model.predict(np.array(X))))#打印在上述模型配比下,多模型组合学习器的均方根对数误差(Root Mean Squared Logarithmic Error ,RMSLE)#使用训练数据对创造的模型进行k折交叉验证,以训练创造出的模型的参数配置。交叉验证训练过程结束后,将得到模型的参数配置。使用得出的参数配置下,在全体训练数据上进行验证,验证模型对全体训练数据重构的误差。print('融合后的训练模型对原数据重构时的均方根对数误差RMSLE score on train data:')print(rmsle(y, blend_models_predict(X)))########定义个体学习器的预测值融合函数,检测预测值融合策略的效果-【结束】###############将测试集的特征矩阵作为输入,传入训练好的模型,得出的输出写入.csv文件的第2列-【开始】########print('使用测试集特征进行房价预测 Predict submission', datetime.now(),)submission = pd.read_csv("../input/house-prices-advanced-regression-techniques/sample_submission.csv")#函数注释:.iloc[:,1]是基于索引位来选取数据集,[索引1:索引2],左闭右开。submission.iloc[:,1] = np.floor(np.expm1(blend_models_predict(X_sub)))########将测试集的特征矩阵作为输入,传入训练好的模型,得出的输出写入.csv文件的第2列-【结束】#########---------------------------------------------------------------------------------------------------------------------------##---------------------------------------------------------------------------------------------------------------------------##---------------------------------------------------------------------------------------------------------------------------## 当对平台未公开的测试集进行预测时,前述模型的误差是0.114 this kernel gave a score 0.114# 为了提高模型的得分,引入其他模型的优秀预测结果,与前述模型的预测结果进行混合(有点类似抄别人的答案,但实质是扩大集成模型的规模,引入更多的模型) let's up it by mixing with the top kernels######################模型输出结果融合-【开始】##############################在多模型集成学习器预测结果的基础上,融合其他优秀模型(即平台上其他均方根对数误差小的模型)的预测结果。#这步操作是为了降低多模型集成学习器的方差。print('融合其他优秀模型的预测结果 Blend with Top Kernals submissions', datetime.now(),)sub_1 = pd.read_csv('../input/top-10-0-10943-stacking-mice-and-brutal-force/House_Prices_submit.csv')sub_2 = pd.read_csv('../input/hybrid-svm-benchmark-approach-0-11180-lb-top-2/hybrid_solution.csv')sub_3 = pd.read_csv('../input/lasso-model-for-regression-problem/lasso_sol22_Median.csv')submission.iloc[:,1] = np.floor((0.25 * np.floor(np.expm1(blend_models_predict(X_sub)))) + (0.25 * sub_1.iloc[:,1]) + (0.25 * sub_2.iloc[:,1]) + (0.25 * sub_3.iloc[:,1]))######################模型输出结果融合-【结束】#################################################融合结果的极端值剔除-【开始】########################### #处理融合后结果中的极端值。把太大的数值(降序排列时,位于顶部往下0.005的数值,就是只有0.005的数比它大)缩小一点(乘以0.77),把太小的数值(降序排列时,位于顶部往下0.99的数值)放大一点(乘以1.1)q1 = submission['SalePrice'].quantile(0.005)q2 = submission['SalePrice'].quantile(0.995)submission['SalePrice'] = submission['SalePrice'].apply(lambda x: x if x > q1 else x*0.77)submission['SalePrice'] = submission['SalePrice'].apply(lambda x: x if x < q2 else x*1.1)####################融合结果的极端值剔除-【结束】############################以csv文件的形式输出预测值submission.to_csv("House_price_submission.csv", index=False)print('融合结果.csv文件输出成功 Save submission', datetime.now())##############################################################机器学习-【结束】###################################################################################

其实这个代码里是省略了写步骤的,只是给出了最优解的方式。本来至少还是需要做数据分析的。如果看了上面一个数据分析的优化方法,里面应该有些困惑是可以解决的。标注几个我一开始也没想通的问题。

1、“train.GrLivArea”——这是其中的一个列值,本来是可以通过数据分析发现GrLivArea这一值有部分极端值的,所以需要去掉;

2、对后面每个特征值的分别处理,也是需要先进行数据分析,再找到最合适的填充值的。

其实这个大佬已经将能使用的模型运用到极致了。而且观察后也能发现,基本上排行榜在前的大佬都是将所有的模型都运用一遍,比较得到最好的结果再用来预测,所以我上面的“使用TPOT自动选择模型”的方法似乎不需要了。

有机会我再在别的地方试一下吧,这篇博文主要还是学习为主。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。