Kaggle竞赛——房价预测

目录

  • 1. 特征分析
    • 1.1 数据集导入
    • 1.2 统计缺失值
    • 1.3 可视化缺失值
    • 1.4 缺失值相关性分析
    • 1.5 训练集和测试集缺失数据对比
    • 1.6 统计特征的数据类型
    • 1.7 数值型特征分布直方图
    • 1.8 数值型特征与房价的线性关系
    • 1.9 非数值型特征的分布直方图
    • 1.10 非数值型特征箱线图
    • 1.11 数值型特征填充前后的分布对比
    • 1.12 时序特征分析
    • 1.13 用热图分析数值型特征之间的相关性
  • 2. 数据处理
    • 2.1 正态化 SalePrice
    • 2.2 时序特征处理
    • 2.3 特征融合
    • 2.4 填充特征值
    • 2.5 连续性数据正态化
    • 2.5 编码数据集后切分数据集
  • 3. 模型搭建
    • 3.1 模型搭建与超参数调整
    • 3.2 模型交叉验证
    • 3.3 特征重要性分析
    • 3.4 数值预测
  • 4. 参考文献

这是接触Kaggle竞赛的第一个题目,借鉴了其他人可视化分析和特征分析的技巧(文末附链接)。本次提交到Kaggle的得分是0.13227,排名1209(提交日期:2024年6月30日),数据集和代码已经打包放到Gitee,点击直达。
在这里插入图片描述
思路简图:
在这里插入图片描述

1. 特征分析

1.1 数据集导入

将训练集与测试集合并,方便更准确地分析数据特征。

train = pd.read_csv("D:\\Desktop\\kaggle数据集\\house-prices-advanced-regression-techniques\\train.csv")
test  = pd.read_csv("D:\\Desktop\\kaggle数据集\\house-prices-advanced-regression-techniques\\test.csv")
Id = test['Id']
print("训练集大小{}".format(train.shape))
print("测试集大小{}".format(test.shape))
# 合并训练集与测试集,方便更准确地分析数据特征
datas = pd.concat([train, test], ignore_index=True)
# 删除Id列
datas.drop("Id", axis= 1, inplace=True)
训练集大小(1460, 81)
测试集大小(1459, 80)

1.2 统计缺失值

#------------------------------------------------------------------------------------------------------------#
# 统计数据集中的值的空缺情况(以列为统计单位)
# isnull():检查所有数据集,如果是缺失值则返回True,否则返回False
# .sum():计算每列中True的数量
#------------------------------------------------------------------------------------------------------------#
datas.isnull().sum().sort_values(ascending = False).head(40)
PoolQC           2909
MiscFeature      2814
Alley            2721
Fence            2348
MasVnrType       1766
SalePrice        1459
FireplaceQu      1420
LotFrontage       486
GarageFinish      159
GarageQual        159
GarageCond        159
GarageYrBlt       159
GarageType        157
BsmtCond           82
BsmtExposure       82
BsmtQual           81
BsmtFinType2       80
BsmtFinType1       79
MasVnrArea         23
MSZoning            4
BsmtHalfBath        2
Utilities           2
BsmtFullBath        2
Functional          2
Exterior2nd         1
Exterior1st         1
GarageArea          1
GarageCars          1
SaleType            1
KitchenQual         1
BsmtFinSF1          1
Electrical          1
BsmtFinSF2          1
BsmtUnfSF           1
TotalBsmtSF         1
TotRmsAbvGrd        0
Fireplaces          0
SaleCondition       0
PavedDrive          0
MoSold              0
dtype: int64

1.3 可视化缺失值

右侧的微线图概括了数据完整性的一般形状,并标明了具有最多空值(最靠近左侧,数值表示的该行中非空值的数量)和最少空值(最靠近右侧)的行。

msno.matrix(datas)

1.4 缺失值相关性分析

用热图显示数据集中缺失值之间的相关性

  • 1:表示两个特征的缺失模式完全相同,即其中一个缺失时,另一个也缺失
  • -1:表示一个特征有缺失值时,另一个特征没有缺失值
  • 0: 表示两个特征的缺失值模式不相关
msno.heatmap(train)

在这里插入图片描述

1.5 训练集和测试集缺失数据对比

#------------------------------------------------------------------------------------------------------------#
# 比较两个dataframe(train和test)的数据类型,需确保两个数据集具有相同的列标签
#------------------------------------------------------------------------------------------------------------#
train_dtype = train_dtype.drop('SalePrice')
train_dtype.compare(test_dtype)

在这里插入图片描述
由对比结果可知数据类型都是int64和float64的区别,对结果影响不大。

# 缺失值对比
null_train = train.isnull().sum()
null_test = test.isnull().sum()
null_train = null_train.drop('SalePrice')
null_comp = null_train.compare(null_test).sort_values(['self'], ascending=[False])
null_comp

(局部,未截完整)
在这里插入图片描述

1.6 统计特征的数据类型

  • 数值型特征
    • 1.1 离散特征(唯一值(多个重复值只取一个)数量小于25(可视情况而定))
    • 1.2 连续特征(‘Id’列不计入)
  • 非数值型数据
