Bu “saf” karıştırma algoritmasının nesi yanlış?


23

Bu, bir diziyi rastgele karıştırmayla ilgili bir Stackoverflow sorusunun devamıdır .

Kişinin "saf" geçici uygulamalara dayanmak yerine bir diziyi karıştırmak için kullanması gereken algoritmalar ( Knuth-Fisher-Yates Shuffle gibi ) vardır.

Artık saf algoritmamın bozulduğunu ispatlamakla (ya da yanlışlamakla) ilgileniyorum (olduğu gibi: eşit olasılıkla tüm olası izinleri üretmiyor).

İşte algoritma:

Birkaç kez döngü yapın (dizinin uzunluğu yapmalı) ve her yinelemede iki rastgele dizi dizini alın ve buradaki iki öğeyi değiştirin.

Açıkçası, bunun KFY'den daha fazla rasgele sayıya ihtiyacı var (iki katı), ama bunun dışında düzgün çalışıyor mu? Ve uygun sayıda yineleme ne olurdu ("dizi uzunluğu" yeterlidir)?


4
İnsanların neden bu değiş tokuşun neden FY'den 'daha basit' veya 'daha saf' olduğunu düşündüklerini anlayamıyorum ... Bu sorunu ilk kez çözerken FY'yi yeni uyguladım (bir adı bile olduğunu bilmeden). , sadece benim için yapmanın en basit yolu gibi görünüyordu.

1
@mbq: şahsen, onları eşit derecede kolay buluyorum, ancak FY'nin bana daha "doğal" göründüğünü kabul ediyorum.
nico

3
Kendinize yazdıktan sonra karıştırma algoritmalarını araştırdığımda (o zamandan beri bıraktığım bir uygulama), hep "kutsal saçmalık, yapıldı ve bir adı var !!" dedim.
JM, istatistikçi değil

Yanıtlar:


12

Yeterince karıştırırsanız, mükemmel bir yaklaşım olabilir (önceki cevaplarda belirtildiği gibi).

Sadece olup bitenleri ele almak için, algoritmanızın hangi sıklıkla ilk öğenin sabitlendiği bir öğesi dizisinin karıştırmasını üreteceğini düşünün , k 2 . Permütasyonlar eşit olasılıkla üretildiğinde, bunun 1 / k olması gerekir . Let s n sonra bu oluşum göreli frekans olmak sizin algoritması ile shuffles. En çok cömert olalım ve aslında seçerek varsayalım ayrı her bir çift olasılık ile seçildiğini, böylece karıştırır için rastgele eşit endeksler çiftleri =kk21/kpnn 2/(k(k-1))1/(k2)2/(k(k-1)). (Bu, "önemsiz" karıştırma israfının olmadığı anlamına gelir. Öte yandan, iki öğeli bir dizi için algoritmanızı tamamen bozar, çünkü iki öğeyi sabitlemek ve bunları değiştirmek arasında geçiş yaparsınız, yani önceden belirlenmiş bir sayıdan sonra durursanız adımlar, sonuçta hiçbir rasgelelik yoktur!)

