
三个月前我接了个天气预测的活儿一开始觉得自己捡了个便宜——历史数据有、模型会调包无非是拿TimechoAI拉一堆特征丢进回归模型完事。结果真上手才发现天气预测这套东西光整理那21个气象指标就差点把我逼疯。从数据接入、指标口径统一到特征工程和模型上线我整整折腾了三个月中间一度怀疑自己是不是根本不懂气象直到把每一个指标背后的物理含义和模型里的实际表现都摸透了才算真正整明白。这篇我就把这三个月踩过的坑、验证过的结论还有最后留下的指标清单一次性讲透。如果你也想用TimechoAI或者类似工具做天气预测、时序预测或者只是想知道预测温度到底该看哪些特征这篇应该能帮你少走我走掉的那一半弯路。1. 三个月前我为什么一头扎进TimechoAI做天气预测1.1 天气预测的活儿难点从来不在模型很多人跟我一开始的想法一样天气预测不就是个回归问题吗温度、湿度、气压、风速一堆历史数据丢进LightGBM或者LSTM输出未来24小时温度完事。真做起来才明白气象数据的复杂度远超一般业务数据。天气数据有非常强的自相关性、周期性、空间相关性而且21个基础指标之间不是独立变量——温度和湿度耦合气压和风速耦合云量和太阳辐射耦合。一个模型能不能在这堆纠缠的指标里学到稳定规律直接决定预测准不准。而这一步的前提是你得先把每个指标的含义、单位、物理范围、采集频率搞清楚否则后面全是糊涂账。模型反而是最简单的部分。数据整明白了换模型只是换个损失函数的问题。1.2 TimechoAI解决了我最头疼的数据底座问题做天气预测数据底座绕不开时序数据库。气象站的数据天然就是带时间戳的时序数据一小时一条一个站点几年下来就是几万条。如果用传统关系型数据库存查询和聚合的效率一言难尽更别说还要做滑动窗口、时间对齐这些时序专用操作。我这边存量数据已经落在TDengine里面选TimechoAI的原因很直接它和TDengine是同一套体系能直接在时序数据上做特征工程和模型训练不用把几千万行数据导来导去。以前用Python脚本从数据库拉数、拼DataFrame、再写一堆清洗逻辑现在在TimechoAI的工作台里大部分数据接入和特征配置能直接编排省掉了很多重复劳动。当然工具只是省力该懂的指标一个都不能少。2. 21个气象指标全拆解哪些能直接拿哪些得靠算2.1 第一类气象站直接观测的一手指标先说结论这21个指标我按来源分成三类直接观测、衍生计算、统计发布。绝大部分指标是气象站传感器直接测出来的也是最可靠的数据源。我整理的完整清单如下表你可以直接抄走当参考。编号指标单位类型在天气预测里的作用12m气温℃直接观测温度预测的核心目标/特征2最高气温℃直接观测反映白天升温上限3最低气温℃直接观测反映夜间辐射冷却下限4相对湿度%直接观测判断近饱和程度降水/雾的关键5露点温度℃衍生计算反映空气实际水汽含量6比湿度g/kg衍生计算不受温度影响的水汽密度指标7降水量mm直接观测降水目标/特征区分雨强8降水概率%统计发布概率预报短期参考意义有限9海平面气压hPa直接观测指认高/低压系统位置10地面气压hPa直接观测海拔订正前的气压反映本地条件1110m风速m/s直接观测风预测目标/特征1210m风向°直接观测气团来源方向影响温度/湿度13阵风m/s直接观测极端风事件特征14总云量0-1直接观测影响辐射和最高温关键特征15低云量0-1直接观测短临降水前兆16能见度km直接观测雾、霾判定指标17太阳辐射W/m²直接观测地表增温的热力来源18紫外线指数无量纲衍生计算云量与辐射的综合产物19蒸发量mm直接观测水循环与干旱监测20雪深cm直接观测低温维持与融雪预报21体感温度℃衍生计算温度/湿度/风速的综合感知量直接观测指标里最核心的是温度、湿度、气压、风、降水、云量这几组。每一组内部都存在物理关联比如气压突然下降往往意味着低压系统靠近后面大概率跟着风力和降水增强云量增加会弱化白天的太阳辐射抑制最高气温。这些物理关系在特征工程里是可以直接利用的先验知识。2.2 第二类需要二次加工的气象衍生量衍生计算指标里露点温度、体感温度、比湿度这三个尤其重要因为它们比原始观测量更稳定也更接近物理本质。露点温度是指在当前水汽压下空气冷却到水汽饱和时的温度。它跟相对湿度最大的区别是露点不受气温影响直接反映空气里有多少水汽。计算露点我用的Magnus公式γ 17.62 b 243.12 α ln(RH/100) (γ * T) / (b T) Td (b * α) / (γ - α)T是当前气温℃RH是相对湿度%Td就是露点℃。举个例子气温30℃、相对湿度60%时露点算出来大约是21.4℃。这意味着如果夜里气温降到21.4℃空气就会饱和出现凝露或雾。体感温度把温度、湿度、风速揉在一起公式有很多版本我用过的一个简化版是这样的e (RH/100) * 6.105 * exp(17.27 * T / (237.7 T)) AT T 0.33 * e - 0.7 * ws - 4.0e是水汽压hPaws是风速m/s。这个值在高温高湿天和低温大风天跟实际体感误差不大至少能抓住湿热比干热难受得多这个规律。比湿度则是绝对湿度的表达单位g/kg不受气温体积膨胀影响在高空分析和强降水研究里比相对湿度更实用。计算需要先求水汽压e再结合气压Pq 0.622 * e / (P - 0.378 * e)2.3 同一指标在预测目标和特征之间随时切换这21个指标里没有谁是绝对的目标或绝对的特征完全看你预测什么。预测未来24小时最高气温那么历史最高气温是特征预测未来一周的逐小时温度那么当前2m气温是特征同时也是要预测的目标序列本身。预测降水时温度、湿度、气压都是特征降水量才是目标。我在前两个月里反复栽跟头就是因为没有在一开始就把这个任务的目标变量是谁哪些指标不能提前知道想清楚。尤其要注意的是未来才知道的指标。比如你现在要预测明天下午2点的温度那就不能用明天下午2点的实测最高气温当特征这是最典型的数据泄漏模型在训练集上效果好到飞起一上线就崩。3. 数据清洗与时间对齐三个月里最隐蔽的隐性消耗战3.1 21个指标的时间戳对齐差点让我把键盘砸了气象站不同传感器的上报频率可能不一致。有的整点报有的每5分钟报还有的夜间维护直接断档。如果直接把原始数据按各自时间戳丢给模型TimechoAI这边首先就会因为时间频率不统一报错就算不报错特征之间的错位也会让模型学到一堆虚假关系。我最后统一成整点小时频率。具体做法是以小时为单位做重采样每个指标先取该小时内的均值能通过标准SQL聚合的就用SQL完成剩下需要在时序管道里对齐的就用插值补齐。TDengine天然的时序索引让这类对齐操作比传统数据库快不少TimechoAI里也可以直接用时间对齐算子处理。这里有个细节对齐之前一定要先确认时区。我刚开始没注意把某站点的UTC时间和本地时间混在一个数据集里直接导致凌晨3点的温度和上午10点的温度混在一起模型完全学不到日变化规律。后来我强制所有表统一用UTC8存储时间戳并在接入时显式声明时区这个坑才算填平。3.2 缺失值补法有讲究不能一股脑填充气象数据的缺失比例通常不高但缺失形态很关键。我统计下来21个指标里降水、能见度、太阳辐射的缺失率最高经常集中在半夜或维修时段。针对不同情况我用了三种处理策略缺失2小时以内线性插值。相邻时次的趋势是可靠的线性插值不会引入明显误差。缺失6小时以内用前一天同时刻的值做基准叠加上相邻时次的趋势修正。比如昨天凌晨2点到8点温度一直在降今天同一时段缺失就按昨天基准 今天前几个小时的温差趋势补。缺失超过24小时直接整段剔除。强行补出来的数据对模型造成的污染比缺失本身更严重。千万别在这时候偷懒用全局均值填充。天气数据有强自相关全局均值会直接抹掉日变化和季节性等于给模型灌迷魂汤。我一开始用均值补过一段温度结果模型短期预测的MAE直接变差了0.6℃后来排查半天才找到原因。3.3 异常值不是垃圾是气象仪器的求救信号气象数据有一些超越物理极限的值比如温度填了个-99湿度填了个150%这种是传感器故障直接删。但更棘手的是看似合理、实际突变的值比如50分钟前还是晴天突然记录到300mm/h的降水量——这几乎不可能是真实天气反而是仪器进了水或者被异物遮挡了。我做了两层筛选第一层是物理范围检查超出合理区间的直接剔除。我的取值范围给到比较保守的安全区间指标合理范围2m气温-55 ~ 55 ℃相对湿度0 ~ 100 %海平面气压870 ~ 1085 hPa10m风速0 ~ 60 m/s小时降水量0 ~ 200 mm第二层是滑动窗口突变检测。用过去3小时的滑动均值算z-score阈值设在4以上才算异常。为什么阈值不设成常见的3因为天气系统本身就会产生快速变化比如冷锋过境时一小时降温8℃、风速翻倍都是真实天气阈值设太低会误删导致模型丢失对剧烈天气的认知。顺便说一句被删除的异常点我不会不管而是单独存一张异常记录表。后面如果发现某类异常频繁出现在同一时段说明是仪器问题而不是天气问题需要在特征里加上一个该时段是否经常缺测的标记防止模型错误学习到周期性假特征。4. 特征工程实战如何把21个指标变成模型的长期口粮4.1 滞后特征和滑动窗口天气也是一个记仇的系统天气系统有很强的惯性。今天的大气状态不会瞬间跳变昨天的温度、湿度对明天的天气仍有显著影响。所以特征工程的第一步就是给每个关键指标构造滞后特征和滑动窗口特征。以预测未来24小时逐时温度为例我给2m气温构造了这些滞后项滞后1小时、3小时、6小时、12小时捕捉短时惯性滞后24小时捕捉同一时刻的昨日温度滞后168小时捕捉同一时刻的上周温度用来压制周尺度波动滑动窗口则构造了过去3小时均值、过去6小时温变斜率、过去24小时最高/最低温、过去7天同时刻温度均值。这些窗口值的意义在于它们不只是某个时间点的离散快照而是把近期趋势和历史背景都折叠成了模型可用的特征。TimechoAI里配置这些滞后和滑动窗口可以直接在特征面板上用算子完成不用在Python手撸循环效率高很多。但我提醒一句滞后特征和窗口宽度不能贪多。滞后项超过7个后特征之间的共线性会急剧上升树模型还好线性模型和部分神经网络会被共线性拖垮。4.2 小时与季节的周期性编码一个sin/cos解决边界突跳天气预测任务里小时和季节是必须进特征的但直接用hour_of_day0和hour_of_day23这种数字模型会认为两者相差很远实际上它们在日周期里是相邻的。用day_of_year1和day_of_year365也同理1月1号和12月31号在季节上是邻居数值上却差了364。解决办法是用三角函数做周期编码hour_sin sin(2π * hour / 24) hour_cos cos(2π * hour / 24) day_sin sin(2π * day_of_year / 365) day_cos cos(2π * day_of_year / 365)这样一来0点和23点在二维编码空间里距离非常近1月和12月也相邻模型不会再被数字表面的大小误导。这个方法我强烈建议做时间序列的人必须使用就算TimechoAI没有现成算子自己写也只要两行代码。4.3 手工交互特征温度和露点差是降水的关键前兆模型能自动学习特征交叉但有些物理规律你不会希望它慢慢摸索直接告诉它更好。我最常用也最有效的一组交互特征是温度与露点的差值简称露点差。当露点差小于2℃时空气接近饱和很容易形成雾或毛毛雨小于4℃且配合上升气流条件对流性降水概率明显增加大于15℃则基本是干燥晴天。我把这个差值直接作为特征灌给模型比把温度和湿度分开让模型自己乘来乘去学得快且稳得多。类似的交互特征还有温度×太阳辐射反映有效增温能力、相对湿度×风速反映蒸发冷却强度、海平面气压与地面气压的差值反映气压梯度梯度越大风力越强。4.4 哪些指标能不做标准化就扔进模型不存在的除了树模型对量纲不敏感其他模型几乎都需要标准化。我的做法是对LightGBM/XGBoost这类梯度提升树数值型指标保持原始量纲即可对LSTM、GRU、TCN以及任何带正则化的线性模型全部做标准化。标准化的关键雷区在于只能用训练集的均值方差去变换测试集不能在整个数据集上先算均值方差再切分。否则训练集里混进了未来的统计信息同样是数据泄漏而且特别隐蔽。TimechoAI的标准化算子默认支持按时间切分后的独立拟合但用之前一定要确认管道的执行顺序别让框架帮你把全局统计量算进去了。5. 模型训练踩坑集从移平均baseline到LightGBM和时序网络5.1 先建个气候学基线不然你不知道模型是真的香还是假的好天气预测有个特别容易让人误判的陷阱随便跑一个模型MAE看起来好像还行但你可能打不过最朴素的历史同期均值。我先建了一个气候学基线——用过去5年同一天同一小时的气温均值作为预测值。这个啥特征都不用的基线在温度预测任务上MAE轻松做到2.4℃。如果模型的MAE连2.4℃都打不过那说明特征工程和模型选择都有问题别急着调参。再往下建一个更复杂的基线移平均预测也就是用过去24小时温度的平均值作为明天同一时刻的预测。这个基线大概在2.1℃左右。我后来的LightGBM模型跑到了1.8℃才算真正有说服力。我建议所有做天气预测的人不管用什么工具第一步都先跑这两个基线把及格线立起来再去堆特征。5.2 模型对比树模型打底时序网络攻坚我在这三个月里试了四类模型结果可能跟很多人想的不一样。模型优点缺点我这里的实测表现线性回归简单、可解释学不了非线性关系MAE 2.5℃左右跟基线差不多LightGBM训练快、特征重要性方便、对表格特征非常强外推能力弱没见过的高温区间容易失效MAE 1.8℃主力模型LSTM能学长期依赖数据量不足时严重过拟合调参成本高MAE 2.1℃反而不如LightGBMTCN感受野可控、训练比LSTM快超参数更敏感需要足够的时序长度才有优势还没完全调通短期看逼近LightGBM核心结论在中小规模气象数据集上单站一年也就8760小时记录树模型加手工特征通常是性价比最高的方案。LSTM这类模型虽然听着高级但数据量不够时真的不如把特征工程做好再喂给LightGBM。5.3 时序切分和数据泄漏机器学习的老规矩在时间序列上会加倍还回来常规机器学习里random split是把样本随机打散成训练集和测试集这一套在时序预测里完全不能用。天气数据相邻时次高度相关如果测试集和训练集混在一起模型等于见过答案附近的上下文测试指标会虚高得非常离谱。我最后用的是滚动切分按时间顺序前70%做训练集中间15%做验证集最后15%做测试集。验证集特意选了包含完整四季的一年保证模型在冬夏冷热极端情况下都能被评估到。数据泄漏还有几个隐蔽来源逐个排查用全局均值方差做标准化第4.4节说的用了未来时次作为滞后特征比如预测明天却用了明天夜里的气压值对缺失值用未来值反向填充时间序列里最常见的隐形泄漏我踩过一次直接把模型回测分数从1.8℃虚高成了1.4℃部署后才现出原形。模型训练完之后别急着高兴先看一眼误差的时间分布。如果误差集中在夜间或夏季说明日周期特征还没学透如果误差在降温天气明显放大说明气压变化类特征强度不够。这些都比单纯看整体MAE更有指导意义。6. 花了三个月才看明白这21个指标的含金量排序6.1 换一个预测目标指标重要性就全变了21个指标没有固定的重要性排行榜一切取决于预测目标。我同时做了三套预测任务特征重要性排序完全不同预测最高气温最核心的特征是前一天最高气温、总云量、太阳辐射、14时气温。云量多的时候太阳辐射被削弱高温就上不去这跟物理直觉完全一致。预测小时降水量相对湿度、露点差、低云量、气压变化率重要性最高风速和风向只在中等到偏弱水平。预测风速前一时段风速的滞后项重要性一骑绝尘气压梯度差和阵风历史值是第二梯队。风的持续性比温度还强短临预测里前6小时风速几乎决定了未来几小时的大致水平。所以如果你问我哪个指标最重要我只能反过来问你你到底要预测什么6.2 SHAP值告诉我温度预测不是温度重要这么简单到了第三个月我才开始认真用SHAP值看特征依赖图这才算真正把指标看明白了。特征重要性排名能告诉你谁重要但SHAP依赖图能告诉你每个特征在什么区间、朝哪个方向影响预测。举两个例子。总云量对最高气温预测的SHAP依赖图显示云量从0到0.3时每增加一点预测最高温就显著下降但当云量超过0.7以后继续增加云量对温度的影响明显减弱因为云已经厚到完全遮住太阳再厚就没有额外降温效果了。这是典型的非线性饱和效应。再比如风速SHAP显示只有在风速小于3m/s区间风速增加才会显著降低体感温度对预测的影响而超过4m/s后影响趋缓。这种只在特定区间起作用的信息光看特征重要性表是完全看不出来的。6.3 最终我留下的核心指标清单三个月折腾下来我把最初21个指标精简成了一个主打特征集总共11个其余10个并没有丢弃只是不再进入高频模型核心指标保留理由2m气温及其滞后项温度预测最直接的基础特征最高气温/最低气温刻画日变化幅度相对湿度关键辅助特征对降水/体感都重要露点温度更稳定地反映水汽含量海平面气压/地面气压天气系统位置的代理变量气压差可构造梯度特征10m风速/风向风场预测和目标也影响体感/蒸发总云量/低云量辐射与降水前兆太阳辐射地表增温热力源被精简掉的10个指标里降水概率短期在站点级预测里价值有限紫外线指数和太阳辐射高度共线蒸发量和雪深对城市站点温度预测贡献微弱。这说明一个道理指标不是越多越好冗余特征会抬高计算成本还会增加过拟合风险。我最后在TimechoAI里把整个管道固化成了标准流程TDengine数据接入 → 时间对齐与清洗 → 特征工程滞后/窗口/周期编码/交互特征→ LightGBM训练 → SHAP解释 → 结果落库。整个流程跑一轮从原来的几天压缩到两三个小时而且可复现。最后再分享一个小技巧每次改完特征或者模型配置都要记录一版当时的验证集误差和特征集合哪怕只是在文档里随手记两行。这三个月里我因为不记录版本曾经把一个看起来变好实际是数据泄漏的配置当成进步反复回滚了好几次。不管是天气预测还是别的时序任务可复现性比偶尔一次的精度提升值钱得多。