资讯详情

从零实现天气生成器:用自回归模型和状态机合成小时级天气数据

📅 2026/10/13 3:06:41 | 华诺云谱 👁 阅读
从零实现天气生成器:用自回归模型和状态机合成小时级天气数据
天气生成器我在模拟项目里从零手搓了一套天气数据引擎前段时间接了个模拟项目需要一个虚构城镇的全年天气数据用来驱动游戏里的季节变化、农田作物生长模拟顺便喂给一个机器学习模型做测试。一开始我的想法很简单天气生成器嘛不就是随机撒一堆温度和湿度数字真正动手以后才发现如果只是靠random()出来的数据要么是“今天30度明天零下10度”要么是“连续半年不下雨、然后一场雨下一个月”完全没法用。后来我花了几个周末基于气候统计约束、随机过程和状态机搭了一套还算稳的天气生成器用 Python NumPy 实现能生成小时级、带季节规律和地域差异的天气序列供游戏、仿真和算法测试使用。这篇文章就是把整套思路、代码结构和踩过的坑完整记录下来适合想自己动手做合成天气数据的开发者参考。1. 项目概述我在做一个什么样的 Weather Generator1.1 为什么需要天气生成器很多场景其实都缺不了合成天气数据。游戏里需要有昼夜温差和随机降雨农业仿真需要合理的积温曲线光伏功率预测模型训练需要大批量有标签的天气样本还有我这次做的城镇模拟系统需要一整套时间线齐整的天气数据来驱动交通、能耗、甚至NPC行为。真实气象数据当然最准但问题很多一是获取门槛和授权限制二是不一定覆盖你需要的虚拟地域三是真实数据往往存在大量缺失和异常不适合做“干净”的基准测试。这时候自己写一个 Weather generator 就非常合适——你能完全控制数据的分布、季节特征和随机性生成源源不断的样本。1.2 我设定的目标与约束为了避免把项目做成一个无底洞我一开始就明确了几个硬性目标输出为小时级时间序列至少能生成一整年8760个点的数据。包含核心字段温度、相对湿度、露点、风速、风向、降水类型、降水强度。数据要符合基本的物理逻辑白天温度高、夜间低湿度随温度反向变化风速和气压有相关性降水不是均匀连续的“淋浴”而是有过程的。支持通过参数控制地域特征比如热带、温带、干旱区。生成速度快一次性生成10年数据也不能让 CPU 烧太久。技术选型上我用了 Python 和 NumPy没上 Pandas 和数据库因为核心逻辑是数值计算NumPy 的向量化操作能省下不少循环时间。后期接了个小前端做可视化展示才加的 Pandas 和 Matplotlib。1.3 整体思路的一条主线整套生成器的核心是“分层合成”。简单说就是先把确定性的气候规律写进一个基础函数它给出每天的平均温度、日均光照时长、理论湿度范围然后叠加一个随机扰动模拟天气系统自身的波动最后再通过事件触发器把降水、寒潮、热浪这些“离散天气事件”插入到连续序列里。我常用的一个类比是基础函数就像演员的台词随机扰动是演员的临场发挥事件触发则是导演临时加的戏剧冲突——三者缺一不可否则成片就不好看。2. 天气生成的设计思路与核心原理2.1 天气不是随机数是“带约束的随机”如果只是给每个小时生成一个独立随机数温度序列会显得非常“碎”像是收音机里的白噪声。真实天气有很强的自相关性今天中午30度明天中午不太可能只有10度这一小时风速大下一小时大概率也不小。这种“惯性”在统计学上叫自相关在气象上则来源于大尺度天气系统的平流和地表能量平衡。所以在设计时我首先放弃独立随机采样转而使用自回归过程。最基础的是 AR(1) 模型x[t] a * x[t-1] epsilon[t]其中a是自相关系数0.9左右代表天气状态延续性epsilon[t]是白噪声。温度、气压、风速这类连续性变量都用类似方式处理区别只是参数不同。2.2 三层的分层架构我把整个生成过程拆成三层第一层气候基线层。由经纬度、月份、海拔决定日均温度、光照时长、平均湿度。这部分是完全确定性的可以用三角函数拟合。第二层随机天气层。在基线之上叠加 AR(1) 扰动产生前后关联的风、云量、温度偏差。第三层天气事件层。包括降水、雷暴、热浪、寒潮等用状态机或泊松过程触发会影响第二层的多个变量并持续数小时到数天。这种分层的好处是调参容易想要更热就调基线想要更“抽风”就加大扰动方差想要更多暴雨就调事件触发概率彼此之间不会打架。2.3 时间尺度拆分年、日、小时的节律天气数据至少有三种时间规律必须同时满足年周期夏季温度高冬季温度低用正弦函数模拟一条年基线峰值出现在7月底或8月初谷值在1月底。日周期温度和太阳辐射有24小时节律最低温通常出现在日出前最高温在14点到15点之间。短期波动持续数小时到数天的天气系统变化比如冷锋过境、副高控制下的稳定晴热。我分别用不同频率的正弦波和 AR 过程来表示它们最后叠加。这里频率是关键做低频时域合成时一定把角频率算对不然肯定会出现“上午热下午冷”这种荒唐数据。3. 核心模块的实操实现3.1 温度生成日变化曲线 季节漂移温度是最基础的气象变量其他很多变量都从它衍生。我先定义一个基准日平均温度函数参数是年内第几天day_of_year、纬度区域类型和海拔修正值。一个典型的温带地区表达式是daily_mean annual_mean annual_amplitude * cos(2*pi*day/365 - phase)annual_mean是全年平均气温annual_amplitude是季节振幅phase控制最热时刻的位相。对北半球中纬地区相位大约偏移让峰值落在7月中下旬。然后我把日平均温度按“日变化曲线”分配到24小时。常用方法是用半正弦模拟白天升温段夜间用指数衰减近似T_hour daily_mean diurnal_range * (0.6*sin(pi*(hour-6)/(14-6)) - 0.2*cos(2*pi*hour/24))更精确的做法是引入日出时间和日落时间日出前温度以低速率下降日出后开始上升。我为了简化用了一个固定的“日较差”参数并假设日最低温出现在6点最高温出现在14点。代码里用的是 NumPy 的linspace和三角运算直接向量化生成整年的温度序列。实际效果年温度带在-5°C到32°C之间变化日较差约8-12°C加上 AR 扰动后序列有波动的“毛刺”但不会出现一天之内从30°C骤降到15°C离奇走势。如果你拿真实数据比会发现我这种合成结果虽然平滑但已经是够用的程度。3.2 湿度与露点温度衍生的物理一致性湿度不能独立乱生成否则会出现“低温高湿但又不降雨”的矛盾。我先用温度算饱和蒸汽压再按相对湿度反推露点。常用的简化公式是 Magnus 公式饱和水汽压 es(T) 6.112 * exp(17.67 * T / (T 243.5))然后通过相对湿度 RH 得到实际水汽压 e RH * es / 100露点温度 Td 243.5 * ln(e/6.112) / (17.67 - ln(e/6.112))。我用这个方法先设定一个相对湿度基值白天较低夜间较高。然后在基值上叠加 AR 扰动但把扰动幅度限制在20%-90%之间。随后计算露点这样生成的露点永远比干球温度低物理上不会出错。我踩过的一个坑是在很冷的时候比如零下5°C饱和水汽压很小同样的水汽含量相对湿度会更高。如果只按固定湿度范围生成会出现“零下十度湿度高达90%”这种其实也算正常但配合降水状态容易误触发降雪。所以后来我把湿度生成改为先由温度分布决定一个“可持水量”再随机一个“相对饱和度”来求实际湿度。3.3 风向风速向量合成与阵风噪声风向和风速是一对耦合变量。如果独立生成会出现“风速很大但风向完全随机”的不自然情况。更合理的做法是生成一个二维风矢量uv其中u是东向分量v是北向分量然后从矢量里计算风速和风向角。wind_speed sqrt(u^2 v^2) wind_direction atan2(v, u) * 180 / pi我用 AR(1) 分别生成u和v但是给它们设置一个共同的大尺度偏移用来模拟主导风向。比如在多风区域u的均值设为5 m/sv的均值设为0那样风大体吹向偏东方向叠加AR扰动后风向会在主方向上摆动而不是毫无章法地乱转。阵风是更高频率的噪声我用一个快速的余弦噪声叠加到风速上gust gust_strength * (0.5*sin(2*pi*time*0.02) 0.5*random_noise)这样在处理光伏板风载荷模拟时输出数据有高频分量的震动感更接近真实风速仪记录的毛边。由于是合成数据我不能保证绝对精确但至少统计上特征像。3.4 降水生成马尔可夫状态机 雨量分布降水是整个项目里最复杂的部分不能简单地“随机下雨”。我参考了降水模拟里常用的生成思路把天气分为两类状态——“干”和“湿”状态之间的转移由转移概率决定这是一个二态马尔可夫链。状态转移矩阵长这样干 湿 干 0.95 0.05 湿 0.30 0.70意思是如果今天是干天明天有5%概率变湿如果今天湿明天有30%概率转干、70%概率继续保持湿。这样生成的干湿周期会成段出现符合实际气候的“连晴”和“连雨”特点。当状态是“湿”时我用 Gamma 分布生成降水强度mm/hGamma 分布的形状参数和尺度参数取决于季节和地域。比如热带夏季容易有短时强降水形状参数小、尺度参数大温带绵绵细雨则相反。rain_mm gamma.rvs(shape, scale, sizen)然后把降水强度插到小时序列里同时修正当时的温度和湿度下雨时云量增加日较差减小夜间温度不会降得太低湿度接近饱和。这些联动效果是让我这套生成器看起来“聪明”的关键。3.5 对外接口与数据结构我最后把核心逻辑封装成了一个类WeatherGenerator对外就暴露一个方法weather generator.generate(start_date2025-01-01, days365, regiontemperate)返回一个 NumPy 结构化数组或字典包含时间戳、每个小时间隔的温度、湿度、露点、风速、风向、降水类型和降水量。使用者可以选择“一次性生成所有数据”或者“按天流式生成”——对于需要长时间运行的游戏服务端后者更友好。我也加入了随机种子机制传入相同的seed就能复现完全一样的天气序列方便做对照测试。这在机器学习训练场景里特别重要否则每次喂给模型的数据都不一致没法判断模型改进效果。4. 我在实际调试中踩过的坑4.1 温度曲线卡在凌晨不敢升温第一次跑全年的温度序列时早晨6-8点的温度总有一个突兀的“平台”怎么都不自然。后来我发现是日曲线公式里的相位写错了我用了一个固定的整数小时偏移没有考虑到日出时间每天都在变。凌晨5点已经天亮但公式里还是夜间的衰减段升温和降温两段衔接区产生了一个不连续的拐点。解决办法是把“日出时间”作为参数用一年中的日序计算一个简单的日出时间公式不考虑经度时区的情况下然后把日变化曲线分裂成两段一段是夜间指数衰减另一段是白天正弦上升。在两段之间取最大值或最小值来过渡。4.2 降水状态机太“持久”导致长旱期我最初设的转移概率是“干转湿0.1湿转干0.2”理论上平均湿期为5天干期为9天看起来合理。但实际生成连续十年数据时出现了长达两个月没有降雨的极端旱期把整个模拟项目的农田系统直接搞崩溃了。后来查了一下因为马尔可夫链的无记忆性和转移概率误差会放大极端事件。我调整了概率并加入了“最大干期”约束当连续干天数超过阈值时强制把下一个小时设为湿状态。虽然这破坏了纯马尔可夫的性质但换来的是不会出现地球变成沙漠的离奇数据。4.3 噪声频率不对风像是在抽风写阵风时我一开始用np.random.randn直接乘一个幅值加在风速上结果五分钟级的数据还好一缩放到小时级就全是毛刺甚至出现负风速。问题的根源是我把白噪声当成了高频噪声白噪声在小时级采样下也会表现为剧烈跳跃而真实风的变化是相对平滑的更多的符合布朗运动或低频扰动。最终我改用低通滤波后的噪声先生成高频随机序列再用滑动平均窗口比如6小时窗口做平滑然后叠加到主风场上。这样一来阵风有了但不会严重影响整体风速的趋势。4.4 随机种子的科学使用刚开始我没有认真管理随机种子每次生成结果都不同导致同事以为我的代码里有bug。后来我把随机种子拆成两个部分一个全局种子控制气候基线一个阶段种子控制每天的扰动。这样我可以做到复现整个月的数据或者只复现某一天的天气而不会打乱后续序列。另外别忘了np.random和 Python 的random模块是两套随机数流如果你同时用到两者必须在两处都设置种子否则复现会失效。我当时就被这个坑烦了很久。5. 常见问题速查与扩展方向5.1 常见问题速查表现象可能原因解决方式温度序列像白噪声自回归系数太小把 AR(1) 系数调到0.85-0.95生成的雨量总是毛毛雨Gamma 分布尺度参数太小按季节调大尺度参数或改用混合分布冬季湿度出现明显不合理低值直接用夏季的相对湿度参数用湿度发生器基于饱和水汽压反推相对湿度风速偶发负值未对风速做非负约束用abs()或clip()但不能影响主风向降水时温度不降降水事件未联动温度修正降水时降低日较差增加云量遮挡复现失败随机数未全部指定种子统一np.random.seed()检查多个循环入口生成速度太慢用纯 Python 循环逐小时迭代尽量向量化按天或按月批量计算5.2 后续还能怎么扩展我现在这个版本可以输出小时级连续天气但还有几个方向可以继续完善空间扩展把单个点变成二维网格加入空间相关性让相邻区域的天气相似可以模拟气象前锋扫过一片区域的过程。更复杂的降水模型引入层状云降水和对流性降水的区别把降水量分成大尺度背景雨和局地阵雨分别触发。极端天气事件库添加台风、冰雹、龙卷风参数化模型不只是温度和雨量还包含气压突变和风灾影响范围。校准到真实统计分布如果手头有某个真实气象站的多年统计数据可以提取月平均温和湿度方差然后将生成器的参数自动拟合到这些统计量上这样生成数据虽然不完全等于真实值但统计特征完全一致。个人体会是天气生成器的核心不在代码多复杂而在于你对“变量之间的物理约束”理解有多深。与其堆一大堆神经网络模型不如先把确定性规律写扎实再用简单的随机过程去叠加。这样出来的数据既可控又可解释调试起来也方便得多。最后再分享一个小技巧在写任何气象变量之间联动逻辑前先把所有物理量单位统一温度用开尔文还是摄氏度、风速用m/s还是km/h、降水用mm/h还是mm/day最容易出错的地方往往不是公式本身而是单位换算。我最早就是因为把mm/day和mm/h混用导致生成了“每平方米每天一吨水”的离谱降雨量。如果你也准备折腾一个自己的天气生成器建议先从小范围开始只生成温度和时间序列跑通后再加入湿度、风速和降水。每加一个变量都要重新审视它和已有变量之间是否矛盾这样才能一步步搭出一套真实可用的系统。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