Python: Как запретить функции Scipy optimize.minimize изменить форму начального предположения x0?
Я пытаюсь реализовать алгоритм оптимизации от Scipy. Он прекрасно работает, когда я реализую его без ввода функции градиента Якоби. Я полагаю, что проблема, которую я получаю при вводе градиента, заключается в том, что сама функция минимизации меняет форму первоначального предположения x0. Вы можете увидеть это из вывода кода ниже.
Входные данные:
import numpy as np
from costFunction import *
import scipy.optimize as op
def sigmoid(z):
epsilon = np.finfo(z.dtype).eps
g = 1/(1+np.exp(-z))
g = np.clip(g,epsilon,1-epsilon)
return g
def costFunction(theta,X,y):
m = y.size
h = sigmoid(X@theta)
J = 1/(m)*(-y.T@np.log(h)-(1-y).T@np.log(1-h))
grad = 1/m*X.T@(h-y)
print ('Shape of theta is',np.shape(theta),'\n')
print ('Shape of gradient is',np.shape(grad),'\n')
return J, grad
X = np.array([[1, 3],[5,7]])
y = np.array([[1],[0]])
m,n = np.shape(X)
one_vec = np.ones((m,1))
X = np.hstack((one_vec,X))
initial_theta = np.zeros((n+1,1))
print ('Running costFunction before executing minimize function...\n')
cost, grad = costFunction(initial_theta,X,y) #To test the shape of gradient before calling minimize
print ('Executing minimize function...\n')
Result = op.minimize(costFunction,initial_theta,args=(X,y),method='TNC',jac=True,options={'maxiter':400})
Выход:
Running costFunction before executing minimize function...
Shape of theta is (3, 1)
Traceback (most recent call last):
Shape of gradient is (3, 1)
Executing minimize function...
Shape of theta is (3,)
File "C:/Users/#####/minimizeshapechange.py", line 34, in <module>
Shape of gradient is (3, 2)
Result = op.minimize(costFunction,initial_theta,args=(X,y),method='TNC',jac=True,options={'maxiter':400})
File "C:\Users\#####\anaconda3\lib\site-packages\scipy\optimize\_minimize.py", line 453, in minimize
**options)
File "C:\Users\#####\anaconda3\lib\site-packages\scipy\optimize\tnc.py", line 409, in _minimize_tnc
xtol, pgtol, rescale, callback)
ValueError: tnc: invalid gradient vector from minimized function.
Process finished with exit code 1
4 ответа
Я не буду анализировать ваши точные вычисления, но некоторые замечания:
- (1) Ваш градиент сломан!
- Сципи ожидает частичную производную, в результате чего массив формы, равный вашему
x0
, - ваш градиент имеет форму
(3,2)
, в то время как(n+1, 1)
ожидается - сравнить с примером, приведенным в учебнике, который использует
scipy.optimize.rosen_der
(der = производная)
- Сципи ожидает частичную производную, в результате чего массив формы, равный вашему
- (2) Кажется, ваша scipy-версия немного старше, потому что моя (0.19.0) говорит мне:
ValueError: tnc: invalid gradient vector from minimized function.
Некоторый поддерживающий исходный код от scipy:
if (PyArray_SIZE(arr_grad) != py_state->n)
{
PyErr_SetString(PyExc_ValueError,
"tnc: invalid gradient vector from minimized function.");
goto failure;
Примечание: этот код выше был изменен / затронут / введен 5 лет назад. Если вы действительно не получаете эту ошибку при использовании вашего кода в списке (с удалением импорта costFunction), похоже, вы используете scipy
У меня была та же проблема со Сципи, который пытался сделать то же самое, что и ты. Я не совсем понимаю, почему это решает проблему, но игра с формами массива, пока она не сработала, дала мне следующее:
Градиентная функция определяется следующим образом
def Gradient(theta,X,y):
#Initializing variables
m = len(y)
theta = theta[:,np.newaxis] #<---- THIS IS THE TRICK
grad = np.zeros(theta.shape)
#Vectorized computations
z = X @ theta
h = sigmoid(z)
grad = (1/m)*(X.T @ ( h - y));
return grad #< --- also works with grad.ravel()
Initial_theta инициализируется как
initial_theta = np.zeros((n+1))
initial_theta.shape
(3,)
то есть простой массив NumPy, а не вектор столбца.
Функция градиента возвращает
Gradient(initial_theta,X,y).shape
(3,1) или (3,) в зависимости от того, возвращает ли функция grad
или же grad.ravel
scipy.optimize называется
import scipy.optimize as opt
model = opt.minimize(fun = CostFunc, x0 = initial_theta, args = (X, y), method = 'TNC', jac = Gradient)
Что не работает со Scipy
Initial_theta формы (3,1) с использованием initial_theta = np.zeros((n+1))[:,np.newaxis]
вылетает вызов функции scipy.minimize.
ValueError: tnc: недопустимый вектор градиента из свернутой функции.
Если бы кто-то мог уточнить эти моменты, это было бы здорово! Спасибо
Пожалуйста скопируйте и вставьте в jpuiter in1 и так далее в отдельную ячейку
In 1
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
filepath =('C:/Pythontry/MachineLearning/dataset/couresra/ex2data1.txt')
data =pd.read_csv(filepath,sep=',',header=None)
#print(data)
X = data.values[:,:2] #(100,2)
y = data.values[:,2:3] #(100,1)
#print(np.shape(y))
#In 2
#%% ==================== Part 1: Plotting ====================
postive_value = data.loc[data[2] == 1]
#print(postive_value.values[:,2:3])
negative_value = data.loc[data[2] == 0]
#print(len(postive_value))
#print(len(negative_value))
ax1 = postive_value.plot(kind='scatter',x=0,y=1,s=50,color='b',marker="+",label="Admitted") # S is line width #https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.scatter.html#matplotlib.axes.Axes.scatter
ax2 = negative_value.plot(kind='scatter',x=0,y=1,s=50,color='y',ax=ax1,label="Not Admitted")
ax1.set_xlabel("Exam 1 score")
ax2.set_ylabel("Exam 2 score")
plt.show()
#print(ax1 == ax2)
#print(np.shape(X))
# In 3
#============ Part 2: Compute Cost and Gradient ===========
[m,n] = np.shape(X) #(100,2)
print(m,n)
additional_coulmn = np.ones((m,1))
X = np.append(additional_coulmn,X,axis=1)
initial_theta = np.zeros((n+1), dtype=int)
print(initial_theta)
# In4
#Sigmoid and cost function
def sigmoid(z):
g = np.zeros(np.shape(z));
g = 1/(1+np.exp(-z));
return g
def costFunction(theta, X, y):
J = 0;
#print(theta)
receive_theta = np.array(theta)[np.newaxis] ##This command is used to create the 1D array
#print(receive_theta)
theta = np.transpose(receive_theta)
#print(np.shape(theta))
#grad = np.zeros(np.shape(theta))
z = np.dot(X,theta) # where z = theta*X
#print(z)
h = sigmoid(z) #formula h(x) = g(z) whether g = 1/1+e(-z) #(100,1)
#print(np.shape(h))
#J = np.sum(((-y)*np.log(h)-(1-y)*np.log(1-h))/m);
J = np.sum(np.dot((-y.T),np.log(h))-np.dot((1-y).T,np.log(1-h)))/m
#J = (-y * np.log(h) - (1 - y) * np.log(1 - h)).mean()
#error = h-y
#print(np.shape(error))
#print(np.shape(X))
grad =np.dot(X.T,(h-y))/m
#print(grad)
return J,grad
#In5
[cost, grad] = costFunction(initial_theta, X, y)
print('Cost at initial theta (zeros):', cost)
print('Expected cost (approx): 0.693\n')
print('Gradient at initial theta (zeros): \n',grad)
print('Expected gradients (approx):\n -0.1000\n -12.0092\n -11.2628\n')
In6 # Compute and display cost and gradient with non-zero theta
test_theta = [-24, 0.2, 0.2]
#test_theta_value = np.array([-24, 0.2, 0.2])[np.newaxis] #This command is used to create the 1D row array
#test_theta = np.transpose(test_theta_value) # Transpose
#test_theta = test_theta_value.transpose()
[cost, grad] = costFunction(test_theta, X, y)
print('\nCost at test theta: \n', cost)
print('Expected cost (approx): 0.218\n')
print('Gradient at test theta: \n',grad);
print('Expected gradients (approx):\n 0.043\n 2.566\n 2.647\n')
#IN6
# ============= Part 3: Optimizing using range =============
import scipy.optimize as opt
#initial_theta_initialize = np.array([0, 0, 0])[np.newaxis]
#initial_theta = np.transpose(initial_theta_initialize)
print ('Executing minimize function...\n')
# Working models
#result = opt.minimize(costFunction,initial_theta,args=(X,y),method='TNC',jac=True,options={'maxiter':400})
result = opt.fmin_tnc(func=costFunction, x0=initial_theta, args=(X, y))
# Not working model
#costFunction(initial_theta,X,y)
#model = opt.minimize(fun = costFunction, x0 = initial_theta, args = (X, y), method = 'TNC',jac = costFunction)
print('Thetas found by fmin_tnc function: ', result);
print('Cost at theta found : \n', cost);
print('Expected cost (approx): 0.203\n');
print('theta: \n',result[0]);
print('Expected theta (approx):\n');
print(' -25.161\n 0.206\n 0.201\n');
Результат: выполнение функции минимизации...
Тэты, найденные функцией fmin_tnc: (массив ([-25.16131854, 0.20623159, 0.20147149]), 36, 0) Стоимость в тете найдена: 0.218330193827 Ожидаемая стоимость (приблизительно): 0,203
тета: [-25,16131854 0,20623159 0,20147149] Ожидаемая тета (приблизительно):
-25,161 0,206 0,201
Ваш код costFunctuion неправильный, может быть, вы должны посмотреть, что
def costFunction(theta,X,y):
h_theta = sigmoid(X@theta)
J = (-y) * np.log(h_theta) - (1 - y) * np.log(1 - h_theta)
return np.mean(J)
Для меня сработало изменение формы y в виде вектора (1-D), а не матрицы (2-D массив). Я просто использовал следующий код, а затем перезапустил функцию минимизации SciPy, и это сработало.
y = np.reshape (y, 100) #eg, если ваша переменная y имеет 100 точек данных.
fmin_tnc scipy не очень хорошо работает с вектором столбца или строки. Ожидается, что параметры будут в формате массива.
Реализация курса машинного обучения Эндрю Нга на Python (часть 2.1)
opt.fmin_tnc(func = costFunction, x0 = theta.flatten(),fprime = gradient, args = (X, y.flatten()))
Немного поздно, но я также начал выполнять задание на Python и приложил много усилий для решения упомянутой проблемы. Наконец-то это работает для меня.
Этот блог мне поможет, но с одним изменением в вызове функции fmin_tnc см. Ниже:-
result = op.fmin_tnc(func=costFunction, x0=initial_theta, fprime=None, approx_grad=True, args=(X, y))
Получил эту информацию отсюда