一种比较省内存的稀疏矩阵Python存储方案
原文:http://www.pythontab.com/html/2014/pythonhexinbiancheng_0522/788.html
推荐系统中经常需要处理类似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以二进制字符串形式存储,直接上代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
'''
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__( self ):
pass
'''
从文件中生成matrix
考虑到dbm读写的性能不如内存,我们做了一些缓存,每1000W次批量写入一次
考虑到字符串拼接性能不太好,我们直接用StringIO来做拼接
'''
def from_file( self , fp, sep = 't' ):
cnt = 0
cache = {}
for l in fp:
if 10000000 = = cnt:
self ._flush(cache)
cnt = 0
cache = {}
i, j, v = [ float (i) for i in l.split(sep)]
ik = ( 'i%d' % i)
ib = struct.pack( 'if' , j, v)
jk = ( 'j%d' % j)
jb = struct.pack( 'if' , i, v)
try :
cache[ik].write(ib)
except :
cache[ik] = StringIO()
cache[ik].write(ib)
try :
cache[jk].write(jb)
except :
cache[jk] = StringIO()
cache[jk].write(jb)
cnt + = 1
self ._nums + = 1
self ._flush(cache)
return self ._nums
def _flush( self , cache):
for k,v in cache.items():
v.seek( 0 )
s = v.read()
try :
self ._data[k] + = s
except :
self ._data[k] = s
if __name__ = = '__main__' :
db = bsddb.btopen( None , cachesize = 268435456 )
data = DictMatrix(db)
data.from_file( open ( '/path/to/log.txt' , 'r' ), ',' )
|
测试4500W条rating数据(整形,整型,浮点格式),922MB文本文件导入,采用内存dict储存的话,12分钟构建完毕,消耗内存1.2G,采用示例代码中的bdb存储,20分钟构建完毕,占用内存300~400MB左右,比cachesize大不了多少,数据读取测试:
1
2
|
import timeit
timeit.Timer( 'foo = __main__.data[9527, ...]' , 'import __main__' ).timeit(number = 1000 )
|
消耗1.4788秒,大概读取一条数据1.5ms。
采用类Dict来存储数据的另一个好处是你可以随便用内存Dict或者其他任何形式的DBM,甚至传说中的Tokyo Cabinet….
好的,码完收工。
一种比较省内存的稀疏矩阵Python存储方案相关推荐
- tinyFlash:一种超轻量级的嵌入式单片机flash KV 数据存储方案
tinyFlash 一种超轻量级的flash KV数据存储方案 Github 地址:https://github.com/ospanic/tinyFlash 设计原理 本方案采用两个扇区轮流使用的方法 ...
- 带你了解两种线性规划的方法:稀疏矩阵存储和预处理
摘要:本文为大家带来线性规划的稀疏矩阵存储和数据预处理. 本文分享自华为云社区<线性规划--稀疏矩阵>,原文作者:Bale10 . 随着AI时代的发展,线性规划问题的规模越来越大是一种必然 ...
- python idle 常规命令_Python的3种运行方式:命令行窗口、Python解释器、IDLE的实现
1 命令行窗口 开始栏搜索command,打开命令提示符,即为命令行窗口. 运行一个Python程序,需要输入:Python + 程序地址 + 程序名.py 如图: 2 Python解释器 开始栏搜索 ...
- python内存池机制,python基础—12python内存管理机制
一.内存池机制 1.对象池 面试题目: python内存管理机制是什么? 1). 由于python中万物皆对象,内存管理机制就是对象的存储问题,Python会分 配一块内存空间去存储对象. 2) 对于 ...
- 精华阅读第 13 期 |常见的八种导致 APP 内存泄漏的问题 1
2019独角兽企业重金招聘Python工程师标准>>> 本期是移动开发精英俱乐部的第13期文章,都是以技术为主,所以这里就不过多的进行赘述了,我们直接看干货内容吧!本文系ITOM管理 ...
- python3 urllib 内存泄露_【专家专栏】张昊 | 从urllib2的内存泄露看python的GC
原标题:[专家专栏]张昊 | 从urllib2的内存泄露看python的GC 惨案回顾 领导:小张啊,安排你个任务,团队需要你做一个功能,提取一批页面上的数据,有问题吗? 小张:当然没问题,您啥时候要 ...
- python稀疏矩阵的存储与表示
参考链接: https://blog.csdn.net/bitcarmanlee/article/details/52668477 https://blog.csdn.net/wangjian1204 ...
- android内存池,两种常见的内存管理方法:堆和内存池
描述 本文导读 在程序运行过程中,可能产生一些数据,例如,串口接收的数据,ADC采集的数据.若需将数据存储在内存中,以便进一步运算.处理,则应为其分配合适的内存空间,数据处理完毕后,再释放相应的内存空 ...
- python之路 mysql 博客园_教为学:Python学习之路(二):MySQLdb的几种安装方式,以及用Python测试连接MySql...
教为学:Python学习之路(二):MySQLdb的几种安装方式,以及用Python测试连接MySql Easy_install安装MySQLdb 很简单,以至于我不晓得该怎么说.一句话. sodu ...
最新文章
- 牛客练习赛64 - B Dis2(树,基础图论)
- [置顶] 给Fedora修改默认的软件下载源
- 学python能赚什么外卖-用python模拟美团外卖骑手推送请求
- SpringMVC获取参数的几种方式
- InputStream 、 InputStreamReader 、 BufferedReader区别
- html怎么建立段落,HTML 段落
- kali NETCAT NC的使用
- 不同性能极限下的服务器,探求极限性能 服务器测试之ScienceMark
- python游戏源码回合制游戏_python game源码下载
- python中不可以用来表示字符串_在Python中,不可以用来表示字符串的符号是____________。...
- 从头推导与实现 BP 网络
- 1.Ubuntu Server下搭建LAMP环境
- pytorch项目源码理解
- 只需要几行代码就可以轻松实现OCR图片转文字
- 软件测试52讲-测试先行:测试驱动开发(TDD)
- Iptables-外网地址及端口映射到内网地址及端口
- 3dmax 2014加载panda3d插件失败
- 数据加密-国密SM2对数据进行加解密
- 塔多漫画一直维护服务器,塔多漫画
- c语言*p1 什么意思,p1什么意思_p1,意思_词汇大全意思全集
热门文章
- php怎么查帮助,需要有关MySQL查询和PHP的帮助
- linux 脚本自动编制工具,全自动工具链编译脚本
- python条件表达式有哪几个_python条件表达式:多项分支,双向分支
- java query类是什么类_java – 从包生成QueryDsl Q类
- html 文字倒映效果,HTML图片CSS滤镜—倒影效果
- android h5 禁止缩放,vue h5移动端禁止缩放代码
- javaee校园信息服务器,基于javaEE服务器 学生考勤管理系统的设计与实现开题报告...
- 11月数据库排行:PostgreSQL起飞、三巨头分数持续低迷
- K8S面试大通关!赶紧收藏!
- 每日一皮:程序员的神逻辑...