两个卡片组之间的相关性?


11

我编写了一个程序来模拟牌洗牌。

每张卡都有编号,西装CLUBS, DIAMONDS, HEARTS, SPADES的等级从2到10,然后是Jack,Queen,King和Ace。因此,两家具乐部的个数为1,三家具乐部的个数为2 .... A俱乐部数为13,黑桃A为52。

确定卡片混洗程度的方法之一是将其与未混洗的卡片进行比较,并查看卡片的顺序是否相关。

也就是说,我可能拥有这些卡,并使用未洗牌的卡进行比较:

Unshuffled          Shuffled            Unshuffled number   Shuffled number
Two of Clubs        Three of Clubs      1                   2
Three of Clubs      Two of Clubs        2                   1
Four of Clubs       Five of Clubs       3                   4
Five of Clubs       Four of Clubs       4                   3

皮尔森法的相关性为:0.6

使用大量的卡片(共52张),您可能会看到图案出现。我的假设是,经过更多的改组,您将获得更少的相关性。

但是,有很多方法可以测量相关性。

我已经尝试过Pearson的相关性,但是不确定在这种情况下使用的相关性是否正确。

这是合适的相关度量吗?有没有更合适的措施?

红利积分我有时会在结果中看到这种数据:

样本卡关联

显然存在一些相关性,但我不知道您如何衡量单独的“趋势线”?


为了帮助我们更好地理解您想要的内容,也许您对“卡的顺序是相关的”的含义可能会更加精确。
whuber

@whuber,我认为OP表示洗牌前后的给定卡位置。例如,红桃A可能是排名前3位,之后是8位。
gung-恢复莫妮卡

我想知道,“过度洗牌”是指维基百科所说的“浅滩洗牌”吗?
gung-恢复莫妮卡

1
@gung您链接到的Wikipedia页面上有OP所谈论的“浅滩混洗”和“过度混洗”的条目。很高兴阅读您链接到的链接:)
bdeonovic

1
@Pureferret在这种情况下,我会改写。您应该在计算排名相关性。
tchakravarty13年

Answers:


14

您可以使用所有相邻卡对之间的面值差异的香农熵来衡量相关的相对水平(或更准确地说,是随机性的增加水平)。

对于随机洗牌的52张卡片,这是计算方法。首先循环遍历整个平台,然后构建一种直方图。对于每个卡位置,计算面值之差。为了更具体地说明,假设第位的牌是黑桃王,而第位的牌是四家具乐部。那么我们有和以及。当您达到,这是一个特例;您再次绕回甲板的开头并取i=1,2,...,52ΔFi=Fi+1Fi(i+1)iFi+1=51Fi=3ΔFi=513=48i=52ΔF52=F1F52。如果最后得到的为负数,请加52以使面值差回到1-52范围内。ΔF

您最终将获得52对相邻卡的面值差异集,每对落入允许范围1到52之间。使用带有52个元素的直方图(即一维数组)对这些元素的相对频率进行计数。直方图记录了平台的一种“观察到的概率分布”;您可以通过将每个bin中的计数除以52来归一化此分布。因此,您将得到一系列变量,其中每个变量可能具有离散值可能值的范围:{0、1 / 52、2 / 52、3 / 52等},这取决于在直方图的特定区域中随机结束了多少对成对的面值差异。p1,p2,...p52

获得直方图后,您可以针对特定混洗迭代计算香农熵,因为

E=k=152pkln(pk)
我在R中编写了一个小型仿真来演示结果。第一张图显示了熵如何在20次随机播放迭代过程中演化。值0与完美排序的牌组相关;值越大,表示牌组越无序或与装饰相关。第二个图显示了一系列的20个构面,每个构图都包含一个与最初包含在问题中的图相似的图,显示了洗牌顺序与初始卡片顺序。第二个绘图中的20个构面与第一个绘图中的20个迭代相同,并且它们的颜色也相同,因此您可以直观地看到Shannon熵的多少对应于多少随机性。排序顺序。最后生成了生成曲线图的仿真代码。

香农信息熵与混洗迭代

洗牌顺序与开始顺序的混洗次数为20次,显示牌的相关性逐渐降低,随着时间的推移分布更加随机。

library(ggplot2)

