【六 (2)机器学习-机器学习建模步骤/kaggle房价回归实战】

一、确定问题和目标:

1、业务需求分析:

与业务团队或相关利益方进行深入沟通,了解他们的需求和期望。
分析业务流程,找出可能的瓶颈、机会或挑战。
思考机器学习如何帮助解决这些问题或实现业务目标。

2、问题定义:

将业务需求转化为一个或多个具体的机器学习问题,例如分类、回归、聚类等。
定义问题的输入(特征)和输出(目标变量)。
明确问题的约束条件,如数据可用性、计算资源、时间限制等。

3、目标设定:

确定机器学习模型需要达到的性能指标,如准确率、召回率、F1值等。
根据业务需求,设定合理的性能阈值。
考虑模型的泛化能力,确保模型能在未知数据上表现良好。

4、数据可行性评估:

检查现有数据是否足够支持机器学习模型的训练和评估。
分析数据的质量和分布,确保数据能够反映问题的真实情况。
如果数据不足或质量不佳,考虑是否需要收集更多数据或进行数据增强。

5、资源评估:

评估可用的计算资源,如CPU、GPU和内存等,以确保能够支持模型的训练和推断。
考虑是否需要额外的工具或平台来支持建模过程,如数据预处理工具、机器学习框架等。

6、风险评估:

分析可能的风险和挑战,如数据泄露、模型过拟合、性能波动等。
制定应对策略,如加密数据、使用正则化技术、进行模型监控等。

二、数据收集:

1、明确数据需求

在开始收集数据之前,需要明确所需的数据类型、格式和数量。这取决于具体的应用场景和问题。

2、选择数据来源

数据可以从多种渠道收集,包括公共数据集、网站爬虫、传感器数据、数据库等。确保所选的数据源与问题和目标紧密相关。

3、考虑数据质量和完整性

在收集数据时,要特别注意数据的准确性和可靠性。确保数据的完整性和一致性,避免数据缺失或异常值。

三、EDA

EDA(Exploratory Data Analysis)即探索性数据分析,EDA通过可视化、统计和图形化的方法,对数据集进行全面的、非形式化的初步分析,帮助分析人员了解数据的基本特征,发现数据中的规律和模式。这有助于获取对数据的直观感受和深刻理解,为后续的数据处理和建模提供基础。

1、查看数据基本信息

# 查看数据基本信息
train_df.info()

2、查看每个特征的含义

SalePrice: 房产销售价格,以美元计价。所要预测的目标变量
MSSubClass: Identifies the type of dwelling involved in the sale 住所类型
MSZoning: The general zoning classification 区域分类
LotFrontage: Linear feet of street connected to property 房子同街道之间的距离
LotArea: Lot size in square feet 建筑面积
Street: Type of road access 主路的路面类型
Alley: Type of alley access 小道的路面类型
LotShape: General shape of property 房屋外形
LandContour: Flatness of the property 平整度
Utilities: Type of utilities available 配套公用设施类型
LotConfig: Lot configuration 配置
LandSlope: Slope of property 土地坡度
Neighborhood: Physical locations within Ames city limits 房屋在埃姆斯市的位置
Condition1: Proximity to main road or railroad 附近交通情况
Condition2: Proximity to main road or railroad (if a second is present) 附近交通情况(如果同时满足两种情况)
BldgType: Type of dwelling 住宅类型
HouseStyle: Style of dwelling 房屋的层数
OverallQual: Overall material and finish quality 完工质量和材料
OverallCond: Overall condition rating 整体条件等级
YearBuilt: Original construction date 建造年份
YearRemodAdd: Remodel date 翻修年份
RoofStyle: Type of roof 屋顶类型
RoofMatl: Roof material 屋顶材料
Exterior1st: Exterior covering on house 外立面材料
Exterior2nd: Exterior covering on house (if more than one material) 外立面材料2
MasVnrType: Masonry veneer type 装饰石材类型
MasVnrArea: Masonry veneer area in square feet 装饰石材面积
ExterQual: Exterior material quality 外立面材料质量
ExterCond: Present condition of the material on the exterior 外立面材料外观情况
Foundation: Type of foundation 房屋结构类型
BsmtQual: Height of the basement 评估地下室层高情况
BsmtCond: General condition of the basement 地下室总体情况
BsmtExposure: Walkout or garden level basement walls 地下室出口或者花园层的墙面
BsmtFinType1: Quality of basement finished area 地下室区域质量
BsmtFinSF1: Type 1 finished square feet Type 1完工面积
BsmtFinType2: Quality of second finished area (if present) 二次完工面积质量(如果有)
BsmtFinSF2: Type 2 finished square feet Type 2完工面积
BsmtUnfSF: Unfinished square feet of basement area 地下室区域未完工面积
TotalBsmtSF: Total square feet of basement area 地下室总体面积
Heating: Type of heating 采暖类型
HeatingQC: Heating quality and condition 采暖质量和条件
CentralAir: Central air conditioning 中央空调系统
Electrical: Electrical system 电力系统
1stFlrSF: First Floor square feet 第一层面积
2ndFlrSF: Second floor square feet 第二层面积
LowQualFinSF: Low quality finished square feet (all floors) 低质量完工面积
GrLivArea: Above grade (ground) living area square feet 地面以上部分起居面积
BsmtFullBath: Basement full bathrooms 地下室全浴室数量
BsmtHalfBath: Basement half bathrooms 地下室半浴室数量
FullBath: Full bathrooms above grade 地面以上全浴室数量
HalfBath: Half baths above grade 地面以上半浴室数量
Bedroom: Number of bedrooms above basement level 地面以上卧室数量
KitchenAbvGr: Number of kitchens 厨房数量
KitchenQual: Kitchen quality 厨房质量
TotRmsAbvGrd: Total rooms above grade (does not include bathrooms) 总房间数(不含浴室和地下部分)
Functional: Home functionality rating 功能性评级
Fireplaces: Number of fireplaces 壁炉数量
FireplaceQu: Fireplace quality 壁炉质量
GarageType: Garage location 车库位置
GarageYrBlt: Year garage was built 车库建造时间
GarageFinish: Interior finish of the garage 车库内饰
GarageCars: Size of garage in car capacity 车壳大小以停车数量表示
GarageArea: Size of garage in square feet 车库面积
GarageQual: Garage quality 车库质量
GarageCond: Garage condition 车库条件
PavedDrive: Paved driveway 车道铺砌情况
WoodDeckSF: Wood deck area in square feet 实木地板面积
OpenPorchSF: Open porch area in square feet 开放式门廊面积
EnclosedPorch: Enclosed porch area in square feet 封闭式门廊面积
3SsnPorch: Three season porch area in square feet 时令门廊面积
ScreenPorch: Screen porch area in square feet 屏风门廊面积
PoolArea: Pool area in square feet 游泳池面积
PoolQC: Pool quality 游泳池质量
Fence: Fence quality 围栏质量
MiscFeature: Miscellaneous feature not covered in other categories 其它条件中未包含部分的特性
MiscVal: $Value of miscellaneous feature 杂项部分价值
MoSold: Month Sold 卖出月份
YrSold: Year Sold 卖出年份
SaleType: Type of sale 出售类型
SaleCondition: Condition of sale 出售条件

