Python 2.7 优化读与写;写入搁置对象以放大更大的数据集
上下文:我正在用python生成合成数据,然后将其存储为搁置对象 除此之外,我还使用每个类别的个人评分、频率项目集挖掘和协同过滤来构建我的评分模型。在后两个版本中,我需要能够扫描除此之外的其他用户的类似类别。这就是为什么我选择使用dict数据结构,以便访问速度更快。 如果您看到此用例有更好的数据结构,请告诉我 我的主要想法是-在完成这个原型之后,这将为真正的用户完成,因此np.random.choice不会消耗当前消耗的98%的时间。除此之外,我还有什么别的方法可以让它更快 我还提到了列表中#项的范围,为您提供了#users>>#epoch times/footprints per user的上下文 数据结构如下-:Python 2.7 优化读与写;写入搁置对象以放大更大的数据集,python-2.7,dictionary,shelve,Python 2.7,Dictionary,Shelve,上下文:我正在用python生成合成数据,然后将其存储为搁置对象 除此之外,我还使用每个类别的个人评分、频率项目集挖掘和协同过滤来构建我的评分模型。在后两个版本中,我需要能够扫描除此之外的其他用户的类似类别。这就是为什么我选择使用dict数据结构,以便访问速度更快。 如果您看到此用例有更好的数据结构,请告诉我 我的主要想法是-在完成这个原型之后,这将为真正的用户完成,因此np.random.choice不会消耗当前消耗的98%的时间。除此之外,我还有什么别的方法可以让它更快 我还提到了列表中#项
{
'U1': {
u'Vegetarian/Vegan': [1401572571,
7.850284461542393e-06],
u'Dumplings': [1402051698,
1.408092980963553e-05],
u'Gluten-free': [1400490069,
2.096967508708229e-06],
u'Lawyer': [1406549628,
0.0033942020684690575],
u'Falafel': [1409365870,
0.10524975778067258]
},
'U0': {
u'GasStation/Garage': [1394649440,
1.1279761215136923e-09],
u'MusicFestival': [1398401459,
1.0948922055743449e-07],
u'Chinese': [1408116633,
0.015294426605167652]
}}
您在这里看到的每个历元时间之后的浮点数是该用户在该类别中的分数。我在计算完分数后写了下来(这篇文章中提到的分数代码)
有关数据的更多信息-:
我有一个主键名为用户U0、U1等,还有一个副键名为“类别”,这里是“素食者/素食者”等。每个副键都有一个更多项目的列表。因此,我需要画2个随机数(不替换,在低索引和高索引中。这些项依次是纪元时间。从概念上讲,它表示用户U1在多个纪元时间与素食者/素食者交互,我将其作为类别键的值存储在列表中
假设它是u‘素食主义者/素食主义者’:[1401572571],然后对于每个类别,我计算一个分数并将其写回同一个搁置对象,发布合成数据生成。下面是代码的精简版本
问题:我注意到,在5000个用户的数据集上,仅创建搁置对象就需要6个多小时的时间我做错了什么?我需要能够将其扩展到50000个或更多用户。我还做了一些预镜像和内存分析,并且我正在连接profiling一组5个用户的结果
import json,math,codecs,pickle
import numpy as np
from collections import defaultdict
import shelve
from contextlib import closing
global low,high,no_categories,low_epoch_time,high_epoch_time,epoch_time_range,no_users
basepath="/home/ekta/LatLongPrototype/FINALDUMP/"
low,high=6,15
no_categories=xrange(low,high+1)
low_epoch_time,high_epoch_time=1393200055,1409400055
epoch_time_range=xrange(low_epoch_time,high_epoch_time+1)
no_users=5000
global users
users=[]
global shelf_filehandle
shelf_filehandle=basepath+"shelf_contents"
def Synthetic_data_shelve(path, list_cat,list_epoch_time):
for j in xrange(len(list_cat)):
if not list_cat[j] in path.keys():
path[list_cat[j]] = [list_epoch_time[j]]
else :
path[list_cat[j]] = path[list_cat[j]]+[list_epoch_time[j]]
return path
def shelving():
dict_user = shelve.open(shelf_filehandle)
for i in xrange(no_users):
each_footprint=int(np.random.choice(no_categories, 1,replace=False))
list_cat=np.random.choice(sub_categories,each_footprint,replace=True)
list_epoch_time=np.random.choice(epoch_time_range,each_footprint,replace=False)
path =dict_user.get("U"+str(i), dict(defaultdict(dict)))
path=Synthetic_data_shelve(path, list_cat,list_epoch_time)
dict_user["U"+str(i)] = path
dict_user.close()
#To test this quickly consider, categories as,
sub_categories=["C"+str(i) for i in xrange(50)]
shelving()
我到目前为止所做的尝试-:
分析程序-:
以下是测线评测的结果-我看到列表\u epoch\u time=np.random。选择(epoch\u time\u range,每个\u footprint,replace=False)占用99.8%的时间!
我可以表面上尝试将其定义为choice=np.random.choice
,但这并没有给出明显较低的%时间
如前所述,以下结果适用于无用户=5
ekta@superwomen:~$ kernprof.py -l -v LatLong_shelving.py
Wrote profile results to LatLong_shelving.py.lprof
Timer unit: 1e-06 s
File: LatLong_shelving.py
Function: Synthetic_data_shelve at line 22
Total time: 0.000213 s
Line # Hits Time Per Hit % Time Line Contents
==============================================================
22 @profile
23 def Synthetic_data_shelve(path, list_cat,list_epoch_time):
24 46 49 1.1 23.0 for j in xrange(len(list_cat)):
25 41 88 2.1 41.3 if not list_cat[j] in path.keys():
26 19 28 1.5 13.1 path[list_cat[j]] = [list_epoch_time[j]]
27 else :
28 22 44 2.0 20.7 path[list_cat[j]] = path[list_cat[j]]+[list_epoch_time[j]]
29 5 4 0.8 1.9 return path
File: LatLong_shelving.py
Function: shelving at line 31
Total time: 32.008 s
Line # Hits Time Per Hit % Time Line Contents
==============================================================
31 @profile
32 def shelving():
33 1 4020 4020.0 0.0 dict_user = shelve.open(shelf_filehandle)
34 6 13 2.2 0.0 for i in xrange(no_users):
35 5 541 108.2 0.0 each_footprint=int(np.random.choice(no_categories, 1,replace=False))
36 5 226 45.2 0.0 list_cat=np.random.choice(sub_categories,each_footprint,replace=True)
37 5 31942152 6388430.4 99.8 list_epoch_time=np.random.choice(epoch_time_range,each_footprint,replace=False)
38 5 1074 214.8 0.0 path =dict_user.get("U"+str(i), dict(defaultdict(dict)))
39 5 360 72.0 0.0 path=Synthetic_data_shelve(path, list_cat,list_epoch_time)
40 5 3302 660.4 0.0 dict_user["U"+str(i)] = path
41 1 56352 56352.0 0.2 dict_user.close()
下面是关于内存分析的内容。
我们如何减少对“合成数据搁置”的调用?如果检查list_cat[j]是否在path.keys()中的整个逻辑被转储到“搁置”中,它会更快吗?显然,我不能做reduce(合成数据搁置,path),因为path是一个dict,并且不允许减少dict。此外,I,j循环
“合成数据搁置”和“搁置”是reduce的一个很好的候选,因为它们是每个用户的独立属性。我如何利用这一事实&更多
ekta@superwomen:~$ python -m memory_profiler LatLong_shelving.py
Line # Mem usage Increment Line Contents
================================================
23 15.2 MiB 0.0 MiB @profile
24 def Synthetic_data_shelve(path, list_cat,list_epoch_time):
25 15.2 MiB 0.0 MiB for j in xrange(len(list_cat)):
26 15.2 MiB 0.0 MiB if not list_cat[j] in path.keys():
27 15.2 MiB 0.0 MiB path[list_cat[j]] = [list_epoch_time[j]]
28 else :
29 15.2 MiB 0.0 MiB path[list_cat[j]] = path[list_cat[j]]+[list_epoch_time[j]]
30 15.2 MiB 0.0 MiB return path
Filename: LatLong_shelving.py
Line # Mem usage Increment Line Contents
================================================
23 15.2 MiB 0.0 MiB @profile
24 def Synthetic_data_shelve(path, list_cat,list_epoch_time):
25 15.2 MiB 0.0 MiB for j in xrange(len(list_cat)):
26 15.2 MiB 0.0 MiB if not list_cat[j] in path.keys():
27 15.2 MiB 0.0 MiB path[list_cat[j]] = [list_epoch_time[j]]
28 else :
29 15.2 MiB 0.0 MiB path[list_cat[j]] = path[list_cat[j]]+[list_epoch_time[j]]
30 15.2 MiB 0.0 MiB return path
Filename: LatLong_shelving.py
Line # Mem usage Increment Line Contents
================================================
23 15.2 MiB 0.0 MiB @profile
24 def Synthetic_data_shelve(path, list_cat,list_epoch_time):
25 15.2 MiB 0.0 MiB for j in xrange(len(list_cat)):
26 15.2 MiB 0.0 MiB if not list_cat[j] in path.keys():
27 15.2 MiB 0.0 MiB path[list_cat[j]] = [list_epoch_time[j]]
28 else :
29 15.2 MiB 0.0 MiB path[list_cat[j]] = path[list_cat[j]]+[list_epoch_time[j]]
30 15.2 MiB 0.0 MiB return path
Filename: LatLong_shelving.py
Line # Mem usage Increment Line Contents
================================================
23 15.2 MiB 0.0 MiB @profile
24 def Synthetic_data_shelve(path, list_cat,list_epoch_time):
25 15.2 MiB 0.0 MiB for j in xrange(len(list_cat)):
26 15.2 MiB 0.0 MiB if not list_cat[j] in path.keys():
27 15.2 MiB 0.0 MiB path[list_cat[j]] = [list_epoch_time[j]]
28 else :
29 15.2 MiB 0.0 MiB path[list_cat[j]] = path[list_cat[j]]+[list_epoch_time[j]]
30 15.2 MiB 0.0 MiB return path
Filename: LatLong_shelving.py
Line # Mem usage Increment Line Contents
================================================
23 15.2 MiB 0.0 MiB @profile
24 def Synthetic_data_shelve(path, list_cat,list_epoch_time):
25 15.2 MiB 0.0 MiB for j in xrange(len(list_cat)):
26 15.2 MiB 0.0 MiB if not list_cat[j] in path.keys():
27 15.2 MiB 0.0 MiB path[list_cat[j]] = [list_epoch_time[j]]
28 else :
29 15.2 MiB 0.0 MiB path[list_cat[j]] = path[list_cat[j]]+[list_epoch_time[j]]
30 15.2 MiB 0.0 MiB return path
Filename: LatLong_shelving.py
Line # Mem usage Increment Line Contents
================================================
32 14.5 MiB 0.0 MiB @profile
33 def shelving():
34 14.6 MiB 0.1 MiB dict_user = shelve.open(shelf_filehandle)
35 15.2 MiB 0.7 MiB for i in xrange(no_users):
36 15.2 MiB 0.0 MiB each_footprint=int(np.random.choice(no_categories, 1,replace=False))
37 15.2 MiB 0.0 MiB list_cat=np.random.choice(sub_categories,each_footprint,replace=True)
38 15.2 MiB 0.0 MiB list_epoch_time=choice(epoch_time_range,each_footprint,replace=False)
39 15.2 MiB 0.0 MiB path =dict_user.get("U"+str(i), dict(defaultdict(dict)))
40 15.2 MiB 0.0 MiB path=Synthetic_data_shelve(path, list_cat,list_epoch_time)
41 15.2 MiB 0.0 MiB dict_user["U"+str(i)] = path
42 15.2 MiB 0.0 MiB dict_user.close()
相关-我现在没有时间阅读整件事,但显而易见的第一个问题是:为什么您认为
shelve
是正确的数据结构?如果您希望存储超过2个级别的层次数据,则第二级dict必须取消勾选,并针对其任何键或值的每次更改重新勾选s、 关系数据库、文档存储或老式的分层数据库更适合吗?@abarnert-如果我需要在这些数据的基础上构建统计模型(用Python)-RDBMS/其他替代方案更适合吗?抱歉,如果这听起来很幼稚,但我还没有处理过这种规模的用例(我需要将其存储为散列映射,以维护关联),这就是为什么要问这个问题-然后从那里阅读,或者使用MongoDB来扩展。我的主要问题是有5000个用户,创建工具架文件需要6个小时以上是没有道理的。感谢您花时间阅读。