2014-01-10 4 views
0

Я изучаю некоторые функции numpy/scipy, и я заметил, что scipy.optimize.fmin_bfgs требует изменения вызываемой функции, чтобы дать правильные результаты по сравнению с прямой вызов функции. Мое первое определение функции fnRSS возвращает правильное значение при вызове функции, но отказывается работать в оптимизации; мое второе определение дает неправильный результат при вызове функции, но правильный при запуске оптимизации. Может ли кто-нибудь сказать мне, что так важно для переноса параметра vY для оптимизации? Он должен быть уже 164x1.Оптимизация scipy.optimize.fmin_bfgs дает отличный результат от простого вызова функции

import numpy as np 
import scipy as sp 
import pandas as pd 
from scipy import optimize 

if __name__ == "__main__": 
    urlSheatherData = "http://www.stat.tamu.edu/~sheather/book/docs/datasets/MichelinNY.csv" 
    data = pd.read_csv(urlSheatherData) 
    Xs = np.vstack(data[['Service','Decor', 'Food', 'Price']].values) 
    Xs = np.concatenate((np.vstack(np.ones(Xs.shape[0])),Xs), axis=1) 
    Ys = np.vstack(data[['InMichelin']].values) 
    # optimal solution (given) 
    vBeta = np.array([-1.49209249, -0.01117662, 0.044193, 0.05773374, 0.00179794]).reshape(5,1) 

    print Ys.shape, Xs.shape, vBeta.shape 
    # first definition of function 
    def fnRSS(vBeta, vY, mX): 
     return np.sum((vY - np.dot(mX, vBeta))**2) 
    print fnRSS(vBeta, Ys, Xs) # correct value 
    print np.linalg.lstsq(Xs, Ys)[1] # confirm correct value 
    print sp.optimize.fmin_bfgs(fnRSS, x0=vBeta, args=(Ys,Xs)) # wrong value 
    # second definition 
    def fnRSS(vBeta, vY, mX): 
     return np.sum((vY.T - np.dot(mX, vBeta))**2) 
    print fnRSS(vBeta, Ys, Xs) # incorrect value 
    print sp.optimize.fmin_bfgs(fnRSS, x0=vBeta, args=(Ys,Xs)) # correct convergence but simple call gives different value 

Мой выход:

(164, 1) (164, 5) (5, 1) 
26.3239061505 
[ 26.32390615] 
Warning: Desired error not necessarily achieved due to precision loss. 
     Current function value: 6660.000000 
     Iterations: 39 
     Function evaluations: 3558 
     Gradient evaluations: 480 
[ 4.51220111e-01 1.32711255e-07 8.09143368e-08 -1.06633003e-07 
    -5.18448332e-08] 
9002.87916028 
Warning: Desired error not necessarily achieved due to precision loss. 
     Current function value: 26.323906 
     Iterations: 29 
     Function evaluations: 1954 
     Gradient evaluations: 260 
[-1.49209095 -0.0111764 0.04419313 0.05773347 0.00179789] 
+0

as followup on alko: просто играйте с точкой и посмотрите, какую форму вы получите, когда vBeta - это одномерное по сравнению с массивом столбцов. np.dot транслирует/переносит 1d-массив, если необходимо, но форма и ndim разные. Y должен соответствовать вашему vBeta.ndim – user333700

+0

Спасибо, я буду играть с этим. Мне кажется, мне не нравится, что вам нужно оптимизировать функцию, которая дает неверный доход, когда вы проверяете результат оптимизации - это убивает много модульных тестов. –

ответ

0

Это не о vY.T, но vBeta, т.е. x передается от fmin_bfgs к fnRSS как не 2d вектора, но в 1d массиве. Поэтому, несмотря на то, что вы явно пытаетесь указать x0=vBeta как массив формы (5,1), он преобразуется внутренне в 1d массив формы (5) и в конце возвращается как таковой.

+0

Я понимаю, что вы имеете в виду, и я вижу, что это происходит, когда я помещаю 'print vY.shape, mX.shape, vBeta.shape' внутри функции' fnRSS', но я не вижу, как это испортит конвергенцию или требуется 'vY.T'. Не поймите меня неправильно, вы, вероятно, правы, потому что это работает, но в первом определении вы должны получить '(164,1) - (164,)' внутри первых скобок, но второе определение должно дать '(1,164) - (164,) ', который еще не должен вычислять. –

Смежные вопросы