3、查看目标变量分布

plt.figure()
sns.distplot(train_df['SalePrice'])
plt.title('SalePrice分布')
plt.show()

在这里插入图片描述

# 计算峰度和偏度
# - Kurtosis=0 与正态分布的陡缓程度相同
# - Kurtosis>0 比正态分布的高峰陡峭——尖顶峰
# - Kurtosis<0 比正态分布的高峰平缓——平顶峰
# - Skewness=0 分布形态与正态分布偏度相同
# - Skewness>0 正偏差数值较大,为正偏或右偏。长尾巴拖在右边
# - Skewness<0 负偏差数值较大,为负偏或左偏。长尾巴拖在左边
print('峰度(Kurtosis): ', train_df['SalePrice'].kurt())
print('偏度(Skewness): ', train_df['SalePrice'].skew())
峰度(Kurtosis):  6.536281860064529
偏度(Skewness):  1.8828757597682129

4、查看定量变量分布

先取出定量变量

# 特征变量按照数据类型分成定量变量和定性变量
quantitative = [feature for feature in train_df.columns if train_df.dtypes[feature] != 'object'] # 定量变量
quantitative.remove('Id')
quantitative.remove('SalePrice')
print('定量变量')
print(quantitative)
qualitative = [feature for feature in train_df.columns if train_df.dtypes[feature] == 'object'] # 定性变量
print('定性变量')
print(qualitative)
m_cont = pd.melt(train_df, value_vars=quantitative)
g = sns.FacetGrid(m_cont, col='variable', col_wrap=4, sharex=False, sharey=False)
g.map(sns.distplot, 'value')

在这里插入图片描述

5、查看定量变量与目标变量的关系

m_cont = pd.melt(train_df, id_vars='SalePrice', value_vars=quantitative)
g = sns.FacetGrid(m_cont, col='variable', col_wrap=4, sharex=False, sharey=True)
g.map(plt.scatter, 'value', 'SalePrice')

在这里插入图片描述

6、查看定性变量对目标变量的显著性影响程度

目标变量的显著性影响程度对机器学习建模有重要影响。这涉及到特征选择(feature selection)和特征工程(feature engineering)的过程。

特征选择是选择对目标变量具有显著影响的特征,以便在建模过程中仅使用最相关的特征。如果一个特征对目标变量的显著性影响较高,那么将其包含在模型中可能会提供更好的预测能力。

def anova(frame, qualitative):
    anv = pd.DataFrame()
    anv['feature'] = qualitative
    p_vals = []
    for fea in qualitative:
        samples = []
        cls = frame[fea].unique() # 变量的类别值
        for c in cls:
            c_array = frame[frame[fea]==c]['SalePrice'].values
            samples.append(c_array)
        p_val = stats.f_oneway(*samples)[1] # 获得p值,p值越小,对SalePrice的显著性影响越大
        p_vals.append(p_val)
    anv['pval'] = p_vals
    return anv.sort_values('pval')
a = anova(train_df, qualitative)
a['disparity'] = np.log(1./a['pval'].values) # 对SalePrice的影响悬殊度
plt.figure(figsize=(8, 6))
sns.barplot(x='feature', y='disparity', data=a)
plt.xticks(rotation=90)
plt.show()

在这里插入图片描述

7、查看定性变量与目标变量的spearman相关系数

Spearman相关系数是一种用于衡量两个变量之间的单调关系的非参数统计指标。与皮尔逊相关系数不同,Spearman相关系数不要求变量之间的关系是线性的,而是可以捕捉到任何单调的关系,包括非线性的关系。

Spearman相关系数的取值范围为-1到1。以下是对Spearman相关系数取值的一般解释:

  • 当Spearman相关系数为-1时,表示变量之间存在完全的负相关关系。即,当一个变量增加时,另一个变量会完全减小,并且变量之间的关系可以通过一个单调递减函数来描述。
  • 当Spearman相关系数为0时,表示变量之间不存在单调关系。即,一个变量的值的变化并不意味着另一个变量的值会发生变化。
  • 当Spearman相关系数为1时,表示变量之间存在完全的正相关关系。即,当一个变量增加时,另一个变量会完全增加,并且变量之间的关系可以通过一个单调递增函数来描述。

Spearman相关系数是基于变量的排序顺序进行计算的,而不是直接使用原始变量的值。对于定性变量(也称为分类变量),它们通常没有直接可比较的数值关系。例如,一个定性变量可能是颜色,有"红"、"绿"和"蓝"等等取值,这些取值之间没有明确的大小关系。因此,为了能够计算Spearman相关系数,我们需要将定性变量转换为数值表示。编码定性变量可以为每个不同的取值分配一个数值标签,使得不同的取值之间存在一种排序关系。常见的编码方法包括使用整数编码、独热编码(One-Hot Encoding)等。

def encode(frame, feature):
    ordering = pd.DataFrame()
    ordering['val'] = frame[feature].unique()
    ordering.index = ordering['val']
    ordering['spmean'] = frame[[feature, 'SalePrice']].groupby(feature)['SalePrice'].mean()
    ordering = ordering.sort_values('spmean')
    ordering['ordering'] = np.arange(1, ordering.shape[0]+1)
    ordering = ordering['ordering'].to_dict() # 返回的数据样例{category1:1, category2:2, ...}

    # 对frame[feature]编码
    for category, code_value in ordering.items():
        frame.loc[frame[feature]==category, feature+'_E'] = code_value
