[SciPy-User] return "full_output" or how to stop throwing away already calculated results

josef.pktd@gmai... josef.pktd@gmai...
Tue Mar 9 22:54:15 CST 2010


On Tue, Mar 9, 2010 at 10:37 PM, Rob Falck <robfalck@gmail.com> wrote:
> Returning an object would be my preference as well, it seems more
> pythonic.  Most optimizers should be able to return at a minimum
>
> result.x
> result.objfun
> result.iterations
> result.exit_status
>
> Some optimizers have other useful data to return, such as the Lagrange
> multiplers from slsqp.  Going down that path means probably breaking
> current implementations of the optimizers, but doing it right would be
> worth it, in my opinion.  We should also agree upon names for the
> common attributes.

If we create new functions, as David argued, then the old signature
could still be kept.

I was curious what the increase in call overhead is, and for an
essentially empty function it would be up to 60%. However, since this
is mainly for functions that do heavier work, this will not be really
relevant. (It might add a little bit to my Monte Carlos or bootstrap,
but this should be negligible), and we will gain if we don't have to
redo some calculations.

The main reason I liked the full output option instead of always
returning a result instance, is that, if full_output is true, then
additional results can be calculated, that I don't want when I just
need a fast minimal result.

Josef

>
> On Tue, Mar 9, 2010 at 8:56 PM, David Warde-Farley <dwf@cs.toronto.edu> wrote:
>>
>> On 9-Mar-10, at 4:01 PM, josef.pktd@gmail.com wrote:
>>
>>> in statsmodels, I am switching more to the pattern when
>>> full_output=True (or similar keyword) for a function, then all
>>> intermediate results are returned, attached to a generic class
>>> instance ( or could be a struct in matlab or a bunch for Gael,...)
>>
>> David Cournapeau pointed out (in the thread "anyone to look at #1402?"
>> on the numpy-discussion list) that the wider Python community frowns
>> on the type of the returned value depending on a boolean flag
>> argument, preferring instead different function names that call some
>> common (private) helper function. It provided some validation for my
>> uncomfortable feelings about scipy.optimize methods that do this.
>>
>> I do think it's worth thinking about returning some sort of proxy
>> object that can have attributes set to either 'None' or the
>> appropriate values. It would certainly make code more readable (except
>> in the situation where you use argument unpacking, but even then it
>> isn't obvious to an outsider how crucial that full_output thing is).
>>
>> David
>> _______________________________________________
>> SciPy-User mailing list
>> SciPy-User@scipy.org
>> http://mail.scipy.org/mailman/listinfo/scipy-user
>>
>
>
>
> --
> - Rob Falck
> _______________________________________________
> SciPy-User mailing list
> SciPy-User@scipy.org
> http://mail.scipy.org/mailman/listinfo/scipy-user
>
-------------- next part --------------


import numpy as np

class Store(object):
    pass

def function0():
    y = 0
#    x = np.random.randn(20,20)
#    y = np.linalg.inv(x)
#    y = np.corrcoef(x)
    return y

def function1():
    result = Store()
    result.a = np.arange(5)
    result.b = function0()
    return result

def function2():
    return np.arange(5), function0()
    
def function3():
    result = function1()
    return result.a, result.b

def function4(full_output=True):
    if full_output:
        result = Store()
        result.a = np.arange(5)
        result.b = function0()
        return result
    else:
        return np.arange(5), function0()

if __name__=='__main__':
    from timeit import Timer
    n = 10000
    t = Timer("r = function1()", "from __main__ import np,Store,function1")
    t1 = t.timeit(n)
    print 'function1', t1
    t = Timer("r = function2()", "from __main__ import np,Store,function2")
    t2 = t.timeit(n)
    print 'function2', t2
    t = Timer("r = function3()", "from __main__ import np,Store,function3")
    t3 = t.timeit(n)
    print 'function3', t3, t3/t2
    t = Timer("r = function1()", "from __main__ import np,Store,function1")
    t1 = t.timeit(n)  #repeated
    print 'function1', t1, t1/t2
    t = Timer("r = function4()", "from __main__ import np,Store,function4")
    t4a = t.timeit(n)
    print 'function4a', t4a, t4a/t2
    t = Timer("r = function4(full_output=0)", 
              "from __main__ import np,Store,function4")
    t4b = t.timeit(n)
    print 'function4b', t4b, t4b/t2


More information about the SciPy-User mailing list