Bu frekans basit bir yinelemeyi tatmin eder, çünkü ilk eleman karıştırıldıktan sonra iki ayrı şekilde orijinal konumunda bulunur . Birincisi, karışmalarından sonra sabitlenmiş olması ve bir sonraki karışma, birinci elemanı hareket ettirmemesidir. Diğer bunun sonrasında taşınmış olmasıdır karıştırır ama geri hamle bunu karıştırmak. Şansı olup birinci eleman hareket eşit = birinci eleman geri hareket şansı eşit ise, = . Nereden:n n n + 1 s t ( k - 1n+1nnn+1st (k-2)/k1/ ( k(k12)/(k2)(k2)/k 2/(k(k-1))1/(k2)2/(k(k1))

p0=1
çünkü ilk eleman doğru yerde başlıyor;

pn+1=k2kpn+2k(k1)(1pn).

Çözüm şudur

pn=1/k+(k3k1)nk1k.

çıkarıldığında , frekansın yanlış> olduğunu yanlış görüyoruz . Büyük ve için iyi bir yaklaşım . Bu, bu belirli frekanstaki hatanın , dizi büyüklüğüne göre ( ) göreceli olarak değiştirilen takas sayısıyla üssel olarak azalacağını, nispeten fazla sayıda takas yaptıysanız, büyük dizilerle tespit etmenin zor olacağını göstermektedir -ama hata her zaman oradadır.( k - 31/k knk-1(k3k1)nk1kknn/kk1kexp(2nk1)n/k

Tüm frekanslardaki hataların kapsamlı bir analizini sağlamak zordur. O hangi gösterileri olsa da, büyük olasılıkla onlar bunun gibi davranacaktır var en azından sen gerekir hata kabul edilebilecek kadar küçük hale getirmek için yeterince büyük olması (takası sayısı). Yaklaşık bir çözümn

n>12(1(k1)log(ϵ))

nerede kıyasla çok küçük olmalıdır . Bu ifade eder birkaç kez olmalıdır bile ham yaklaşık değerler için ( yani , burada mertebesindedir bazen kadar).1 / k , n k ε 0.01 1 / kϵ1/knkϵ0.011/k

Bütün bunlar şu soruyu soruyor: neden doğru olmayan (ancak sadece yaklaşık olarak) doğru olmayan, kesinlikle doğru olan ve daha fazla hesaplama gerektiren başka bir algoritma ile aynı teknikleri kullanan bir algoritmayı kullanmayı tercih edersiniz?

Düzenle

THilo'nun yorumu uygun (ve kimsenin bunu işaret etmeyeceğini umuyordum, bu yüzden bu fazladan çalışmayı bırakabilirim!). Mantığı açıklayayım.

  • Her seferinde gerçek takas oluşturduğunuzdan emin olursanız, tamamen sıkılırsınız. durumu için belirttiğim problem tüm dizilere uzanıyor. Tüm olası permütasyonların sadece yarısı, çift sayıda takas uygulanarak elde edilebilir; diğer yarısı tek sayıda takas uygulanarak elde edilir. Bu nedenle, bu durumda, hiçbir zaman muntazam bir dağılım dağılımına yakın hiçbir yerde üretemezsiniz (ancak, herhangi bir büyük için bir simülasyon çalışmasının problemi tespit edemeyeceği kadar çok olası olanlar vardır ). Bu gerçekten kötü.kk=2k

  • Bu nedenle, iki pozisyonu bağımsız olarak rastgele oluşturarak rastgele takas oluşturmak akıllıca olacaktır. Bu, her zaman bir elementi kendisiyle değiştirmenin şansı olduğu anlamına gelir ; yani, hiçbir şey yapmamaktır. Bu işlem algoritmayı biraz yavaşlatır: adımından sonra , sadece gerçek takas işleminin gerçekleşmesini bekleriz .n k - 11/knk1kN<N

  • Farklı takasların sayısıyla hatanın boyutunun monoton bir şekilde azaldığına dikkat edin. Bu nedenle, ortalama olarak daha az takas yapılması , hatayı ortalama olarak da arttırır . Ancak bu, ilk mermide açıklanan sorunun üstesinden gelmek için ödemek istediğiniz bir bedeldir. Sonuç olarak, benim hata tahminim, yaklaşık faktörü ile konservatif olarak düşüktür .(k1)/k

Hata formülü yakından bakmak olduğunu göstermektedir: Ben de ilginç bir belirgin istisna işaret etmek istediği hiçbir durumda hata . Bu bir hata değil: doğru. Ancak burada, permütasyonların düzgün dağılımı ile ilgili sadece bir istatistiği inceledim. Algoritmanın olduğunda (yani, herhangi bir pozisyonu sabitleyen doğru permütasyon frekansını elde etme) bu istatistiği yeniden üretebilmesi gerçeği , permütasyonların gerçekten düzgün bir şekilde dağıtıldığını garanti etmez. Aslında, gerçek takaslardan sonra , üretilebilecek tek olası izinler ,k=3k=32n(123)(321)ve kimlik. Sadece ikincisi verilen herhangi bir pozisyonu düzeltir, bu yüzden permütasyonların tam olarak üçte biri bir pozisyonu düzeltir. Fakat permütasyonların yarısı kayıp! Diğer durumda, fiili takaslardan sonra , olası tek permütasyonlar , ve . Yine, tam olarak bunlardan biri verilen herhangi bir pozisyonu sabitleyecektir, bu yüzden yine o pozisyonu sabitleyen doğru permütasyon sıklığını elde ediyoruz, ancak yine olası permütasyonların sadece yarısını elde ediyoruz.2n+1(12)(23)(13)

Bu küçük örnek, tartışmanın ana ipuçlarını ortaya çıkarmaya yardımcı olur: “cömert olma” yoluyla, belirli bir istatistik için hata oranını muhafazakar bir şekilde küçümsüyoruz . Bu hata oranı tüm için sıfır olmadığından, algoritmanın bozulduğunu görüyoruz. Dahası, bu istatistik için hata oranındaki bozulmayı analiz ederek, tüm permütasyonların tekdüze dağılımına yaklaşmak için herhangi bir umuduna ihtiyaç duyan algoritmanın yinelemelerinin sayısına daha düşük bir sınır koyarız .k4


1
"Ayrıca cömert olalım ve aslında karışıklıklarınız için rastgele bir şekilde farklı indeks çiftleri seçtiğinizi varsayalım". Bu varsayımın neden yapıldığını ve bunun nasıl cömert olduğunu anlamıyorum. Daha az rastgele bir dağılıma yol açan olası permütasyonları atıyor gibi görünüyor.
Thilo

1
@Thilo: Teşekkürler. Yorumunuz uzatılmış bir cevabı hak ediyor, ben de cevabın içine koydum. Burada “cömert” olmanın aslında herhangi bir permütasyonu atmadığını belirteyim: algoritmada, aksi takdirde hiçbir şey yapmayacak olan adımları ortadan kaldırır.
whuber

2
Bu problem tam olarak permütasyon grubunun Cayley grafiğinde bir Markov zinciri olarak analiz edilebilir. K = 1 ila 7 (5040 x 5040 matris!) İçin sayısal hesaplamalar, boyuttaki en büyük öz değerlerin (1 ve -1'den sonra) tam olarak . Bu permütasyon işareti alternatif sorunu ile başa bir kez hataları, (-1 özdeğerine gelen) ifade eder , tüm olasılıklar oranda çürüme veya Daha hızlı. Bunun daha büyük olan için tutmaya devam ettiğini düşünüyorum . (k3)/(k1)=12/(k1)(12/(k1))nk
whuber

1
daha iyi yapabilirsiniz, çünkü olasılıklar eşzamanlılık sınıflarında değişmezdir ve bunun yerine bölümü vardır, böylece bunun yerine matrisi analiz edebilirsiniz . 5040×504015715×15
Douglas Zare

8

Sanırım, basit algoritmanız, sayıların sonsuzluğa meyilli olduğu gibi kartları doğru şekilde karıştırır.

Üç kartınız olduğunu varsayalım: {A, B, C}. Kartlarınızın aşağıdaki sırayla başladığını varsayalım: A, B, C. Sonra bir karışıklıktan sonra aşağıdaki kombinasyonları izlersiniz:

{A,B,C}, {A,B,C}, {A,B,C} #You get this if choose the same RN twice.
{A,C,B}, {A,C,B}
{C,B,A}, {C,B,A}
{B,A,C}, {B,A,C}

Bu nedenle, A kartının {1,2,3} konumunda olma ihtimali {5/9, 2/9, 2/9}.

Kartları ikinci kez karıştırırsak, o zaman:

Pr(A in position 1 after 2 shuffles) = 5/9*Pr(A in position 1 after 1 shuffle) 
                                     + 2/9*Pr(A in position 2 after 1 shuffle) 
                                     + 2/9*Pr(A in position 3 after 1 shuffle) 

Bu 0,407 verir.

Aynı fikri kullanarak tekrarlama ilişkisi kurabiliriz, yani:

Pr(A in position 1 after n shuffles) = 5/9*Pr(A in position 1 after (n-1) shuffles) 
                                     + 2/9*Pr(A in position 2 after (n-1) shuffles) 
                                     + 2/9*Pr(A in position 3 after (n-1) shuffles).

Bunu R'ye kodlamak (aşağıdaki koda bakın), A kartının on karıştırmadan sonra {1,2,3} konumunda {0.33334, 0.33333, 0.33333} pozisyonunda olma olasılığını verir.

R kodu

## m is the probability matrix of card position
## Row is position
## Col is card A, B, C
m = matrix(0, nrow=3, ncol=3)
m[1,1] = 1; m[2,2] = 1; m[3,3] = 1

## Transition matrix
m_trans = matrix(2/9, nrow=3, ncol=3)
m_trans[1,1] = 5/9; m_trans[2,2] = 5/9; m_trans[3,3] = 5/9

for(i in 1:10){
  old_m = m
  m[1,1] = sum(m_trans[,1]*old_m[,1])
  m[2,1] = sum(m_trans[,2]*old_m[,1])
  m[3,1] = sum(m_trans[,3]*old_m[,1])

  m[1,2] = sum(m_trans[,1]*old_m[,2])
  m[2,2] = sum(m_trans[,2]*old_m[,2])
  m[3,2] = sum(m_trans[,3]*old_m[,2])

  m[1,3] = sum(m_trans[,1]*old_m[,3])
  m[2,3] = sum(m_trans[,2]*old_m[,3])
  m[3,3] = sum(m_trans[,3]*old_m[,3])
}  
m

1
+1. Bu, belirli bir kartın belirli bir pozisyonda bitme olasılığının, karıştırma sayısı arttıkça beklenen orana yaklaştığını göstermektedir. Ancak, aynı zamanda diziyi rastgele bir miktarda bir kez döndüren bir algoritma da geçerli olacaktır: Tüm kartların tüm konumlarda sonlanma eşit bir olasılığı vardır, ancak yine de hiçbir rasgelelık yoktur (dizi kalır).
Thilo

@Thilo: Üzgünüm yorumunuzu takip etmiyorum. Bir "algoritma rastgele bir miktarda döner" fakat yine de "rastlantısallık yoktur"? Daha fazla açıklayabilir misiniz?
csgillespie

Bir N-elemanı dizisini 0 ile N-1 pozisyonları arasında (rastgele) döndürerek "karıştırırsanız", o zaman her kart N pozisyonlarından herhangi birinde sona erme olasılığı aynıdır, fakat 2 hala her zaman 1 arasında bulunur. ve 3.
Thilo

1
@Thio: Ah, amacını anlıyorum. Olasılık (yukarıdaki 2 ile aynı fikri kullanarak), Pr (A 2. konumda) ve Pr (A 3. konumda) için - B ve C kartları için dito olasılığını hesaplayabilirsiniz. 1/3. Not: Cevabım sadece belirli bir durum verirken, @whuber güzel cevap genel durumu verir.
csgillespie

4

Mükemmel bir üniform dağılım elde edemeyeceğinizi görmenin bir yolu bölünebilirliktir. Tekdüze dağılımda, her permütasyon olasılığı . Eğer bir dizi üretmek zaman t rastgele transpozisyonları ve bunların ürün ile daha sonra toplama dizileri almak olasılıkları formu olan bir / n 2 t bir tamsayı için A . Eğer 1 / n ! = A / n 2 t , sonra n 2 t / n ! = A1/n!tA/n2tA1/n!=A/n2tn2t/n!=A. Bertrand'ın Postulate'i (bir teorem), için , paydada meydana gelen ve n'yi bölmeyen primler var , n 2 t / n ! bir tamsayı değil ve aktarımları n'ye eşit şekilde bölmenin bir yolu yok ! permütasyon. Örneğin, eğer n = 52 , daha sonra payda 1 / 52 ! bölünemeyen bir 3 , 5 , 7 , . . . , 47 ise payda 1 /n3nn2t/n!n!n=521/52!3,5,7,...,47 çok değildir, bir / 52 2 ton için azaltamamaktadır 1 / 52 ! .1/522tA/522t1/52!

Rasgele bir permütasyona yaklaşık olarak ne kadar yaklaşmanız gerekiyor? Rastgele transpozisyonlarla rastgele bir permütasyon oluşturmak, simetrik grubun temsil teorisi kullanılarak Diaconis ve Shahshahani tarafından analiz edildi.

Diaconis, P., Shahshahani, M. (1981): "Rastgele aktarımlarla rastgele bir permütasyon oluşturmak." Z. Wahrsch. Verw. Geb. 57, 159-179.

Bir sonuç aldı ki transpozisyonu anlamında sonra(1-ϵ)112ngünlüknpermütasyonlar rastgele olmaktan uzak, ancak sonra(1+ϵ)1(1-ε)12ngünlüknsonuç toplam varyasyon anlamında ve hem de yakın rasgele olanL2mesafe. Bu tür kesme fenomeni, gruplar üzerinde rastgele yürüyüşlerde yaygındır vebir güverte rastgele hale gelmeden önce7oluk fırçasınaihtiyaç duyduğunuz ünlü sonucuyla ilgilidir.(1+ε)12ngünlüknL27


2

Aklımda bir istatistikçi değilim, ama 2 sentimi koyacağım.

R'de küçük bir test yaptım (dikkatli, yüksek için çok yavaş numTrials, kod muhtemelen optimize edilebilir):

numElements <- 1000
numTrials <- 5000

swapVec <- function()
    {
    vec.swp <- vec

    for (i in 1:numElements)
        {
        i <- sample(1:numElements)
        j <- sample(1:numElements)

        tmp <- vec.swp[i]
        vec.swp[i] <- vec.swp[j]
        vec.swp[j] <- tmp
        }

    return (vec.swp)
    }

# Create a normally distributed array of numElements length
vec <- rnorm(numElements)

# Do several "swapping trials" so we can make some stats on them
swaps <- vec
prog <- txtProgressBar(0, numTrials, style=3)

for (t in 1:numTrials)
    {
    swaps <- rbind(swaps, swapVec())
    setTxtProgressBar(prog, t)
    }

Bu, satırlar (deneme başına bir + orijinal) ve sütunlar (her vektör öğesi için bir tane ) swapsiçeren bir matris oluşturur . Metot doğruysa, her bir sütunun dağılımı (örneğin, her bir elemanın denemeler üzerindeki değerleri), orijinal verilerin dağıtımından farklı olmamalıdır.numTrials+1numElements

Orijinal verilerimiz normal dağıldığı için tüm sütunların bundan sapmamasını beklerdik.

Eğer koşarsak

par(mfrow= c(2,2))
# Our original data
hist(swaps[1,], 100, col="black", freq=FALSE, main="Original")
# Three "randomly" chosen columns
hist(swaps[,1], 100, col="black", freq=FALSE, main="Trial # 1") 
hist(swaps[,257], 100, col="black", freq=FALSE, main="Trial # 257")
hist(swaps[,844], 100, col="black", freq=FALSE, main="Trial # 844")

Biz alırız:

Rastgele denemelerin histogramları

çok umut verici görünüyor. Şimdi, eğer dağılımları istatistiksel olarak doğrulamak istiyorsak, orijinallerden sapmadıklarını düşünüyorum. Bir Kolmogorov-Smirnov testi kullanabiliriz (lütfen bazı istatistikçiler bunun doğru olduğunu onaylayabilir mi?) Ve örneğin

ks.test(swaps[1, ], swaps[, 234])

Bu bize p = 0,9926 verir

Tüm sütunları kontrol edersek:

ks.results <- apply(swaps, 2, function(col){ks.test(swaps[1,], col)})
p.values <- unlist(lapply(ks.results, function(x){x$p.value})

Ve koşuyoruz

hist(p.values, 100, col="black")

Biz alırız:

Kolmogorov-Smirnov test p değerleri histogramı

Dolayısıyla, dizinin öğelerinin büyük çoğunluğu için, takas yönteminiz, çeyrekleri de görebildiğiniz gibi iyi bir sonuç verdi.

1> quantile(p.values)
       0%       25%       50%       75%      100% 
0.6819832 0.9963731 0.9999188 0.9999996 1.0000000

Açıkçası, daha az sayıda denemeyle durumun iyi olmadığını unutmayın:

50 deneme

1> quantile(p.values)
          0%          25%          50%          75%         100% 
0.0003399635 0.2920976389 0.5583204486 0.8103852744 0.9999165730

100 deneme

          0%         25%         50%         75%        100% 
 0.001434198 0.327553996 0.596603804 0.828037097 0.999999591 

500 deneme

         0%         25%         50%         75%        100% 
0.007834701 0.504698404 0.764231550 0.934223503 0.999995887 

0

Algoritmanızın sözde kodunda nasıl yorumlandığını aşağıda bulabilirsiniz:

void shuffle(array, length, num_passes)
  for (pass = 0; pass < num_passes; ++pass) 
    for (n = 0; n < length; ++)
      i = random_in(0, length-1)
      j = random_in(0, lenght-1)
      swap(array[i], array[j]

2xlengthxnum_pbirsses[0,length-1]length

length2xlengthxnum_pbirsses

length!length!<length2xlengthxnum_pbirsses

length!|length2xlengthxnum_pbirsses

pp<lengthplengthlength>2p|length!length2xlengthxnum_pbirsseslength!length2×length×num_passeslength>2

lengthp<lengthlength1length1length

lengthlength1length!length!|length!. Her izin farklı bir permütasyonla sonuçlandığını göstermek zor değildir ve oradan Fisher-Yates'ün her olasılıkla eşit olasılıkla üretildiğini görmek kolaydır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.