# 在 pandas 中,如果一个列的数据类型无法确定为数值型,则会被标记为 '0'
numerical_features = [col for col in datas.columns if datas[col].dtypes != 'O']
discrete_features = [col for col in numerical_features if len(datas[col].unique()) < 25]
continuous_features = [feature for feature in numerical_features if feature not in discrete_features]
non_numerical_features = [col for col in datas.columns if datas[col].dtype == 'O']

print("Total Number of Numerical Columns : ",len(numerical_features))
print("Number of discrete features : ",len(discrete_features))
print("No of continuous features are : ", len(continuous_features))
print("Number of non-numeric features : ",len(non_numerical_features))

print("离散型数据: ",discrete_features)
print("连续型数据:", continuous_features)
print("非数值型数据:",non_numerical_features)
Total Number of Numerical Columns :  37
Number of discrete features :  15
No of continuous features are :  22
Number of non-numeric features :  43
离散型数据:  ['MSSubClass', 'OverallQual', 'OverallCond', 'BsmtFullBath', 'BsmtHalfBath', 'FullBath', 'HalfBath', 'BedroomAbvGr', 'KitchenAbvGr', 'TotRmsAbvGrd', 'Fireplaces', 'GarageCars', 'PoolArea', 'MoSold', 'YrSold']
连续型数据: ['LotFrontage', 'LotArea', 'YearBuilt', 'YearRemodAdd', 'MasVnrArea', 'BsmtFinSF1', 'BsmtFinSF2', 'BsmtUnfSF', 'TotalBsmtSF', '1stFlrSF', '2ndFlrSF', 'LowQualFinSF', 'GrLivArea', 'GarageYrBlt', 'GarageArea', 'WoodDeckSF', 'OpenPorchSF', 'EnclosedPorch', '3SsnPorch', 'ScreenPorch', 'MiscVal', 'SalePrice']
非数值型数据: ['MSZoning', 'Street', 'Alley', 'LotShape', 'LandContour', 'Utilities', 'LotConfig', 'LandSlope', 'Neighborhood', 'Condition1', 'Condition2', 'BldgType', 'HouseStyle', 'RoofStyle', 'RoofMatl', 'Exterior1st', 'Exterior2nd', 'MasVnrType', 'ExterQual', 'ExterCond', 'Foundation', 'BsmtQual', 'BsmtCond', 'BsmtExposure', 'BsmtFinType1', 'BsmtFinType2', 'Heating', 'HeatingQC', 'CentralAir', 'Electrical', 'KitchenQual', 'Functional', 'FireplaceQu', 'GarageType', 'GarageFinish', 'GarageQual', 'GarageCond', 'PavedDrive', 'PoolQC', 'Fence', 'MiscFeature', 'SaleType', 'SaleCondition']

1.7 数值型特征分布直方图

离散数据分布直方图

