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

501次阅读  |  发布于5年以前

推荐系统中经常需要处理类似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以二进制字符串形式存储,直接上代码:

复制代码 代码如下:

'''
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__(

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8