ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

广州二手房房价预测:Python数据清洗与LightGBM回归建模全流程

广州二手房房价预测:Python数据清洗与LightGBM回归建模全流程 简介针对广州市二手房价预测这一典型数据分析场景该压缩包提供了一套由数据、代码与图表构成的完整示例项目。压缩包共十九个文件大小约1.05MB以一份Python预测脚本、一份广州二手房数据集和十七张可视化图片为主要内容结构清晰便于对照学习。代码部分涉及数据读取、缺失值处理、特征分析、模型训练与效果评估等关键流程调用Pandas、Scikit-learn等常用库完成十七张图表则从朝向、所在区域、面积、装修、楼层、建成时间等维度展示了数据分布与总价关系有助于直观理解特征对房价的影响。资源目前已有984人学习下载适合希望借助真实数据掌握房价预测全流程的Python数据分析初学者。解压后可直接运行脚本复用数据清洗与建模思路并进一步尝试特征筛选和参数优化。1. 广州二手房价预测用一份 rar 把「玄学估价」变成可复现的回归模型做二手房估价这件事中介靠经验和话术买家靠感觉和砍价其实本质上都是同一个需求——给一套房定一个「合理的价」。我拿到「广州市二手房价预测——数据python代码.rar」这个包第一反应是这题值得认真做它有明确的业务场景广州真实的挂牌房价、现成的数据文件、和一套可以改改就跑起来的 Python 代码正好把「预测房价」从拍脑袋变成可复现的回归任务。这个方向适合三类人想找笋盘的自住买家可以用模型把挂牌价和预测价做差筛漏房产相关从业者可以用它批量估价做市场复盘还有正在做数据挖掘项目或毕设的同学它给你一个完整的数据清洗、特征工程、建模评估链路不用从零攒数据和造轮子。这篇文章我就顺着这条线把数据怎么盘、特征怎么造、模型怎么调、哪些坑必踩完整过一遍。2. 数据怎么盘把挂牌数据从 Excel 洗成能喂给模型的特征表2.1 数据结构长什么样先看清楚每一列的含义再动手任何一份二手房价数据拿到的第一时间别急着跑模型先搞清楚这张表到底长什么样。常见的 rar 解压后是一个 CSV 或 Excel 文件加一个 ipynb 或 py 脚本数据列一般覆盖小区名称、所在行政区天河、海珠、越秀、番禺、黄埔、白云、荔湾、花都、南沙、增城、从化、户型几室几厅、建筑面积、单价、总价、朝向、楼层、楼龄、装修情况、挂牌时间、关注人数、带看次数。有些数据集还会带经纬度、到最近地铁站距离、周边学校医院数量这些衍生字段但这通常要自己做地理编码补齐原始文件里不一定有。先写一段代码把基础信息打印出来这在任何数据处理项目里都是第一步import pandas as pd # 如果解压出来是 xlsx 就用 pd.read_excel是 csv 就编码选 utf-8-sig df pd.read_excel(guangzhou_house_data.xlsx) # 核心摸底三件套 print(df.shape) # 行数、列数 print(df.columns.tolist())# 完整字段名 print(df.head(10).to_string()) # 前 10 行肉眼看数据质量 print(df.dtypes) # 看每列的类型是否被 Excel 的格式带偏这段代码没做任何加工只是把「数据长什么样」这个问题可视化。dtypes 这一步非常关键Excel 里常见的坑是数字列被读成文本、日期列变成字符串、金额里有逗号或单位这些都会在后面计算时报莫名其妙的错。接着统计每列的缺失率missing_df df.isnull().sum() missing_df missing_df[missing_df 0] / len(df) * 100 missing_df.sort_values(ascendingFalse)缺失率超过三成的列要慎重——要么放弃要么用「存在与否」做二值特征而不是硬把缺失值补成一个常数。比如「带看次数」这一列在热度高的区域里缺失可能代表少人看补 0 和补均值含义完全不同这个业务判断只能由你来定。2.2 缺失值、重复记录和「-1 层」三类脏数据的标准清理姿势二手房价数据是典型的多源整合结果脏得很有规律。最常见的有三类。第一类是重复记录。同一套房子在不同中介网站上挂牌会出现多次总价、户型、面积完全相同但挂牌时间可能有细微差异。判断重复不能用「小区名总面积」因为同一楼栋不同楼层的定价逻辑不同要用「小区户型面积朝向」四要素加总价重复且总价相同才值得怀疑subset [小区名称, 户型结构, 建筑面积, 朝向, 总价] df df.drop_duplicates(subsetsubset, keeplast) # 去重后顺手检查分布 print(df.shape) print(df[总价].describe())参数说明keeplast 表示保留同组中最后一条记录因为最后一条往往是最新挂牌、价格更接近业主真实预期子集列的粒度按你的数据字段调整但总价不能放进 subset因为同户型同面积也可能因楼层出现合理价差放进 total_price 会误删有效样本。第二类是「-1 层」「低层、中层、高层」这类文本楼层。先说地下室、车库改住房这种-1 层房价预测里我一般不直接剔除而是把楼层做一次映射floor_map {-1: -1, 低层: 1, 中层: 2, 高层: 3, 顶层: 4, 别墅: 0} df[floor_level] df[楼层].map(floor_map) # map 没匹配上的会变成 NaN打印出来看还剩哪些奇葩值 print(df[楼层].value_counts().tail(20)) print(df[floor_level].isnull().sum())逻辑说明低层中层高层本来就是模糊语义直接转数字后会丢失「相对位置」信息但作为回归特征已经够用。最关键的是 NaN 的检查——如果某些房源写着「共 30 层, 所在 25 层」就必须从这句话里拆出两个特征这种信息密度比「高层」高值得单独解析。第三类是总价和单价之间的常识矛盾。广州的房价水平下单价在 5 万与楼龄二十年的房子同时存在是合理的但「建筑面积 70 平、总价 9999 万」这种明显录入错误必须先过滤否则一个错误样本就能把模型训歪# 通过单价与总价的乘积关系反推建筑面积再和原始建筑面积对撞 df[calc_area] df[总价] / df[单价] df[area_error_ratio] (df[calc_area] - df[建筑面积]).abs() / df[建筑面积] # 误差超过 15% 的样本多半是字段填错 df df[df[area_error_ratio] 0.15]参数说明15% 这个阈值是经验值广州房产证面积和挂牌面积极少差超过 15%超过就说明其中一个字段录错了。做完这步再检查area_error_ratio的分布如果大量样本落在 10%-15% 区间说明原始数据里单价和总价本身就不互洽可能要回到来源端重抓。2.3 数据质量自查哪些房源该过滤哪些字段该留着做特征清理完显性脏数据还得做一遍业务层面的过滤。广州的二手房市场有明显「结构性异常」房源法拍房产权风险高、定价逻辑不同车位、商铺改住宅首层带花园的特殊户型以及楼龄超过 40 年没有电梯的老破小。它们不是数据错误但会严重干扰回归模型的稳定性因为它们的基本面价值逻辑完全不同。我的处理原则是——先看样本量如果异常房源占比小于 5%直接剔除如果超过 10%就加一个is_special二值特征而不是硬删。数据质量要可视化自查import matplotlib.pyplot as plt fig, axes plt.subplots(1, 3, figsize(15, 4)) df[单价].hist(bins50, axaxes[0]) axes[0].set_title(单价分布: 单峰才正常, 双峰说明混入了非住宅房源) df[建筑面积].hist(bins50, axaxes[1]) axes[1].set_title(面积分布: 200 平以上样本极少, 需要观察) df.groupby(行政区)[总价].median().plot.bar(axaxes[2]) axes[2].set_title(各区总价中位数: 异常高或异常低都要查明原因) plt.tight_layout() plt.savefig(eda_qc.png, dpi150)这段代码输出的三张图基本能看出数据能不能继续用。单价分布出现双峰常见原因是把车位和住宅混在了一张表里——车位单价低但总价高拉出的形态完全不一样。面积分布右侧长尾太长说明有些「超大户型」其实是别墅或者办公产权这类样本要么剔除要么单独标注。各区中位数如果出现前面前 3 名的区不如后面几个区要查是不是行政区字段有别名——「天河」和「天河区」在原始数据里常被写成了两个值这必须做一次字段归并。提示这一步做完数据的行数和列数你自己要心里有数。后面所有特征工程都建立在这张「干净表」上如果这时候就发现原始数据只有两三百行我的建议是别硬做回归了直接用统计描述出报告样本量撑不起机器学习模型。3. 特征工程与模型选型为什么广州房价不适合跑线性回归3.1 从地址解析到位置特征用 haversine 计算地铁站距离原始数据里如果有「地址」或「小区名」位置信息可以说是房价预测里信息量最大的一层。广州的房价跟交通结构强相关同样的面积和楼龄珠江新城地铁站旁和从化城区郊单价能差 3 到 5 倍只看面积和户型根本解释不了。如果原始数据自带经纬度直接用它做距离计算如果只有小区名就需要地理编码的步骤。常见做法是调用高德或百度地图 API把小区名转成经纬度再算到地铁站的距离。依赖外部 API 的和已经固定经纬度的情况分开处理没有坐标就用不了直接方案。我自己会先看数据集里有没有线经度列没有就写一个简单的补全逻辑import math # 广州主要地铁站点经纬度时效性检查后再补全这里只做示范 subway_stations [ {name: 体育西路, lat: 23.1357, lon: 113.3212}, {name: 珠江新城, lat: 23.1200, lon: 113.3185}, {name: 公园前, lat: 23.1260, lon: 113.2660}, ] def haversine(lat1, lon1, lat2, lon2): R 6371.0 phi1, phi2 math.radians(lat1), math.radians(lat2) dphi math.radians(lat2 - lat1) dlambda math.radians(lon2 - lon1) a math.sin(dphi / 2)**2 math.cos(phi1) * math.cos(phi2) * math.sin(dlambda / 2)**2 return 2 * R * math.asin(math.sqrt(a)) def nearest_subway_distance(lat, lon): if pd.isna(lat) or pd.isna(lon): return None return min(haversine(lat, lon, s[lat], s[lon]) for s in subway_stations) df[地铁距离] df.apply(lambda r: nearest_subway_distance(r[纬度], r[经度]), axis1)逻辑说明haversine 公式用来算球面两点距离单位是公里广州主城区范围不大用这个公式已经够精确不需要引入地理库加重依赖。地铁站点列表是静态的只列出几个核心站做演示——实际做的时候要把广州所有已运营站点加进列表数据量大概在两百个级别不会对性能造成压力。参数说明距离小于 0.3 公里和距离 3 公里以上的房源预测误差表现完全不同这个数字可直接作为后续特征交叉的依据——「地铁距离 × 行政区」的组合特征常常比单独距离列对模型提升更明显。3.2 房价不是只跟面积有关构造小区梯度特征和楼龄分段广州房产市场有一个明显特征小区与小区之间的价格梯度往往比同小区内不同房源之间的梯度大得多。同一地段老牌大型社区的均价和旁边新建高端盘的均价能差 40%。这提示我们小区级别的聚合统计特征非常有用。# 按小区聚合, 计算该小区已成交房源的均价中位数 community_stats df.groupby(小区名称)[单价].agg([median, count, std]).rename( columns{median: 小区单价中位数, count: 小区样本数, std: 小区单价标准差} ) # 样本数少于 3 的小区, 中位数不可靠, 用全区中位数填充 community_stats.loc[community_stats[小区样本数] 3, 小区单价中位数] \ df.groupby(行政区)[单价].transform(median).median() df df.merge(community_stats, left_on小区名称, right_indexTrue, howleft)逻辑说明建模时给新购入二手房估价它的「小区中位数」不是已知量只有历史成交样本存在时这个特征才有值。所以这个特征必须限制在「训练集内有出现过的小区」测试集里出现全新小区时该特征缺失要再设计一个 fallback 值。参数说明聚合至少 3 个样本的门槛是我给的底线少于 3 个样本的小区中位数的波动极大直接用均值会造成特征泄漏的错觉。楼龄的处理也是一样。广州的二手房楼龄跨度从 1980 年代的老破小到 2023 年交付的次新房楼龄与房价不完全是线性关系——楼龄 10 年以内价格递减不明显超过 20 年跌幅趋缓30 年以上反而有一些「待拆迁或学位价值」支撑的价格反弹def age_segment(age): if age 5: return 次新 elif age 15: return 中年 elif age 25: return 老旧 else: return 老破小 df[楼龄段] df[楼龄].map(age_segment)分段编码的解释能力远强于直接把楼龄做数字回归根本原因是非线性且分段的逻辑在不同价位段不同——珠江新城的老房子和番禺的老房子年龄衰减速率差异巨大。同样的思路可以考虑用于房型层数、视野朝向保持为分类特征不做硬编码。3.3 模型选型与参数为什么 LightGBM 是这类表格回归的默认项广州房价这种规模的表格数据我一般不会拿深度学习出来跑两个原因一是有几千行的话神经网络没有优势调起来还慢二是特征里大量离散分类行政区、朝向、装修和缺失值树模型天生能处理。xgboost 和 LightGBM 都是首选但我更倾向 LightGBM因为样本量几千时它的直方图算法已经足够快对缺失值有原生支持支持类别特征直接 doi。from lightgbm import LGBMRegressor from sklearn.model_selection import train_test_split feature_cols [ 建筑面积, 户型结构调整为整数, 容积率, 绿化率, 行政区, 朝向, 装修情况, 楼层level, 地铁距离, 小区单价中位数, 楼龄段 ] X df[feature_cols].copy() y df[总价].copy() # 类别型字段显式声明 cat_cols [行政区, 朝向, 装修情况, 楼龄段] for col in cat_cols: X[col] X[col].astype(category) X_train, X_val, y_train, y_val train_test_split( X, y, test_size0.2, random_state42 ) model LGBMRegressor( n_estimators1200, learning_rate0.05, max_depth6, num_leaves31, subsample0.8, colsample_bytree0.8, reg_alpha0.1, reg_lambda0.5, random_state42, verbose-1 ) model.fit(X_train, y_train) y_pred model.predict(X_val)参数选择依据n_estimators1200 配 learning_rate0.05 的组合适合几千行的中小数据集默认的学习率要同步调大树的棵数只动其中一个没有意义。max_depth6 加 num_leaves31 是 LightGBM 的保守默认值广州房价数据没有复杂到需要几十万叶子才能拟合控制叶结点数量就是控制过拟合。subsample 和 colsample 都是 0.8 属于轻量防过拟合如果验证集表现比训练集差 5% 以上把这两个降到 0.7 同时加大 reg_alpha 和 reg_lambda。reg_alpha 是 L1 正则帮助稀疏类别特征不单独分叉过深reg_lambda 是 L2 正则主要防数值型特征的大梯度异动。提示如果你调整了上面参数后训练时间翻了两倍但精度只涨千分之几立刻回滚。这类中小数据集上 80% 的提升来自特征而不是模型复杂度和调参。省钱省力才是参数选择的判断标准。4. 广州房价预测常见问题与避坑连续模型翻车的那几个瞬间4.1 现象训练集 R² 0.98验证集 R² 0.72第一次跑出来 R² 高得离奇的那几天我一度以为找到房价密码了直到把验证集的残差打出来才意识到是特征用错了。原因「小区单价中位数」这个特征里有它的同期总价信息。理论上更常见也更阴险的是原始数据里「单价」列被复制到了特征列或者「小区均价」列直接包含了待预测样本本身。模型中包含与预测目标同源的列是典型的特征泄漏。另一个隐蔽来源是groupby transform做小区聚合时把当前行的目标值也纳入了均值计算变形实现就成了泄漏。解决用train_test_split划分之后必须在训练集内部计算聚合特征再 merge 回验证集如果这份预测是针对「某小区首个待估价房」这种全新样本小区聚合特征不复存在要用二值缺失标记 区级均值做兜底# 先划分再建小区聚合特征, 而不是先整体聚合再划分 df_train, df_val train_test_split(清理完成的df, test_size0.2, random_state42) comm_train df_train.groupby(小区名称)[总价].agg([median, count]) df_train df_train.merge(comm_train, left_on小区名称, right_indexTrue, howleft) # 验证集按训练集的聚合结果做映射, 测试集中新小区的小区特征是空 df_val df_val.merge(comm_train, left_on小区名称, right_indexTrue, howleft)这段代码的关键在于验证集不参与聚合计算只做一个查询动作。线下验证指标的可靠性严重依赖这类「会不会用到未来信息」的顺序是否正确。4.2 现象房价预测出负值或低于 1 万元的怪值二手房成交量在某几个远郊板块本来就少负预测值和极端离谱的预测值几乎是每个做回归的人都会碰到的坑。原因一是训练集本身就含有车位、楼梯房、半产权房这些单价极低的样本模型把这类样本学成了一个数量级二是模型在特征空间外推时没有物理约束总价 30 万的车位和总价 800 万的住宅在面积特征上可能只差 20 平树模型这种非线性拟合很容易在样本稀疏区域拉出负区间。解决最简单直接的方案是给 y 取对数让它满足正态分布假设让预测输出限制在合理区间import numpy as np df[log_total_price] np.log1p(df[总价]) # 训练用 log_total_price 做目标 # 预测结果出来后再 expm1 还原 pred_total_price np.expm1(model.predict(X_val))log1p是针对总价整体偏移 1 的对数变换把 100 万和 800 万的量级差距压缩到可学习的范围。预测完成后用expm1还原真实总价。如果还原后仍然出现低于同区最低价的预测直接用后处理裁剪预测总价低于 30 万或者高于 1 亿就按该行政区的 1% 和 99% 分位数做截断。物理常识是模型的兜底机制这不是玄学。4.3 现象单价和总价同时进特征模型学到的是「乘法」单价、总价、建筑面积三个字段很多新手会一起塞进特征表因为看起来它们都是「不同」的列。但是废掉。原因单价 总价 / 建筑面积三者两两相乘自然构成一个周期性变形树模型不需要聪明到这个程度它只是从中找到了一个近乎线性的绑定规则结果就是模型严重依赖单价一旦某套房没有单价或者单价不准预测直接崩盘。解决这三列里只能选一个作为目标另外两个最多选一个作特征。我的标准做法是用「总价」做预测目标用「建筑面积」和「单价」中选建筑面积——因为单价本身是目标除以面积的商等于在特征里已经泄露了一半的答案。单价这个列可以在 EDA 阶段用来看数据分布不进建模特征。4.4 现象地铁站距离算出来全是同一个小数有一次我拿到坐标列后发现所有房源的经纬度完全一样连小区都区分不出来才知道是网络抓取时字段错位所有行都拿到了某个地图 center 的坐标距离自然都是一个常数。原因原始数据的经纬度批量抓取时如果爬虫代码里的坐标解析出了问题经常整断落到同一个网格中心或者同一个值。这个不通过分布检查完全看不出来。解决写一个极简单例检查建筑面积和经纬度是否具有足够的方差# 坐标方差接近 0 直接判定为抓取异常 print(df[[纬度, 经度]].std()) # 如果 std 只有 0.0001 这个量级, 说明所有点在差不多同一个位置 # 此时放弃经纬度, 用地名文本匹配 行政区级特征做位置信息参数说明0.0001 度大约对应 11 米广州主城区正常房源间的经纬度标准差应该是这个的十倍以上。如果数据真的损坏成一条线与其硬用距离特征不如退回到「行政区 小区」的组合作为位置代理损失的信息量从实践来看可控。4.5 现象模型在珠江新城区域整体便宜了 15%有一次模型的 SHAP 图上「珠江新城」区域的预测整体偏低误差高度集中在高价区而几千万的豪宅却预测得像刚需盘。树模型对样本量充足的中间价位拟合好对头顶上的长尾极值几乎无感因为损失函数被多数样本主导——这是回归模型对「量级不均」的天然偏置没法靠调参完全扭转。原因训练样本中 80% 是 200 万到 1000 万之间的房子太贵的豪宅挂牌量本来就少数据量不够模型学不到那类样本的特殊规律。解决广州只有天河和越秀的头部分区有这个情况此时不是删掉高价样本而是对训练样本加指数权重——把总价超过 1500 万的样本权重设成常规样本的 2 到 3 倍强制损失函数去关注高价样本# 按总价区间设置样本权重, 让模型不能无视豪宅 def price_weight(total_price): if total_price 1500: return 3.0 elif total_price 800: return 1.8 else: return 1.0 sample_weight np.array([price_weight(p) for p in y_train]) model.fit(X_train, y_train, sample_weightsample_weight)这只是把问题从「整体平均」往「局部也合理」拉一步。更好的方案是单独建一个高价房专用模型但要靠额外的高价挂牌源数据在只有这份 rar 数据的前提下权重很难说是最优雅的但至少管用且容易落地。5. 评估与验证判断预测值能不能用先看这三张图5.1 评估指标怎么选RMSE 与 MAE 的分歧说明了什么做回归最常见的误区是只盯着 R² 看。房价这种目标值方差很大R² 在 0.85 以上都算正常但 R² 对错误量级的惩罚是非线性的RMSE、MAE 和 MAPE 三个指标合起来看才能反映出模型真正的误差面貌。from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score rmse mean_squared_error(y_val, y_pred, squaredFalse) mae mean_absolute_error(y_val, y_pred) r2 r2_score(y_val, y_pred) mape (abs(y_val - y_pred) / y_val).mean() * 100 print(fRMSE: {rmse:.2f} 万元) print(fMAE: {mae:.2f} 万元) print(fR²: {r2:.4f}) print(fMAPE: {mape:.2f}%)用广州的房价量级来感受这几个数字如果 MAE 是 60 万RMSE 是 120 万说明模型在一部分房源上出现了「离群极值」级别的预测错误拉高了平方项而大部分房子预测质量还行——RMSE 对这类集中性的偏离尤其敏感。如果 RMSE 和 MAE 差距不大误差分布均匀模型整体稳定。MAPE 在 12% 以内对一个几十万套房的片区做趋势性判断才说得过去。任何单一指标都有盲区RMSE 和 MAE 的分歧本身就诊断了误差分布到底有多偏。5.2 残差图只有一张图能看出模型哪里系统性出错评估指标是浓缩信息真正的诊断要靠残差图。横轴是预测总价纵轴是真实总价减预测总价正负 100 万之内为合理这张图暴露的问题种类比任何指标说明都多import matplotlib.pyplot as plt resid y_val - y_pred plt.figure(figsize(8, 6)) plt.scatter(y_pred, resid, alpha0.4, s10) plt.axhline(y0, colorred, linestyle--, linewidth1) plt.xlabel(预测总价万元) plt.ylabel(实际总价 - 预测总价万元) plt.title(残差散点图按预算分段看误差方向) plt.savefig(residual_check.png, dpi150)这张图看三个现象。预测值 300 万以下的位置残差基本在零轴上下对称分散说明刚需盘的预测是正常的500 万到 1000 万区间残差开始出现大面积负值说明真实总价普遍高于预测也就是 4.5 那个「珠江新城系统性偏低」问题的证据200 万以下区域出现尾部向上的极端正残差说明低价盘被高估了。这种分段式的残差规律R² 指标永远看不出来但它直接告诉你要不要做样本加权要不要单独训练区间模型。5.3 用 Shap 解释关键特征别把模型当黑匣子很多人把 Shap 当成一种「高级可视化」实际上它是回归落地的必要环节——没有它就说不清模型是在靠逻辑判断还是在抄数据作弊。import shap explainer shap.TreeExplainer(model) shap_values explainer.shap_values(X_val) shap.summary_plot(shap_values, X_val, plot_typebar, max_display12)运行这个对小数据集几乎不耗时。我重点看的是训练过的模型对哪个特征的依赖最大。广州房价如果依赖度前三名是「小区单价中位数」「建筑面积」「行政区编码」说明模型学的是市场聚群效应符合业务常理如果「地铁距离」排到十名开外「朝向」反而排到前三那就要怀疑原始数据里朝向字段是不是变成了某种错乱的编号在跟具体地段高度相关。Shap 这层检验做扎实了模型放进业务场景才敢让人信。提示Shap 值最大的用途是给非技术方做决策解释。有老板过来问「为什么这套 1000 万的老房子你预测 850 万」拿 shap.force_plot 一拉楼龄、学qu划分、地铁距离、小区梯度这四个因素的影响全部列出来比任何空口解释都有说服力。6. 把模型用起来批量估价、笋盘筛选与工作流落地模型训练好了评估也过了最后要让它真正为买房决策服务。我平时会做一个小的批处理脚本把目标区域的在售房源从 Excel 读进来跑一遍已经训练好的模型输出一张带「预测价/挂牌价偏离率」的表然后按偏离率排序。这里有一个很重要的工程细节——模型要序列化保存不然每次预测都要重新训练import joblib # 保存模型 joblib.dump(model, gz_house_price_lgb.pkl) # 新数据到来时直接加载不做训练 loaded_model joblib.load(gz_house_price_lgb.pkl) # 生成批量估价报告 df_new[预测总价] np.expm1(loaded_model.predict(X_new)) df_new[偏离率] (df_new[总价] - df_new[预测总价]) / df_new[预测总价] result df_new.sort_values(偏离率, ascendingFalse) result.to_excel(笋盘筛选结果.xlsx, indexFalse)做完这套脚本再把每天的挂牌数据更新进来跑一遍偏离率超过 8% 的房源就值得人工核实一下是业主急售的笋盘还是房源信息本身有水分。我会把这些候选小区再放回 EDA 阶段的单价分布图里看一眼确认它们不是数据异常导致的虚假信号才进入线下看房环节。说实话用模型估价这件事我栽过最大的跟头就是对低价上榜的房源太兴奋忘了一张图——残差图。后来每次批量预测跑完都先看残差趋势再谈「笋盘」。这套流程从数据清洗到最后的筛选脚本每一步都是踩过坑才补上的希望帮到你。本文还有配套的精品资源点击获取
返回列表