# Number of cards
ncard <- 52 
# Number of shuffles to plot
nshuffle <- 20
# Parameter between 0 and 1 to control randomness of the shuffle
# Setting this closer to 1 makes the initial correlations fade away
# more slowly, setting it closer to 0 makes them fade away faster
mixprob <- 0.985 
# Make data frame to keep track of progress
shuffleorder <- NULL
startorder <- NULL
iteration <- NULL
shuffletracker <- data.frame(shuffleorder, startorder, iteration)

# Initialize cards in sequential order
startorder <- seq(1,ncard)
shuffleorder <- startorder

entropy <- rep(0, nshuffle)
# Loop over each new shuffle
for (ii in 1:nshuffle) {
    # Append previous results to data frame
    iteration <- rep(ii, ncard)
    shuffletracker <- rbind(shuffletracker, data.frame(shuffleorder,
                            startorder, iteration))
    # Calculate pairwise value difference histogram
    freq <- rep(0, ncard)
    for (ij in 1:ncard) {
        if (ij == 1) {
            idx <- shuffleorder[1] - shuffleorder[ncard]
        } else {
            idx <- shuffleorder[ij] - shuffleorder[ij-1]
        }
        # Impose periodic boundary condition
        if (idx < 1) {
            idx <- idx + ncard
        }
        freq[idx] <- freq[idx] + 1
    }
    # Sum over frequency histogram to compute entropy
    for (ij in 1:ncard) {
        if (freq[ij] == 0) {
            x <- 0
        } else {
            p <- freq[ij] / ncard
            x <- -p * log(p, base=exp(1))
        }
        entropy[ii] <- entropy[ii] + x
    }
    # Shuffle the cards to prepare for the next iteration
    lefthand <- shuffleorder[floor((ncard/2)+1):ncard]
    righthand <- shuffleorder[1:floor(ncard/2)]
    ij <- 0
    ik <- 0
    while ((ij+ik) < ncard) {
        if ((runif(1) < mixprob) & (ij < length(lefthand))) {
            ij <- ij + 1
            shuffleorder[ij+ik] <- lefthand[ij]
        }
        if ((runif(1) < mixprob) & (ik < length(righthand))) {
            ik <- ik + 1
            shuffleorder[ij+ik] <- righthand[ik]
        }
    }
}
# Plot entropy vs. shuffle iteration
iteration <- seq(1, nshuffle)
output <- data.frame(iteration, entropy)
print(qplot(iteration, entropy, data=output, xlab="Shuffle Iteration", 
            ylab="Information Entropy", geom=c("point", "line"),
            color=iteration) + scale_color_gradient(low="#ffb000",
            high="red"))

# Plot gradually de-correlating sort order
dev.new()
print(qplot(startorder, shuffleorder, data=shuffletracker, color=iteration,
            xlab="Start Order", ylab="Shuffle Order") + facet_wrap(~ iteration,
            ncol=4) + scale_color_gradient(low="#ffb000", high="red"))

2

我知道这篇文章将近4岁了,但是我是一名业余密码分析家,并且一直在研究扑克牌密码。因此,我已经一遍又一遍地回到这篇文章,来解释甲板改组是作为随机地锁定甲板的熵的一种来源。最后,我决定通过手工洗甲板来验证答案,并在每次洗牌后估计甲板熵。

TL; DR,以最大化甲板熵:

  • 仅用于浅滩混洗,您需要11-12次混洗。
  • 要先剪切甲板然后再进行浅滩混洗,您只需要进行6到7次剪切和混洗。

首先,水草提到的用于计算香农熵的一切都是正确的。可以这样将其归结为:

  1. 通过数字方式为平台中的52张卡片分配唯一值。
  2. 洗净甲板。
  3. 对于n = 0到n = 51,记录(n-(n + 1)mod 52)mod 52的每个值
  4. 计算出现次数0、1、2,...,49、50、51
  5. 将这些记录除以52来归一化这些记录
  6. 对于i = 1到i = 52,计算-p_i * log(p_i)/ log(2)
  7. 求和

stachyra做出一个微妙的假设的地方是,在计算机程序中实现人为改组会带来一些负担。使用纸质扑克牌时,纸上的油脂会从您的手中转移到扑克牌上。在较长的时间内,由于油的堆积,卡将开始粘在一起,最终会洗牌。牌组使用得越多,两张或更多相邻纸牌粘在一起的可能性就越大,发生的频率就越高。

此外,假设两个球杆和红色的杰克粘在一起。他们可能会在您洗牌的整个过程中粘在一起,永不分离。这可以在计算机程序中模仿,但是stachyra的R例程不是这种情况。

