【问题标题】:Storing and loading numpy arrays as files将 numpy 数组存储和加载为文件
【发布时间】:2013-07-08 15:19:45
【问题描述】:

在我的程序中,我正在处理各种大小不同的 numpy 数组。我需要将它们存储到 XML 文件中以备后用。我没有将它们写入二进制文件,因此我将所有数据放在一个位置(XML 文件),而不是分散在 200 个文件中。

所以我尝试使用 numpy 的 array_str() 方法将数组转换为字符串。 生成的 XML 如下所示:

-<Test date="2013-07-10-17:19">
    <Neurons>5</Neurons>
    <Errors>[7.7642140551985428e-06, 7.7639131137987232e-06]</Errors>
    <Iterations>5000</Iterations>
    <Weights1>[[ 0.99845902 -0.70780512 0.26981375 -0.6077122 0.09639695] [ 0.61856711 -0.74684913 0.20099992 0.99725171 -0.41826754] [ 0.79964397 0.56620812 -0.64055346 -0.50572793 -0.50100635]]</Weights1>
    <Weights2>[[-0.1851452 -0.22036027] [ 0.19293429 -0.1374252 ] [-0.27638478 -0.38660974] [ 0.30441414 -0.01531598] [-0.02478953 0.01823584]]</Weights2>
</Test>

权重是我要存储的值。现在的问题是 numpy 的 fromstring() 方法显然无法重新加载这些...... 我得到“ValueError:字符串大小必须是元素大小的倍数”

我用“np.array_str(w1)”编写它们并尝试用“np.fromstring(w_str1)”读取它们。 显然,即使它有效,结果也只是一个一维数组,所以我必须手动恢复形状。呃,这已经很痛苦了,因为我也必须以某种方式存储它。

正确执行此操作的最佳方法是什么?最好是同时保存我的数组的形状和数据类型,而无需为每一件小事手动整理。

【问题讨论】:

    标签: python arrays string serialization numpy


    【解决方案1】:

    您可以使用numpy.ndarray.tostring() 将数组转换为字符串(实际上是字节数组)。 Numpy.ndarray.tostring()

    然后这可以稍后用于使用numpy.fromstring() 读回数组。

    In [138]: x = np.arange(12).reshape(3,4)
    
    In [139]: x.tostring()
    Out[139]: '\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x08\x00\x00\x00\t\x00\x00\x00\n\x00\x00\x00\x0b\x00\x00\x00'
    
    In [140]: np.fromstring(x.tostring(), dtype=x.dtype).reshape(x.shape)
    Out[140]: 
    array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11]])
    

    【讨论】:

    • 注意 .tostring() .. np.fromstring() 失去了数组的形状;它作为单行读回——因此在示例中使用了 .reshape() 。您必须以其他方式传达形状。
    【解决方案2】:

    如果您真的想保留最初的 XML 格式,我的建议是使用 json 模块在 ndarraystring 之间进行转换。

    检查以下内容:

    import json, numpy
    
    w1 = numpy.array([[ 0.99845902, -0.70780512, 0.26981375, -0.6077122, 0.09639695],
                      [ 0.61856711, -0.74684913, 0.20099992, 0.99725171, -0.41826754],
                      [ 0.79964397, 0.56620812, -0.64055346, -0.50572793, -0.50100635]])
    
    print w1
    print
    
    #####
    
    w1string = json.dumps(w1.tolist())
    
    ## NOW YOU COULD PASS "w1string" TO/FROM XML
    
    #####
    
    
    print w1string
    print
    
    w1back = numpy.array(json.loads(w1string))
    
    print w1back
    print
    

    【讨论】:

      【解决方案3】:

      不幸的是,没有简单的方法可以将当前输出读回 numpy。输出在您的 xml 文件上看起来不太好,但您可以创建数组的可读版本,如下所示:

      >>> import cStringIO
      >>> a = np.array([[ 0.99845902, -0.70780512, 0.26981375, -0.6077122, 0.09639695], [ 0.61856711, -0.74684913, 0.20099992, 0.99725171, -0.41826754], [ 0.79964397, 0.56620812, -0.64055346, -0.50572793, -0.50100635]])
      >>> out_f = cStringIO.StringIO()
      >>> np.savetxt(out_f, a, delimiter=',')
      >>> out_f.getvalue()
      '9.984590199999999749e-01,-7.078051199999999543e-01,2.698137500000000188e-01,-6.077122000000000357e-01,9.639694999999999514e-02\n6.185671099999999756e-01,-7.468491299999999722e-01,2.009999199999999986e-01,9.972517100000000134e-01,-4.182675399999999932e-01\n7.996439699999999817e-01,5.662081199999999814e-01,-6.405534600000000189e-01,-5.057279300000000477e-01,-5.010063500000000447e-01\n'
      

      并将其加载回:

      >>> in_f = cStringIO.StringIO(out_f.getvalue())
      >>> np.loadtxt(in_f, delimiter=',')
      array([[ 0.99845902, -0.70780512,  0.26981375, -0.6077122 ,  0.09639695],
             [ 0.61856711, -0.74684913,  0.20099992,  0.99725171, -0.41826754],
             [ 0.79964397,  0.56620812, -0.64055346, -0.50572793, -0.50100635]])
      

      【讨论】:

        【解决方案4】:

        Numpy 提供了一种将许多数组存储在压缩文件中的简单方法:

        a = np.arange(10)
        b = np.arange(10)
        np.savez_compressed('file.npz', a=a, b=b)
        

        您甚至可以在保存时更改数组名称,例如:np.savez_compressed('file.npz', newa=a, newb=b)

        要读取保存的文件,请使用np.load(),它会返回一个类似于字典的NpzFile 实例:

        loaded = np.load('file.npz')
        

        加载数组:

        a_loaded = loaded['a']
        b_loaded = loaded['b']
        

        或:

        from operator import itemgetter
        g = itemgetter( 'a', 'b' )
        a_loaded, b_loaded = g(np.load('file.npz'))
        

        【讨论】:

        • 谢谢,这不是我的想法(这仍然会创建大量外部文件),但至少这个解决方案非常简单。我可以使用日期作为文件名将 npz 文件与我的 XML 数据相关联。
        • 至少在这里您可以在一个文件中存储许多数组,并且可以稍后使用字典键作为日期来完成访问,例如:np.savez_compressed('all.npz', d2013_12_29=a, d2013_12_30=b, d2013_12_31=c),您可以包含尽可能多的日期你想在这里...
        猜你喜欢
        • 1970-01-01
        • 2021-03-01
        • 2021-09-20
        • 1970-01-01
        • 2020-10-30
        • 2018-05-31
        • 2019-12-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多