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

使用scipy minimize时log函数出现RuntimeWarning,该如何修复?

RuntimeWarning: invalid value encountered in log 当使用scipy.minimize拟合参数时

问题描述

使用NumPy结合scipy的minimize函数进行参数拟合时触发RuntimeWarning: invalid value encountered in log,对应代码为计算model的语句。流程是先生成模拟数据,定义对数似然函数log_likelihood,通过最小化负对数似然拟合参数,但运行后minimize返回初始参数值,同时出现上述警告。

已检查初始参数下的log函数参数数组1-s*np.sin(2*np.pi*t/p_orb-phi_orb),确认无零或负值,但警告仍存在。

相关代码

r = 9.85E-6
i = np.pi/2
s = np.sin(i)
N = 157788
t = np.linspace(0 , 9.461E7 , N)
p_orb = 2400
phi_orb = np.pi/3
R = 1.496E11
c = 299752498
D = 1000
Beta = 50*np.pi/180
Lambda = np.pi/4
sigmas = np.ones(N)*0.000001
data = ((-2*r) * np.log(1-s*np.sin(2*np.pi*t/p_orb-phi_orb))) + (-(R**2)/(c*D*9.461E15)*(np.cos(Beta)**2)*np.cos((4*np.pi*t)/(3.154E7)-2*Lambda)) + sigmas

def log_likelihood(theta , t , data , sigmas):
    r , s , D = theta
    model = ((-2*r) * np.log(1-s*np.sin(2*np.pi*t/p_orb-phi_orb))) + (-(R**2)/(c*D*9.461E15)*(np.cos(Beta)**2)*np.cos((4*np.pi*t)/(3.154E7)-2*Lambda))
    return -0.5 * sum(((data - model)**2)/(sigmas**2))

nll = lambda *args: -log_likelihood(*args)
initial = np.array([r , s , D])
soln = minimize(nll , initial , args = (t , data , sigmas))
r_ml, s_ml, D_ml = soln.x
print(r_ml , s_ml , D_ml)

检查代码及结果

array = 1-s*np.sin(2*np.pi*t/p_orb-phi_orb)
# Check for zeros
zeros_indices = array == 0
zeros_exist = np.any(zeros_indices)

# Check for negative values
negative_indices = array < 0
negatives_exist = np.any(negative_indices)

if zeros_exist:
    print("Array contains zero(s).")
else:
    print("Array does not contain any zero.")

if negatives_exist:
    print("Array contains negative value(s).")
else:
    print("Array does not contain any negative value.")

输出:

Array does not contain any zero.
Array does not contain any negative value.

修复方案

1. 给参数添加边界约束

minimize在迭代过程中会尝试不同的参数值,可能出现s的绝对值大于1的情况,导致1-s*sin(...)变成非正值。针对参数的物理意义设置边界:

from scipy.optimize import Bounds

# 设置边界:r>0, s∈[-1,1], D>0
bounds = Bounds([0, -1, 0], [np.inf, 1, np.inf])
soln = minimize(nll, initial, args=(t, data, sigmas), bounds=bounds)

L-BFGS-B算法(默认支持边界的算法)会自动限制参数在合法范围内迭代。

2. 提升log计算的数值稳定性

即使有边界约束,浮点精度问题可能导致输入接近0,触发警告。可以用np.maximum强制log输入大于极小值:

def log_likelihood(theta , t , data , sigmas):
    r , s , D = theta
    # 确保log输入始终大于等于1e-12
    log_arg = np.maximum(1-s*np.sin(2*np.pi*t/p_orb-phi_orb), 1e-12)
    model = ((-2*r) * np.log(log_arg)) + (-(R**2)/(c*D*9.461E15)*(np.cos(Beta)**2)*np.cos((4*np.pi*t)/(3.154E7)-2*Lambda))
    return -0.5 * sum(((data - model)**2)/(sigmas**2))

3. 调试迭代过程中的参数

在似然函数中加入调试代码,定位迭代时是否出现非法参数:

def log_likelihood(theta , t , data , sigmas):
    r , s , D = theta
    log_arg = 1-s*np.sin(2*np.pi*t/p_orb-phi_orb)
    # 打印当前参数和log输入的极值
    print(f"Params: r={r:.6e}, s={s:.6f}, D={D:.0f}")
    print(f"log_arg min: {np.min(log_arg):.6e}, max: {np.max(log_arg):.6e}")
    if np.any(log_arg <= 0):
        print("⚠️ Invalid log argument detected!")
    log_arg = np.maximum(log_arg, 1e-12)
    model = ((-2*r) * np.log(log_arg)) + (-(R**2)/(c*D*9.461E15)*(np.cos(Beta)**2)*np.cos((4*np.pi*t)/(3.154E7)-2*Lambda))
    return -0.5 * sum(((data - model)**2)/(sigmas**2))

通过输出可以确认约束是否生效,以及问题出现的具体参数组合。

4. 指定合适的优化算法

明确指定支持边界约束的算法,避免默认算法切换带来的问题:

soln = minimize(nll, initial, args=(t, data, sigmas), bounds=bounds, method='L-BFGS-B')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 11:19:50