qual_encoded = []
for qual in qualitative:
    encode(train_df, qual)
    qual_encoded.append(qual+'_E')
print(qual_encoded)
#  计算特征变量与房价的spearman相关系数
def spearman(frame, features):
    spr =  pd.DataFrame()
    spr['feature'] = features
    spr['spearman'] = [frame[f].corr(frame['SalePrice'], 'spearman') for f in features]
    spr = spr.sort_values('spearman')

    plt.figure(figsize=(6, 0.25*len(features)))
    sns.barplot(x='spearman', y='feature', data=spr)
spearman(train_df, quantitative+qual_encoded)

在这里插入图片描述

四、数据预处理

1、数据清洗

包括去除异常值、处理缺失数据、处理样本不平衡等。例如,缺失值可以通过填充均值、中位数或特定值来处理;异常值可以通过阈值法、IQR法等方法识别和处理。

异常值处理

查看异常值

train = pd.read_csv('train.csv')
test = pd.read_csv('test.csv')
plt.figure(figsize=(12,6))
plt.scatter(train['GrLivArea'], train['SalePrice'])
plt.xlabel('GrLivArea')
plt.ylabel('SalePrice')
plt.title('GrLivArea与SalePrice散点图,观察异常值')
plt.grid(b=True, ls=':')
plt.show()

异常值较少,选择删除

# 删除两个离群点
train.drop(train[(train.GrLivArea>4000) & (train.SalePrice<200000)].index, inplace=True)
# 合并训练集和测试集,便于同时对两个数据集进行数据清洗和特征工程
full = pd.concat([train, test], axis=0, ignore_index=True)
train.shape, test.shape, full.shape
缺失值处理

查看每个特征的缺失情况

def audit_missing_values(df):  
    audit_result = {}  
    for col in df.columns:  
        count = df[col].isnull().sum()  
        ratio = count / len(df) if len(df) > 0 else 0  
        audit_result[col] = {'缺失数量': count, '缺失百分比': ratio}  
    return audit_result

audit_missing_values(full)
中位数填充

房子同街道之间的距离,按照建筑面积分为10块,用每块的中位数填充

full['LotAreaCut'] = pd.qcut(full['LotArea'], 10)
full.groupby(['LotAreaCut', 'Neighborhood'])['LotFrontage'].agg(['count', 'mean', 'median'])
full['LotFrontage'] = full.groupby(['LotAreaCut', 'Neighborhood'])['LotFrontage'].transform(lambda x: x.fillna(x.median()))
# 由于某些分组没有数据,因此未填补的缺失值单独利用LotAreaCut填充
full['LotFrontage'] = full.groupby(['LotAreaCut'])['LotFrontage'].transform(lambda x: x.fillna(x.median()))
None填充

游泳池质量、车库质量、车库条件是类型特征,可以用None填充

cols = ["PoolQC" , "MiscFeature", "Alley", "Fence", "FireplaceQu", "GarageQual", "GarageCond", "GarageFinish", "GarageYrBlt", "GarageType", "BsmtExposure", "BsmtCond", "BsmtQual", "BsmtFinType2", "BsmtFinType1", "MasVnrType"]
for col in cols:
    full[col] = full[col].fillna('None')
0填充

装饰石材面积、地下室区域未完工面积缺失时可视为0

cols2 = ["MasVnrArea", "BsmtUnfSF", "TotalBsmtSF", "GarageCars", "BsmtFinSF2", "BsmtFinSF1", "GarageArea"]
for col in cols2:
    full[col] = full[col].fillna(0)
众数填充

区域分类、地下室全浴室数量、功能性评级类似特征可以用众数填充

cols3 = ["MSZoning", "BsmtFullBath", "BsmtHalfBath", "Utilities", "Functional", "Electrical", "KitchenQual", "SaleType","Exterior1st", "Exterior2nd"]
for col in cols3:
    full[col] = full[col].fillna(full[col].mode()[0])
默认值填充
full['GarageYrBlt'] = full['GarageYrBlt'].replace(['', ' ', 'None'], np.nan)
full['GarageYrBlt'] = full['GarageYrBlt'].fillna(-1)
full.GarageYrBlt    
确认填充结果
full.isnull().sum()[full.isnull().sum()>0] # 缺失值填补完毕

只有SalePrice 有缺失,这是正常的,因为测试集没有SalePrice值

2、特征归一化

将数据特征缩放到同一尺度上,使得不同特征的权重相当,便于模型处理。

3、离散特征编码

对于类别型数据,可以通过独热编码、标签编码等方式将其转换为数值型数据。

有序编码
# 定义映射函数
def map_values(df):
    df['MSSubClass'] = df['MSSubClass'].map({180:1,
                                             30:2, 45:2,
                                             190:3, 50:3, 90:3, 
                                             85:4, 40:4, 160:4, 
                                             70:5, 20:5, 75:5, 80:5, 150:5,
                                             120: 6, 60:6})

    df['MSZoning'] = df['MSZoning'].map({'C (all)':1, 'RM':2, 'RH':2, 'RL':3, 'FV':4})

    df['Neighborhood'] = df['Neighborhood'].map({'MeadowV':1,
                                               'IDOTRR':2, 'BrDale':2,
                                               'OldTown':3, 'Edwards':3, 'BrkSide':3,
                                               'Sawyer':4, 'Blueste':4, 'SWISU':4, 'NAmes':4,
                                               'NPkVill':5, 'Mitchel':5,
                                               'SawyerW':6, 'Gilbert':6, 'NWAmes':6,
                                               'Blmngtn':7, 'CollgCr':7, 'ClearCr':7, 'Crawfor':7,
                                               'Veenker':8, 'Somerst':8, 'Timber':8,
                                               'StoneBr':9,
                                               'NoRidge':10, 'NridgHt':10})

    df['HouseStyle'] = df['HouseStyle'].map({'1.5Unf':1, 
                                           '1.5Fin':2, '2.5Unf':2, 'SFoyer':2, 
                                           '1Story':3, 'SLvl':3,
                                           '2Story':4, '2.5Fin':4})

    df['MasVnrType'] = df['MasVnrType'].map({'BrkCmn':1, 'None':1, 'BrkFace':2, 'Stone':3})

    df['ExterQual'] = df['ExterQual'].map({'Po':1, 'Fa':2, 'TA':3, 'Gd':4, 'Ex':5})

    df['ExterCond'] = df['ExterCond'].map({'Po':1, 'Fa':2, 'TA':3, 'Gd':4, 'Ex':5})

    df['Foundation'] = df['Foundation'].map({'Slab':1, 'BrkTil':2, 'CBlock':2, 'Stone':2, 'Wood':3, 'PConc':4})

    df['BsmtQual'] = df['BsmtQual'].map({'None':1, 'Po':2, 'Fa':3, 'TA':4, 'Gd':5, 'Ex':6})

    df['BsmtCond'] = df['BsmtCond'].map({'None':1, 'Po':2, 'Fa':3, 'TA':4, 'Gd':5, 'Ex':6})

    df['BsmtExposure'] = df['BsmtExposure'].map({'None':1, 'No':2, 'Mn':3, 'Av':4, 'Gd':5})

    df['BsmtFinType1'] = df['BsmtFinType1'].map({'None':1, 'Unf':2, 'LwQ':3, 'Rec':4, 'BLQ':5, 'ALQ':6, 'GLQ':7})

    df['BsmtFinType2'] = df['BsmtFinType2'].map({'None':1, 'Unf':2, 'LwQ':3, 'Rec':4, 'BLQ':5, 'ALQ':6, 'GLQ':7})

    df['HeatingQC'] = df['HeatingQC'].map({'Po':1, 'Fa':2, 'TA':3, 'Gd':4, 'Ex':5})

    df['KitchenQual'] = df['KitchenQual'].map({'Po':1, 'Fa':2, 'TA':3, 'Gd':4, 'Ex':5})

    df['Functional'] = df['Functional'].map({'Maj2':1, 'Maj1':2, 'Min1':2, 'Min2':2, 'Mod':2, 'Sev':2, 'Typ':3})

    df['FireplaceQu'] = df['FireplaceQu'].map({'None':1, 'Po':2, 'Fa':3, 'TA':4, 'Gd':5, 'Ex':6})

    df['GarageFinish'] = df['GarageFinish'].map({'None':1, 'Unf':2, 'RFn':3, 'Fin':4})

    df['GarageQual'] = df['GarageQual'].map({'None':1, 'Po':2, 'Fa':3, 'TA':4, 'Gd':5, 'Ex':6})

    df['GarageCond'] = df['GarageCond'].map({'None':1, 'Po':2, 'Fa':3, 'TA':4, 'Gd':5, 'Ex':6})

    df['PavedDrive'] = df['PavedDrive'].map({'N':1, 'P':2, 'Y':3})

    df['PoolQC'] = df['PoolQC'].map({'None':1, 'Fa':2, 'TA':3, 'Gd':4, 'Ex':5})

    df['Fence'] = df['Fence'].map({'None':1, 'MnWw':2, 'GdWo':3, 'MnPrv':4, 'GdPrv':5})

# 有序特征编码
map_values(full)
标签编码
lab = LabelEncoder()
full['YearBuilt'] = lab.fit_transform(full['YearBuilt'])
full['YearRemodAdd'] = lab.fit_transform(full['YearRemodAdd'])
full['GarageYrBlt'] = lab.fit_transform(full['GarageYrBlt'])
对数变换
full.drop(['SalePrice', 'Id'], axis=1, inplace=True)
# 数据做一备份
full_fe = full.copy()
# 对于偏度大于1的定量变量进行对数变换
full_numeric = full_fe.select_dtypes(exclude='object')
skew = full_numeric.apply(lambda x: x.skew())
skew_features = skew[abs(skew) >= 1].index
full_fe[skew_features] = np.log1p(full_fe[skew_features])

4、连续特征离散化

将连续型特征划分为不同的区间或类别,有助于处理非线性关系或简化模型。

5、特征缩放

特征缩放在机器学习中是一种常见的预处理步骤,它对特征数据进行线性变换,使得特征值落入特定的范围或分布,以便更好地满足模型的要求和优化算法的性质。并非所有机器学习算法都对特征缩放敏感,例如决策树和随机森林等基于树的算法通常不需要特征缩放。然而,对于许多线性模型、支持向量机、神经网络等模型,特征缩放通常是一个重要的步骤,有助于提升模型的性能和稳定性。

scaler = RobustScaler()
# 分离训练集和测试集
n_train = train.shape[0]
train_X = full_fe[:n_train]
test_X = full_fe[n_train:]
train_y = train['SalePrice']
# 区间缩放
# 注意事项:不能分别对训练集和测试集训练与转换,应该在训练集上训练,在测试集上转换
train_X = scaler.fit_transform(train_X)
test_X = scaler.transform(test_X)
train_y = np.log(train_y)
# robustscaler
scaler = RobustScaler()
train_X = scaler.fit_transform(train_X)
test_X = scaler.transform(test_X)
train_y = np.log(train_y)
train_X[:5]

5、特征选择

从原始特征中选择对模型有用的特征,去除冗余特征,提高模型效果。这可以通过基于统计的方法(如卡方检验、互信息法等)或基于模型的方法(如决策树、随机森林的特征重要性评分)来实现。

通过Lasso回归模型选择特征
lasso = Lasso(alpha=0.001)
lasso.fit(train_X, train_y)
Lasso(alpha=0.001, copy_X=True, fit_intercept=True, max_iter=1000,
   normalize=False, positive=False, precompute=False, random_state=None,
   selection='cyclic', tol=0.0001, warm_start=False)
lasso_fi = pd.DataFrame({'feature_importance':lasso.coef_}, index=full_fe.columns)
lasso_fi.sort_values('feature_importance', ascending=False)
plt.figure()
lasso_fi[lasso_fi['feature_importance'] != 0].sort_values('feature_importance').plot(kind='barh', figsize=(12, 25))
plt.grid()
plt.show()

6、特征构造

