Вы можете удалить .Random.seed
самостоятельно, прежде чем заблокировать среду. Также вам нужно загрузить библиотеку (или использовать функцию раньше) и присвоить tmp
что-то.
library(parallel)
tmp <- NULL
rm(".Random.seed", envir = .GlobalEnv, inherits = FALSE)
lockEnvironment(globalenv())
tmp <- parallel::mclapply(1:2, identity, mc.cores = 2)
Конечно, это не позволит работать функциям, которым требуется .Random.seed
, например, rnorm
.
Обходной путь должен изменить вид RNG на «L'Ecuyer-CMRG», см. Также здесь ?nextRNGStream
:
library(parallel)
tmp <- NULL
RNGkind("L'Ecuyer-CMRG")
lockEnvironment(globalenv())
tmp <- parallel::mclapply(1:2, rnorm, mc.cores = 2)
РЕДАКТИРОВАТЬ
Я подумал о другом решении вашей проблемы, и я думаю, что это будет работать с любым RNG (не тестировал много). Вы можете переопределить функцию, которая удаляет .Random.seed
, с помощью функции, которая просто устанавливает ее на NULL
library(parallel)
mc.set.stream <- function () {
if (RNGkind()[1L] == "L'Ecuyer-CMRG") {
assign(".Random.seed", get("LEcuyer.seed", envir = RNGenv),
envir = .GlobalEnv)
} else {
if (exists(".Random.seed", envir = .GlobalEnv, inherits = FALSE)) {
assign(".Random.seed", NULL, envir = .GlobalEnv)
}
}
}
assignInNamespace("mc.set.stream", mc.set.stream, asNamespace("parallel"))
tmp <- NULL
set.seed(0)
lockEnvironment(globalenv())
tmp <- parallel::mclapply(1:2, rnorm, mc.cores = 2)
Одна заключительная мысль: вы можете создать новую среду, содержащую все вещи, которые вы не хотите изменять Закрой его и работай там.
По крайней мере две опции:
От вычисления в современной физике William R. Gibbs:
Можно всегда численно интегрировать [функцию] и инвертировать [cdf], но это часто не очень удовлетворительно особенно, если PDF изменяется быстро.
Вы буквально создаете таблицу, которая переводит диапазон [0-1)
в соответствующие диапазоны в целевом распределении. Затем бросьте свой обычный (высококачественный) PRNG и переведите с таблицей. Это является громоздким, но ясным, осуществимым, и абсолютно общим.
Нормализуйте целевую гистограмму, затем
x
) вдоль диапазона случайным образом.Снова, бесхитростный, но ясный и рабочий. Это может быть медленно для распределения с большой очень низкой вероятностью (пики с длинными хвостами).
С обоими из этих методов можно приблизить данные с кусочно-полиномиальными сглаживаниями или шлицами для генерации плавной кривой, если гистограмма ступенчатой функции не желаема---, но оставьте это на потом, поскольку это может быть преждевременная оптимизация.
Лучшие методы могут существовать для особых случаев.
Все это довольно стандартно и должно появиться в любом Числовом Аналитическом учебнике, если я больше детали необходим.
Если необходимо вытянуть большое количество образцов со взвешенным распределением дискретных точек, то посмотрите на ответ на подобный вопрос.
Однако, если необходимо приблизить некоторую непрерывную случайную функцию с помощью гистограммы, затем лучший выбор является, вероятно, числовым ответом интеграции dmckee. С другой стороны, можно использовать искажение, и сохранить точку налево и выбрать универсальное число между двумя точками.
Больше информации о проблеме было бы полезно. Например, какие значения являются законченными гистограммами? Действительно ли они являются категориальными (например, цвета, буквы) или непрерывными (например, высоты, время)?
Если гистограммы по категориальным данным, я думаю, что может быть трудно параметризовать дистрибутивы, если нет много корреляций между категориями.
Если гистограммы по текущим данным, Вы могли бы попытаться соответствовать распределению с помощью смесей Gaussians. Таким образом, попытайтесь соответствовать гистограмме с помощью $\\sum_ {i=1} ^n w_i N (m_i, v_i) $, где m_i и v_i являются средним и различием. Затем когда Вы хотите генерировать данные, Вы сначала выбираете меня от 1.. n с вероятностью, пропорциональной весам w_i и затем, выбирают x ~ n (m_i, v_i), как Вы были бы от любого Гауссова.
Так или иначе можно хотеть читать больше о моделях смеси.
Таким образом, кажется, что то, что я хочу для генерации данного распределения вероятности, является Функцией Квантиля, которая является инверсией кумулятивной функции распределения, как говорит @dmckee.
Вопрос становится: Что лучший способ состоит в том, чтобы генерировать и сохранить функцию квантиля описание данной непрерывной гистограммы? У меня есть чувство, что ответ будет зависеть значительно от формы входа - если это будет следовать за каким-либо видом шаблона должны быть упрощения по наиболее общему случаю. Я обновлю здесь, когда я иду.
Править:
Я разговаривал на этой неделе, который напомнил мне об этой проблеме. Если я воздерживаюсь от описания гистограммы как уравнение и просто храню таблицу, я могу сделать выборы в O (1) время? Оказывается, что Вы можете, без любой потери точности, за счет O (N lgN) время создания.
Создайте массив объектов N. Универсальный случайный выбор в массив найдет объект с probablilty 1/Н. Для каждого объекта сохраните часть хитов, для которых этот объект должен на самом деле быть выбран, и индекс другого объекта, который будет выбран, если этот не будет.
Взвешенная Случайная Выборка, C реализация:
//data structure
typedef struct wrs_data {
double share;
int pair;
int idx;
} wrs_t;
//sort helper
int wrs_sharecmp(const void* a, const void* b) {
double delta = ((wrs_t*)a)->share - ((wrs_t*)b)->share;
return (delta<0) ? -1 : (delta>0);
}
//Initialize the data structure
wrs_t* wrs_create(int* weights, size_t N) {
wrs_t* data = malloc(sizeof(wrs_t));
double sum = 0;
int i;
for (i=0;i<N;i++) { sum+=weights[i]; }
for (i=0;i<N;i++) {
//what percent of the ideal distribution is in this bucket?
data[i].share = weights[i]/(sum/N);
data[i].pair = N;
data[i].idx = i;
}
//sort ascending by size
qsort(data,N, sizeof(wrs_t),wrs_sharecmp);
int j=N-1; //the biggest bucket
for (i=0;i<j;i++) {
int check = i;
double excess = 1.0 - data[check].share;
while (excess>0 && i<j) {
//If this bucket has less samples than a flat distribution,
//it will be hit more frequently than it should be.
//So send excess hits to a bucket which has too many samples.
data[check].pair=j;
// Account for the fact that the paired bucket will be hit more often,
data[j].share -= excess;
excess = 1.0 - data[j].share;
// If paired bucket now has excess hits, send to new largest bucket at j-1
if (excess >= 0) { check=j--;}
}
}
return data;
}
int wrs_pick(wrs_t* collection, size_t N)
//O(1) weighted random sampling (after preparing the collection).
//Randomly select a bucket, and a percentage.
//If the percentage is greater than that bucket's share of hits,
// use it's paired bucket.
{
int idx = rand_in_range(0,N);
double pct = rand_percent();
if (pct > collection[idx].share) { idx = collection[idx].pair; }
return collection[idx].idx;
}
Редактирование 2: После небольшого исследования я нашел, что даже возможно сделать конструкцию в O (N) время. С тщательным отслеживанием Вы не должны сортировать массив для нахождения больших и маленьких мусорных ведер. Обновленная реализация здесь
Для нормального распределения следующее может помочь:
http://en.wikipedia.org/wiki/Normal_distribution#Generating_values_for_normal_random_variables
Чтобы выбрать гистограмму (исходную или уменьшенную), Метод псевдонима Уокера быстро и просто.