python - 存储该向量的最有效方法?

标签 python numpy scipy

我有一个 JSON 字符串,其中包含将索引映射到 float 值的字典。这是向量的代表。例如,

{
    'distro': {0: 2.42, 3: 2.56},
    'constant': 4.55
    'size': 10000
}

表示大小为 10000 的向量,索引 0 上具有 2.42,索引 2 上具有 2.56 。该向量中的所有其他值均为 4.55

表示此数据结构的最有效方式是什么?会scipy.sparse帮我?我的主要应用是快速创建密集表示,但我不想预先将它们存储在内存中(因为有很多这样的向量)。

最佳答案

我想你的迭代方式是这样的:

In [204]: dd = {
     ...:     'distro': {0: 2.42, 3: 2.56},
     ...:     'constant': 4.55,
     ...:     'size': 10,
     ...: }
In [205]: dd
Out[205]: {'constant': 4.55, 'distro': {0: 2.42, 3: 2.56}, 'size': 10}

In [207]: x = np.zeros(dd['size'])
In [208]: x[:] = dd['constant']
In [210]: for i,v in dd['distro'].items():
     ...:     x[i] = v
In [211]: x
Out[211]: array([ 2.42,  4.55,  4.55,  2.56,  4.55,  4.55,  4.55,  4.55,  4.55,  4.55])

x[:] 的替代方案,是x.fill(dd['constant']) ,但不认为速度有太大差异。

这是一种无需显式迭代即可从字典中设置值的方法:

In [221]: ddvals = np.array(list(dd['distro'].items()),dtype='i,f')
In [222]: ddvals
Out[222]: 
array([(0,  2.42000008), (3,  2.55999994)], 
      dtype=[('f0', '<i4'), ('f1', '<f4')])
In [223]: x[ddvals['f0']]=ddvals['f1']
In [224]: x
Out[224]: 
array([ 2.42000008,  4.55      ,  4.55      ,  2.55999994,  4.55      ,
        4.55      ,  4.55      ,  4.55      ,  4.55      ,  4.55      ])

或者没有结构化数组:

In [225]: vals = np.array(list(dd['distro'].items()))
In [226]: vals
Out[226]: 
array([[ 0.  ,  2.42],
       [ 3.  ,  2.56]])
In [227]: x[vals[:,0]] = vals[:,1]
...
IndexError: arrays used as indices must be of integer (or boolean) type
In [228]: x[vals[:,0].astype(int)] = vals[:,1]
In [229]: x
Out[229]: array([ 2.42,  4.55,  4.55,  2.56,  4.55,  4.55,  4.55,  4.55,  4.55,  4.55])

字典items() (或 PY3 中的 list(items()))给出元组列表。较新 numpy版本不喜欢使用 float 作为索引,因此我们必须添加一些步骤来保留整数键值。

这可能是最简单的:

x[list(dd['distro'].keys())] = list(dd['distro'].values())

(我假设 keysvaluesitems 以相同的键顺序返回值)。

对于这个小案例,我怀疑简单的迭代方法更快。但后一种更大的东西可能会更好。我无法预测交叉发生在哪里。

scipy.sparse制作二维矩阵。它没有实现任何类型的 const充满。 ( Pandas 稀疏确实有这样的填充)。我们当然可以构造一个sparse矩阵来自dd['size']dd['distro'] 。但我不知道它是否会提供任何速度优势。

如果 Tensorflow 是你真正的目标,那么你可能需要更多地了解它的构建方法。也许你不需要经过numpysparse完全没有。

<小时/>

这个x ,没有 const可以表示为scipy稀疏矩阵:

In [247]: Xo = sparse.coo_matrix([x])
In [248]: Xo
Out[248]: 
<1x10 sparse matrix of type '<class 'numpy.float64'>'
    with 2 stored elements in COOrdinate format>

其主要属性是:

In [249]: Xo.data
Out[249]: array([ 2.42,  2.56])
In [250]: Xo.row
Out[250]: array([0, 0], dtype=int32)
In [251]: Xo.col
Out[251]: array([0, 3], dtype=int32)
In [252]: Xo.shape
Out[252]: (1, 10)

Xr=Xo.tocsr() csr格式类似,除了 row属性被替换为 indptr数组,每行有一个值 (+1),因此它不会随着非零项的数量而增长。它用于大多数稀疏数学。

还有一个dok format,它实际上是一个字典子类:

In [258]: dict(Xo.todok())
Out[258]: {(0, 0): 2.4199999999999999, (0, 3): 2.5600000000000001}
<小时/>

如果输入有效json ,您需要将索引键转换为整数。

In [281]: jstr
Out[281]: '{"distro": {"0": 2.42, "3": 2.56}, "constant": 4.55, "size": 10}'
In [282]: jdd = json.loads(jstr)
In [283]: jdd
Out[283]: {'constant': 4.55, 'distro': {'0': 2.42, '3': 2.56}, 'size': 10}
In [284]: list(jdd['distro'].keys())
Out[284]: ['0', '3']
In [285]: np.array(list(jdd['distro'].keys()),int)
Out[285]: array([0, 3])
In [286]: np.array(list(jdd['distro'].values()))
Out[286]: array([ 2.42,  2.56])

我对 SO 搜索的印象是 json.loadeval 一样快,甚至更快。它必须解析更简单的语法。

python eval vs ast.literal_eval vs JSON decode

如果您可以处理json字符串,并将它们存储在某种中间数据结构中,有几种可能性。这些向量有多“稀疏”?如果字典具有几乎所有 1000 个“大小”条目的值,则最好构建完整的 numpy 数组并保存它(例如使用 np.save/load 对)。

如果它是稀疏的(比如 10% 的值是非常量),则保存 2 个索引和值数组可能更有意义(285 和 284)。要么将它们分开,要么将它们加入到我之前生成的结构化数组中。

关于python - 存储该向量的最有效方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42983554/

相关文章:

python - 按唯一值对列进行排序

python-2.7 - 我在 python-multiprocessing/multithreading 中缺少什么?

python - 矩阵乘法在 Python (SciPy/PyLab) 中给出了不正常的结果

python - 属性错误: 'numpy.datetime64' object has no attribute 'toordinal'

python - 更改 Flask 中的 URL 路由会破坏代码吗?

python - 将 py.test 与已编译的库代码一起使用

python - 为什么第一次导入 skimage 失败,但第二次导入成功?

python - Scipy 最大化线性规划不起作用

Python - 具有稀疏结果的矩阵乘法

java - 斯坦福解析器内存不足