根据业务领域或数据背景,人工构造新的特征。例如,在电商领域,可以构造用户购买频率、购买间隔等特征。又比如从时间特征衍生出日/周/月/年/季度特征。

增加特征
def add_feature(X):
    X['TotalHouse'] = X['TotalBsmtSF'] + X['1stFlrSF'] + X['2ndFlrSF']
    X['TotalArea'] = X['TotalBsmtSF'] + X['1stFlrSF'] + X['2ndFlrSF'] + X['GarageArea']
    X['TotalQuality'] = X['OverallQual'] + X['OverallCond']

    X['TotalHouse_OverallQual'] = X['TotalHouse'] * X['OverallQual']
    X['GrLivArea_OverallQual'] = X['GrLivArea'] * X['OverallQual']
    X['MSZoning_TotalHouse'] = X['MSZoning'] * X['TotalHouse']
    X['MSZoning_OverallQual'] = X['MSZoning'] + X['OverallQual']
    X['MSZoning_YearBuilt'] = X['MSZoning'] + X['YearBuilt']
    X['Neighborhood_TotalHouse'] = X['Neighborhood'] * X['TotalHouse']
    X['Neighborhood_OverallQual'] = X['Neighborhood'] + X['OverallQual']
    X['Neighborhood_YearBuilt'] = X['Neighborhood'] + X['YearBuilt']
    X['BsmtFinSF1_OverallQual'] = X['BsmtFinSF1'] * X['OverallQual']
    X['Functional_TotalHouse'] = X['Functional'] * X['TotalHouse']
    X['Functional_OverallQual'] = X['Functional'] + X['OverallQual']
    X['LotArea_OverallQual'] = X['LotArea'] * X['OverallQual']
    X['LotArea_TotalHouse'] = X['LotArea'] + X['TotalHouse']

    X['Bsmt'] = X['BsmtFinSF1'] + X['BsmtFinSF2'] + X['BsmtUnfSF']
    X['PorchArea'] = X['OpenPorchSF'] + X['EnclosedPorch'] + X['3SsnPorch'] + X['ScreenPorch']

    X['TotalPlace'] = X['TotalArea'] + X['PorchArea']
# 获取原数据
full_fe1 = full.copy()
 
full_fe1.shape
# 增加特征
add_feature(full_fe1)

full_fe1.shape
# 数据转换
full_numeric1 = full_fe1.select_dtypes(exclude='object')
skew1 = full_numeric1.apply(lambda x: x.skew())
skew_features1 = skew1[abs(skew1) >= 1].index
full_fe1[skew_features1] = np.log1p(full_fe1[skew_features1])
# one-hot编码
full_fe1 = pd.get_dummies(full_fe1)
full_fe1.shape

7、特征降维

当特征维度过高时,可能导致模型复杂度增加、计算成本上升以及过拟合等问题。特征降维旨在减少特征数量,同时保留尽可能多的有用信息。常用的方法包括主成分分析(PCA)、线性判别分析(LDA)等。

pca = PCA(n_components=205)
train_X = pca.fit_transform(train_X)
test_X = pca.transform(test_X)
train_X.shape, test_X.shape

五、模型选择

1、理解问题类型

首先,需要明确问题的类型,是分类、回归还是聚类等。这决定了选择哪种类型的机器学习模型。

该问题为回归

2、考虑数据特性

数据的规模、分布和特征等都会影响模型的选择。例如,对于大规模数据集,可能需要选择计算效率更高的模型;对于非线性关系的数据,可能需要选择能够处理复杂关系的模型。

3、选择常用模型

根据问题的类型和数据的特性,可以选择一些常用的模型进行尝试,如线性回归、逻辑回归、决策树、随机森林、支持向量机等。

4、考虑集成学习和深度学习

对于复杂的问题,可以考虑使用集成学习或深度学习模型。集成学习可以通过结合多个模型的预测结果来提高性能,而深度学习可以处理大规模和高维度的数据。

六、模型训练

1、数据准备

将经过预处理的数据划分为训练集、验证集和测试集。训练集用于训练模型,验证集用于调整模型的超参数,测试集用于评估模型的性能。

# 分离训练集和测试集
n_train = train.shape[0]
train_X = full_fe1[:n_train]
test_X = full_fe1[n_train:]
train_y = train.SalePrice
train_X.shape, test_X.shape, train_y.shape

2、模型初始化

选择好模型后,需要进行初始化,包括设置模型的参数和结构等。

models = [LinearRegression(),Ridge(),Lasso(alpha=0.01,max_iter=10000),RandomForestRegressor(),GradientBoostingRegressor(),SVR(),LinearSVR(),
          ElasticNet(alpha=0.001,max_iter=10000),SGDRegressor(max_iter=1000,tol=1e-3),BayesianRidge(),KernelRidge(alpha=0.6, kernel='polynomial', degree=2, coef0=2.5),
          ExtraTreesRegressor(),XGBRegressor()]
names = ["LR", "Ridge", "Lasso", "RF", "GBR", "SVR", "LinSVR", "Ela","SGD","Bay","Ker","Extra","Xgb"]
cv_results = []
for name, model in zip(names, models):
    score = rmse_cv(model, train_X, train_y)
    cv_results.append(score)
    print('%s: %f (%f)' % (name, score.mean(), score.std()))
LR: 20981998087.207458 (36234568672.259140)
Ridge: 0.118677 (0.004891)
Lasso: 0.124334 (0.006086)
RF: 0.136326 (0.006123)
GBR: 0.129313 (0.005787)
SVR: 0.143337 (0.012095)
LinSVR: 0.121567 (0.005950)
Ela: 0.113721 (0.004883)
SGD: 0.133089 (0.009391)
Bay: 0.113197 (0.004988)
Ker: 0.110177 (0.005107)
Extra: 0.132725 (0.006600)
Xgb: 0.146359 (0.005729)

3、训练模型

使用训练集对模型进行训练。在训练过程中,模型会学习数据的特征和规律,并不断优化自身的参数以减小预测误差。

4、验证和调整

使用验证集对训练好的模型进行验证,并根据验证结果调整模型的超参数。这个过程可能需要进行多次迭代,以找到最优的超参数组合。

七、模型评估

1、选择评估指标

