当前位置:   article > 正文

python机器学习 波士顿房价预测 详细教程 数据集+源码+结果图+远程部署_波士顿房价数据集

波士顿房价数据集

项目数据集+源码+部署:python机器学习 波士顿房价预测 详细教程 源码+结果图+远程部署

目录

数据集

导包

导入数据集

数据处理

配置流水线

分割训练集和测试集

自定义模型

模型训练

验证

特征重要性

特征选择

网格搜索

结果可视化 


数据集

波士顿房价数据集(Boston Housing Dataset)是一个非常著名的数据集,广泛用于回归分析和机器学习的入门研究。它最初由哈里森和鲁宾菲尔德(Harrison, D. and Rubinfeld, D.L.)在1978年发布,包含了波士顿地区房价的中位数与各种影响房价的因素。

这个数据集包含506个数据点,每个数据点有14个属性。具体属性如下:

  1. CRIM:城镇人均犯罪率。
  2. ZN:住宅用地超过25000 sq.ft. 的比例。
  3. INDUS:城镇非零售商用土地的比例。
  4. CHAS:查尔斯河虚拟变量(如果边界是河流,则为1;否则为0)。
  5. NOX:一氧化氮浓度(每千万份)。
  6. RM:住宅平均房间数。
  7. AGE:1940年之前建成的自用房屋比例。
  8. DIS:到五个波士顿就业中心的加权距离。
  9. RAD:辐射性公路的接近指数。
  10. TAX:每10000美元的全值财产税率。
  11. PTRATIO:城镇师生比例。
  12. B:1000(Bk - 0.63)^2 其中Bk为城镇中黑人的比例。
  13. LSTAT:人口中地位较低人群的百分比。
  14. MEDV:自有住房的中位数价值(单位:千美元)。

导包

我们首先导入需要的所有数据库、模型库、评价函数等。

  1. # 导入包
  2. import warnings
  3. import lightgbm as lgb
  4. import matplotlib.pyplot as plt
  5. import numpy as np
  6. import pandas as pd
  7. import shap
  8. import sklearn
  9. from sklearn.base import BaseEstimator, TransformerMixin
  10. from sklearn.ensemble import RandomForestRegressor
  11. from sklearn.metrics import mean_squared_error
  12. from sklearn.metrics import r2_score
  13. from sklearn.model_selection import GridSearchCV
  14. from sklearn.model_selection import train_test_split
  15. from sklearn.pipeline import Pipeline
  16. warnings.filterwarnings('ignore')

导入数据集

注意:
过去大多数情况下会直接用这种方式加载数据集,目前因为1.2版本以后就删除

了数据集,有两种解决方案(1.直接下载数据集.2.降低版本)

报错: 

ImportError: 
`load_boston` has been removed from scikit-learn since version 1.2.

我们才采用直接下载数据集到本地的方法来加载数据集

boston = pd.read_csv('data.csv')

 将数据集换分为X,Y.

  1. # 假设最后一列是目标变量
  2. X = boston.iloc[:, 1:-1] # 所有行,除了最后一列的所有列
  3. y = boston.iloc[:, -1] # 所有行,只有最后一列
  4. # 把 X 和 y 转换为 DataFrame
  5. X = pd.DataFrame(X)
  6. y = pd.DataFrame(y)
  7. # 打印信息查看
  8. print(X)
  9. print(y)

对特征进行重新命名

X.columns = list(map(lambda x: 'feature' + str(x), X.columns))

数据处理

  1. cate_cols = [] # 离散特征
  2. num_cols = [] # 数值型特征
  3. # 获取各个特征的数据类型
  4. dtypes = X.dtypes
  5. for col, dtype in dtypes.items():
  6. if dtype == 'object':
  7. cate_cols.append(col)
  8. else:
  9. num_cols.append(col)

数值型特征

  1. class Num_Encoder(BaseEstimator, TransformerMixin):
  2. def __init__(self, cols=[], fillna=False, addna=False):
  3. self.fillna = fillna
  4. self.cols = cols
  5. self.addna = addna
  6. self.na_cols = []
  7. self.imputers = {}
  8. def fit(self, X, y=None):
  9. for col in self.cols:
  10. if self.fillna:
  11. self.imputers[col] = X[col].median()
  12. if self.addna and X[col].isnull().sum():
  13. self.na_cols.append(col)
  14. print(self.na_cols, self.imputers)
  15. return self
  16. def transform(self, X, y=None):
  17. df = X.loc[:, self.cols]
  18. for col in self.imputers:
  19. df[col].fillna(self.imputers[col], inplace=True)
  20. for col in self.na_cols:
  21. df[col + '_na'] = pd.isnull(df[col])
  22. return df

