тензор потока распределяют целые числа в соответствии с вероятностями - PullRequest
0 голосов
/ 22 сентября 2018

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

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:

Я думаю, что tenorflow gpu способен решить эту проблему, поскольку выходной результат имеет размер только 10 ** 7.Кто-нибудь знает как это сделать?

1 Ответ

0 голосов
/ 22 сентября 2018

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

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

Преодоление ошибки MemoryErp на процессоре:

Строка, производящая 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, чтобы превратить его в словарь частот.Преимущество состоит в том, что мы знаем, что словарь частот при преобразовании в список или массив с пустыми значениями никогда не будет превышать размер 10**7, что не приводит к ошибке памяти.

Как некоторые из элементовможет не каждый раз находиться в массиве выборки, вместо преобразования словаря счетчика в список напрямую, мы обновим этот словарь, используя словарь на предыдущей итерации, чтобы сохранить частоты конкретных элементов.

Однажды весьцикл завершен, мы конвертируем созданный словарь в список.Я добавил индикатор выполнения, чтобы отслеживать прогресс, поскольку вычисления могут занять много времени.Кроме того, вам не нужно добавлять параметр 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)

Использование tennsflow-gpu:

Как вы упомянули tensorflow-gpu Я могу предположить, что вы либо хотите избавиться от MemoryError с помощью tensorflow-gpu, либо запустить его вместе с tensorflow-gpu при использовании графического процессора.

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

Если вы хотите выполнить это как часть обучения некоторой модели, например, вы можете использовать Distributed Tensorflow, чтобы поместить эту часть графика вычислений в CPU какЗадача 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()
...