根据问题的类型和需求,选择合适的评估指标。对于分类问题,常用的评估指标包括准确率、精确率、召回率和F1分数等。对于回归问题,常用的指标有均方误差(MSE)、均方根误差(RMSE)和决定系数(R2)等。

回归模型,这里选择rmse作为评价指标

def rmse_cv(model, X, y):
    rmse = np.sqrt(-cross_val_score(model, X, y, scoring='neg_mean_squared_error', cv=5))
    return rmse

2、计算评估指标

使用测试集对模型进行预测,并根据预测结果计算评估指标。确保测试集与训练集和验证集完全独立,以准确评估模型的泛化能力。

# 创建模型并训练
models = [LinearRegression(),Ridge(),Lasso(alpha=0.01,max_iter=10000),RandomForestRegressor(),GradientBoostingRegressor(),SVR(),LinearSVR(),
          ElasticNet(alpha=0.001,max_iter=10000),SGDRegressor(max_iter=1000,tol=1e-3),BayesianRidge(),KernelRidge(alpha=0.6, kernel='polynomial', degree=2, coef0=2.5),
          ExtraTreesRegressor(),XGBRegressor()]
names = ["LR", "Ridge", "Lasso", "RF", "GBR", "SVR", "LinSVR", "Ela","SGD","Bay","Ker","Extra","Xgb"]
cv_results = []
for name, model in zip(names, models):
    score = rmse_cv(model, train_X, train_y)
    cv_results.append(score)
    print('%s: %f (%f)' % (name, score.mean(), score.std()))

3、解读评估结果

分析评估指标的值,了解模型在不同方面的性能表现。例如,准确率可以反映模型整体预测正确的比例,而精确率和召回率则可以帮助了解模型在不同类别上的表现。

LR: 0.116180 (0.005230)
Ridge: 0.115855 (0.005188)
Lasso: 0.124334 (0.006086)
RF: 0.134958 (0.007572)
GBR: 0.128602 (0.004423)
SVR: 0.142950 (0.011931)
LinSVR: 0.116312 (0.004945)
Ela: 0.113806 (0.004936)
SGD: 0.134785 (0.007010)
Bay: 0.113186 (0.005027)
Ker: 0.110572 (0.004634)
Extra: 0.132237 (0.006353)
Xgb: 0.139968 (0.005361)

从结果看核岭回归表现最好,平均值为0.110572,标准差为0.004634

八、模型验证

1、交叉验证

采用交叉验证方法,如k折交叉验证,来评估模型的稳定性和泛化能力。将数据集分成k个子集,每次使用k-1个子集进行训练,剩下的一个子集进行验证。重复这个过程k次,得到k个验证结果,最后取平均值作为最终的评估结果。

def rmse_cv(model, X, y):
    rmse = np.sqrt(-cross_val_score(model, X, y, scoring='neg_mean_squared_error', cv=5))
    return rmse
# 创建模型并训练
models = [LinearRegression(),Ridge(),Lasso(alpha=0.01,max_iter=10000),RandomForestRegressor(),GradientBoostingRegressor(),SVR(),LinearSVR(),
          ElasticNet(alpha=0.001,max_iter=10000),SGDRegressor(max_iter=1000,tol=1e-3),BayesianRidge(),KernelRidge(alpha=0.6, kernel='polynomial', degree=2, coef0=2.5),
          ExtraTreesRegressor(),XGBRegressor()]
names = ["LR", "Ridge", "Lasso", "RF", "GBR", "SVR", "LinSVR", "Ela","SGD","Bay","Ker","Extra","Xgb"]
cv_results = []
for name, model in zip(names, models):
    score = rmse_cv(model, train_X, train_y)
    cv_results.append(score)
    print('%s: %f (%f)' % (name, score.mean(), score.std()))

2、绘制学习曲线

通过绘制学习曲线,可以观察模型随着训练样本数量的增加,其性能的变化趋势。这有助于判断模型是否存在过拟合或欠拟合的问题。

3、比较不同模型

如果有多个候选模型,可以通过比较它们在测试集上的评估指标,选择性能最优的模型。

LR: 0.116180 (0.005230)
Ridge: 0.115855 (0.005188)
Lasso: 0.124334 (0.006086)
RF: 0.134958 (0.007572)
GBR: 0.128602 (0.004423)
SVR: 0.142950 (0.011931)
LinSVR: 0.116312 (0.004945)
Ela: 0.113806 (0.004936)
SGD: 0.134785 (0.007010)
Bay: 0.113186 (0.005027)
Ker: 0.110572 (0.004634)
Extra: 0.132237 (0.006353)
Xgb: 0.139968 (0.005361)

从结果看核岭回归表现最好,平均值为0.110572,标准差为0.004634

九、模型优化

1、理解超参数

超参数是模型训练前需要设定的参数,如学习率、正则化系数、树的数量等。它们对模型的性能有很大影响。

2、网格搜索与随机搜索

使用网格搜索或随机搜索来系统地探索超参数空间,找到最佳的超参数组合。

def grid(model, X, y, params):
    grid_search = GridSearchCV(model, params, scoring='neg_mean_squared_error', cv=5)
    grid_search.fit(X, y)
    print(grid_search.best_params_, np.sqrt(-grid_search.best_score_))
params_lasso = {'alpha': [0.0004,0.0005,0.0007,0.0009], 'max_iter':[10000]}
grid(Lasso(), train_X, train_y, params_lasso)
params_lasso = {'alpha': [0.0004,0.0005,0.0007,0.0009], 'max_iter':[10000]}
grid(Lasso(), train_X, train_y, params_lasso)
params_svr = {'C':[11,13,15],'kernel':["rbf"],"gamma":[0.0003,0.0004],"epsilon":[0.008,0.009]}
grid(SVR(), train_X, train_y, params_svr)
params_ker = {'alpha':[0.2,0.3,0.4], 'kernel':["polynomial"], 'degree':[3],'coef0':[0.8,1]}
grid(KernelRidge(), train_X, train_y, params_ker)
params_ela = {'alpha':[0.0008,0.004,0.005],'l1_ratio':[0.08,0.1,0.3],'max_iter':[10000]}
grid(ElasticNet(), train_X, train_y, params_ela)

使用搜索后的参数重新训练模型

