You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GR4J模型随机参数优化循环代码修正问题

原代码核心问题
  • 循环逻辑完全失效:原代码用遍历数据长度的for循环搭配多层嵌套if,判断条件写反(比如先判断1 < NSE即NSE大于1,属于不可能出现的有效值区间),导致参数更新分支根本无法正常触发
  • 计算逻辑错误:参数更新分支中误将实测径流替换为降雨数据,导致指标计算完全失真;LMI公式笔误多写1个负号,计算结果错误
  • 冗余代码过多:参数生成、模型运行、指标计算的相同逻辑重复编写6次,极易引入笔误
  • 无效重复赋值:降雨、潜在蒸散等固定不变的输入数据,每次循环都重复赋值,浪费计算资源
修正后可直接运行的代码
import numpy as np

# ---------- 固定输入数据,仅需赋值1次 ----------
rainfall = dataframe['RAINFALL']
potential_evap = dataframe['PE or ETP or Evapotrans (mm)']
true_flow = df_3['Flows (m3/s)']  # 实测径流,全程固定不变
true_flow_mean = np.mean(true_flow)  # 实测径流均值提前计算,避免循环内重复运算
max_iter = 10000  # 最大迭代次数限制,防止程序无限卡死
iter_count = 0
best_params = None
best_metrics = None
best_sim_flow = None

# ---------- 重复逻辑封装为简单函数,无复杂语法 ----------
def generate_random_params():
    """生成指定取值范围内的GR4J随机参数与初始状态"""
    x1 = np.random.uniform(100, 1200)
    x2 = np.random.uniform(-5, 3)
    x3 = np.random.uniform(20, 300)
    x4 = np.random.uniform(1.1, 2.9)
    params = {'X1': x1, 'X2': x2, 'X3': x3, 'X4': x4}
    init_states = {
        'production_store': 0.6 * params['X1'],
        'routing_store': 0.7 * params['X3']
    }
    return params, init_states

def calc_eval_metrics(simulated, observed, obs_mean):
    """计算NSE、IA、LMI三项评价指标"""
    # 计算NSE
    nse = 1 - np.sum((simulated - observed)**2) / np.sum((observed - obs_mean)**2)
    # 计算IA
    ia = 1 - np.sum((observed - simulated)**2) / np.sum(
        (np.abs(simulated - obs_mean) + np.abs(observed - obs_mean))**2
    )
    # 计算LMI(修正原代码多写负号的笔误)
    lmi = 1 - np.sum(np.abs(simulated - observed)) / np.sum(np.abs(observed - obs_mean))
    return nse, ia, lmi

# ---------- 循环迭代寻优 ----------
while True:
    iter_count += 1
    # 生成随机参数与初始状态
    params, init_states = generate_random_params()
    # 运行GR4J模型得到模拟径流
    sim_flow = gr4j(rainfall, potential_evap, params, init_states)
    # 计算三项评价指标
    nse, ia, lmi = calc_eval_metrics(sim_flow, true_flow, true_flow_mean)
    
    # 每100次迭代打印进度,方便查看运行状态
    if iter_count % 100 == 0:
        print(f"已迭代{iter_count}次,当前指标:NSE={nse:.3f}, IA={ia:.3f}, LMI={lmi:.3f}")
    
    # 判断是否满足终止条件:三个指标全部落在0.5~1区间
    meet_threshold = (0.5 <= nse <= 1) and (0.5 <= ia <= 1) and (0.5 <= lmi <= 1)
    if meet_threshold:
        best_params = params
        best_metrics = (nse, ia, lmi)
        best_sim_flow = sim_flow
        print(f"\n找到符合要求的参数,共迭代{iter_count}次")
        print(f"参数值:X1={params['X1']:.2f}, X2={params['X2']:.2f}, X3={params['X3']:.2f}, X4={params['X4']:.2f}")
        print(f"指标值:NSE={nse:.3f}, IA={ia:.3f}, LMI={lmi:.3f}")
        break
    
    # 达到最大迭代次数则退出
    if iter_count >= max_iter:
        print(f"\n达到最大迭代次数{max_iter}次,未找到满足阈值要求的参数,请检查参数范围或阈值设置")
        break
代码说明
  • 没有使用复杂的类逻辑,仅将重复执行的代码块封装为两个简单函数,逻辑和原代码单段书写的逻辑完全一致,只是避免重复抄写引入笔误
  • 采用while循环实现迭代逻辑,每次循环重新生成随机参数、运行模型、计算指标,只有当三项指标同时满足阈值要求时才终止循环
  • 保留了和原代码完全一致的参数取值范围、初始状态计算规则、GR4J模型调用方式、指标计算公式,仅修正了笔误
  • 运行过程中会自动打印迭代进度,找到符合要求的参数后会直接输出最终参数与对应指标值

内容的提问来源于stack exchange,提问作者kiwi_kimchi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 14:09:18