实现一个简单的持久值和函数缓存。
easycache的Python项目详细描述
版权所有2017 Jeff Ward
根据apache许可证2.0版(以下简称“许可证”)授权; 除非符合许可证,否则您不能使用此文件。 您可以在
http://www.apache.org/licenses/LICENSE-2.0
除非适用法律要求或书面同意, 根据许可证分发的软件在 “原样”基础,无任何保证或条件, 明示的或暗示的。具体见许可证 管理许可下的权限和限制的语言。
这是一个非常basic的值和函数缓存实现。我肯定有更好的工具。 它处于初始开发阶段,因此可能存在主要的错误。我可以更新这个,因为我使用它更多,但你是最安全的 不需要进一步的更新。
这个包背后的目的是提供一些东西,在一行中装饰函数调用,以透明的方式 尽可能缓存其结果。我围绕这个构建的用例是搜索超参数。通过包装您的 在这个缓存中的模型调用,您可以快速实现随机搜索,甚至mct,其中先前生成的 结果会自动重新加载,而不会将自定义缓存逻辑放入代码中。另外,如果你 用a-c和后面的realize中的参数值执行网格搜索 使用此函数缓存允许您重新计算并自动重新加载现有结果,而仅计算 新的结果。
一个简单的例子:
import easycache as ec import time def myExpensiveFunction(cost, extraCost=0.0): time.sleep(cost) time.sleep(extraCost) print("This was expensive!") return cost def gridSearchExample(paramA, paramB): """ Simulates a grid search over parameter values :param paramA: list of values :param paramB: list of values :return: """ cachedEF = ec.cacheFunction(myExpensiveFunction, 'example.pkl', name="myExpensiveFunction") bestValue = None bestA = None bestB = None for a in paramA: for b in paramB: newValue = cachedEF(a+b) if bestValue is None or newValue > bestValue: bestValue = newValue bestA = a bestB = b return bestValue, bestA, bestB print("Best Value={} using A={} and B={}".format(*gridSearchExample([.1, .2], [.01, .02]))) #Oh, we REALLY should have searched more! This should only run the 2 new tests print("Best Value={} using A={} and B={}".format(*gridSearchExample([.1, .2], [.01, .02, .003])))
当然,您还可以做其他事情:
def runClass(cache): print("Cached Value={}".format(cache.someValue)) #Assignment will flush the cache. #If this is a complex object you will need to manually flush if internal state changes cache.someValue = 12 print("Cached Value={}".format(cache.someValue)) print("peek={}".format(cache.myExpensiveFunction(.5, mode="cache_peek"))) cache.myExpensiveFunction(.5) def classExample(): cache = ec.EasyCache("exampleClass.pkl") cache.clearCache() cache.cacheFunction(myExpensiveFunction, name="myExpensiveFunction") cache.cacheProperty("someValue", initialValue=42) runClass(cache) runClass(cache) cache.myExpensiveFunction(.5,mode="force_run") #need 'mode' for a parameter? change it cache.modeArg='mode2' cache.myExpensiveFunction(.5,mode2="clear_clear") cache.myExpensiveFunction(.5) del cache.someValue del cache.myExpensiveFunction classExample()
您可以忽略用于缓存的参数:
def myComplexExpensiveFunction(cost, uglyState, moreUglyState=None): time.sleep(cost) print("This was expensive and complex!") return cost def ignoreParametersExample(): cachedCEF = ec.cacheFunction(myComplexExpensiveFunction, 'example.pkl', name="myComplexExpensiveFunction", ignoreArgs=(1,), ignorekwArgs=('moreUglyState')) cachedCEF(.5, 'ignored for caching purposes', moreUglyState='also ignored for caching purposes') cachedCEF(.5, 'still cached', moreUglyState='still cached') cachedCEF(.1, 'this wasn\'t cached', moreUglyState='because the arg changed') ignoreParametersExample()