如何在IPython Notebook中进行缓存?

22

环境:

  • Python 3
  • IPython 3.2

每次关闭并重新打开一个IPython笔记本时,我都必须重新运行所有单元格。但是有些单元格涉及密集的计算。

相比之下,R中的knitr默认将结果保存在缓存目录中,因此只有新代码和新设置才会调用计算。

我看了一下ipycache,但它似乎只缓存一个单元格而不是整个笔记本。是否存在与IPython中的knitr缓存相对应的缓存方式?


2
我不知道Ipython是否具备这样的功能,但是你可以使用例如joblib.Memory将昂贵的计算结果简单地缓存到磁盘中。 - rth
4个回答

11

不幸的是,似乎没有像自动缓存这样方便的东西。 %store 魔术选项很接近,但需要您手动和明确地进行缓存和重新加载。

在您的Jupyter笔记本中:


在您的Jupyter笔记本中:

a = 1
%store a

现在,假设你关闭笔记本并重新启动内核。你将无法再访问局部变量。但是,你 可以 使用 -r 选项重新加载你已存储的变量。

%store -r a
print a # Should print 1

这个在两个不同的笔记本之间能用吗?看起来是可以的。 - BND

7
事实上,您所要求的功能已经存在,无需通过手动转储来重新实现它。您可以使用%store或者更好的%%cache魔法(扩展)来存储这些间歇单元格的结果,以便它们不必重新计算(请参见https://github.com/rossant/ipycache)。它很简单:
%load_ext ipycache

然后,在一个单元格中,例如:

%%cache mycache.pkl var1 var2
var1 = 1
var2 = 2

当您第一次执行此单元格时,代码将被执行,并且变量var1和var2将与输出一起保存在当前目录中的mycache.pkl中。仅当您使用IPython的开发版本时,才会保存丰富的显示输出。当您再次执行此单元格时,代码将被跳过,变量将从文件中加载并注入命名空间,而输出将在笔记本中恢复。它会自动为您保存所有生成的图形、输出和指定的所有变量 :)

非常有用,对我来说比%autoreload更容易使用(这是我绕过更改模块但不想重新加载数据的另一种方式)。 - ijoseph
3
"ipycache"似乎需要更多关注。警告频出,最后更新于2016年5月。 - Tom Hale
1
该死,以前它很低维护:S 我猜随着Python版本的进展,事情会改变...仍然有一些美好的回忆,到目前为止我找到的最佳解决方案,希望能找到更好/更活跃的东西。 - ntg
%store 有什么不同? - BND
以前没有真正使用过%store(但现在打算使用:))好久没用ipycache了...如果记忆没错,它可以保存单元格的所有图形输出等以及变量的值。此外,您只需说出一个单元格被缓存以及输出变量即可。如果从缓存时起未编辑单元格,则使用缓存,可以处理多个变量,可以定义变量,如果更改则缓存无效等。它并不完美,但我真的很想再次看到类似的东西。 - ntg
3
ipycache不再维护,你知道其他的工具吗? - Chris_Rands

4
使用缓存魔法(cache magic)
%cache myVar = someSlowCalculation(some, "parameters")

This will calculate someSlowCalculation(some, "parameters") once. And in subsequent calls it restores myVar from storage.

https://pypi.org/project/ipython-cache/

在幕后,它基本上与被接受的答案做了相同的事情。


1
缓存变量何时失效?理想情况下,它应该在其依赖的变量发生更改时失效,但这似乎有点聪明。 - Att Righ
1
默认情况下,当等号右侧的字符串更改时,它会更改。因此,当方法或其直接参数更改时,它会更改,但不会查看方法或参数值。 - wotanii
1
哦,那听起来确实是我想要的。 - Att Righ
哦,当我刚测试时似乎没有进行缓存失效。 - Att Righ

0
你能举个例子说明你想要做什么吗?当我在 IPython Notebook 中运行一个昂贵的程序时,几乎总是在之后将其写入磁盘。例如,如果我的数据是 JSON 对象列表,我会将其写为行分隔的 JSON 格式字符串。
with open('path_to_file.json', 'a') as file:
    for item in data: 
        line = json.dumps(item)
        file.write(line + '\n')

然后您可以以相同的方式读取数据:

data = []
with open('path_to_file.json', 'a') as file:
    for line in file: 
        data_item = json.loads(line)
        data.append(data_item)

一般来说,我认为这是一个很好的实践,因为它提供了备份。您也可以使用pickle做同样的事情。如果数据真的很大,您可以使用gzip.open直接写入zip文件。

编辑

要将Scikit Learn模型保存到磁盘,请使用joblib.pickle

from sklearn.cluster import KMeans

km = KMeans(n_clusters=num_clusters)
km.fit(some_data)


from sklearn.externals import joblib
# dump to pickle
joblib.dump(km, 'model.pkl')

# and reload from pickle
km = joblib.load('model.pkl')

我尝试将机器学习模型应用于数据集。例如,我通过pandas导入一些数据(几百MB),然后使用scikit-learn训练和测试两个模型。我想“缓存”所有中间转换的DataFrame,以及训练好的模型。这样我就可以在不重新读取底层数据的情况下,在中间DataFrame上“继续”实验。 - Zelong
@zelong 好的,你应该使用joblib来序列化你的sklearn模型。请看我上面的修改。而要将你的数据框写入磁盘,只需使用dataframe.to_csv('yourfile.csv)即可。 - brandomr
非常感谢。scikit-learn模型的腌制看起来相当不错。我尝试了很多DataFrame的整理,保存一堆中间DataFrame到csv文件似乎很费劲。但是似乎IPython没有提供RData缓存的对应项,它可以将所有内容放在一个单独的立方体中。 - Zelong
我删除了 file.close() 调用,因为 with 会自动关闭文件 - Eric O. Lebigot
另外,由于data是一个“列表”,因此可以更简单地执行json.dump(data, file),而不需要任何循环。同样地,也可以使用json.load(file) - Eric O. Lebigot
最后,官方不建议将某些东西命名为“文件(file)”,因为这会覆盖内置的“文件(file)”类型。 - Eric O. Lebigot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接