繁体   English   中英

如何使用 Python timeit 模块捕获返回值?

[英]How can I capture return value with Python timeit module?

我在 for 循环中使用 sklearn 运行几种机器学习算法,并想看看每个算法需要多长时间。 问题是我还需要返回一个值,并且不想多次运行它,因为每个算法都需要很长时间。 有没有一种方法可以使用 python 的 timeit 模块或具有类似功能的类似模块来捕获返回值“clf”...

def RandomForest(train_input, train_output):
    clf = ensemble.RandomForestClassifier(n_estimators=10)
    clf.fit(train_input, train_output)
    return clf

当我像这样调用函数时

t = Timer(lambda : RandomForest(trainX,trainy))
print t.timeit(number=1)

PS我也不想设置全局'clf',因为我以后可能想做多线程或多处理。

对于 Python 3.5,您可以覆盖timeit.template的值

timeit.template = """
def inner(_it, _timer{init}):
    {setup}
    _t0 = _timer()
    for _i in _it:
        retval = {stmt}
    _t1 = _timer()
    return _t1 - _t0, retval
"""

unutbu 的答案适用于 python 3.4 但不适用于 3.5,因为 _template_func 函数似乎已在 3.5 中删除

问题归结为timeit._template_func不返回函数的返回值:

def _template_func(setup, func):
    """Create a timer function. Used if the "statement" is a callable."""
    def inner(_it, _timer, _func=func):
        setup()
        _t0 = _timer()
        for _i in _it:
            _func()
        _t1 = _timer()
        return _t1 - _t0
    return inner

我们可以通过一些猴子补丁来使timeit符合我们的意愿:

import timeit
import time

def _template_func(setup, func):
    """Create a timer function. Used if the "statement" is a callable."""
    def inner(_it, _timer, _func=func):
        setup()
        _t0 = _timer()
        for _i in _it:
            retval = _func()
        _t1 = _timer()
        return _t1 - _t0, retval
    return inner

timeit._template_func = _template_func

def foo():
    time.sleep(1)
    return 42

t = timeit.Timer(foo)
print(t.timeit(number=1))

返回

(1.0010340213775635, 42)

第一个值是 timeit 结果(以秒为单位),第二个值是函数的返回值。

请注意,上面的monkey-patch 仅在通过timeit.Timer可调用时影响timeit的行为。 如果您传递一个字符串语句,那么您必须(类似地)对timeit.template字符串进行猴子补丁。

有趣的是,我也在做机器学习,并且有类似的要求 ;-)

我通过编写一个函数来解决它,如下所示:

  • 运行你的函数
  • 打印运行时间以及函数名称
  • 返回结果

假设您想计时:

clf = RandomForest(train_input, train_output)

然后做:

clf = time_fn( RandomForest, train_input, train_output )

Stdout 将显示如下内容:

mymodule.RandomForest: 0.421609s

time_fn 的代码:

import time

def time_fn( fn, *args, **kwargs ):
    start = time.clock()
    results = fn( *args, **kwargs )
    end = time.clock()
    fn_name = fn.__module__ + "." + fn.__name__
    print fn_name + ": " + str(end-start) + "s"
    return results

如果我理解得很好,在 python 3.5 之后,您可以在每个 Timer 实例上定义全局变量,而不必在代码块中定义它们。 我不确定它是否会遇到与并行化相同的问题。

我的方法是这样的:

clf = ensemble.RandomForestClassifier(n_estimators=10)
myGlobals = globals()
myGlobals.update({'clf'=clf})
t = Timer(stmt='clf.fit(trainX,trainy)', globals=myGlobals)
print(t.timeit(number=1))
print(clf)

截至 2020 年,在 ipython 或 jupyter notebook 中

t = %timeit -n1 -r1 -o RandomForest(trainX, trainy)
t.best

如果您不想猴子补丁timeit ,您可以尝试使用全局列表,如下所示。 这也适用于 python 2.7,它在timeit()中没有globals参数:

from timeit import timeit
import time

# Function to time - plaigiarised from answer above :-)
def foo():
    time.sleep(1)
    return 42

result = []
print timeit('result.append(foo())', setup='from __main__ import result, foo', number=1)
print result[0]

将打印时间,然后打印结果。

我使用的一种方法是将运行时间“附加”到定时函数的结果中。 因此,我使用“time”模块编写了一个非常简单的装饰器:

def timed(func):
    def func_wrapper(*args, **kwargs):
        import time
        s = time.clock()
        result = func(*args, **kwargs)
        e = time.clock()
        return result + (e-s,)
    return func_wrapper

然后我将装饰器用于我想要计时的功能。

我在for循环中使用sklearn运行了几种机器学习算法,并希望了解每种算法花费的时间。 问题是我还需要返回一个值,并且DONT希望多次运行它,因为每种算法都花很长时间。 有没有一种方法可以使用python的timeit模块或具有类似功能的类似模块捕获返回值'clf'...

def RandomForest(train_input, train_output):
    clf = ensemble.RandomForestClassifier(n_estimators=10)
    clf.fit(train_input, train_output)
    return clf

当我这样调用函数时

t = Timer(lambda : RandomForest(trainX,trainy))
print t.timeit(number=1)

PS我也不想设置一个全局'clf',因为我以后可能想做多线程或多处理。

对于 Python 3.XI 使用这种方法:

# Redefining default Timer template to make 'timeit' return
#     test's execution timing and the function return value
new_template = """
def inner(_it, _timer{init}):
    {setup}
    _t0 = _timer()
    for _i in _it:
        ret_val = {stmt}
    _t1 = _timer()
    return _t1 - _t0, ret_val
"""
timeit.template = new_template

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM