我正在生成项目之间的相似性矩阵,以便将其提供给Django中的推荐系统。 (一天结束时为n ^ 2。)

我遇到的问题是,无论我是否使用iterator(),RAM仍然被占用。
我做这样的事情:

rated_apps_list = Rating.objects.values_list('item_id', flat=True).order_by('-item_id').distinct()
rated_apps_iter = MemorySavingQuerysetIterator(rated_apps_list[start:])

for app_above in rated_apps_iter:
    rated_apps_below_iter = MemorySavingQuerysetIterator(rated_apps_list[i+1:])
    for app_below in rated_apps_below_iter:
        ...


其中MemorySavingQuerySetIterator为:

class MemorySavingQuerysetIterator(object):

def __init__(self,queryset,max_obj_num=1000):
    self._base_queryset = queryset
    self._generator = self._setup()
    self.max_obj_num = max_obj_num

def _setup(self):
    for i in xrange(0,self._base_queryset.count(),self.max_obj_num):
        # By making a copy of of the queryset and using that to actually access
        # the objects we ensure that there are only `max_obj_num` objects in
        # memory at any given time
        smaller_queryset = copy.deepcopy(self._base_queryset)[i:i+self.max_obj_num]
        #logger.debug('Grabbing next %s objects from DB' % self.max_obj_num)
        for obj in smaller_queryset.iterator():
            yield obj

def __iter__(self):
    return self

def next(self):
    return self._generator.next()


最初,我只尝试使用.iterator()函数,但后来我相信是由数据库客户端缓存结果。
泄漏仍然存在,过一会儿我必须重新加载脚本。

我知道创建与元素一样多的迭代器看起来并不高效,因为那样我最终将所有元素都存储在内存中,你们会怎么做?

有什么想法吗?谢谢!

最佳答案

实际上,您的解决方案几乎可以。有一些建议:


不要deepcopy queryset,无论如何切片它都会被克隆。
从数据库角度来看,切片效率低下(SQL中的偏移量较大),这意味着数据库需要准备很多行,然后只传递几行。
如果可以在表之间添加或删除任何内容,切片也不安全。


您可以使this thing适应您的情况。只需使用item_id而不是pk。它使用条件而不是偏移量,因此效率更高。

关于python - 在Django中计算大型数据集,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24152324/

10-14 18:30
查看更多