pickle.dumps序列化-量化

本文介绍了Python中pickle模块的功能及使用方法,通过pickle可以将内存中的数据序列化后保存到磁盘,再次使用时只需reload即可恢复数据,避免重复计算,特别适合于机器学习模型的训练结果保存。
摘要由CSDN通过智能技术生成


前言:

pickle的功能就是把你上次计算得到的数据保存起来,当你需要使用这些数据时,直接通过reload把数据恢复了就行,这样的好处有:

  1. 被pickle的数据,在被多次reload时,不需要重新去计算得到这些数据,这样节省计算机资源,如果你不pickle,你每调用一次数据,就要计算一次。
  2. 通过pickle的数据,被reload时,可以更好的被内存调用,不需要经过数据格式的转换。(即:python自带的file函数只能存储和读取字符串格式的数据.pickle可以存储和读取成其他格式比如list dict的数据

有人可能觉得,我直接通过open把数据写到一个txt文档也能达到以上的效果,但是这样做的结果是,你能够达到pickle的功能,把数据保存起来,但是当你再去调用这些数据时,你的txt格式的数据,没有pickle的数据读取更高效。

另外还有一点,你通过open把数据存储到txt中时的效率,就不如pickle的效率高。

综上,你如果只是做一次的数据存储和调用,以及数据量很小的情况下,你可以用open等方法保存数据和调用数据,但是当你需要通过大量计算得到一个数据,同时后期还会多次使用这个数据时,pickle的节省计算机资源的效果就出来了。举例:比如说构建机器学习模型,例如决策树,一般情况都是先建树,后剪枝,再预测,但这样有一个缺点,即明明是一棵树上跑测试数据,但每次都需要建树,决策树的大部分时间都浪费在建树上了,所以我们可以在第一次跑完时用pickle把整个树保存起来,以后测试时直接load进来预测或剪枝就好了,这样做节省了时间。

量化中, 序列化的变量是有持久性的,在每次重启时,变量数据均不会丢失,joinquant中,定义全局变量中,有的变量如果不想被序列化,会在变量以“_”开头,这样,这个变量在序列时就会被忽略。 注:query()返回的对象本身就不具有持久性,故在存储时,要将它放到process_initialize()中初始化它并且名字以"_"开头。

例:

defprocess_initialize(context):
    g.__query = query(valuation)

恢复过程是这样的:

  1. 加载策略代码, 因为python是动态语言, 编译即运行, 所以全局的(在函数外写的)代码会被执行一遍.
  2. 使用保存的状态恢复 g, context, 和函数外定义的全局变量.
  3. 执行 process_initialize, 每次启动时都会执行这个函数.
  4. 如果策略代码和上一次运行时发生了修改,而且代码中定义了 after_code_changed 函数,则会运行after_code_changed函数.
  5. 模拟盘更改回测之后上述的全局变量(包括 g 和 context 中保存的)不会丢失. 新代码中 initialize 不会执行.
    如果需要修改原来的值, 可以在 after_code_changed 函数里面修改, 比如, 原来代码是:
    a = 1
    def initialize(context):
        g.stock = '000001.XSHE'

    代码改成:

    a = 2
    def initialize(context):
        g.stock = '000002.XSHE'

    执行时, a 仍然是 1, g.stock 仍然是 ‘000001.XSHE’, 要修改他们的值, 必须定义 after_code_changed:

    def after_code_changed(context):
        global a
        a = 2
        g.stock = '000002.XSHE'



正文:

在程序运行的过程中,所有的变量都是在内存中,比如,定义一个dict:

d = dict(name='Bob', age=20, score=88)

可以随时修改变量,比如把name改成'Bill',但是一旦程序结束,变量所占用的内存就被操作系统全部回收。如果没有把修改后的'Bill'存储到磁盘上,下次重新运行程序,变量又被初始化为'Bob'

我们把变量从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。

序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。

反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。

Python提供两个模块来实现序列化:cPicklepickle。这两个模块功能是一样的,区别在于cPickle是C语言写的,速度快,pickle是纯Python写的,速度慢,跟cStringIOStringIO一个道理。用的时候,先尝试导入cPickle,如果失败,再导入pickle

try:
    import cPickle as pickle
except ImportError:
    import pickle

首先,我们尝试把一个对象序列化并写入文件:

>>> d = dict(name='Bob', age=20, score=88)
>>> pickle.dumps(d)
"(dp0\nS'age'\np1\nI20\nsS'score'\np2\nI88\nsS'name'\np3\nS'Bob'\np4\ns."

pickle.dumps()方法把任意对象序列化成一个str,然后,就可以把这个str写入文件。或者用另一个方法pickle.dump()直接把对象序列化后写入一个file-like Object:

>>> f = open('dump.txt', 'wb')
>>> pickle.dump(d, f)
>>> f.close()

看看写入的dump.txt文件,一堆乱七八糟的内容,这些都是Python保存的对象内部信息。

当我们要把对象从磁盘读到内存时,可以先把内容读到一个str,然后用pickle.loads()方法反序列化出对象,也可以直接用pickle.load()方法从一个file-like Object中直接反序列化出对象。我们打开另一个Python命令行来反序列化刚才保存的对象:

>>> f = open('dump.txt', 'rb')
>>> d = pickle.load(f)
>>> f.close()
>>> d
{'age': 20, 'score': 88, 'name': 'Bob'}

变量的内容又回来了!

当然,这个变量和原来的变量是完全不相干的对象,它们只是内容相同而已。

Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值