tensorflow根据概率分布整数

时间:2018-09-22 08:12:43

标签: python tensorflow random choice

我想将一个整数(例如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。 有谁知道如何做到这一点?

1 个答案:

答案 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()