тензорный поток распределяет целые числа в соответствии с вероятностями

Я хотел бы распределить целое число, например 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. Кто-нибудь знает как это сделать?


person ZHANG Juenjie    schedule 22.09.2018    source источник
comment
проверьте: stackoverflow.com/questions/41123879/   -  person vijay m    schedule 22.09.2018
comment
@ Виджай. Нет, это не только вопрос np.random.choice, но и счетчик.   -  person ZHANG Juenjie    schedule 22.09.2018


Ответы (1)


Здесь есть несколько вопросов, о которых следует подумать.

Если вы запускаете код на графическом процессоре, он никогда не будет работать, потому что графические процессоры предназначены не для хранения, а для быстрых вычислений, поэтому пространство на графическом процессоре меньше, чем на процессоре. Однако этот код может вызвать ошибку памяти и на ЦП, как это было на моей машине. Итак, мы сначала пытаемся преодолеть это.

Устранение ошибки 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 к функции 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, либо запустить это в сочетании с tensorflow-gpu при использовании графического процессора.

Чтобы решить MemoryError, вы можете попробовать функцию tf.multinomial() с тем же эффектом, что и np.random.choice(), как показан здесь, но вряд ли он поможет преодолеть проблему, заключающуюся в хранении данных определенного размера и невыполнении каких-то альтернативных вычислений.

Если вы хотите запустить это как часть обучения какой-либо модели, например, вы можете использовать Distributed Tensorflow, чтобы поместить эту часть графа вычислений на ЦП в качестве задачи PS, используя приведенный выше код. Вот окончательный код для этого:

# 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()
person Vedang Waradpande    schedule 22.09.2018