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


Posted in Python onJune 27, 2014

推荐系统中经常需要处理类似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 相关文章推荐
Python socket.error: [Errno 98] Address already in use的原因和解决方法
Aug 25 Python
浅析Python中元祖、列表和字典的区别
Aug 17 Python
使用C++扩展Python的功能详解
Jan 12 Python
Python查找两个有序列表中位数的方法【基于归并算法】
Apr 20 Python
python操作mysql代码总结
Jun 01 Python
Python UnboundLocalError和NameError错误根源案例解析
Oct 31 Python
python模拟鼠标点击和键盘输入的操作
Aug 04 Python
python实现的接收邮件功能示例【基于网易POP3服务器】
Sep 11 Python
pandas 缺失值与空值处理的实现方法
Oct 12 Python
Python3内置函数chr和ord实现进制转换
Jun 05 Python
Django数据库迁移常见使用方法
Nov 12 Python
Pytorch如何切换 cpu和gpu的使用详解
Mar 01 Python
Python实现的百度站长自动URL提交小工具
Jun 27 #Python
python使用心得之获得github代码库列表
Jun 25 #Python
在Python中使用异步Socket编程性能测试
Jun 25 #Python
Python开发的单词频率统计工具wordsworth使用方法
Jun 25 #Python
python 字典(dict)遍历的四种方法性能测试报告
Jun 25 #Python
用python登录Dr.com思路以及代码分享
Jun 25 #Python
python正则表达式re模块详解
Jun 25 #Python
You might like
《被神捡到的男人》动画化计划进行中!
2020/03/06 日漫
php 用sock技术发送邮件的函数
2007/07/21 PHP
浅谈php+phpStorm+xdebug配置方法
2015/09/17 PHP
PHP 中魔术常量的实例详解
2017/10/26 PHP
yii2多图上传组件的使用教程
2018/05/10 PHP
PHP Laravel中的Trait使用方法
2019/01/20 PHP
laravel通用化的CURD的实现
2019/12/13 PHP
Tab页界面,用jQuery及Ajax技术实现
2009/09/21 Javascript
JS实现self的resend
2010/07/22 Javascript
JavaScript取得gridview中获取checkbox选中的值
2017/07/24 Javascript
微信小程序之前台循环数据绑定
2017/08/18 Javascript
使用puppeteer破解极验的滑动验证码
2018/02/24 Javascript
vue+jquery+lodash实现滑动时顶部悬浮固定效果
2018/04/28 jQuery
vue-router的HTML5 History 模式设置
2018/09/08 Javascript
微信小程序 数据缓存实现方法详解
2019/08/26 Javascript
微信小程序scroll-view锚点链接滚动跳转功能
2019/12/12 Javascript
js实现弹幕墙效果
2020/12/10 Javascript
Python version 2.7 required, which was not found in the registry
2014/08/26 Python
python 遍历字符串(含汉字)实例详解
2017/04/04 Python
使用python opencv对目录下图片进行去重的方法
2019/01/12 Python
python3对接mysql数据库实例详解
2019/04/30 Python
用Python画一个LinkinPark的logo代码实例
2019/09/10 Python
python 中Arduino串口传输数据到电脑并保存至excel表格
2019/10/14 Python
Hudson Jeans官网:高级精制牛仔裤
2018/11/28 全球购物
澳洲网红粉泥面膜:Sand & Sky
2019/08/13 全球购物
MIRTA官网:手工包,100%意大利制造
2020/02/11 全球购物
荷兰最大的鞋子、服装和运动折扣店:Bristol
2021/01/07 全球购物
酒店管理专业毕业生推荐信
2013/11/10 职场文书
运动会开幕式邀请函
2014/02/03 职场文书
超市开店计划书
2014/04/26 职场文书
个人四风问题整改措施思想汇报
2014/10/04 职场文书
国际贸易实务实训报告
2014/11/05 职场文书
八月迷情观后感
2015/06/11 职场文书
浅谈Redis主从复制以及主从复制原理
2021/05/29 Redis
教你用python实现12306余票查询
2021/06/30 Python
Mysql分析设计表主键为何不用uuid
2022/03/31 MySQL