Jump to content

Отбор проб из резервуара

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

Мотивация

[ редактировать ]

Предположим, мы видим последовательность элементов, один за другим. Мы хотим хранить в памяти десять элементов и хотим, чтобы они выбирались из последовательности случайным образом. Если мы знаем общее количество элементов n и можем получить к ним произвольный доступ, то решение простое: выберите 10 различных индексов i между 1 и n с равной вероятностью и сохраните i -ые элементы. Проблема в том, что мы не всегда знаем точное n заранее.

Просто: алгоритм R

[ редактировать ]

Простой и популярный, но медленный алгоритм Алгоритм R был создан Джеффри Виттером. [1]

Инициализировать массив проиндексировано из к , содержащий первые k элементов входных данных . Это резервуар .

Для каждого нового входа , сгенерируйте случайное число j равномерно по . Если , затем установите В противном случае отбросить .

Возвращаться после обработки всех входных данных.

Этот алгоритм работает методом индукции по .

Доказательство

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

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

Примените алгоритм R к -й вход. Вход включено с вероятностью по определению алгоритма. Для любого другого ввода , по гипотезе индукции, вероятность того, что он окажется в резервуаре непосредственно перед -й ввод обрабатывается . Вероятность того, что он все еще будет включен в резервуар после обрабатывается (другими словами, что не заменяется на ) является . Последнее следует из предположения, что целое число генерируется равномерно случайным образом; как только станет ясно, что замена действительно произойдет, вероятность того, что в частности заменяется на является .

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

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

Это алгоритм R, реализованный следующим образом:

(* S has items to sample, R will contain the result *)
ReservoirSample(S[1..n], R[1..k])
  // fill the reservoir array
  for i := 1 to k
      R[i] := S[i]
  end

  // replace elements with gradually decreasing probability
  for i := k+1 to n
    (* randomInteger(a, b) generates a uniform integer from the inclusive range {a, ..., b} *)
    j := randomInteger(1, i)
    if j <= k
        R[j] := S[i]
    end
  end
end

Оптимально: алгоритм L

[ редактировать ]

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

Этот процесс можно выполнить, не зная :

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

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

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

Первое упрощение: нет необходимости тестировать новые один за другим, поскольку вероятность того, что следующая приемка произойдет в является , то есть интервал принятия следует геометрическому распределению .

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

  • Каждый раз что-то новое выбран для ввода в хранилище, равномерно случайная запись в хранилище отбрасывается.
  • имеет то же распределение, что и , где все независимо. Это может быть отобрано путем первой выборки. , затем берём .

Это алгоритм L , [2] который реализуется следующим образом:

(* S has items to sample, R will contain the result *)
ReservoirSample(S[1..n], R[1..k])
  // fill the reservoir array
  for i = 1 to k
      R[i] := S[i]
  end

  (* random() generates a uniform (0,1) random number *)
  W := exp(log(random())/k)

  while i <= n
      i := i + floor(log(random())/log(1-W)) + 1
      if i <= n
          (* replace a random item of the reservoir with item i *)
          R[randomInteger(1,k)] := S[i]  // random index between 1 and k, inclusive
          W := W * exp(log(random())/k)
      end
  end
end

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

Со случайной сортировкой

[ редактировать ]

Если мы свяжем с каждым элементом входных данных равномерно сгенерированное случайное число, k элементов с наибольшими (или, что эквивалентно, наименьшими) связанными значениями образуют простую случайную выборку. [3] Таким образом, простой отбор проб из резервуара сохраняет k элементов с наибольшими на данный момент связанными значениями в приоритетной очереди .

(*
  S is a stream of items to sample
  S.Current returns current item in stream
  S.Next advances stream to next position
  min-priority-queue supports:
    Count -> number of items in priority queue
    Minimum -> returns minimum key value of all items
    Extract-Min() -> Remove the item with minimum key
    Insert(key, Item) -> Adds item with specified key
 *)