lasso = Lasso(alpha=0.0009, max_iter=10000)
ridge = Ridge(alpha=65)
svr = SVR(C=15, epsilon=0.009, gamma= 0.0004, kernel='rbf')
ker = KernelRidge(alpha=0.4, coef0=1, degree=3, kernel='polynomial')
ela = ElasticNet(alpha=0.005,l1_ratio=0.1,max_iter=10000)
bay = BayesianRidge()

3、贝叶斯优化

对于复杂的模型,如深度学习模型,贝叶斯优化是一种有效的超参数调整方法。

十、模型融合

1、平均融合

将多个模型的预测结果进行加权平均或简单平均,以得到最终的预测结果。对于分类问题,还可以将预测结果转化为概率分布后再求平均。这种方法的优点是简单易实现,不需要训练额外的模型,但缺点是每个模型都被平等对待,无法充分利用模型之间的差异性。

class AverageWeight(BaseEstimator, RegressorMixin):
    def __init__(self, mods, weight):
        self.mods = mods
        self.weight = weight

    def fit(self, X, y):
        self.models_ = [clone(x) for x in self.mods]
        for model in self.models_:
            model.fit(X, y)
        return self

    def predict(self, X):
        results = [model.predict(X) for model in self.models_]
        # 各个模型预测结果加权平均
        pre = np.dot(np.array(self.weight), np.array(results))
        return pre
model_weight = [0.05, 0.2, 0.3, 0.35, 0.03, 0.07]
models = [lasso, ridge, svr, ker, ela, bay]
avg_w = AverageWeight(models, model_weight)
avg_score = rmse_cv(avg_w, train_X, train_y)
print(avg_score.mean())
0.1090625412907696
avg_w2.fit(train_X, train_y)
y_pred = np.exp(avg_w2.predict(test_X))
result = pd.DataFrame({'Id':test['Id'], 'SalePrice':y_pred})
result.to_csv('submission_avg.csv', index=False)

2、投票融合

对于分类问题,每个模型都给出一个预测结果,最终预测结果取多数投票。这也是一种简单直接的方法,能够综合考虑多个模型的意见。

3、堆叠融合

这是一种更为复杂的融合方式,将多个模型的预测结果作为输入,再训练一个元模型来得到最终的预测结果。这种方法能够充分利用各个模型的优点,但训练过程相对复杂,且可能增加过拟合的风险。

class stacking(BaseEstimator, RegressorMixin):
    def __init__(self, base_models, stack_model):
        self.base_models = base_models
        self.stack_model = stack_model
        self.kf = KFold(n_splits=5, random_state=42, shuffle=True)

    def fit(self, X, y):
        # 注:这里要把数据转换成数组类型,避免传入的数据不是数组类型时报错
        X = np.array(X)
        y = np.array(y)

        self.saved_models = [list() for model in self.base_models]
        oof_train = np.zeros((X.shape[0], len(self.base_models)))
        for i, model in enumerate(self.base_models):
            for train_idx, val_idx in self.kf.split(X, y):
                fit_model = clone(model)            
                fit_model.fit(X[train_idx], y[train_idx])
                self.saved_models[i].append(fit_model)
                oof_train[val_idx, i] = fit_model.predict(X[val_idx])

        self.stack_model.fit(oof_train, y)
        return self

    def predict(self, X):
        X = np.array(X)
        oof_test = np.zeros((X.shape[0], len(self.base_models)))

        for i, model in enumerate(self.saved_models):
            model_pred = np.column_stack([fit_model.predict(X) for fit_model in model])
            oof_test[:, i] = model_pred.mean(1)

        return self.stack_model.predict(oof_test)


stack_model = stacking(base_models=[lasso, ridge, svr, ker, ela, bay], stack_model=ker)
stack_score = rmse_cv(stack_model, train_X, train_y)
print(stack_score.mean())
0.1081483570026502
stack_model.fit(train_X, train_y)
stack_pred =np.exp(stack_model.predict(test_X))
result_s = pd.DataFrame({'Id':test['Id'], 'SalePrice':stack_pred})
result_s.to_csv('submmision_stack.csv', index=False)

十一、完整代码

通过百度网盘分享的文件:房价预测-回归算…
链接:https://pan.baidu.com/s/1NCHAgKefth5BTuGyPNmDYA?pwd=4349
提取码:4349
复制这段内容打开「百度网盘APP 即可获取」

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

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

相关文章

四种IP地址的区别

动态IP、固定IP、实体IP和虚拟IP是计算机网络中常见的IP地址类型&#xff0c;它们在分配方式、稳定性、应用场景等方面存在显著的差异。下面将详细阐述这四种IP地址的区别。 首先&#xff0c;动态IP地址是一种临时分配给设备或主机的可变IP地址。每次设备连接到网络时&#xf…

4.2作业

使用模板类&#xff0c;实现顺序栈 #include <iostream> #include <iomanip>using namespace std;template <typename T>class stack{public:T *data;T top;T MAXsizeof;//操作函数stack(int buf 100); //栈的建立bool push(const T a); //出栈bool pop(); …

rhce复习1

虚拟机初始化配置 bash 1、安装系统&#xff0c;选择对应的linux版本&#xff0c;阿里云镜像站点、163镜像站点等等 2、装好系统后&#xff0c;先配置网络&#xff1a;ip地址&#xff0c;掩码&#xff0c;网关&#xff0c;dns域名解析服务器 [rootlocalhost ~]# nmtui [rootlo…

3.写一个char类型的字符数组,对该数组访问越界时抛出异常,并做处理。

#include <iostream>using namespace std;char arr[10]"12345678"; void show(int i) {if(i>10){throw int(2);}cout << arr[i] <<endl; } int main() {int i;cin >> i;try {show(i);} catch (int) {cout << "越界" <…

SSM框架学习——工厂模式、Spring核心容器与Bean

工厂模式、核心容器与Spring Bean 工厂模式 工厂模式是Java中常用的一种设计模式&#xff0c;这种类型的设计模式属于创建型模式。说白了在代码层面就是取消了new的使用。 工厂模式有三种&#xff1a; 简单工厂模式工厂方法模式抽象工厂模式 举个例子&#xff0c;我们去买…

