Случайный индекс из тензора (выборка с заменой из тензора) - PullRequest
1 голос
/ 28 апреля 2019

Я пытаюсь манипулировать индивидуальными весами разных нейронных сетей, чтобы увидеть, как их производительность ухудшается. Как часть этих экспериментов, я должен выбрать случайные образцы из их весовых тензоров, которые я начал понимать как выборку с заменой (в статистическом смысле). Тем не менее, так как он многомерен, я был озадачен тем, как сделать это честно. Вот подходы и исследования, которые я вложил в рассмотрение этой проблемы:

  • Ранее это было реализовано путем выбора случайного слоя и последующего выбора случайного веса в этом слое (игнорируйте реализацию выбора случайного веса). Поскольку слои имеют разные размеры, мы обнаружили, что выборка весов осуществлялась неравномерно.

  • Я подумал, что произойдет, если мы выберем в соответствии с numpy.shape тензора; однако теперь я понимаю, что это сталкивается с той же проблемой, что и выше.

    Рассмотрим, что происходит с тензором ранга 2 следующим образом:

    [[*, *, *],
     [*, *, *, *]]
    

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

    Обратите внимание, что этот возможный дубликат фактически реализует его таким образом.

  • Я нашел людей, предлагающих сгладить тензор, и использую numpy.random.choice для случайного выбора из одномерного массива. Это простое решение, за исключением того, что я понятия не имею, как вернуть сплющенный тензор обратно в его первоначальную форму. Кроме того, выравнивание миллионов весов будет несколько медленной реализацией.

  • Я нашел кого-то, кто обсуждал tf.random.multinomial здесь , но я не понимаю достаточно, чтобы знать, применимо ли это или нет.

  • Я столкнулся с этой бумагой о повторной выборке , но, опять же, она прошла через мою голову.

  • Я нашел другую статью , в которой конкретно обсуждаются тензоры и методы выборки, но она пошла еще дальше над моей головой.

  • Товарищ по команде нашел этот другой документ , в котором говорится о случайной выборке из тензора, но это только для тензоров ранга 3.


Помогите понять, как это сделать? Я работаю в Python с Keras, но я возьму алгоритм в любой существующей форме. Заранее спасибо.

1 Ответ

0 голосов
/ 28 июня 2019

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

  1. Используйте общее упорядочение на скалярных элементах тензора.Это эффективно перечисляет ваши элементы, то есть выравнивает их.Тем не менее, вы можете сделать это, сохраняя первоначальную форму.Рассмотрим этот псевдокод (в Python-подобном синтаксисе):

    def sample_tensor(tensor, chosen_index: int) -> Tuple[int]:
        """Maps a chosen random number to its index in the given tensor.
    
        Args:
            tensor: A ragged-array n-tensor.
            chosen_index: An integer in [0, num_scalar_elements_in_tensor).
        Returns:
            The index that accesses this element in the tensor.
    
        NOTE: Entirely untested, expect it to be fundamentally flawed.
        """
        remaining = chosen_index
        for (i, sub_list) in enumerate(tensor):
            if type(sub_list) is an iterable:
                if |sub_list| > remaining:
                    remaining -= |sub_list|
                else:
                    return i joined with sample_tensor(sub_list, remaining)
            else: 
                if len(sub_list) <= remaining:
                    return tuple(remaining)
    

    Прежде всего, я знаю, что это не здравый алгоритм.Идея состоит в том, чтобы вести обратный отсчет, пока вы не достигнете своего элемента, с учетом для индексов.

    Здесь необходимо сделать важные предположения.1) Все списки в конечном итоге будут содержать только скаляры.2) По прямому следствию, если список содержит списки, предположим, что он также не содержит скаляров на том же уровне.(Остановитесь и убедите себя в (2).)

    Здесь мы также должны сделать критическое замечание: мы не можем измерить количество скаляров в любом заданном списке, если список не состоит из однородных скаляров.,Чтобы избежать измерения этой величины в каждой точке, мой алгоритм выше должен быть подвергнут рефакторингу для спуска сначала, а затем вычитания.

    Этот алгоритм имеет некоторые последствия:

    • Это быстрая во всем своем подходе к проблеме.Если вы хотите написать функцию f: [0, total_elems) -> Tuple[int], вы должны знать количество предшествующих скалярных элементов вдоль полного упорядочения тензора.Это эффективно ограничено значением Theta(l), где l - количество списков в тензоре (поскольку мы можем вызвать len для списка скаляров).
    • Это медленно .Это слишком медленно по сравнению с выборочными лучшими тензорами, которые имеют определенную форму.

    Возникает вопрос: можем ли мы добиться большего успеха?См. Следующее решение.

  2. Используйте распределение вероятностей в сочетании с numpy.random.choice.Идея заключается в том, что если мы заранее знаем, каково распределение скаляров, мы можем проводить выборку на каждом уровне нисходящего тензора.Сложная проблема заключается в создании этого дистрибутива.

    Я не буду писать для этого псевдокод, но изложу некоторые цели:

    • Это можно вызвать только один раз для построения структуры данных..
    • Алгоритм должен объединять итеративные и рекурсивные методы для а) построения распределений для списков родных и дочерних объектов и б) построения распределений для потомков соответственно.
    • Алгоритму потребуется сопоставить индексы с вероятностьюраспределение, соответствующее спискам братьев и сестер (обратите внимание на предположения, рассмотренные выше).Для этого требуется , зная количество элементов в произвольном подтензоре.
    • На нижних уровнях, где списки содержат только скаляры, мы можем упростить, просто сохранив количество элементов в указанном списке (в отличие от хранения вероятностей случайного выбора скаляров из одномерного массива).
    • Скорее всего, вам потребуется 2-3 функции: одна, которая использует распределение вероятностей для возврата индекса, функция, которая строит объект распределения, ивозможно, функция, которая просто считает элементы, чтобы помочь построить распределение.

    Это также быстрее в O(n), где n - ранг тензора.Я убежден, что это самый быстрый из возможных алгоритмов, но мне не хватает времени, чтобы попытаться это доказать.

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


Обратите внимание, что (2) действительно то же самое, что (1), но мы предварительно вычислим знания о плотноститензор.

Надеюсь, это поможет.

...