machine-learning - scipy.optimize.minimize 如何对损失函数求导?
问题描述
我试图弄清楚 scipy.optimize.minimize 在机器学习中是如何工作的。到目前为止,我知道您向它传递了一个损失函数,以便它可以找到给您带来最低损失的参数值。但据我了解,它首先必须找到损失函数的梯度/Hessian,然后才能找到最小值。它是如何做到的?它是如何知道如何获取包含其他函数调用和算法的python函数的导数?它如何将其推导出为一个数学函数,它可以对其进行导数?在我的例子中,我传递给最小化的损失函数执行以下操作:首先它解决了一个流行病学模型 (SEIRD),该模型旨在预测 COVID-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')
它最终给了我一个非常低的 MSLE,所以它工作得很好,我只是不明白到底是怎么回事。
解决方案
但据我了解,它首先必须找到损失函数的梯度/Hessian,然后才能找到最小值。它是如何做到的?
这取决于您为参数提供的内容以及您在 python 环境中拥有的 SciPy 版本。最后我检查了一些支持渐变的方法。此处 1.4.1 版本的文档: https ://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html
节目
jac{callable, ‘2-point’, ‘3-point’, ‘cs’, bool}, optional
并描述了哪些最小化器支持哪些。您可以使用有限差分方案“2 点”,这是许多人的默认设置。
Acallable
表示您提供了一个已__call__
实现属性的函数或对象(独立函数默认具有此属性,对象没有)。如果你知道你已经分析计算并在 python 中实现的雅可比或梯度 b/c(或通过低级可调用的 C/C++:https ://docs.scipy.org/doc/scipy-),通常会使用它1.4.0/reference/generated/scipy.LowLevelCallable.html?highlight=lowlevelcallable#scipy.LowLevelCallable )
这个cs
选项非常酷,我在第一次开始使用 SciPy 时就知道了这个选项。基本上,您在目标函数中的所有操作都传递了具有非常小的复杂值(例如 0.0001)的复杂参数,然后取结果的复杂部分可以很好地估计梯度(优于有限差分)。
布尔值更多的是关于是否表示为稀疏或密集,并且并非在所有优化程序例程中都使用。
我应该澄清的一件事是minimize
例程只是转发到实际处理优化的相关优化器方法(例如'trust-constr'、'slsqp'等)。尤其是黑森州。
希望这可以帮助您了解minimize
例行程序的“幕后”发生了什么。
它是如何知道如何获取包含其他函数调用和算法的python函数的导数?
在您提供的情况下,我认为它只是调用该函数并没有什么特别之处。
此外,作为旁注(不是您的两个问题中的任何一个),如果您想跟踪优化器的进度,您可以通过disp=True
,或者disp=1
随着优化器的进展,它应该向您显示一些高级跟踪输出。
推荐阅读
- c# - PDFium - 从图像流创建 PDF 文档而不在 c# 中转换为位图
- optimization - float32 between (0, 1) 优化无线传输
- c - 如何让用户只输入来自txt文件的特定输入
- c# - Angular ASP.NET SQL:将表变量值发送到另一个组件
- javascript - 我想将 app.js 中存在的 count 值获取到 counter.js 我是新来的反应 js
- ios - 如何找到所有未指定访问级别的函数?
- c++ - 如何在 I2C 中使用 Arduino 从 LIDAR 的正确地址读取?
- excel - 如何下拉菜单依赖照片粘贴vba excel
- sql - 如何从 Oracle 和 SQLServer 上的数据库中列出模式名称?
- google-calendar-api - 更新用户 responseStatus Google Calendar API