Machine learning scipy.optimize.minimize如何获取损失函数的导数?

Machine learning scipy.optimize.minimize如何获取损失函数的导数?,machine-learning,optimization,scipy,loss-function,scipy-optimize-minimize,Machine Learning,Optimization,Scipy,Loss Function,Scipy Optimize Minimize,我试图弄清楚scipy.optimize.minimize在机器学习中是如何工作的。到目前为止,我知道你给它传递了一个损失函数,这样它就可以找到给你最低损失的参数值。但据我所知,它必须先找到损失函数的梯度/Hessian,然后才能找到极小值。它是怎么做到的?它如何知道如何获取python函数的派生,python函数中包含其他函数调用和算法?它怎么能把它推导出一个数学函数,它可以取它的导数? 在我的情况下,我传递到最小化的损失函数执行以下操作: 首先,它解决了一个流行病学模型(SEIRD),该模型

我试图弄清楚scipy.optimize.minimize在机器学习中是如何工作的。到目前为止,我知道你给它传递了一个损失函数,这样它就可以找到给你最低损失的参数值。但据我所知,它必须先找到损失函数的梯度/Hessian,然后才能找到极小值。它是怎么做到的?它如何知道如何获取python函数的派生,python函数中包含其他函数调用和算法?它怎么能把它推导出一个数学函数,它可以取它的导数? 在我的情况下,我传递到最小化的损失函数执行以下操作: 首先,它解决了一个流行病学模型(SEIRD),该模型用于预测新冠病毒-19的确诊病例和死亡。然后将模型结果与实际数据进行比较,并找到它返回的MSLE。代码如下所示:

def model_decay(params, data, population, return_solution=False, full_validation=True, forecast_days=0):
R_0, theta, k, L, R_t, D_rec, D_inc = params # R_0, fatality rate, k form, L shape, R end
N = population # Population of each country

n_infected = data['ConfirmedCases'].iloc[0] 
n_dead = data['Fatalities'].iloc[0]
max_days = len(data) + forecast_days 
rho = 1.0 / D_rec
alpha = 1.0 / D_inc    
beta = R_0 * rho  

y0 = N - n_infected, 0, n_infected, 0 ,0  

def beta(t):
    return ((R_0-R_t) / (1 + (t/L)**k)+R_t) * rho

t= np.arange(max_days)

# Solve the SEIR differential equation.
sol = solve_ivp(seir_d, [0, max_days],y0,  args=(N, beta, rho, alpha, theta),t_eval=t)
sus, exp, inf, rec, dead = sol.y    

#model_decay.counter +=1
#print(model_decay.counter)

# Predict confirmedcases
y_pred_cases = np.clip((inf + rec+dead),0,np.inf) 
y_true_cases = data['ConfirmedCases'].values

# Predict fatalities
y_pred_dead = np.clip((dead),0,np.inf) 
y_true_dead = data['Fatalities'].values    

#Thanks to anjum-48 for the following lines of code in this function.

optim_days = min(20, len(data))  # Days to optimise for finds the lowest num. 

weights = 1 / np.arange(1, optim_days+1)[::-1]  # Recent data is more heavily weighted
# using mean squre log error to evaluate
msle_conf = mean_squared_log_error(y_true_cases[-optim_days:], y_pred_cases[-optim_days:],weights)
msle_dead = mean_squared_log_error(y_true_dead[-optim_days:], y_pred_dead[-optim_days:],weights)
if full_validation == True :
    msle = np.mean([msle_conf,msle_dead])
else : 
    msle = msle_conf

if return_solution:
    return msle, sol
else:
    return msle
model_decay_res = minimize(model_decay, [1.8, 0.04, 2, 20, 1 ,15, 4.9], 
                bounds=((0, 6.49), (0.01, 0.15), (0, 5), (0, 200),(0,6.49),(3.48,18),(4.9,5.9)),
                args=(train_data, population, False,full_validation),
                method='L-BFGS-B')
最小化调用如下所示:

def model_decay(params, data, population, return_solution=False, full_validation=True, forecast_days=0):
R_0, theta, k, L, R_t, D_rec, D_inc = params # R_0, fatality rate, k form, L shape, R end
N = population # Population of each country

n_infected = data['ConfirmedCases'].iloc[0] 
n_dead = data['Fatalities'].iloc[0]
max_days = len(data) + forecast_days 
rho = 1.0 / D_rec
alpha = 1.0 / D_inc    
beta = R_0 * rho  

y0 = N - n_infected, 0, n_infected, 0 ,0  

def beta(t):
    return ((R_0-R_t) / (1 + (t/L)**k)+R_t) * rho

t= np.arange(max_days)

# Solve the SEIR differential equation.
sol = solve_ivp(seir_d, [0, max_days],y0,  args=(N, beta, rho, alpha, theta),t_eval=t)
sus, exp, inf, rec, dead = sol.y    

#model_decay.counter +=1
#print(model_decay.counter)

