python - 根据所选参数记忆函数结果
问题描述
我有一个具有以下签名的函数:
def spectrogram(signal: numpy.ndarray, sampling_frequency=16000, win_len=512, hop=256, win_type='hanning')
该函数在输入(信号)上需要一个 numpy 数组,加上其他参数的数量,并输出一个 numpy 数组。它计算给定音频文件的频谱图以获得某些声学特征。对于每个文件,我将多次调用此函数,通常使用相同的参数,但并非总是如此。对于某些功能,我可能会更改hop
or win_type
。我正在考虑缓存结果,这样我就不会多次运行相同的计算。结果对每个文件有效。这些文件将与 joblib 并行处理。
我正在考虑根据文件名(这不是我通常在函数上使用的参数)和字段、、和sampling_frequency
(win_len
即NOT - 这可能是一个大数组并且它更有效)来记忆结果查看文件名,这是唯一的)。hop
win_type
signal
我怎样才能最好地记住结果?我见过的所有解决方案都根据提供的输入缓存结果;就我而言,我想根据选定的字段进行记忆。我在 Python 3.6 上。
解决方案
我决定通过添加两个元素来发布基于@Ethan 答案(+1 票)的我自己的答案:
缓存的边界。这是我的先决条件之一,这也是我无法接受 Ethan 回答的原因。后者是无限的,会很快耗尽我的记忆。
我觉得它更优雅;它使用了一个装饰器和一个为缓存而设计的模块(并捕获一些极端情况)。它更可重用,因此对其他人更友好。
from cachetools.keys import hashkey
from cachetools import cached, LRUCache
def mykey(signal, *args, **kwargs):
key = hashkey(*args, **kwargs)
return key
@cached(LRUCache(maxsize=6), key=mykey)
def spectrogram(signal: numpy.ndarray, filename, sampling_frequency=16000, win_len=512, hop=256, win_type='hanning')
本质上,我只是忽略了signal
,而是将filename
其作为缓存的额外参数。在某些情况下,甚至filename
不需要。如果每个文件生成一个单独的进程,则不需要这种保护措施,因为无论如何进程之间都无法共享缓存。
奖金
我还决定尝试Memory
使用 joblib,它也表现良好。这是一个片段:
from joblib import Memory
memory = Memory('cachedir', verbose=0, bytes_limit=100000)
@memory.cache
def spectrogram(signal: numpy.ndarray, sampling_frequency=16000, win_len=512, hop=256, win_type='hanning')
它的性能平均比第一个解决方案差 25%,因为:
- 它写入磁盘
- 它计算一个完整的哈希
numpy.ndarray
考虑到上述情况,它仍然是一个很好的分数。
推荐阅读
- c++ - 从签名cryptopp中提取哈希
- python - OS Walk 异常处理
- java - 在maven构建期间添加log4j1x和log4j2x依赖会导致重复类错误
- php - 即使使用本地主机,ftp_connect 也无法正常工作
- javascript - 发送到客户端后无法设置标头 | express.js res.status().json()
- postgresql - 在 Postgresgl 中创建外键会出现此错误:错误:添加 toast 表需要 AccessExclusiveLock
- c# - 我的 C# win 表单应用程序在内部调用批处理脚本,如何在 Visual Studio 中导出时向最终用户隐藏它?
- google-app-engine - Cloud.google.com/go/datastore 中的 GetAll() 事务{}?
- angular - Angular Universal:路由解析器 + Firebase 加载超时
- microsoft-translator - 从 Microsoft Translator API V3 获取替代翻译