离散型特征

  1. class Cat_Encoder(BaseEstimator, TransformerMixin):
  2. def __init__(self, cols, max_n_cat=7, onehot_cols=[], orders={}):
  3. self.cols = cols
  4. self.onehot_cols = onehot_cols
  5. self.cats = {}
  6. self.max_n_cat = max_n_cat
  7. self.orders = orders
  8. def fit(self, X, y=None):
  9. df_cat = X.loc[:, self.cols]
  10. for n, c in df_cat.items():
  11. df_cat[n].fillna('NAN', inplace=True)
  12. df_cat[n] = c.astype('category').cat.as_ordered()
  13. if n in self.orders:
  14. df_cat[n].cat.set_categories(self.orders[n], ordered=True, inplace=True)
  15. cats_count = len(df_cat[n].cat.categories)
  16. if cats_count <= 2 or cats_count > self.max_n_cat:
  17. self.cats[n] = df_cat[n].cat.categories
  18. if n in self.onehot_cols:
  19. self.onehot_cols.remove(n)
  20. elif n not in self.onehot_cols:
  21. self.onehot_cols.append(n)
  22. print(self.onehot_cols)
  23. return self
  24. def transform(self, df, y=None):
  25. X = df.loc[:, self.cols]
  26. for col in self.cats:
  27. X[col].fillna('NAN', inplace=True)
  28. X.loc[:, col] = pd.Categorical(X[col], categories=self.cats[col], ordered=True)
  29. X.loc[:, col] = X[col].cat.codes
  30. if len(self.onehot_cols):
  31. df_1h = pd.get_dummies(X[self.onehot_cols], dummy_na=True)
  32. df_drop = X.drop(self.onehot_cols, axis=1)
  33. return pd.concat([df_drop, df_1h], axis=1)
  34. return X

配置流水线

  1. num_pipeline = Pipeline([
  2. ('num_encoder', Num_Encoder(cols=num_cols, fillna='median', addna=True)),
  3. ])
  4. X_num = num_pipeline.fit_transform(X)
  5. cat_pipeline = Pipeline([
  6. ('cat_encoder', Cat_Encoder(cols=cate_cols))
  7. ])
  8. X_cate = cat_pipeline.fit_transform(X)

分割训练集和测试集

我们将数据集分割为8:2, 80%作为训练集,20%作为测试集.

  1. y = np.log(y)
  2. X = pd.concat([X_num, X_cate], axis=1)
  3. print(X.shape, y.shape)
  4. X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=2022)
  5. print('训练集:', X_train.shape, y_train.shape)
  6. print('测试集:', X_test.shape, y_test.shape)

自定义模型

我们采用了LGB模型作为实例,之后我们会对其使用网格搜索找到最优的参数.

  1. lgbmodel = lgb.LGBMRegressor(boosting_type='gbdt',
  2. metric='mse',
  3. n_estimators=50,
  4. max_depth=3,
  5. lambda_l1=1e-5,
  6. lambda_l2=1e-3)

模型训练

lgbmodel.fit(X_train, y_train)

验证

  1. y_train_pred = lgbmodel.predict(X_train)
  2. y_test_pred = lgbmodel.predict(X_test)
  3. mse_train = mean_squared_error(y_train, y_train_pred)
  4. mse_test = mean_squared_error(y_test, y_test_pred)
  5. r2_score_train = r2_score(y_train, y_train_pred)
  6. r2_score_test = r2_score(y_test, y_test_pred)
  7. print('训练集的MSE: ', mse_train)
  8. print('测试集的MSE: ', mse_test)
  9. print('训练集的R2: ', r2_score_train)
  10. print('测试集的R2: ', r2_score_test)

 测试集明显差于训练集,模型的泛化性比较低,在训练集上过拟合了, 需要对其进行参数调参.

特征重要性

可以根据每个特征的重要性进行特征选择

  1. feature_importance = pd.DataFrame(lgbmodel.feature_importances_.reshape(X.shape[1], 1), index=list(X.columns),
  2. columns=['特征重要性'])
  3. print(feature_importance)

特征选择

  1. def feature_importance(lgbmodel, df):
  2. return pd.DataFrame({'cols': df.columns, 'importance': lgbmodel.feature_importances_}).sort_values('importance',
  3. ascending=False)
  4. features = feature_importance(lgbmodel, X_train)
  5. print(features)

特征选择的工具我们选用SHAP,SHAP 在波士顿房价预测中的特征选择中提供了一种强大且直观的方式来评估和理解各特征对模型预测的贡献,从而辅助我们做出更为明智的决策。通过使用 SHAP,我们可以在保持模型性能的同时,尽量简化模型,避免不必要的复杂性。

  1. shap.initjs()
  2. explainer = shap.TreeExplainer(lgbmodel)
  3. shap_values = explainer(X_train)
  4. shap.plots.waterfall(shap_values[0])

shap.plots.beeswarm(shap_values, max_display=10)

shap.plots.bar(shap_values, max_display=11)

