Bạn có thể sử dụng scipy.optimize.minimize
với jac=True
. Nếu đó không phải là một lựa chọn cho một số lý do, sau đó bạn có thể nhìn vào how it handles this situation:
class MemoizeJac(object):
""" Decorator that caches the value gradient of function each time it
is called. """
def __init__(self, fun):
self.fun = fun
self.jac = None
self.x = None
def __call__(self, x, *args):
self.x = numpy.asarray(x).copy()
fg = self.fun(x, *args)
self.jac = fg[1]
return fg[0]
def derivative(self, x, *args):
if self.jac is not None and numpy.alltrue(x == self.x):
return self.jac
else:
self(x, *args)
return self.jac
Lớp này kết thúc tốt đẹp một hàm trả về giá trị chức năng và gradient, giữ một bộ nhớ cache một phần tử và kiểm tra mà để xem nếu nó đã biết kết quả của nó. Cách sử dụng:
fmemo = MemoizeJac(f, fprime)
xopt = fmin_cg(fmemo, x0, fmemo.derivative)
Điều kỳ lạ về mã này là nó giả định f
luôn gọi trước khi fprime
(nhưng không phải mọi f
gọi Tiếp theo là một cuộc gọi fprime
). Tôi không chắc chắn nếu scipy.optimize
thực sự đảm bảo rằng, nhưng mã có thể dễ dàng thích nghi để không làm cho rằng giả định, mặc dù. Phiên bản mạnh mẽ của các bên trên (chưa được kiểm tra ):
class MemoizeJac(object):
def __init__(self, fun):
self.fun = fun
self.value, self.jac = None, None
self.x = None
def _compute(self, x, *args):
self.x = numpy.asarray(x).copy()
self.value, self.jac = self.fun(x, *args)
def __call__(self, x, *args):
if self.value is not None and numpy.alltrue(x == self.x):
return self.value
else:
self._compute(x, *args)
return self.value
def derivative(self, x, *args):
if self.jac is not None and numpy.alltrue(x == self.x):
return self.jac
else:
self._compute(x, *args)
return self.jac
+1 đẹp cách của bộ nhớ đệm trở lại cuộc gọi ngoái! Sẽ không quá khó để vượt qua giới hạn tiềm năng cuối cùng đó ('f' được gọi trước' fprime'), đúng không? – Jaime
@Jaime: không, chỉ cần lặp lại mẹo được sử dụng trong 'đạo hàm'. Xem câu trả lời được cập nhật. –
Waw, đây là một giải pháp tuyệt vời, tôi chỉ thử nghiệm mã của tôi với một cái gì đó như 'minim (fun = self._cost_grad, x0 = initial_theta, method = 'Newton-CG', tùy chọn = {'maxiter': 20, 'disp ': True}, jac = True, args = (X, n_features, n_samples)) ', và tôi có kết quả tuyệt vời. Tham số 'fun' mong đợi một hàm trả về (cost, grad) như tuple và' method' có thể được thay đổi đơn giản để thực hiện 'l_bfgs',' bfgs', 'cg' hoặc bất kỳ trình tối ưu hóa nào có trong scipy. Cảm ơn rất nhiều! Tôi ngạc nhiên câu trả lời này không phổ biến. – Curious