而且,水苏属具有操纵变量“ mixprob”。如果不完全了解此变量,则有点黑匣子。您可能会错误地设置它,从而影响结果。因此,我想确保他的直觉是正确的。因此,我手动进行了验证。

在两种不同的情况下,我手动洗了20次甲板(总共洗了40次)。在第一种情况下,我只是略作混编,将左右两边的割缝保持接近。在第二种情况下,我故意将甲板从甲板中间(1 / 3、2 / 5、1 / 4等)切开,然后再将浅滩混洗进行均匀切割。在第二种情况下,我的直觉是通过在改组之前切开甲板,并远离中间,我可以比普通的浅滩混编更快地将扩散引入甲板。

这是结果。首先,直接浅滩混洗:

浅滩混洗每张卡的熵

这是削减甲板与浅滩改组:

带有切割和浅滩混洗的每张卡的熵

似乎熵是水苏树声称的时间的1/2左右。此外,我的直觉是正确的,即在浅滩混洗确实将更多的扩散引入甲板之前,有意将甲板从中间首先切开。但是,经过大约5次改组后,它实际上不再重要了。您可以看到,经过大约6到7次洗牌后,熵达到了最大,而10到12则是我的水苏打法。7次洗牌就足够了吗,还是我被蒙蔽了双眼?

您可以在Google表格中查看我的数据。我可能错误地记录了一张或两张纸牌,因此不能保证数据的100%准确性。

同样重要的是,您的发现也必须得到独立验证。哈佛大学数学系的布拉德·曼(Brad Mann)研究了在纸牌中的任何一张纸牌的可预测性完全不可预测(香农熵最大化)之前,需要洗牌多少次。他的结果可以在这份33页的PDF中找到

他的发现有趣的是,他实际上是在独立验证Persi Diaconis在1990年的《纽约时报》上的一篇文章,该文章声称7个混洗足以通过浅滩混洗彻底混合一副扑克牌。

布拉德·曼(Brad Mann)在混洗中研究了几种不同的数学模型,包括马尔可夫链,得出以下结论:

对于n = 52,这大约为11.7,这意味着,按照这种观点,我们期望平均需要11或12次随机播放才能随机分配一张真正的纸牌。请注意,这实际上大于7。

布拉德·曼(Brad Mann)只是独立地证实了水苏木的结果,而不是我的。因此,我仔细查看了我的数据,发现为什么7次混洗不足。首先,卡组中任何卡的理论最大香农熵(以位为单位)为log(52)/ log(2)〜= 5.7位。但是我的数据从未真正突破5位以上。奇怪的是,我在Python中创建了一个由52个元素组成的数组,将其改组为:

>>> import random
>>> r = random.SystemRandom()
>>> d = [x for x in xrange(1,52)]
>>> r.shuffle(d)
>>> print d
[20, 51, 42, 44, 16, 5, 18, 27, 8, 24, 23, 13, 6, 22, 19, 45, 40, 30, 10, 15, 25, 37, 52, 34, 12, 46, 48, 3, 26, 4, 1, 38, 32, 14, 43, 7, 31, 50, 47, 41, 29, 36, 39, 49, 28, 21, 2, 33, 35, 9, 17, 11]

计算其每卡熵产生约4.8位。进行十次左右的测试显示相似的结果在5.2位和4.6位之间变化,平均值为4.8至4.9。因此,仅查看数据的原始熵值是不够的,否则我可以称其为5次混洗。

当我仔细查看数据时,我注意到“零存储桶”的数量。这些是存储区,在该存储区中没有该编号的卡面之间的增量数据。例如,当减去两张相邻纸牌的值时,在计算所有52个增量之后就没有“ 15”结果。

我看到它最终在11-12个混洗附近稳定在17-18个“零桶”附近。果然,我经过Python洗牌后的牌组平均有17-18个“零桶”,最高分为21个,最低为14个。为什么17-18是已结算的结果,我还不能解释...。但是,似乎我既需要约4.8位的熵,又需要17个“零桶”。

用我的股票浅滩混洗,这是11-12次混洗。用我的即洗即用,就是6-7。因此,在游戏方面,我建议您随意剪切和拖曳。这不仅可以确保顶牌和底牌在每次混洗中都混入卡组中,而且比11-12个混洗还快。我不了解您,但是当我与家人和朋友玩纸牌游戏时,他们还没有足够的耐心让我进行12次浅滩混音。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.