Я пытаюсь использовать библиотеку scipy.least_squares для решения больших, разреженных, нелинейных задач.Пока это было здорово!
Однако, один недостаток, с которым я столкнулся и до сих пор не смог обойти, - это использование матрицы весов для наблюдений и / или остаточного вектора.ПРИМЕЧАНИЕ. Я знаю, что можно установить границы параметров, однако это не то, чего я пытаюсь достичь.
Этот пример был взят из предыдущего вопроса о переполнении стека, но ответ включал scipy.optimize,не scipy.optimize.least_squares.Хотя этот конкретный пример несколько тривиален, проблемы, которые я пытаюсь решить, могут включать сотни тысяч наблюдений и десятки тысяч параметров.Следовательно, поэтому крайне важно использовать наименьшие квадраты.
В этом случае я хотел бы использовать веса из остатков первоначальной подгонки и попытаться выполнить перестройку с помощью наименьших квадратов с использованием весов.Веса должны быть обратными к остаткам (или обратным значениям остатков, умноженным на коэффициент масштабирования).
import numpy as np
from scipy.optimize import least_squares
ydata = [9.7372923, 10.0587245, 10.3838510, 10.6931371, 10.9616260, 11.1833220, 11.3806770, 11.5248917, 11.7353000]
xdata = np.array([j+5 for j in range(len(ydata))])
def get_weights(resid):
"""
This function calculates the weights per (x,y) by using the inverse of the squared residuals divided by the total sum of the inverse of the squared residuals.
This might be incorrect but should work for the sake of example.
"""
total = sum([abs(resid[i]) for i in range(len(resid))])
fract = np.array([resid[i]/total for i in range(len(resid))])
return fract
def get_least_squares_fit(xs, ys):
"""
This function finds alpha (1/slope) and the y-intercept in the equation
of a line y = x / alpha + intercept = mx + b
"""
## SPECIFY INITIAL GUESS OF OPTIMIZED PARAMETERS
params_guess = [1/3, 9] ## ps = [alpha, intercept]
## DEFINE FITTING FUNCTIONS
fit_func = lambda ps,x : x/ps[0] + ps[1]
err_func = lambda ps,x,y : fit_func(ps,x) - y
## GET OPTIMIZED PARAMETERS, RESIDUALS & WEIGHTS
res = least_squares(err_func, params_guess, args=(xs, ys))
alpha, intercept, residuals = res.x[0], res.x[1], res.fun
weights = get_weights(residuals)
return alpha, intercept, residuals, weights
alpha, intercept, residuals, weights = get_least_squares_fit(xdata, ydata)
print(alpha, intercept)
>> 4.03378447722 8.6198247828
print(residuals)
>> [ 0.12206326 0.04853721 -0.02868313 -0.09006308 -0.11064582 -0.08443567
-0.03388451 0.06980694 0.1073048 ]