# Predict confirmedcases
y_pred_cases = np.clip((inf + rec+dead),0,np.inf) 
y_true_cases = data['ConfirmedCases'].values

# Predict fatalities
y_pred_dead = np.clip((dead),0,np.inf) 
y_true_dead = data['Fatalities'].values    

#Thanks to anjum-48 for the following lines of code in this function.

optim_days = min(20, len(data))  # Days to optimise for finds the lowest num. 

weights = 1 / np.arange(1, optim_days+1)[::-1]  # Recent data is more heavily weighted
# using mean squre log error to evaluate
msle_conf = mean_squared_log_error(y_true_cases[-optim_days:], y_pred_cases[-optim_days:],weights)
msle_dead = mean_squared_log_error(y_true_dead[-optim_days:], y_pred_dead[-optim_days:],weights)
if full_validation == True :
    msle = np.mean([msle_conf,msle_dead])
else : 
    msle = msle_conf

if return_solution:
    return msle, sol
else:
    return msle
model_decay_res = minimize(model_decay, [1.8, 0.04, 2, 20, 1 ,15, 4.9], 
                bounds=((0, 6.49), (0.01, 0.15), (0, 5), (0, 200),(0,6.49),(3.48,18),(4.9,5.9)),
                args=(train_data, population, False,full_validation),
                method='L-BFGS-B')
它给了我一个非常低的MSLE在最后,所以它的工作相当好,我只是不明白到底如何

但据我所知,它必须先找到损失函数的梯度/Hessian,然后才能找到极小值。它是怎么做到的

这取决于为参数指定的内容以及python环境中使用的SciPy版本。最后我检查了一些支持的渐变方法。此处列出了1.4.1版本的文档:

展示

jac{callable,'2-point','3-point','cs',bool},可选

并描述了哪些最小化支持哪些。 您可以使用有限差分格式“2点”,这是许多应用程序的默认值

可调用
表示您提供的函数或对象实现了
\uuuu调用
属性(默认情况下,独立函数具有此属性,而对象不具有此属性)。如果您知道用python(或c/c++通过低级可调用:)分析计算并实现的jacobian或gradient b/c,通常会使用此选项

cs
选项非常酷,是我第一次开始使用SciPy时学到的。基本上,目标函数中的所有操作都是通过复数参数传递的,复数值很小(例如0.0001),然后通过结果的复数部分,可以很好地估计梯度(比有限差分更好)

布尔值更多的是表示为稀疏还是密集,并不是在所有优化器例程中都使用

我应该澄清的一件事是
最小化
例程只是转发到相关的优化器方法(例如“trust constr”、“slsqp”等),在那里实际处理优化。
我喜欢黑森人

希望这能帮助您了解
minimize
例行程序的“幕后”情况

它如何知道如何获取python函数的派生,python函数中包含其他函数调用和算法

在您提供的情况下,我认为它只是调用函数,没有什么特别之处

另外,作为旁注(不是你的两个问题中的任何一个),如果你想跟踪优化器的进度,你可以传递
disp=True
disp=1
,这应该会随着优化器的进度向你显示一些高级跟踪输出

但据我所知,它必须先找到损失函数的梯度/Hessian,然后才能找到极小值。它是怎么做到的

这取决于为参数指定的内容以及python环境中使用的SciPy版本。最后我检查了一些支持的渐变方法。此处列出了1.4.1版本的文档:

展示

jac{callable,'2-point','3-point','cs',bool},可选

并描述了哪些最小化支持哪些。 您可以使用有限差分格式“2点”,这是许多应用程序的默认值

可调用
表示您提供的函数或对象实现了
\uuuu调用
属性(默认情况下,独立函数具有此属性,而对象不具有此属性)。如果您知道用python(或c/c++通过低级可调用:)分析计算并实现的jacobian或gradient b/c,通常会使用此选项

cs
选项非常酷,是我第一次开始使用SciPy时学到的。基本上,目标函数中的所有操作都是通过复数参数传递的,复数值很小(例如0.0001),然后通过结果的复数部分,可以很好地估计梯度(比有限差分更好)

布尔值更多的是表示为稀疏还是密集,并不是在所有优化器例程中都使用

我应该澄清的一件事是
最小化
例程只是转发到相关的优化器方法(例如“trust constr”、“slsqp”等),在那里实际处理优化。
我喜欢黑森人

希望这能帮助您了解
minimize
例行程序的“幕后”情况

它如何知道如何获取python函数的派生,python函数中包含其他函数调用和算法

在您提供的情况下,我认为它只是调用函数,没有什么特别之处

另外,作为旁注(不是你的两个问题中的任何一个),如果你想跟踪优化器的进度,你可以传递
disp=True
disp=1
,这应该会随着优化器的进度向你显示一些高级跟踪输出

见和。在您使用
'L-BFGS-B'
的案例中,我认为数值微分外包给了解算器基于fortran的外部代码(而不是使用scipy的代码)。当然有一些规则需要遵守:scipy.optimize中的大多数解算器都假设您的目标是两次可微的,类似于
np.clip((inf+rec+dead),0