IT评测·应用市场-qidao123.com技术社区
标题:
深入探索Python呆板学习算法:(加州房价预测)XGBoost 与贝叶斯优化驱动的
[打印本页]
作者:
罪恶克星
时间:
2025-3-8 18:00
标题:
深入探索Python呆板学习算法:(加州房价预测)XGBoost 与贝叶斯优化驱动的
深入探索Python呆板学习算法:(加州房价预测)XGBoost 与贝叶斯优化驱动的鲁棒性集成模子
一、弁言
在房地产市场分析和预测范畴,准确预测房价不停是研究的热门和难点。加州作为美国经济发达且房地产市场活泼的地区,其房价受到多种因素的综合影响,如地理位置、房屋特性、周边配套等。通过呆板学习方法构建房价预测模子,可以资助投资者、购房者和政策制定者更好地了解市场动态,做出公道的决策。
本文将详细介绍一个基于Python实现的加州房价预测全流程模子,涵盖数据加载与预处理、特性工程、特性选择、超参数调优、模子训练、评估以及可视化等多个关键步骤。通过对这些步骤的深入分析,我们可以了解如何运用呆板学习技能解决实际的房价预测问题,并学习到一些实用的本事和方法。
数据文件
20640条数据
longitude经度
latitude纬度
housing_median_age住房年龄中位数
total_rooms总房间数
total_bedrooms总卧室数
population人口数
households家庭数
median_income收入中位数
median_house_value房屋价值中位数
ocean_proximity海洋邻近性
复制代码
二、环境预备与依靠库介绍
2.1 环境预备
在开始实现加州房价预测模子之前,我们必要搭建相应的Python环境。建议利用Anaconda来管理Python环境和安装依靠库,由于Anaconda提供了丰富的科学计算和数据分析库,而且可以方便地创建和管理虚拟环境。
以下是创建和激活虚拟环境的命令:
conda create -n housing_prediction python=3.8
conda activate housing_prediction
复制代码
我用的Pycharm,但是用jupyter notebook会方便操作
2.2 依靠库介绍
本项目利用了多个Python库,下面临这些库的功能和作用进行简要介绍:
NumPy
:是Python中用于科学计算的底子库,提供了高效的多维数组对象和各种数学函数,可用于处理和计算大规模的数值数据。
Pandas
:是一个强大的数据处理和分析库,提供了DataFrame和Series等数据结构,方便进行数据的读取、洗濯、转换和分析。
Matplotlib
:是Python中常用的绘图库,可用于创建各种静态、交互式的图表,如折线图、柱状图、散点图等。
Seaborn
:是基于Matplotlib的高级数据可视化库,提供了更美观、更简洁的绘图风格和接口,能够快速创建高质量的统计图表。
SHAP
:是一个用于解释呆板学习模子预测效果的库,通过计算特性的SHAP值,可以直观地了解每个特性对模子预测效果的影响水平。
Joblib
:是Python中用于并行计算和持久化的库,可用于生存和加载呆板学习模子,方便模子的复用和部署。
Scikit-learn
:是Python中最常用的呆板学习库,提供了丰富的呆板学习算法和工具,如数据预处理、特性选择、模子训练、评估等。
XGBoost
:是一个高效的梯度提升库,在呆板学习角逐和实际应用中都有广泛的应用,具有快速、准确、可扩展性强等优点。
Bayes_opt
:是一个用于贝叶斯优化的库,可用于自动调整呆板学习模子的超参数,提高模子的性能。
以下是安装这些依靠库的命令:
requirements.txt
numpy==2.1.3
pandas==2.2.3
matplotlib==3.10.1
seaborn==0.13.2
shap==0.47.0
joblib==1.4.2
scikit-learn==1.6.1
xgboost==2.1.4
bayes_opt==2.0.3
复制代码
pip install -r requirements.txt
三、数据加载与预处理
3.1 数据加载
在代码中,我们利用pandas库的read_csv函数从CSV文件中加载加州房价数据集。数据加载部门的代码如下:
def load_data(self) -> pd.DataFrame:
"""数据加载与预处理"""
try:
df = pd.read_csv(DATA_PATHS["raw_data"])
logger.info(" 初始数据行数: %d", len(df))
# 数据校验
expected_cols = ['longitude', 'latitude', 'housing_median_age', 'total_rooms',
'total_bedrooms', 'population', 'households', 'median_income',
'median_house_value', 'ocean_proximity']
if list(df.columns) != expected_cols:
raise ValueError(f"CSV列名不匹配,期待顺序:{expected_cols}")
# 处理异常值(动态分位数)
df = self._handle_outliers(df)
logger.info(" 异常值处理后行数: %d", len(df))
# 填补缺失值
df = self._impute_missing(df)
logger.info(" 缺失值填补后行数: %d", len(df))
return df
except Exception as e:
logger.error(" 数据加载失败: %s", str(e))
raise
复制代码
在数据加载过程中,我们起首记录了初始数据的行数,然后对数据的列名进行了校验,确保数据的列名与预期一致。如果列名不匹配,将抛出ValueError异常。
3.2 异常值处理
异常值是指数据会合与其他数据点显着不同的值,可能会对模子的训练和预测效果产生负面影响。在本项目中,我们利用动态分位数的方法处理房价的异常值。详细来说,我们计算房价的0.01和0.99分位数,然后过滤掉低于0.01分位数和高于0.99分位数的数据点。异常值处理部门的代码如下:
def _handle_outliers(self, df: pd.DataFrame) -> pd.DataFrame:
"""动态异常值处理"""
# 房价过滤(基于分位数)
price_q_low = df['median_house_value'].quantile(0.01)
price_q_high = df['median_house_value'].quantile(0.99)
df = df[(df['median_house_value'] >= price_q_low) &
(df['median_house_value'] <= price_q_high)]
return df
复制代码
3.3 缺失值填补
数据会合可能存在缺失值,必要进行填补处理。在本项目中,我们利用IterativeImputer进行多重填补,该方法基于迭代的方式,通过创建一个回归模子来预测缺失值。详细来说,我们利用RandomForestRegressor作为估计器,将max_iter参数从默认的10增长到20,以解决收敛问题。同时,我们还添加了维度检查,确保填补后的数据维度与原始数据维度一致。缺失值填补部门的代码如下:
def _impute_missing(self, df: pd.DataFrame) -> pd.DataFrame:
"""高级缺失值填补(关键修正部分)"""
if df['total_bedrooms'].isnull().sum() > 0:
logger.info(" 检测到缺失值,开始多重填补...")
# 修正1:增加迭代次数解决收敛问题
imputer = IterativeImputer(
estimator=RandomForestRegressor(n_estimators=50),
max_iter=20, # 从10增加到20
random_state=42
)
# 修正2:添加维度检查
imputed_values = imputer.fit_transform(
df[['total_bedrooms', 'total_rooms', 'households']]
)
# 检查维度一致性
if imputed_values.shape[0] != df.shape[0]:
logger.error(" 填补维度不匹配: 输入数据%d行,输出%d行",
df.shape[0], imputed_values.shape[0])
raise ValueError("填补维度不一致")
# 修正3:正确维度转换
df['total_bedrooms'] = imputed_values[:, 0]
logger.info(" 缺失值填补完成,剩余缺失值数量: %d",
df['total_bedrooms'].isnull().sum())
return df
复制代码
四、特性工程
特性工程是呆板学习中非常告急的一步,它可以通过对原始数据进行转换和组合,提取出更有价值的特性,从而提高模子的性能。在本项目中,我们进行了以下几个方面的特性工程:
4.1 底子特性构建
我们计算了每个家庭的房间数和每个房间的卧室数,以反映房屋的居住密度和空间利用环境。为了防止除零错误,我们对total_rooms和total_bedrooms进行了处理。底子特性构建部门的代码如下:
# 防止除零错误
df['total_rooms'] = df['total_rooms'].replace(0, 1e-6)
df['total_bedrooms'] = df['total_bedrooms'].clip(lower=0.1)
# 基础特征
df['rooms_per_household'] = df['total_rooms'] / df['households']
df['bedrooms_per_room'] = df['total_bedrooms'] / df['total_rooms']
复制代码
4.2 地理特性计算
地理位置是影响房价的告急因素之一。我们利用Haversine公式计算每个房屋到旧金山的距离,作为地理特性。地理特性计算部门的代码如下:
def _add_geo_features(self, df: pd.DataFrame) -> pd.DataFrame:
"""精确地理特征计算"""
san_francisco_coord = (37.7749, -122.4194)
R = 6371 # 地球半径(千米)
lat1 = np.radians(df['latitude'])
lon1 = np.radians(df['longitude'])
lat2, lon2 = np.radians(san_francisco_coord[0]), np.radians(san_francisco_coord[1])
dlon = lon2 - lon1
dlat = lat2 - lat1
a = np.sin(dlat / 2) ** 2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon / 2) ** 2
c = 2 * np.arctan2(np.sqrt(a), np.sqrt(1 - a))
df['dist_to_sf_km'] = R * c
return df
复制代码
4.3 分箱处理
分箱处理是将连续变量离散化的一种方法,可以减少数据的噪声和异常值的影响。我们利用KBinsDiscretizer对房屋的中位年事进行分箱处理,将其分为5个等级。分箱处理部门的代码如下:
def _binning_features(self, df: pd.DataFrame) -> pd.DataFrame:
"""安全分箱处理"""
try:
binner = KBinsDiscretizer(n_bins=5, encode='ordinal', strategy='quantile')
df['housing_age_bin'] = binner.fit_transform(
df[['housing_median_age']]
).astype(int)
except ValueError as e:
logger.warning("分箱失败: %s,使用原始特征", str(e))
return df
复制代码
4.4 分类变量编码
数据会合的ocean_proximity是一个分类变量,我们利用pandas的get_dummies函数对其进行独热编码,将其转换为数值特性。分类变量编码部门的代码如下:
# 分类变量编码
return pd.get_dummies(df, columns=['ocean_proximity'], drop_first=True)
复制代码
五、特性选择
特性选择是从原始特性中选择出最相关、最有价值的特性,以减少特性维度,提高模子的训练效率和泛化本领。在本项目中,我们利用递归特性消除(Recursive Feature Elimination,RFE)方法进行特性选择。详细来说,我们利用RFECV类,以XGBRegressor作为估计器,通过交织验证选择最优的特性子集。特性选择部门的代码如下:
def feature_selection(self, X: pd.DataFrame, y: pd.Series) -> pd.DataFrame:
"""递归特征消除(带异常处理)"""
try:
self.feature_selector = RFECV(
estimator=XGBRegressor(),
step=1,
cv=5,
scoring='neg_mean_absolute_error',
min_features_to_select=10
)
X_selected = self.feature_selector.fit_transform(X, y)
self.feature_names = X.columns[self.feature_selector.support_]
logger.info("特征选择完成,保留特征数:%d", len(self.feature_names))
return X_selected
except Exception as e:
logger.error("特征选择失败: %s,使用原始特征", str(e))
return X.values
复制代码
六、超参数调优
超参数是呆板学习模子中必要手动设置的参数,不同的超参数组合会对模子的性能产生显著影响。在本项目中,我们利用贝叶斯优化方法对XGBRegressor的超参数进行调优。贝叶斯优化是一种基于概率模子的优化方法,通过不断地探索超参数空间,找到最优的超参数组合。超参数调优部门的代码如下:
def hyperparameter_tuning(self, X: np.ndarray, y: np.ndarray) -> Dict:
"""鲁棒的贝叶斯优化"""
def xgb_cv(max_depth, learning_rate, n_estimators, subsample):
params = {
'max_depth': int(round(max_depth)),
'learning_rate': max(learning_rate, 0.001),
'n_estimators': int(round(n_estimators)),
'subsample': max(min(subsample, 1), 0.1),
'eval_metric': 'mae'
}
try:
cv_scores = cross_val_score(
XGBRegressor(**params), X, y,
cv=5, scoring='neg_mean_absolute_error', n_jobs=-1
)
return cv_scores.mean()
except Exception as e:
logger.warning("参数调优失败: %s", str(e))
return -np.inf
optimizer = BayesianOptimization(
f=xgb_cv,
pbounds={
'max_depth': (3, 10),
'learning_rate': (0.01, 0.3),
'n_estimators': (100, 1000),
'subsample': (0.5, 1)
},
random_state=42,
allow_duplicate_points=True
)
# 移除不支持的参数设置
# optimizer.set_gp_params(n_jobs=-1)
optimizer.maximize(init_points=5, n_iter=5)
if not optimizer.res:
raise RuntimeError("贝叶斯优化失败,无有效结果")
self.best_params = optimizer.max['params']
logger.info("最佳参数:%s", self.best_params)
return self.best_params
复制代码
七、模子训练
在完成特性选择和超参数调优后,我们利用集成学习的方法训练一个堆叠模子(Stacking Model)。堆叠模子是一种将多个底子模子的预测效果作为输入,再通过一个元模子进行最终预测的模子。在本项目中,我们利用XGBRegressor和RandomForestRegressor作为底子模子,LassoCV作为元模子。模子训练部门的代码如下:
def train_stacking_model(self, X: np.ndarray, y: np.ndarray):
"""训练集成模型"""
try:
base_models = [
('xgb', XGBRegressor(**{
'max_depth': int(self.best_params['max_depth']),
'learning_rate': self.best_params['learning_rate'],
'n_estimators': int(self.best_params['n_estimators']),
'subsample': self.best_params['subsample']
})),
('rf', RandomForestRegressor(
n_estimators=200,
max_depth=8,
n_jobs=-1
))
]
self.model = StackingRegressor(
estimators=base_models,
final_estimator=LassoCV(cv=5),
cv=3,
n_jobs=-1
)
logger.info("开始训练Stacking模型...")
self.model.fit(X, y)
self._is_trained = True
return self.model
except Exception as e:
logger.error("模型训练失败: %s", str(e))
self._is_trained = False
raise
复制代码
八、模子评估
模子评估是衡量模子性能的告急步骤,通过计算不同的评估指标,我们可以了解模子的预测本领和泛化本领。在本项目中,我们利用以下几个评估指标来评估模子的性能:
匀称绝对偏差(MAE)
:预测值与真实值之间的匀称绝对偏差,反映了模子预测的匀称偏差水平。
均方根偏差(RMSE)
:预测值与真实值之间的均方根偏差,对异常值比力敏感,反映了模子预测的团体偏差水平。
决定系数(R²)
:体现模子对数据的拟合水平,取值范围为[0, 1],越靠近1体现模子拟合效果越好。
匀称绝对百分比偏差(MAPE)
:预测值与真实值之间的匀称绝对百分比偏差,反映了模子预测的相对偏差水平。
准确率(偏差≤20%)
:预测值与真实值之间的偏差在20%以内的样本占总样本的比例,反映了模子的预测准确性。
模子评估部门的代码如下:
def evaluate(self, y_true: np.ndarray, y_pred: np.ndarray) -> Dict:
"""综合模型评估"""
if not self._is_trained:
raise RuntimeError("模型未训练")
metrics = {
'MAE': mean_absolute_error(y_true, y_pred),
'RMSE': np.sqrt(mean_squared_error(y_true, y_pred)),
'R²': r2_score(y_true, y_pred),
'MAPE': mean_absolute_percentage_error(y_true, y_pred),
'准确率(误差≤20%)': np.mean(np.abs((y_pred - y_true) / y_true) <= 0.2) * 100
}
复制代码
九、运行效果
MAE: 28651.010141975672
RMSE: 44915.080348747775
R²: 0.8543913449901033
MAPE: 0.1496618109522733
准确率(误差≤20%): 76.40009782342871
示例预测结果:171846.38 vs 真实值:178100.00
复制代码
可以调参重新运利用模子准确率更高(
本文只给出了部门代码
)
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/)
Powered by Discuz! X3.4