加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

Python使用稀疏矩阵节省内存实例

发布时间:2020-12-17 07:19:10 所属栏目:Python 来源:网络整理
导读:推荐系统中经常需要处理类似user_id,item_id,rating这样的数据,其实就是数学里面的稀疏矩阵,scipy中提供了sparse模块来解决这个问题,但scipy.sparse有很多问题不太合用: 1、不能很好的同时支持data[i,...]、data[...,j]、data[i,j]快速切片; 2、由于数

推荐系统中经常需要处理类似user_id,item_id,rating这样的数据,其实就是数学里面的稀疏矩阵,scipy中提供了sparse模块来解决这个问题,但scipy.sparse有很多问题不太合用:

1、不能很好的同时支持data[i,...]、data[...,j]、data[i,j]快速切片;
2、由于数据保存在内存中,不能很好的支持海量数据处理。

要支持data[i,j]的快速切片,需要i或者j的数据集中存储;同时,为了保存海量的数据,也需要把数据的一部分放在硬盘上,用内存做buffer。这里的解决方案比较简单,用一个类Dict的东西来存储数据,对于某个i(比如9527),它的数据保存在dict['i9527']里面,同样的,对于某个j(比如3306),它的全部数据保存在dict['j3306']里面,需要取出data[9527,...]的时候,只要取出dict['i9527']即可,dict['i9527']原本是一个dict对象,储存某个j对应的值,为了节省内存空间,我们把这个dict以二进制字符串形式存储,直接上代码:

复制代码 代码如下:

'''
Sparse Matrix
'''
import struct
import numpy as np
import bsddb
from cStringIO import StringIO
 
class DictMatrix():
    def __init__(self,container = {},dft = 0.0):
        self._data  = container
        self._dft   = dft
        self._nums  = 0
 
    def __setitem__(self,index,value):
        try:
            i,j = index
        except:
            raise IndexError('invalid index')
 
        ik = ('i%d' % i)
        # 为了节省内存,我们把j,value打包成字二进制字符串
        ib = struct.pack('if',j,value)
        jk = ('j%d' % j)
        jb = struct.pack('if',i,value)
 
        try:
            self._data[ik] += ib
        except:
            self._data[ik] = ib
        try:
            self._data[jk] += jb
        except:
            self._data[jk] = jb
        self._nums += 1
 
    def __getitem__(self,index):
        try:
            i,j = index
        except:
            raise IndexError('invalid index')
 
        if (isinstance(i,int)):
            ik = ('i%d' % i)
            if not self._data.has_key(ik): return self._dft
            ret = dict(np.fromstring(self._data[ik],dtype = 'i4,f4'))
            if (isinstance(j,int)): return ret.get(j,self._dft)
 
        if (isinstance(j,int)):
            jk = ('j%d' % j)
            if not self._data.has_key(jk): return self._dft
            ret = dict(np.fromstring(self._data[jk],f4'))
 
        return ret
 
    def __len__(self):
        return self._nums
 
    def __iter__(

测试代码:

复制代码 代码如下:

import timeit
timeit.Timer('foo = __main__.data[9527,...]','import __main__').timeit(number = 1000)

消耗1.4788秒,大概读取一条数据1.5ms。
采用类Dict来存储数据的另一个好处是你可以随便用内存Dict或者其他任何形式的DBM,甚至传说中的Tokyo Cabinet….

好了,码完收工。

您可能感兴趣的文章:

  • 用Python中的__slots__缓存资源以节省内存开销的方法
  • python如何为创建大量实例节省内存

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读