我想将一个整数(例如20)按照每个部分的概率分成四个部分:p = [0.02,0.5,0.3,0.18]
相应的python代码为:
frequency=np.random.choice([1,2,3,4],20,p=[0.02,0.5,0.3,0.18])
from collections import Counter
np.fromiter(Counter(frequency).values(), dtype=np.float32)
# Out[86]:
# array([8., 8., 4.], dtype=float32)
但是,我有1e8以上的零件,数量不是20,而是1e10。 所以python真的很慢。 例如
frequency=np.random.choice([i for i in range (10**7)],16**10,p=[0.0000001 for i in range(10**7)])
from collections import Counter
r=np.fromiter(Counter(frequency).values(), dtype=np.float32)
现在它只产生MemoryError:
我认为tensorflow gpu可以解决这个问题,因为输出结果的大小仅为10 ** 7。 有谁知道如何做到这一点?
答案 0 :(得分:0)
这里要考虑几个问题。
如果您在GPU上运行代码,它将永远无法工作,因为GPU不是为存储而设计的,而是为了快速计算而设计的,因此GPU上的空间小于CPU。但是,此代码也可能在CPU上产生内存错误,就像在我的计算机上一样。因此,我们首先尝试克服这一点。
克服CPU上的MemoryError:
产生MemoryError
的行本身就是第1行:
In [1]: frequency = np.random.choice([i for i in range (10**7)],16**10,p=[0.0000
...: 001 for i in range(10**7)])
...:
---------------------------------------------------------------------------
MemoryError Traceback (most recent call last)
其原因是第1行的输出的大小不是10**7
,而是16**10
。由于这就是导致MemoryError的原因,因此目标永远不要创建该大小的列表。
要执行此操作,我们将样本的大小减小一个因子,并在块factor
上循环循环多次,以便可以存储。在我的计算机上,因素为1000000
可以解决问题。一旦创建了样本,就可以使用Counter将其变成频率字典。好处是我们知道频率字典在转换为列表或numpy数组后,将永远不会超过10**7
的大小,不会引起存储错误。
由于某些元素可能不会每次都在采样数组中,因此,我们将在上一次迭代中使用字典更新该字典,以保留特定元素的频率,而不是将Counter字典直接直接转换为列表。 / p>
整个循环完成后,我们会将创建的字典转换为列表。我添加了一个进度条,以便跟踪进度,因为计算可能要花费很多时间。另外,由于分布是统一的,因此您无需在特定情况下将参数p
添加到np.random.choice()
函数中。
import numpy as np
import tensorflow as tf
from click import progressbar
from collections import Counter
def large_uniform_sample_frequencies(factor=1000000, total_elements=10**7, sample_size=16**10):
# Initialising progressbar
bar = range(factor)
# Initialise an empty dictionary which
# will be updated in each iteration
counter_dict = {}
for iteration in bar:
# Generate a random sample of size (16 ** 10) / factor
frequency = np.random.choice([i for i in range (total_elements)],
sample_size / factor)
# Update the frequency dictionary
new_counter = Counter(frequency)
counter_dict.update(new_counter)
return np.fromiter(counter_dict.values(), dtype=np.float32)
使用tensorflow-gpu:
正如您提到的tensorflow-gpu
一样,我可以假设您是想使用MemoryError
摆脱tensorflow-gpu
还是要在使用GPU的同时与tensorflow-gpu
一起运行。
要解决MemoryError
,您可以尝试使tf.multinomial()
的功能与shown here的效果与np.random.choice()
相同,但不太可能有助于解决问题,它存储一定大小的数据,并且不执行某些替代计算。
例如,如果要将其作为训练某些模型的一部分来运行,则可以使用分布式Tensorflow通过使用上面给出的代码,将这部分计算图作为PS Task放置在CPU上。这是最终的代码:
# Mention the devices for PS and worker tasks
ps_dev = '/cpu:0'
worker_dev = '/gpu:0'
# Toggle True to place computation on CPU
# and False to place it on the least loaded GPU
is_ps_task = True
# Set device for a PS task
if (is_ps_task):
device_setter = tf.train.replica_device_setter(worker_device=worker_dev,
ps_device=ps_dev,
ps_tasks=1)
# Allocate the computation to CPU
with tf.device(device_setter):
freqs = large_uniform_sample_frequencies()