ReservoirSample(S[1..?])
  H := new min-priority-queue
  while S has data
    r := random()   // uniformly random between 0 and 1, exclusive
    if H.Count < k
      H.Insert(r, S.Current)
    else
      // keep k items with largest associated keys
      if r > H.Minimum
        H.Extract-Min()
        H.Insert(r, S.Current)
    end
    S.Next
  end
  return items in H
end

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

Взвешенная случайная выборка

[ редактировать ]

Этот метод, называемый также последовательной выборкой, некорректен в том смысле, что он не позволяет получить априорно фиксированные вероятности включения. Некоторые приложения требуют, чтобы вероятности выборки элементов соответствовали весам, связанным с каждым элементом. Например, может потребоваться выборка запросов в поисковой системе с весом, определяющим количество раз, когда они выполнялись, чтобы можно было проанализировать выборку на предмет общего влияния на взаимодействие с пользователем. Пусть вес предмета i будет , а сумма всех весов равна W . Существует два способа интерпретации весов, присвоенных каждому элементу набора: [4]

  1. В каждом раунде вероятность того, что каждый невыбранный элемент будет выбран в этом раунде, пропорциональна его весу относительно весов всех невыбранных элементов. Если X — текущая выборка, то вероятность элемента быть выбранным в текущем раунде .
  2. Вероятность включения каждого предмета в случайную выборку пропорциональна его относительному весу, т. е. . Обратите внимание, что эта интерпретация может быть недостижима в некоторых случаях, например, .

Алгоритм A-Res

[ редактировать ]

Следующий алгоритм был предложен Эфраимидисом и Спиракисом и использует интерпретацию 1: [5]

(*
  S is a stream of items to sample
  S.Current returns current item in stream
  S.Weight  returns weight of current item in stream
  S.Next advances stream to next position
  The power operator is represented by ^
  min-priority-queue supports:
    Count -> number of items in priority queue
    Minimum() -> returns minimum key value of all items
    Extract-Min() -> Remove the item with minimum key
    Insert(key, Item) -> Adds item with specified key
 *)
ReservoirSample(S[1..?])
  H := new min-priority-queue
  while S has data
    r := random() ^ (1/S.Weight)   // random() produces a uniformly random number in (0,1)
    if H.Count < k
      H.Insert(r, S.Current)
    else
      // keep k items with largest associated keys
      if r > H.Minimum
        H.Extract-Min()
        H.Insert(r, S.Current)
      end
    end
    S.Next
  end
  return items in H
end

Этот алгоритм идентичен алгоритму, приведенному в разделе «Отбор проб из резервуара со случайной сортировкой», за исключением генерации ключей элементов. Алгоритм эквивалентен присвоению каждому элементу ключа. где r — случайное число, а затем выбирают k элементов с наибольшими ключами. Эквивалентно, более численно стабильная формулировка этого алгоритма вычисляет ключи как и выберите k предметов с наименьшими ключами. [6] [ не удалось пройти проверку ]

Алгоритм A-ExpJ

[ редактировать ]

Следующий алгоритм является более эффективной версией A-Res , также предложенной Эфраимидисом и Спиракисом: [5]

(*
  S is a stream of items to sample
  S.Current returns current item in stream
  S.Weight  returns weight of current item in stream
  S.Next advances stream to next position
  The power operator is represented by ^
  min-priority-queue supports:
    Count -> number of items in the priority queue
    Minimum -> minimum key of any item in the priority queue
    Extract-Min() -> Remove the item with minimum key
    Insert(Key, Item) -> Adds item with specified key
 *)
ReservoirSampleWithJumps(S[1..?])
  H := new min-priority-queue
  while S has data and H.Count < k
    r := random() ^ (1/S.Weight)   // random() produces a uniformly random number in (0,1)
    H.Insert(r, S.Current)
    S.Next
  end
  X := log(random()) / log(H.Minimum) // this is the amount of weight that needs to be jumped over
  while S has data
    X := X - S.Weight
    if X <= 0
      t := H.Minimum ^ S.Weight
      r := random(t, 1) ^ (1/S.Weight) // random(x, y) produces a uniformly random number in (x, y)
    
      H.Extract-Min()
      H.Insert(r, S.Current)

      X := log(random()) / log(H.Minimum)
    end
    S.Next
  end
  return items in H