无缝投屏技巧:怎样将Windows电脑屏幕共享到安卓手机?

使用屏幕共享技术的好处是多方面的。首先&#xff0c;它为远程协助提供了极大的便利。当用户遇到电脑操作难题时&#xff0c;技术支持人员可以远程查看用户的屏幕&#xff0c;实时指导解决问题&#xff0c;就像他们身临其境一样。其次&#xff0c;这种技术也为教育和培训带来了…

时序预测 | Python实现VMD-CNN-LSTM时间序列预测

时序预测 | Python实现VMD-CNN-LSTM时间序列预测 目录 时序预测 | Python实现VMD-CNN-LSTM时间序列预测预测效果基本介绍模型描述代码设计预测效果 基本介绍 VMD-CNN-LSTM 是一种混合深度学习模型,结合了变分模态分解(VMD)、卷积神经网络(CNN)和长短期记忆网络(LSTM)的…

C#中值类型与引用类型的存储

目录 值对象与引用对象的存储 引用对象的成员存储 值对象与引用对象的存储 数据项的类型定义了存储数据需要的内存大小及组成该类型的数据成员。类型还决定了对象在内存中的存储位置——栈或堆。 C#中类型分为两种&#xff1a;值类型和引用类型&#xff0c;这两种类型的对象…

“省钱有道”的太平鸟,如何真正“高飞”?

衣食住行产业中&#xff0c;服装品类消费弹性较大、可选属性较强&#xff0c;其发展可以显著反映当前的经济温度。 根据国家统计局数据&#xff0c;2023年1-12月&#xff0c;我国限额以上单位服装类商品零售额累计10352.9亿元&#xff0c;同比增长15.4%&#xff0c;增速比2022…

LLMs之DBRX:DBRX的简介、安装和使用方法、案例应用之详细攻略

LLMs之DBRX&#xff1a;DBRX的简介、安装和使用方法、案例应用之详细攻略 导读&#xff1a;2024年3月27日(美国时间)&#xff0c;DBRX是Databricks推出的一款新型开源大语言模型&#xff0c;主要特征和优势总结如下&#xff1a; >> 表现优异&#xff1a;DBRX在各类自然语…

Pixelmator Pro:专业级图像编辑,触手可及mac/win版

Pixelmator Pro是一款功能强大的图像编辑软件&#xff0c;专为Mac操作系统设计。它拥有直观的界面和丰富的工具&#xff0c;能够满足用户各种图像处理需求。 Pixelmator Pro软件获取 首先&#xff0c;Pixelmator Pro支持多种文件格式&#xff0c;包括JPEG、PNG、GIF、BMP、TIF…

投稿指南【NO.12_9】【极易投中】核心期刊投稿(现代电子技术)

近期有不少同学咨询投稿期刊的问题&#xff0c;大部分院校的研究生都有发学术论文的要求&#xff0c;少部分要求高的甚至需要SCI或者多篇核心期刊论文才可以毕业&#xff0c;但是核心期刊要求论文质量高且审稿周期长&#xff0c;所以本博客梳理一些计算机特别是人工智能相关的期…

算法第三十八天-故障键盘

故障键盘 题目要求 解题思路 提示&#xff1a;把反转看成是往字符串的头部添加字符。 具体来说&#xff1a; 如果当前处于「往字符串尾部添加字符」的状态&#xff0c;那么遇到 i 后&#xff0c;改成「往字符串头部添加字符」的状态。 如果当前处于「往字符串头部添加字符」…

基于8086贪吃蛇游戏系统方恨设计

**单片机设计介绍&#xff0c;基于8086贪吃蛇游戏系统方恨设计 文章目录 一 概要二、功能设计三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于8086的贪吃蛇游戏系统设计是一个结合了微处理器控制、游戏逻辑以及图形显示技术的综合性项目。该系统旨在通过8086微处理器…

n2.堆栈

1.堆栈的介绍 表达式求值 因为不同的符号优先级不同&#xff0c;所以计算起来相对困难一些 后缀表达式 这里后缀表达式就用到了堆栈。它先从左向右进行扫描&#xff0c;碰到运算数就记住&#xff0c;碰到运算符就将离着这个运算符最近的两个运算数进行运算… 堆栈是一种储存方…

六、从零实战企业级K8S本地部署ThingsBoard专业版集群

1、从 docker hub 拉取 ThingsBoard PE 映像&#xff08;所有节点&#xff09; 1.1、查看k8s信息&#xff08;主节点&#xff09; kubectl cluster-info #查看k8s集群信息 kubectl get node #查看节点信息 kubectl get pod -A #查看内部组件1.2、从 d…

Docker:探索容器化技术,重塑云计算时代应用交付与管理

一&#xff0c;引言 在云计算时代&#xff0c;随着开发者逐步将应用迁移至云端以减轻硬件管理负担&#xff0c;软件配置与环境一致性问题日益凸显。Docker的横空出世&#xff0c;恰好为软件开发者带来了全新的解决方案&#xff0c;它革新了软件的打包、分发和管理方式&#xff…

【C++第二阶段】继承多态电脑组装实例

你好你好&#xff01; 以下内容仅为当前认识&#xff0c;可能有不足之处&#xff0c;欢迎讨论&#xff01; 文章目录 继承继承语法继承方式继承中的对象模型继承中构造和析构顺序同名成员处理同名静态成员处理多继承语法菱形继承问题 多态多态基本概念重写&重载 多态原理多…

中仕公考:不同省事业编考试内容一样吗?

在各省份的事业单位公开招聘过程中&#xff0c;考试内容是不一样的。虽然每一年都有很多省份参加事业编联考&#xff0c;且这些联考的考试日期相同&#xff0c;但是考试内容并不一样。各省将依据当地的特定情况来设计考试题目&#xff0c;其中会涉及到与本省的地理、经济、文化…

文章分享:《呼吸道传染病标本采集及检测专家共识》

【摘要】呼吸道传染病临床特点多表现为发热和&#xff08;或&#xff09;呼吸道症状&#xff0c;病原学组成复杂&#xff0c;标本类型选择多样&#xff0c;如何从发热伴呼吸道症候群患者中早期正确识别出潜在呼吸道传染病患者是防控的关键环节。增强医务人员对呼吸道传染病临床…