#------------------------------------------------------------------------------------------------------------#
# 添加 Label 列用于标识训练集和测试集
#------------------------------------------------------------------------------------------------------------#
datas['Label'] = "Test"
datas['Label'][:1460] = "Train"
#------------------------------------------------------------------------------------------------------------#
# 离散数据直方图
# sharex=False:子图的x轴不共享,每个子图可以独立设置自己的x轴属性
# hue='Label':根据 Label 列的值为直方图上色,不同的 Label 值会分配不同颜色
# ax=axes[i%3,i//3]:确保了直方图可以在一个3xN的网格中均匀分布
#------------------------------------------------------------------------------------------------------------#
fig, axes = plt.subplots(3, 5, figsize=(30, 10), sharex=False)
for i, feature in enumerate(discrete_features):
    sns.histplot(data=datas, x=feature, hue='Label', ax=axes[i%3, i//3])

连续数据分布直方图

fig,axes = plt.subplots(nrows = 4, ncols = 6, figsize=(30,15), sharex=False)
for i, feature in enumerate(continuous_features):
    sns.histplot(data=datas, x=feature, hue='Label',ax=axes[i%4,i//4])

1.8 数值型特征与房价的线性关系

fig, axes = plt.subplots(7, 6, figsize=(30, 30), sharex=False)
for i, feature in enumerate(numerical_features):
    sns.scatterplot(data = datas, x = feature, y="SalePrice", ax=axes[i%7, i//7])

1.9 非数值型特征的分布直方图

f,axes = plt.subplots(7, 7, figsize=(30,30),sharex=False)
for i,feature in enumerate(non_numerical_features):
    sns.countplot(data=datas, x=feature, hue="Label", ax=axes[i%7,i//7])

1.10 非数值型特征箱线图

对每个箱线图内部按照 SalePric 对不同的特征值进行降序排序。

#------------------------------------------------------------------------------------------------------------#
# groupby(feature)['SalePrice'].median():计算每个 feature 分组的SalePrice中位数
# items():将结果转换为一个包含键值对的迭代器(迭代器中的每个元素都是一个二元组),二元组形式:(特征值,中位数)
# x[1]:根据二元组的第二个值进行排序
# reverse = True:降序
# x[0] for x in sort_list:提取二元组的第一个值(键)即特征值
# order=order_list:按 order_list 中的顺序排列 x 轴的分类
#------------------------------------------------------------------------------------------------------------#
fig, axes = plt.subplots(7,7 , figsize=(30, 30), sharex=False)
for i, feature in enumerate(non_numerical_features):
    sort_list = sorted(datas.groupby(feature)['SalePrice'].median().items(), key = lambda x:x[1], reverse = True)
    order_list = [x[0] for x in sort_list ]
    sns.boxplot(data = datas, x = feature, y = 'SalePrice', order=order_list, ax=axes[i%7, i//7])
plt.show()

在这里插入图片描述

1.11 数值型特征填充前后的分布对比

# 原数值数据数据(有数据缺失的列)与使用均值、众数和中位数填充后的数据分布对比
null_numerical_features = [col for col in datas.columns if datas[col].isnull().sum()>0 and col not in non_numerical_features]
plt.figure(figsize=(30, 20))

for i, var in enumerate(null_numerical_features):
    plt.subplot(4,3,i+1)
    sns.distplot(datas[var], bins=20, kde_kws={'linewidth':3,'color':'yellow'}, label="original")
    sns.distplot(datas[var].fillna(datas[var].mean()), bins=20, kde_kws={'linewidth':2,'color':'red'}, label="mean")
    sns.distplot(datas[var].fillna(datas[var].median()), bins=20, kde_kws={'linewidth':2,'color':'green'}, label="median")
    sns.distplot(datas[var].fillna(datas[var].mode()[0]), bins=20, kde_kws={'linewidth':2,'color':'blue'}, label="mode") 

1.12 时序特征分析

#------------------------------------------------------------------------------------------------------------#
# YrSold是离散型数据,YearBuilt(建房日期),YearRemodAdd(改造日期),GarageYrBlt(车库修建日期)是连续型数据
#------------------------------------------------------------------------------------------------------------#
year_feature = [col for col in datas.columns if "Yr" in col or 'Year' in col]
year_feature
['YearBuilt', 'YearRemodAdd', 'GarageYrBlt', 'YrSold']
# 查看YrSold与售价的关系
datas.groupby('YrSold')['SalePrice'].median().plot()
plt.xlabel('Year Sold')
plt.ylabel('House Price')
plt.title('House price vs YearSold')

# 绘制其他三个特征与销售价格的散点对应图
for feature in year_feature:
    if feature != 'YrSold':
        hs = datas.copy()
        plt.scatter(hs[feature],hs['SalePrice'])
        plt.xlabel(feature)
        plt.ylabel('SalePrice')


可以发现随着时间增加(即建造的时间越近),价格也逐渐增加。

1.13 用热图分析数值型特征之间的相关性

#------------------------------------------------------------------------------------------------------------#
# cmap="YlGnBu":指定从黄绿色(正相关)到蓝绿色(负相关)的颜色渐变
# linewidths=.5:边框宽度为0.5
#------------------------------------------------------------------------------------------------------------#
plt.figure(figsize=(20,10))
numeric_features = train.select_dtypes(include=[float, int])
sns.heatmap(numeric_features.corr(), cmap="YlGnBu", linewidths=.5)

2. 数据处理

2.1 正态化 SalePrice

  • n p . l o g 1 ( ) np.log1() np.log1():即计算 l n ( 1 + x ) ln(1 + x) ln(1+x),使用该函数比直接使用 n p . l o g ( 1 + x ) np.log(1 + x) np.log(1+x) 计算的精度要高。注意:np.log() 函数指的是计算自然对数)
  • n p . e x p m 1 ( ) np.expm1() np.expm1():即计算 e x − 1 e^x-1 ex1,使用该函数比直接计算 e x − 1 e^x-1 ex1 的精度要高。

二者互为反函数,使用 n p . l o g 1 ( ) np.log1() np.log1() 将 SalePrice 平滑化(正态化)后,最后得到的预测值需要用 n p . e x p m 1 ( ) np.expm1() np.expm1() 进行转换。

#------------------------------------------------------------------------------------------------------------#
# 绘制SalePrice的特征分布
# displot:用于绘制直方图和核密度估计图
# kde:用于在直方图上叠加核密度估计曲线
# .skew():算数据集的偏度,偏度是统计数据分布的不对称性的度量
#------------------------------------------------------------------------------------------------------------#
sns.displot(datas['SalePrice'], color='g', bins=50, kde=True)
print("SalePrice的偏度:{:.2f}".format(datas['SalePrice'].skew()))
SalePrice的偏度:1.88

在这里插入图片描述

#------------------------------------------------------------------------------------------------------------#
# 使用 np.log1() 将其平滑化(正态化)
# 偏度为1.88,SalePrice 的数据分布显著偏离正态,正常的数据应该是接近于正态分布的
#------------------------------------------------------------------------------------------------------------#
datas['SalePrice'] = np.log1p(datas['SalePrice'])
sns.displot(datas['SalePrice'], color='g', bins=50, kde=True)
print("正态化后 SalePrice 的偏度:{:.2f}".format(datas['SalePrice'].skew()))
正态化后 SalePrice 的偏度:0.12

在这里插入图片描述

2.2 时序特征处理

将时序特征离散化(用 YrSold 减去 YearBuilt、YearRemodAdd和GarageYrBlt 的时间),YrSold本身离散不用管。时序特征中 GarageYrBlt 数据有缺失,用中位数补足。

for feature in ['YearBuilt','YearRemodAdd','GarageYrBlt']:
    datas[feature]=datas['YrSold']-datas[feature]
datas['GarageYrBlt'].fillna(datas['GarageYrBlt'].median(), inplace = True)

2.3 特征融合

从非数值型特征的分布直方图中可以发现 GarageQual 特征的 Ex 和 Po 占比非常小(如下图),所以将这两个特征值统称为 other(其他列暂不使用,还不知道效果如何)。
在这里插入图片描述

# mask是一个布尔索引数组,长度与列 cGarageQual 的长度相同
# datas['GarageQual'][mask]:选择列 GarageQual 中所有 mask 为 True 的元素,
mask = datas['GarageQual'].isin(['Ex', 'Po'])
datas['GarageQual'][mask] = 'Other'

2.4 填充特征值

缺失最多的特征 PoolQC(泳池质量)并不代表数据缺失,而是没有泳池,因此不能简单地直接删除该列,这里用None替换掉Nan。

datas['PoolQC'].fillna("None", inplace=True)

排查数据缺失列,如果是数值型特征则根据数据 [1.11 数值型特征填充前后的分布对比] 选择中位数、众数还是平均数填充(多数情况下离散型用众数或中位数,连续型用中位数或平均数)。
如果是非数值型数据分两种情况:

  1. 缺失较多,使用 None 填充(新加一个类)
  2. 缺失较少,使用众数(最大类别)填充
# -------------------------------------------------非数值型数据----------------------------------------------#
datas['MiscFeature'].fillna('None', inplace=True)
datas['Alley'].fillna('None', inplace=True)
datas['Fence'].fillna('None', inplace=True)
datas['MasVnrType'].fillna('None', inplace=True)
datas['FireplaceQu'].fillna('None', inplace=True)
datas['GarageQual'].fillna('None', inplace=True)
datas['GarageCond'].fillna('None', inplace=True)
datas['GarageFinish'].fillna('None', inplace=True)
datas['GarageType'].fillna('None', inplace=True)
datas['BsmtCond'].fillna('None', inplace=True)
datas['BsmtExposure'].fillna('None', inplace=True)
datas['BsmtQual'].fillna('None', inplace=True)
datas['BsmtFinType1'].fillna('None', inplace=True)
datas['BsmtFinType2'].fillna('None', inplace=True)

# mode()[0]:计算该列的众数并取第一个值
datas['MSZoning'].fillna(datas['MSZoning'].mode()[0], inplace=True)
datas['Utilities'].fillna(datas['Utilities'].mode()[0], inplace=True)
datas['Functional'].fillna(datas['Functional'].mode()[0], inplace=True)
datas['Electrical'].fillna(datas['Electrical'].mode()[0], inplace=True)
datas['Exterior2nd'].fillna(datas['Exterior2nd'].mode()[0], inplace=True)
datas['Exterior1st'].fillna(datas['Exterior1st'].mode()[0], inplace=True)
datas['SaleType'].fillna(datas['SaleType'].mode()[0], inplace=True)
datas['KitchenQual'].fillna(datas['KitchenQual'].mode()[0], inplace=True)

#--------------------------------------------------数值型数据------------------------------------------------#
datas['MasVnrArea'].fillna(datas['MasVnrArea'].mean(), inplace = True)
datas['LotFrontage'].fillna(datas['LotFrontage'].mean(), inplace = True)
datas['BsmtFullBath'].fillna(datas['BsmtFullBath'].median(), inplace = True)
datas['BsmtHalfBath'].fillna(datas['BsmtHalfBath'].median(), inplace = True)
datas['BsmtFinSF1'].fillna(datas['BsmtFinSF1'].median(), inplace = True)
datas['GarageCars'].fillna(datas['GarageCars'].mean(), inplace = True)
datas['GarageArea'].fillna(datas['GarageArea'].mean(), inplace = True)
datas['TotalBsmtSF'].fillna(datas['TotalBsmtSF'].mean(), inplace = True)
datas['BsmtUnfSF'].fillna(datas['BsmtUnfSF'].mean(), inplace = True)
datas['BsmtFinSF2'].fillna(datas['BsmtFinSF2'].median(), inplace = True)

数据填充完之后确认一下是否还有遗漏的数据

datas.isnull().sum().sort_values(ascending = False).head(10)
SalePrice       1459
MSZoning           0
GarageYrBlt        0
GarageType         0
FireplaceQu        0
Fireplaces         0
Functional         0
TotRmsAbvGrd       0
KitchenQual        0
KitchenAbvGr       0
dtype: int64

2.5 连续性数据正态化

数据填充完毕后,重新挑选出连续型数值特征,观察其分布情况。

numerical_features = [col for col in datas.columns if datas[col].dtypes != 'O']
discrete_features = [col for col in numerical_features if len(datas[col].unique()) < 25 and col not in ['Id']]
continuous_features = [feature for feature in numerical_features if feature not in discrete_features+['Id']]
fig,axes = plt.subplots(nrows = 4, ncols = 6, figsize=(30,15), sharex=False)
for i, feature in enumerate(continuous_features):
    sns.histplot(data=datas, x=feature, hue='Label',ax=axes[i%4,i//4])

在这里插入图片描述
通过直方图可以直观地看出数值的分布是否符合正态分布,再分别计算偏度,通过偏度查看数据的偏离情况。

# 计算偏度
skewed_features = datas[continuous_features].apply(lambda x:x.skew()).sort_values(ascending=False)
print(skewed_features)
MiscVal          21.958480
LotArea          12.829025
LowQualFinSF     12.094977
3SsnPorch        11.381914
BsmtFinSF2        4.148275
EnclosedPorch     4.005950
ScreenPorch       3.948723
MasVnrArea        2.612892
OpenPorchSF       2.536417
WoodDeckSF        1.843380
LotFrontage       1.646420
1stFlrSF          1.470360
BsmtFinSF1        1.426111
GrLivArea         1.270010
TotalBsmtSF       1.163082
BsmtUnfSF         0.919981
2ndFlrSF          0.862118
YearBuilt         0.598917
YearRemodAdd      0.450458
GarageYrBlt       0.392261
GarageArea        0.241342
SalePrice         0.121347
dtype: float64

这里将偏度大于 1.5 的特征进行正态化,值设得太大的话正态化之后会导致原本0-1之间的特征的偏度过于小(-4左右)而出现左偏斜(即数据集中有较多较小的值)。

# 如果偏度的绝对值大于1.5,则用np.log1p进行处理【注:并不保证处理后偏度就会小于1.5,只能是使数据尽量符合正态分布】
# 需要正则化的特征列
log_list=[]
for feature, skew_value in skewed_features.items():
    if skew_value > 1.5:
        log_list.append(feature)
log_list

# 正则化
for i in log_list:
    datas[i] = np.log1p(datas[i])
  
# 检查正则化情况
skewed_features = datas[continuous_features].apply(lambda x:x.skew()).sort_values(ascending=False)
print(skewed_features)
3SsnPorch        8.829794
LowQualFinSF     8.562091
MiscVal          5.216665
ScreenPorch      2.947420
BsmtFinSF2       2.463749
EnclosedPorch    1.962089
1stFlrSF         1.470360
BsmtFinSF1       1.426111
GrLivArea        1.270010
TotalBsmtSF      1.163082
BsmtUnfSF        0.919981
2ndFlrSF         0.862118
YearBuilt        0.598917
MasVnrArea       0.504832
YearRemodAdd     0.450458
GarageYrBlt      0.392261
GarageArea       0.241342
WoodDeckSF       0.158114
SalePrice        0.121347
OpenPorchSF     -0.041819
LotArea         -0.505010
LotFrontage     -1.019985
dtype: float64

由结果可知,3SsnPorch、LowQualFinSF 和 MiscVal 的偏度还是太大(正偏度值大于2通常被认为是严重的右偏斜),但此时不宜再对这三个特征再次进行正态化,否则可能会导致数据失真。

2.5 编码数据集后切分数据集

# 删除Label列后对数据集进行独热(One-hot)编码
datas.drop('Label', axis=1, inplace=True)
datas = pd.get_dummies(datas, dtype=int)
# 切分训练集和测试集
new_train= datas.iloc[:len(train), :]
new_test = datas.iloc[len(train):, :]
X_train = new_train.drop('SalePrice', axis=1)
Y_train = new_train['SalePrice']
X_test = new_test.drop('SalePrice', axis=1)

3. 模型搭建

3.1 模型搭建与超参数调整

import optuna
from sklearn.linear_model import Ridge
from xgboost import XGBRegressor
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.model_selection import cross_val_score

"""
定义超参数优化函数
Params:
    objective:待优化的评估函数
Returns:
    params:最佳超参数组合
"""
def tune(objective):
    # 创建了一个 Optuna 的 Study 对象,用于管理一次超参数优化的过程
    # direction='maximize' 表示优化的目标是最大化目标函数的返回值(返回值是负的均方根误差)
    study = optuna.create_study(direction='maximize')
    
    # 使用 study 对象的 optimize 方法来执行优化过程
    # n_trials=100:指定了进行优化的试验次数
    study.optimize(objective, n_trials=10)
    
    params = study.best_params
    # 获取经过优化后的最佳得分((目标函数的返回值))
    best_score = study.best_value
    print(f"Best score: {-best_score} \nOptimized parameters: {params}")
    return params

"""
Ridge回归
Params:
    trial:是由 Optuna 库提供的对象,用于在超参数优化过程中管理参数的提议和跟踪
Returns:
    score:交叉验证评分
"""
def ridge_objective(trial):
    # 0.1 是超参数的下界,20 是超参数的上界。Optuna 会在指定的范围内为超参数 alpha 提出一个值
    _alpha = trial.suggest_float("alpha",0.1,20)
    ridge = Ridge(alpha=_alpha, random_state=1)
    score = cross_val_score(ridge,X_train,Y_train, cv=10, scoring="neg_root_mean_squared_error").mean()
    return score

"""
梯度增强树回归
Params:
    trial:是由 Optuna 库提供的对象,用于在超参数优化过程中管理参数的提议和跟踪
Returns:
    score:交叉验证评分
"""
def gbr_objective(trial):
    _n_estimators = trial.suggest_int("n_estimators", 50, 2000)
    _learning_rate = trial.suggest_float("learning_rate", 0.01, 1)
    _max_depth = trial.suggest_int("max_depth", 1, 20)
#     _min_samp_split = trial.suggest_int("min_samples_split", 2, 20)
#     _min_samples_leaf = trial.suggest_int("min_samples_leaf", 2, 20)
#     _max_features = trial.suggest_int("max_features", 10, 50)

    gbr = GradientBoostingRegressor(
        n_estimators=_n_estimators,
        learning_rate=_learning_rate,
        max_depth=_max_depth, 
#         max_features=_max_features,
#         min_samples_leaf=_min_samples_leaf,
#         min_samples_split=_min_samp_split,
        
        random_state=1,
    )

    score = cross_val_score(gbr, X_train,Y_train, cv=10, scoring="neg_root_mean_squared_error").mean()
    return score

"""
XGBoost回归模型
Params:
    trial:是由 Optuna 库提供的对象,用于在超参数优化过程中管理参数的提议和跟踪
Returns:
    score:交叉验证评分
"""
def xgb_objective(trial):
    _n_estimators = trial.suggest_int("n_estimators", 50, 2000)
    _max_depth = trial.suggest_int("max_depth", 1, 20)
    _learning_rate = trial.suggest_float("learning_rate", 0.01, 1)
#     _gamma = trial.suggest_float("gamma", 0.01, 1)
#     _min_child_weight = trial.suggest_float("min_child_weight", 0.1, 10)
#     _subsample = trial.suggest_float('subsample', 0.01, 1)
#     _reg_alpha = trial.suggest_float('reg_alpha', 0.01, 10)
#     _reg_lambda = trial.suggest_float('reg_lambda', 0.01, 10)

    xgboost = XGBRegressor(
        n_estimators=_n_estimators,
        max_depth=_max_depth, 
        learning_rate=_learning_rate,
#         gamma=_gamma,
#         min_child_weight=_min_child_weight,
#         subsample=_subsample,
#         reg_alpha=_reg_alpha,
#         reg_lambda=_reg_lambda,
#         random_state=1,
    )
    score = cross_val_score(xgboost, X_train, Y_train, cv=10, scoring="neg_root_mean_squared_error").mean()
    return score

寻找最佳参数,运行下面代码很耗时,可适当减少不重要参数的调优。本地调优后官网提交时不用再次运行,直接用本地运行的最佳参数即可。

# 设置日志级别为 WARNING,减少输出信息的数量
# optuna.logging.set_verbosity(optuna.logging.WARNING)

ridge_params = tune(ridge_objective)
# Best score: 0.13482720346041538 
# Optimized parameters: {'alpha': 14.933121817345844}
# ridge_params = {'alpha': 14.933121817345844}
    
gbr_params = tune(gbr_objective)
# Best score: 0.1388996815131788 
# Optimized parameters: {'n_estimators': 928, 'learning_rate': 0.24282934638611978, 'max_depth': 7}
# gbr_params = {'n_estimators': 928, 'learning_rate': 0.24282934638611978, 'max_depth': 7}

xbg_params = tune(xgb_objective)
# Best score: 0.12403838351336531 
# Optimized parameters: {'n_estimators': 1713, 'max_depth': 3, 'learning_rate': 0.030462678052628034}
# xbg_params = {'n_estimators': 1713, 'max_depth': 3, 'learning_rate': 0.030462678052628034}
              
# **:用于将键值对作为关键字参数传递给函数
ridge = Ridge(**ridge_params, random_state=1)
gbr = GradientBoostingRegressor(**gbr_params, random_state=1)
xgboost = XGBRegressor(**xbg_params, random_state=1)

3.2 模型交叉验证

ridge_score = np.sqrt(-cross_val_score(ridge, X_train, Y_train, cv=10, scoring='neg_mean_squared_error')) 
gbr_score = np.sqrt(-cross_val_score(gbr, X_train, Y_train, cv=10, scoring='neg_mean_squared_error')) 
xgboost_score = np.sqrt(-cross_val_score(xgboost, X_train, Y_train, cv=10, scoring='neg_mean_squared_error')) 
print(f"ridge_score: {np.mean(ridge_score)}")
print(f"gbr_score: {np.mean(gbr_score)}")
print(f"xgboost_score: {np.mean(xgboost_score)}")
ridge_score: 0.13482720346041538
gbr_score: 0.1388996815131788
xgboost_score: 0.12403838351336531

3.3 特征重要性分析

xgboost.fit(X_train, Y_train)
# 删除 "SalePrice" 方便分析特征重要性
imp_datas = datas.drop("SalePrice", axis=1)

# 获取特征重要性
importance = xgboost.feature_importances_

# 创建特征名称与重要性映射,用于合并独热编码之后的特征
feature_importance = pd.Series(importance, index=imp_datas.columns)

# 提取独热编码的特征名
original_feature_names = [col.split('_')[0] for col in imp_datas.columns]

# 聚合特征重要性
aggregated_importance = feature_importance.groupby(original_feature_names).sum()

plt.figure(figsize=(10, 18))

# kind='barh':指定了绘图类型为水平条形图
# sort_values()本身是由小到大的排序,但使用 .plot(kind='barh') 时,水平条形图的 y 轴将显示由高到低的顺序
aggregated_importance.sort_values().plot(kind='barh')
plt.xlabel("Feature Importance")
plt.ylabel('Feature')
plt.title("Aggregated Feature Importance Ranking")
# 调整图表布局,使其更紧凑
plt.tight_layout()

在这里插入图片描述

3.4 数值预测

选择最佳模型xgboost预测售价。

xgboost.fit(X_train, Y_train)
predictions = np.expm1(xgboost.predict(X_test))
submission = pd.DataFrame({'Id': Id,'SalePrice': predictions})
# submission.to_csv('/kaggle/working/submission.csv', index=False)
print('Submission file created!')

4. 参考文献

[1] 机器学习/深度学习实战——kaggle房价预测比赛实战(数据分析篇)
[2] kaggle简单实战——房价预测(xgboost实现)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/762808.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录算法训练营第55天(py)| 单调栈 | 42. 接雨水*、84.柱状图中最大的矩形

42. 接雨水* 力扣链接 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 思路1 暴力 按列来计算。每一列雨水的高度&#xff0c;取决于&#xff0c;该列 左侧最高的柱子和右侧最高的柱子中&#xff0c;…

WMS、ERP、MES之间的关系

WMS&#xff08;仓库管理系统&#xff09;、ERP&#xff08;企业资源计划&#xff09;、MES&#xff08;制造执行系统&#xff09;是企业管理和运作中常见的三种系统&#xff0c;它们在不同的层面上发挥作用&#xff0c;但之间又有紧密的联系。三者之间的区别如下&#xff1a; …

【哈哈大一上学的全忘了,重开!!】STM32从零入门物联网开发

本笔记资料来源 &#xff1a;STM32物联网入门30步&#xff1d;单片机物联网入门教程 WIFI连接阿里云物联网CubeMXHAL库蓝牙ESP8266杜洋主讲_哔哩哔哩_bilibili IOT&#xff1a;Internet of things 学习目标&#xff1a; 1.掌握洋桃IoT开发板的各功能以及驱动与基本应用 2.掌…

【C++11:右值引用,列表初始化】

统一列表初始化&#xff1a; 构造函数的函数名与函数体之间增加一个列表&#xff0c;用于对成员初始化 在实例化对象时&#xff0c;支持单/多参数的隐式转化&#xff0c;同时也可以省略符号&#xff0c;让代码更简洁 右值的引用 左值&#xff1a; 左值与右值的重要区别就是能…

tkinter显示图片

tkinter显示图片 效果代码解析打开和显示图像 代码 效果 代码解析 打开和显示图像 def open_image():file_path filedialog.askopenfilename(title"选择图片", filetypes(("PNG文件", "*.png"), ("JPEG文件", "*.jpg;*.jpeg&q…

专题五:Spring源码之初始化容器上下文

上一篇我们通过如下一段基础代码作为切入点&#xff0c;最终找到核心的处理是refresh方法&#xff0c;从今天开始正式进入refresh方法的解读。 public class Main {public static void main(String[] args) {ApplicationContext context new ClassPathXmlApplicationContext(…

2.3章节Python中的数值类型

1.整型数值 2.浮点型数值 3.复数   Python中的数值类型清晰且丰富&#xff0c;主要分为以下几种类型&#xff0c;每种类型都有其特定的用途和特性。 一、整型数值 1.定义&#xff1a;整数类型用于表示整数值&#xff0c;如1、-5、100等。 2.特点&#xff1a; Python 3中的…

面试题-Spring家族与SpringIOC

1.spring家族的介绍 Spring简单图&#xff1a; 2.IOC原理 IOC就是原先代码里需要开发者实现对象的创建和关系依赖&#xff0c;反转交给SpringIOC容器管理对象的生命周期和对象之间的依赖关系。 依赖注入的方式&#xff1a; Setter&#xff1a;实现特定属性的public sette…

RedHat9 | podman容器-续集

一、管理容器存储和网络资源 使用容器来运行简单的进程&#xff0c;然后退出。可以配置容连续运行特定服务&#xff0c;如数据库服务。如果持续运行服务&#xff0c;需要向容器添加更多的资源&#xff0c;如持久存储或对其他网络的访问权限。 针对企业容器平台上的大型部署&a…

数据资产安全策略的定制化之道:深入了解各企业独特需求,量身打造个性化的数据资产保护方案,确保数据安全无虞,助力企业稳健发展

目录 一、引言 二、企业数据资产安全现状分析 &#xff08;一&#xff09;数据安全风险多样化 &#xff08;二&#xff09;传统安全措施难以满足需求 &#xff08;三&#xff09;企业数据资产安全意识亟待提高 三、定制化数据资产安全策略的重要性 &#xff08;一&#…

SuperMap GIS基础产品FAQ集锦(20240701)

一、SuperMap iDesktopX 问题1&#xff1a;对于数据提供方提供的osgb格式的数据&#xff0c;如何只让他生成一个s3mb文件呢&#xff1f;我用倾斜入库的方式会生成好多个s3mb缓存文件 11.1.1 【解决办法】不能控制入库后只生成一个s3mb文件&#xff1b;可以在倾斜入库的时候设…

永磁同步电机离线参数识别

引言 永磁同步电机&#xff08;PMSM&#xff09;因其结构简单、功率密度高、转矩惯量比大和效率高等优点&#xff0c;在工业生产、航空航天和新能源交通等领域得到了广泛应用。然而&#xff0c;传统的参数辨识方法依赖位置传感器&#xff0c;这不仅增加了硬件成本&#xff0c;…

如何借用物联网快速实现高标准农田信息化

如何借用物联网快速实现高标准农田信息化 高标准农田信息化&#xff0c;作为现代农业发展的重要基石&#xff0c;是指在建设高产、稳产、节水、环保的农田基础上&#xff0c;深度融合现代信息技术&#xff0c;实现农田管理的精准化、智能化和高效化。物联网&#xff08;Intern…

sql server启动、连接 与 navicat连接sql server

一、sql server 启动 1.搜索cmd->以管理员身份运行 2.输入以下命令 net start mssqlserver 3.服务器启动成功 二、sql server连接 1.打开ssms&#xff0c;输入&#xff0c;连接 2.右键&#xff0c;属性 3.连接&#xff0c;勾选允许远程连接到此服务器 三、navicat连接sq…

20人团队如何免费使用 Atlassian 云产品?

企业赚钱越来越难&#xff0c;尤其是初创团队或小型团队更倾向于使用免费工具支持业务。团队规模影响协作复杂度&#xff0c;Atlassian 考虑到小团队的需求&#xff0c;提供了多种选择。比如&#xff0c;Jira 和 Confluence 的云版本有免费版&#xff0c;包含基本的项目管理功能…

三坐标测量机:柔性生产制造中的高精度测量解决方案

柔性生产制造是制造业的核心竞争力之一。它强调生产线的灵活性和适应性&#xff0c;以满足市场对产品多样化和个性化的需求。在当今快速变化的工业环境中&#xff0c;随着消费者对产品个性化和定制化需求的增加&#xff0c;柔性生产制造和三坐标测量机的结合&#xff0c;为智能…

MSVCR120.DLL丢失的多种修复方法,助你快速解决dll问题

在日常生活和工作中&#xff0c;电脑已经成为我们不可或缺的工具。然而&#xff0c;在使用电脑的过程中&#xff0c;我们常常会遇到一些问题&#xff0c;其中之一就是电脑运行软件时提示找不到msvcr120.dll。如果该文件缺失或损坏&#xff0c;可能会导致依赖它的应用程序无法启…

大聪明教你学Java | 深入浅出聊 RocketMQ

前言 &#x1f34a;作者简介&#xff1a; 不肯过江东丶&#xff0c;一个来自二线城市的程序员&#xff0c;致力于用“猥琐”办法解决繁琐问题&#xff0c;让复杂的问题变得通俗易懂。 &#x1f34a;支持作者&#xff1a; 点赞&#x1f44d;、关注&#x1f496;、留言&#x1f4…

一、课程介绍,基础—环境安装、判断、循环语句等(爬虫及数据可视化)

一、课程介绍&#xff0c;基础—环境安装、判断、循环语句等&#xff08;爬虫及数据可视化&#xff09; 1. 课程介绍1.1 相关内容1.2 学习目标1.3 学习内容安排 2. python2.1 环境配置2.2 标识符和关键字2.3 运算符2.4 判断语句2.5 循环语句 1. 课程介绍 1.1 相关内容 10天的…

Node.js安装及配置

文章目录 1.安装Node.js2.创建目录3.配置环境变量4.配置全局安装路径和缓存路径(可选)配置Webstorm 1.安装Node.js https://registry.npmmirror.com/binary.html?pathnode 推荐安装18.x版本 2.创建目录 下载解压后进入目录&#xff0c;创建node_global和node_cache两个空文…