scikit-learn不支持地理空间数据原生处理,需将经纬度转为有物理意义的距离特征(如haversine距离),对离散地理标识优先用目标编码,用geohash/h3网格化降维,并严格保证空间衍生步骤在训练集内完成。

Scikit-learn 本身不支持地理空间数据的原生解析、投影或空间关系计算——它没有 GeoDataFrame、shapely 几何对象或坐标系处理能力。所有“地理特征”必须先被显式转换为数值型向量,才能喂给 sklearn 模型。
把经纬度转成有物理意义的距离特征
直接把 latitude 和 longitude 当作普通数值输入模型,会导致严重误导:一度经度在赤道和极地代表的实际距离差十倍以上。必须先做地理距离编码。
- 用
haversine_distances(来自sklearn.metrics.pairwise)计算两两样本间的球面距离(单位:弧度),再乘以地球平均半径(6371 km)转为公里 - 更实用的是构造“到关键地点的距离”:比如每个样本计算到最近医院、地铁站、商圈中心的
haversine距离,生成新列dist_to_hospital_km、dist_to_subway_km - 避免用
euclidean直接算(lat1-lat2)**2 + (lon1-lon2)**2—— 这在中高纬度会系统性低估东西向距离
对地理区域做可学习的嵌入(如行政区、邮编)
像 city_name、postal_code、admin_level_2 这类离散地理标识,不能简单用 LabelEncoder 或 OneHotEncoder,尤其当类别数多(如全国 3000+ 县)、样本不均衡时。
- 优先用目标编码(
TargetEncoderfromcategory_encoders)或均值编码:用该区域样本的目标变量均值替代原始标签,再加噪声防止过拟合 - 若有多级嵌套(省→市→区),可构建层级特征:比如把
province的目标均值作为一级,再叠加上province + city组合的均值作为二级差分项 - 警惕
OneHotEncoder导致维度爆炸:一个含 2000 个唯一zip_code的列会生成 2000+ 列,且无法泛化到未见过的新邮编
用网格化(geohash / H3)降维并保留局部性
高精度坐标(如 GPS 浮点)直接建模噪声大、无泛化性。需要把连续空间离散为有语义的单元格,同时让相邻格子编码接近。
-
geohash.encode(lat, lon, precision=6)生成字符串(如"w2k4zq"),再用HashingVectorizer或 embedding 层映射为低维稠密向量 - H3 索引(需
h3库)更好:支持固定分辨率六边形网格(如h3.geo_to_h3(lat, lon, resolution=7)),天然满足邻近性,且可向上聚合(resolution 6 → 5) - 别直接对 geohash 字符串用
LabelEncoder:字母顺序不反映空间顺序;必须先哈希或嵌入
时间 + 空间联合特征容易被忽略
纯空间特征常不够——比如“某小区过去 3 天的平均房价”比“该小区坐标”更有预测力;但 sklearn 的 ColumnTransformer 不会自动关联时空维度。
- 必须手动构造:按
geohash分组,再用pandas.groupby().rolling(window='3D').mean()计算时序聚合值 - 注意时区与时间对齐:所有时间戳统一转为 UTC,再按本地日切分(如“工作日早高峰”需基于用户所在时区判断)
- 空间滞后项(spatial lag)要谨慎:用
libpysal构造邻接矩阵后,计算邻居均值作为新特征,但sklearnpipeline 中需自定义 transformer 封装,否则 cross-validation 会泄露
地理特征真正难的不是编码本身,而是确保空间操作不破坏 train/test 独立性——比如用全局 k-d tree 查最近设施、或用全量数据拟合 TargetEncoder,都会让测试集信息提前泄漏。所有空间衍生步骤必须严格限定在训练集内完成,并用相同参数 transform 测试集。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