end

Этот алгоритм использует те же математические свойства, которые используются в A-Res , но вместо вычисления ключа для каждого элемента и проверки, следует ли вставить этот элемент или нет, он вычисляет экспоненциальный переход к следующему элементу, который будет вставлен. Это позволяет избежать необходимости создавать случайные варианты для каждого элемента, что может быть дорогостоящим. Количество необходимых случайных величин уменьшено с к в ожидании, где - размер резервуара, и количество элементов в потоке. [5]

Алгоритм А-Чао

[ редактировать ]

Предупреждение: следующее описание неверно, см. оригинальную статью Чао и обсуждение здесь .

Следующий алгоритм, предложенный М.Т. Чао, использует интерпретацию 2: [7] и Тилле (2006). [8]

(*
  S has items to sample, R will contain the result
  S[i].Weight contains weight for each item
 *)
WeightedReservoir-Chao(S[1..n], R[1..k])
  WSum := 0
  // fill the reservoir array
  for i := 1 to k
      R[i] := S[i]
      WSum := WSum + S[i].Weight
  end
  for i := k+1 to n
    WSum := WSum + S[i].Weight
    p := S[i].Weight / WSum // probability for this item
    j := random();          // uniformly random between 0 and 1
    if j <= p               // select item according to probability
        R[randomInteger(1,k)] := S[i]  //uniform selection in reservoir for replacement
    end
  end
end

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

Обратите внимание, что Чао не указывает, как отбирать первые k элементов. Он просто предполагает, что у нас есть какой-то другой способ выбирать их пропорционально их весу. Чао: «Предположим, что у нас есть план выборки фиксированного размера по отношению к S_k в момент времени A первого порядка ; такой, что вероятность включения X_t равна π(k; i) ».

Алгоритм А-Чао с переходами

[ редактировать ]

Подобно другим алгоритмам, можно вычислить случайный вес. j и вычитаем значения вероятностной массы предметов, пропуская их при этом j > 0, уменьшая количество случайных чисел, которые необходимо сгенерировать. [4]

(*
  S has items to sample, R will contain the result
  S[i].Weight contains weight for each item
 *)
WeightedReservoir-Chao(S[1..n], R[1..k])
  WSum := 0
  // fill the reservoir array
  for i := 1 to k
      R[i] := S[i]
      WSum := WSum + S[i].Weight
  end
  j := random() // uniformly random between 0 and 1
  pNone := 1 // probability that no item has been selected so far (in this jump)
  for i := k+1 to n
    WSum := WSum + S[i].Weight
    p := S[i].Weight / WSum // probability for this item
    j -= p * pNone
    pNone := pNone * (1 - p)
    if j <= 0
        R[randomInteger(1,k)] := S[i]  //uniform selection in reservoir for replacement
        j = random()
        pNone := 1
    end
  end
end

Связь с перетасовкой Фишера-Йейтса

[ редактировать ]

Предположим, кто-то хочет вытащить k случайных карт из колоды карт. Естественным подходом было бы перетасовать колоду и затем взять k верхних карт. В общем случае тасование также должно работать, даже если количество карт в колоде заранее не известно, условие, которому удовлетворяет версия тасования Фишера-Йейтса наизнанку : [9]

(* S has the input, R will contain the output permutation *)
Shuffle(S[1..n], R[1..n])
  R[1] := S[1]
  for i from 2 to n do
      j := randomInteger(1, i)  // inclusive range
      R[i] := R[j]
      R[j] := S[i]
  end
end