最终我们选择了十个最重要的特征作为最终的数据集

  1. # 最好提交的特征,10个
  2. to_keep_final = ['feature12',
  3. 'feature5',
  4. 'feature0',
  5. 'feature4',
  6. 'feature10',
  7. 'feature7',
  8. 'feature11',
  9. 'feature6',
  10. 'feature9',
  11. 'feature3', ]
  12. X_train_final = X_train[to_keep_final].copy()

网格搜索

  1. lgbmodel = lgb.LGBMRegressor()
  2. rfrmodel = RandomForestRegressor()
  3. param_grid_lgb = {
  4. "n_estimators": np.arange(50, 300, 50),
  5. "learning_rate": [0.01, 0.05, 0.1, 0.3],
  6. 'lambda_l1': [1e-5, 1e-3, 1e-1],
  7. 'lambda_l2': [1e-5, 1e-3, 1e-1],
  8. 'max_bin': np.arange(5, 30, 10),
  9. 'num_leaves': np.arange(5, 20, 5),
  10. }
  11. param_grid_rfr = {
  12. "n_estimators": np.arange(50, 300, 50),
  13. "min_samples_leaf": np.arange(1, 101, 30),
  14. "max_depth": np.arange(2, 8, 2),
  15. "max_leaf_nodes": np.arange(5, 20, 5)
  16. }
  17. lgbmodel_grid = GridSearchCV(estimator=lgbmodel,
  18. param_grid=param_grid_lgb,
  19. verbose=1,
  20. n_jobs=-1,
  21. cv=2)
  22. rfrmodel_grid = GridSearchCV(estimator=rfrmodel,
  23. param_grid=param_grid_rfr,
  24. verbose=1,
  25. n_jobs=-1,
  26. cv=2)
  1. lgbmodel_grid.fit(X_train_final, y_train)
  2. rfrmodel_grid.fit(X_train_final, y_train)
  3. print('【LGB】', lgbmodel_grid.best_score_)
  4. print('【RFR】', rfrmodel_grid.best_score_)

  1. best_modellgb = lgb.LGBMRegressor(boosting_type='gbdt',
  2. objective='regression',
  3. colsample_bytree=1,
  4. metrics='mse',
  5. learning_rate=lgbmodel_grid.best_estimator_.get_params()['learning_rate'],
  6. n_estimators=lgbmodel_grid.best_estimator_.get_params()['n_estimators'],
  7. num_leaves=lgbmodel_grid.best_estimator_.get_params()['num_leaves'],
  8. max_bin=lgbmodel_grid.best_estimator_.get_params()['max_bin'],
  9. lambda_l1=lgbmodel_grid.best_estimator_.get_params()['lambda_l1'],
  10. lambda_l2=lgbmodel_grid.best_estimator_.get_params()['lambda_l2'])
  11. best_modelrfr = RandomForestRegressor(n_estimators=rfrmodel_grid.best_estimator_.get_params()['n_estimators'],
  12. min_samples_leaf=rfrmodel_grid.best_estimator_.get_params()['min_samples_leaf'],
  13. max_depth=rfrmodel_grid.best_estimator_.get_params()['max_depth'],
  14. max_leaf_nodes=rfrmodel_grid.best_estimator_.get_params()['max_leaf_nodes'])

best_modellgb.fit(X_train, y_train)

  1. y_train_pred = best_modellgb.predict(X_train)
  2. y_test_pred = best_modellgb.predict(X_test)
  3. mse_train = mean_squared_error(y_train, y_train_pred)
  4. mse_test = mean_squared_error(y_test, y_test_pred)
  5. r2_score_train = r2_score(y_train, y_train_pred)
  6. r2_score_test = r2_score(y_test, y_test_pred)
  7. print('训练集的MSE: ', mse_train)
  8. print('测试集的MSE: ', mse_test)
  9. print('训练集的R2: ', r2_score_train)
  10. print('测试集的R2: ', r2_score_test)

结果可视化 

  1. plt.rcParams['font.sans-serif'] = ['SimHei']
  2. plt.rcParams['axes.unicode_minus'] = False
  1. plt.figure(figsize=(12, 8))
  2. plt.plot(y_train.values, color='blue', label='真实值')
  3. plt.plot(y_train_pred, color='red', label='预测值')
  4. plt.title('训练集')
  5. plt.xlabel('data')
  6. plt.ylabel('price')
  7. plt.legend()
  8. plt.show()

  1. plt.figure(figsize=(12, 8))
  2. plt.plot(y_test.values, color='blue', label='真实值')
  3. plt.plot(y_test_pred, color='red', label='预测值')
  4. plt.title('测试集')
  5. plt.xlabel('data')
  6. plt.ylabel('price')
  7. plt.legend()
  8. plt.show()

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/841996
推荐阅读
相关标签
  

闽ICP备14008679号