源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

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

  • 时间:2020-09-06 11:51 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:Python使用稀疏矩阵节省内存实例
推荐系统中经常需要处理类似user_id, item_id, rating这样的数据,其实就是数学里面的稀疏矩阵,scipy中提供了sparse模块来解决这个问题,但scipy.sparse有很多问题不太合用: 1、不能很好的同时支持data[i, ...]、data[..., j]、data[i, j]快速切片; 2、由于数据保存在内存中,不能很好的支持海量数据处理。 要支持data[i, ...]、data[..., j]的快速切片,需要i或者j的数据集中存储;同时,为了保存海量的数据,也需要把数据的一部分放在硬盘上,用内存做buffer。这里的解决方案比较简单,用一个类Dict的东西来存储数据,对于某个i(比如9527),它的数据保存在dict['i9527']里面,同样的,对于某个j(比如3306),它的全部数据保存在dict['j3306']里面,需要取出data[9527, ...]的时候,只要取出dict['i9527']即可,dict['i9527']原本是一个dict对象,储存某个j对应的值,为了节省内存空间,我们把这个dict以二进制字符串形式存储,直接上代码:
[u]复制代码[/u] 代码如下:
''' 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], dtype = 'i4,f4'))           return ret       def __len__(self):         return self._nums       def __iter__(
测试代码:
[u]复制代码[/u] 代码如下:
import timeit timeit.Timer('foo = __main__.data[9527, ...]', 'import __main__').timeit(number = 1000)
消耗1.4788秒,大概读取一条数据1.5ms。 采用类Dict来存储数据的另一个好处是你可以随便用内存Dict或者其他任何形式的DBM,甚至传说中的Tokyo Cabinet…. 好了,码完收工。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部