Обратите внимание: хотя остальные карты перетасованы, только первые k в данном контексте важны . Следовательно, массиву R необходимо отслеживать карты только в первых k позициях во время перемешивания, что уменьшает объем необходимой памяти. Усекая R до длины k , алгоритм соответствующим образом модифицируется:

(* S has items to sample, R will contain the result *)
ReservoirSample(S[1..n], R[1..k])
  R[1] := S[1]
  for i from 2 to k do
      j := randomInteger(1, i)  // inclusive range
      R[i] := R[j]
      R[j] := S[i]
  end
  for i from k + 1 to n do
      j := randomInteger(1, i)  // inclusive range
      if (j <= k)
          R[j] := S[i]
      end
  end
end

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

Ограничения

[ редактировать ]

Выборка из резервуара предполагает, что желаемая выборка помещается в основную память , часто подразумевая, что k является константой, не зависящей от n . В приложениях, где мы хотели бы выбрать большое подмножество входного списка (скажем, третье, т.е. ), необходимо использовать другие методы. Были предложены распределенные реализации этой проблемы. [10]

  1. ^ Jump up to: Перейти обратно: а б Виттер, Джеффри С. (1 марта 1985 г.). «Случайный отбор проб из резервуара» (PDF) . Транзакции ACM в математическом программном обеспечении . 11 (1): 37–57. CiteSeerX   10.1.1.138.784 . дои : 10.1145/3147.3165 . S2CID   17881708 .
  2. ^ Jump up to: Перейти обратно: а б Ли, Ким-Хун (4 декабря 1994 г.). «Алгоритмы отбора проб из резервуара временной сложности O(n(1+log(N/n)))» . Транзакции ACM в математическом программном обеспечении . 20 (4): 481–493. дои : 10.1145/198429.198435 . S2CID   15721242 .
  3. ^ Фан, К.; Мюллер, Мэн; Резуча, И. (1962). «Разработка планов выборочного контроля с использованием методов последовательного (постатейного) отбора и цифровых компьютеров». Журнал Американской статистической ассоциации . 57 (298): 387–402. дои : 10.1080/01621459.1962.10480667 . JSTOR   2281647 .
  4. ^ Jump up to: Перейти обратно: а б Эфрамидис, Павлос С. (2015). «Взвешенная случайная выборка по потокам данных». Алгоритмы, вероятность, сети и игры . Конспекты лекций по информатике. Том. 9295. стр. 183–195. arXiv : 1012.0256 . дои : 10.1007/978-3-319-24024-4_12 . ISBN  978-3-319-24023-7 . S2CID   2008731 .
  5. ^ Jump up to: Перейти обратно: а б с Эфрамидис, Павлос С.; Спиракис, Пол Г. (16 марта 2006 г.). «Взвешенная случайная выборка с резервуаром». Письма об обработке информации . 97 (5): 181–185. дои : 10.1016/j.ipl.2005.11.003 .
  6. ^ Арратия, Ричард (2002). Бела Боллобас (ред.). «О величине зависимости при простой факторизации равномерного случайного целого числа». Современная комбинаторика . 10 : 29–91. CiteSeerX   10.1.1.745.3975 . ISBN  978-3-642-07660-2 .
  7. ^ Чао, Монтана (1982). «Общий план выборки с неравной вероятностью». Биометрика . 69 (3): 653–656. дои : 10.1093/biomet/69.3.653 .
  8. ^ Тилле, Ив (2006). Алгоритмы выборки . Спрингер. ISBN  978-0-387-30814-2 .
  9. ^ Национальный исследовательский совет (2013). Границы в массовом анализе данных . Пресса национальных академий. п. 121. ИСБН  978-0-309-28781-4 .
  10. ^ Отбор проб из резервуара в MapReduce
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 75af630d0e4ad64a8344e30fe2a34e40__1719045060
URL1:https://arc.ask3.ru/arc/aa/75/40/75af630d0e4ad64a8344e30fe2a34e40.html
Заголовок, (Title) документа по адресу, URL1:
Reservoir sampling - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)