optimize.fmin_tnc не дает правильный ответ в scipy.optimize? - PullRequest
1 голос
/ 13 июня 2019

Я внедряю курс машинного обучения Эндрю Нг в Python. В упражнении по программированию 2 на первый вопрос я получаю ответы на запись для функции стоимости и градиента, но когда вычисления оптимизируют тета, я получаю катастрофический ответ!

Я уже старался изо всех сил, но не смог найти ошибку

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def cost_compute(  theta,x, y):
    J = (-1/m) * np.sum(np.multiply(Y, np.log(sigmoid(X @ theta))) 
        + np.multiply((1-Y), np.log(1 - sigmoid(X @ theta))))
    return J

[m, n] = X.shape
X = np.hstack( (np.ones((m,1)) , X) )
Y = Y[:, np.newaxis]
theta = np.zeros((n+1,1))

def grad( theta, X, Y):
    temp = (1/m) * X.T @ (sigmoid(X @ theta) - Y)  
    return temp

temp = opt.fmin_tnc(func = cost_compute, x0 = theta.flatten() , fprime = grad , args = (X, Y.flatten()))

print(temp)

ожидаемая стоимость 0,693, и я ее получаю. Ожидаемый градус также совпадает с фактическим ответом. Но оптимизированная тэта, которую я получаю, это массив ([4.42735730e-05, 5.31690927e-03, 4.98646266e-03], что дает мне новую цену около 60! (Вместо 0,203)

Ответы [ 2 ]

0 голосов
/ 23 июня 2019

Я провел несколько тестов, изменив формы массивов, сгладив их, изменив их форму, но ничего не получилось.

Поскольку мы вводили одномерную тэту в fmin_tnc путем сглаживания тэты, поэтому я подумал об изменении градиентафункция, предполагающая, что она получит тета одного измерения вместо 3 * 1.

Раньше она была

def grad( theta, X, Y):
    temp = (1/m) * X.T @ (sigmoid(X @ theta) - Y)  
    return temp

Теперь она равна

def grad( theta, X, Y):
    temp = (1/m) * (X.T @ (sigmoid(X @ theta[:,np.newaxis]) - Y))  
    return temp

Теперь онаработает!

0 голосов
/ 14 июня 2019

Проблема в том, что вы вызываете np.sum вместе с np.multiply вместо использования, например, np.dot, эти операции в общем случае не эквивалентны.

Операция np.multiply вычисляет поэлементное произведение,в то время как np.dot вычисляет правильное матричное произведение, см. этот ответ по SO от Anuj Gautam:

np.dot является точечным произведением двух матриц.

|A B| . |E F| = |A*E+B*G A*F+B*H|
|C D|   |G H|   |C*E+D*G C*F+D*H|

Принимая во внимание, что np.multiply выполняет поэлементное умножение двух матриц.

|A B| ⊙ |E F| = |A*E B*F|
|C D|   |G H|   |C*G D*H|

Для расчета перекрестной потери энтропиитребуется умножение матриц.

Изменение функции стоимости на

def cost_compute(  theta, X, Y):
    J = (-1/m) * (np.dot(Y.T, np.log(sigmoid(X @ theta))) 
        + np.dot((1-Y).T, np.log(1 - sigmoid(X @ theta))))
    return J

приводит к желаемому результату для меня:

>> cost_compute(temp[0], X, Y)
array([0.2034977])

Кроме того, случай ваших аргументовx и y функции cost_compute неверны, так как внутри функции используются заглавные версии X и Y.

...