Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用列表理解的Python内存管理_Python_Memory - Fatal编程技术网

使用列表理解的Python内存管理

使用列表理解的Python内存管理,python,memory,Python,Memory,我试图对从磁盘读取文件创建的大型词典进行一些分析。读取操作会产生稳定的内存占用。然后我有了一个方法,它根据我从字典中复制到临时字典中的数据执行一些计算。我这样做是为了所有的复制和数据使用都限定在方法中,并且我希望在方法调用结束时消失 可悲的是,我做错了什么。customerdict定义如下(在.py变量顶部定义): 对象的格式为{customerid:dictionary{id:0 | | 1}} 还有一个定义类似的字典,叫做allids 我有一个计算sim_pearson距离的方法(从编程集体

我试图对从磁盘读取文件创建的大型词典进行一些分析。读取操作会产生稳定的内存占用。然后我有了一个方法,它根据我从字典中复制到临时字典中的数据执行一些计算。我这样做是为了所有的复制和数据使用都限定在方法中,并且我希望在方法调用结束时消失

可悲的是,我做错了什么。customerdict定义如下(在.py变量顶部定义):

对象的格式为{customerid:dictionary{id:0 | | 1}}

还有一个定义类似的字典,叫做allids

我有一个计算sim_pearson距离的方法(从编程集体智能书中修改的代码),如下所示

def sim_pearson(custID1, custID2):
si = []

smallcustdict = {}
smallcustdict[custID1] = customerdict[custID1]
smallcustdict[custID2] = customerdict[custID2]

#a loop to round out the remaining allids object to fill in 0 values
for customerID, catalog in smallcustdict.iteritems():
    for id in allids:
        if id not in catalog:
            smallcustdict[customerID][asin] = 0.0

#get the list of mutually rated items
for id in smallcustdict[custID1]:
    if id in smallcustdict[custID2]:
        si.append(id) # = 1

#return 0 if there are no matches
if len(si) == 0: return 0

#add up all the preferences
sum1 = sum([smallcustdict[custID1][id] for id in si])
sum2 = sum([smallcustdict[custID2][id] for id in si])

#sum up the squares
sum1sq = sum([pow(smallcustdict[custID1][id],2) for id in si])
sum2sq = sum([pow(smallcustdict[custID2][id],2) for id in si])

#sum up the products
psum = sum([smallcustdict[custID1][id] * smallcustdict[custID2][id] for id in si])

#calc Pearson score
num = psum - (sum1*sum2/len(si))
den = sqrt((sum1sq - pow(sum1,2)/len(si)) * (sum2sq - pow(sum2,2)/len(si)))

del smallcustdict
del si
del sum1
del sum2
del sum1sq
del sum2sq
del psum

if den == 0:
    return 0

return num/den
通过sim_pearson方法的每个循环都会无限地增加python.exe的内存占用。我尝试使用“del”方法显式删除局部作用域变量

看看taskmanager,内存以6-10Mb的增量增加。一旦设置了初始customerdict,占用空间为137Mb


你知道我为什么这样做会耗尽内存吗?

我想问题就在这里:

smallcustdict[custID1] = customerdict[custID1]
smallcustdict[custID2] = customerdict[custID2]

#a loop to round out the remaining allids object to fill in 0 values
for customerID, catalog in smallcustdict.iteritems():
    for id in allids:
        if id not in catalog:
            smallcustdict[customerID][asin] = 0.0
customerdict
中的词典将在
smallcustdict
中引用,因此,当您添加到词典时,它们将保持不变。这是我能看到的唯一一点,你在哪里做了任何超出范围的事情,所以我想这就是问题所在

注意:您在许多地方为自己做了大量工作,不使用列表comp,重复做相同的事情,也不使用通用的方法来做事情,更好的版本可能如下所示:

import collections
import functools
import operator

customerdict = collections.defaultdict(dict)

def sim_pearson(custID1, custID2):

    #Declaring as a dict literal is nicer.
    smallcustdict = {
        custID1: customerdict[custID1],
        custID2: customerdict[custID2],
    }

    # Unchanged, as I'm not sure what the intent is here.
    for customerID, catalog in smallcustdict.iteritems():
        for id in allids:
            if id not in catalog:
                smallcustdict[customerID][asin] = 0.0

    #dict views are set-like, so the easier way to do what you want is the intersection of the two.
    si = smallcustdict[custID1].viewkeys() & smallcustdict[custID2].viewkeys()

    #if not is a cleaner way of checking for no values.
    if not si:
        return 0

    #Made more generic to avoid repetition and wastefully looping repeatedly.
    parts = [list(part) for part in zip(*((value[id] for value in smallcustdict.values()) for id in si))]

    sums = [sum(part) for part in parts]
    sumsqs = [sum(pow(i, 2) for i in part) for part in parts]
    psum = sum(functools.reduce(operator.mul, part) for part in zip(*parts))

    sum1, sum2 = sums
    sum1sq, sum2sq = sumsqs

    #Unchanged.
    num = psum - (sum1*sum2/len(si))
    den = sqrt((sum1sq - pow(sum1,2)/len(si)) * (sum2sq - pow(sum2,2)/len(si)))

    #Again using if not.
    if not den:
        return 0
    else:
        return num/den

请注意,这完全没有经过测试,因为您给出的代码不是一个完整的示例。但是,它应该很容易用作改进的基础。

我想问题在于:

smallcustdict[custID1] = customerdict[custID1]
smallcustdict[custID2] = customerdict[custID2]

#a loop to round out the remaining allids object to fill in 0 values
for customerID, catalog in smallcustdict.iteritems():
    for id in allids:
        if id not in catalog:
            smallcustdict[customerID][asin] = 0.0
customerdict
中的词典将在
smallcustdict
中引用,因此,当您添加到词典时,它们将保持不变。这是我能看到的唯一一点,你在哪里做了任何超出范围的事情,所以我想这就是问题所在

注意:您在许多地方为自己做了大量工作,不使用列表comp,重复做相同的事情,也不使用通用的方法来做事情,更好的版本可能如下所示:

import collections
import functools
import operator

customerdict = collections.defaultdict(dict)

def sim_pearson(custID1, custID2):

    #Declaring as a dict literal is nicer.
    smallcustdict = {
        custID1: customerdict[custID1],
        custID2: customerdict[custID2],
    }

    # Unchanged, as I'm not sure what the intent is here.
    for customerID, catalog in smallcustdict.iteritems():
        for id in allids:
            if id not in catalog:
                smallcustdict[customerID][asin] = 0.0

    #dict views are set-like, so the easier way to do what you want is the intersection of the two.
    si = smallcustdict[custID1].viewkeys() & smallcustdict[custID2].viewkeys()

    #if not is a cleaner way of checking for no values.
    if not si:
        return 0

    #Made more generic to avoid repetition and wastefully looping repeatedly.
    parts = [list(part) for part in zip(*((value[id] for value in smallcustdict.values()) for id in si))]

    sums = [sum(part) for part in parts]
    sumsqs = [sum(pow(i, 2) for i in part) for part in parts]
    psum = sum(functools.reduce(operator.mul, part) for part in zip(*parts))

    sum1, sum2 = sums
    sum1sq, sum2sq = sumsqs

    #Unchanged.
    num = psum - (sum1*sum2/len(si))
    den = sqrt((sum1sq - pow(sum1,2)/len(si)) * (sum2sq - pow(sum2,2)/len(si)))

    #Again using if not.
    if not den:
        return 0
    else:
        return num/den

请注意,这完全没有经过测试,因为您给出的代码不是一个完整的示例。但是,它应该很容易用作改进的基础。

尝试更改以下两行:

smallcustdict[custID1] = customerdict[custID1]
smallcustdict[custID2] = customerdict[custID2]


这样,当
sim_pearson()
函数返回时,您对这两个词典所做的更改不会保留在
customerdict
中。

尝试更改以下两行:

smallcustdict[custID1] = customerdict[custID1]
smallcustdict[custID2] = customerdict[custID2]


这样,当
sim_pearson()
函数返回时,您对这两个词典所做的更改不会持续在
customerdict
中。

谢谢dm03514-我试过了,没有什么不同。谢谢dm03514-我试过了,“这没什么区别。”布兰登·沃森不知道你在这里想做什么,很难知道。我不知道
allid
asin
是什么,也不知道您在做什么。问题是,您是否需要将这些值添加到
customerdicts
的子项中?您在这里做了很多新的事情,我将尝试分析这些内容,并学习新的内容。谢谢你。在对sums和sumsq的简化中,我没有“den”变量赋值的单个值。“我错过了什么吗,@BrandonWatson不,我错过了现在编辑的扩展。最后,你可能想直接使用数据结构,而不是像我在编辑中那样解压数据结构,从而修改数学,使其更通用(如果适用)。我不确定你做了什么或是如何做的……你在其中加入了大量有趣的语法。我甚至不明白sum1,sum2=sums行,或者如何查找它。也就是说,内存问题似乎已经解决了。足迹现在上下跳动,但它有一个向上的偏差,并最终耗尽内存。我添加了一个计数器变量,以查看我在61600操作中得到了多少。我还将添加一些性能计数器,但这种方法似乎较慢。更新-您的方法可以在内存不足之前完成240个计算。@BrandonWatson如果不知道您在这里要做什么,很难知道。我不知道
allid
asin
是什么,也不知道您在做什么。问题是,您是否需要将这些值添加到
customerdicts
的子项中?您在这里做了很多新的事情,我将尝试分析这些内容,并学习新的内容。谢谢你。在对sums和sumsq的简化中,我没有“den”变量赋值的单个值。“我错过了什么吗,@BrandonWatson不,我错过了现在编辑的扩展。最后,你可能想直接使用数据结构,而不是像我在编辑中那样解压数据结构,从而修改数学,使其更通用(如果适用)。我不确定你做了什么或是如何做的……你在其中加入了大量有趣的语法。我甚至不明白sum1,sum2=sums行,或者如何查找它。也就是说,内存问题似乎已经解决了。足迹现在上下跳动,但它有一个向上的偏差,并最终耗尽内存。我添加了一个计数器变量,以查看我在61600操作中得到了多少。我还将添加一些性能计数器,但这种方式似乎较慢。更新-您的方式在内存不足之前完成240个计算。不是为了让您感到奇怪,但我爱您。:)这似乎解决了我的记忆问题。现在我明白了,通过添加0.0值的列表理解,我正在向主cu写入内容