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

 更新时间:2014年06月27日 11:31:41   投稿:junjie  
这篇文章主要介绍了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以二进制字符串形式存储,直接上代码:

复制代码 代码如下:

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

测试代码:

复制代码 代码如下:

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

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

好了,码完收工。

相关文章

  • Python画柱状统计图操作示例【基于matplotlib库】

    Python画柱状统计图操作示例【基于matplotlib库】

    这篇文章主要介绍了Python画柱状统计图操作,结合实例形式分析了Python基于matplotlib库实现图形绘制的相关操作技巧,需要的朋友可以参考下
    2018-07-07
  • 在PyCharm中实现添加快捷模块

    在PyCharm中实现添加快捷模块

    今天小编就为大家分享一篇在PyCharm中实现添加快捷模块,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-02-02
  • Python 利用scrapy爬虫通过短短50行代码下载整站短视频

    Python 利用scrapy爬虫通过短短50行代码下载整站短视频

    近日,有朋友向我求助一件小事儿,他在一个短视频app上看到一个好玩儿的段子,想下载下来,可死活找不到下载的方法。经过我的一番研究才找到解决方法,下面小编给大家分享Python 利用scrapy爬虫通过短短50行代码下载整站短视频的方法,感兴趣的朋友一起看看吧
    2018-10-10
  • 在pandas中遍历DataFrame行的实现方法

    在pandas中遍历DataFrame行的实现方法

    这篇文章主要介绍了在pandas中遍历DataFrame行的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • python用pyinstaller封装exe双击后疯狂闪退解决办法

    python用pyinstaller封装exe双击后疯狂闪退解决办法

    本文主要介绍了python用pyinstaller封装exe双击后疯狂闪退解决办法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • python argparse 模块命令行参数用法及说明

    python argparse 模块命令行参数用法及说明

    这篇文章主要介绍了python argparse 模块命令行参数用法及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • python中使用psutil查看内存占用的情况

    python中使用psutil查看内存占用的情况

    今天小编就为大家分享一篇python中使用psutil查看内存占用的情况,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-06-06
  • pytorch如何获得模型的计算量和参数量

    pytorch如何获得模型的计算量和参数量

    这篇文章主要介绍了pytorch如何获得模型的计算量和参数量操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-05-05
  • Django 实现jwt认证的示例

    Django 实现jwt认证的示例

    这篇文章主要介绍了Django 实现jwt 认证的示例,帮助大家更好的理解和学习使用django,感兴趣的朋友可以了解下
    2021-04-04
  • Python使用Pygame绘制时钟

    Python使用Pygame绘制时钟

    这篇文章主要为大家详细介绍了Python使用Pygame绘制时钟,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11

最新评论