打败人类,Pluribus第一课,如何抽象德扑的牌组——Kmeans with EMD distance

打败人类,Pluribus第一课,如何抽象德扑的牌组——Kmeans with EMD distance

最近一直在看Pluribus相关的文献,开始研究实现德扑ai的第一步将牌组分类简化,根据Sam Ganzfried和Tuomas Sandholm的文章Potential-Aware Imperfect-RecallAbstraction with EarthMover’s Distance in Imperfect-Information Games,用的方法就是Kmeans聚类,聚类的时候使用的距离并不是常见的欧式距离,而是使用了判断向量相似性的emd距离,将概率分布相近的牌组视为同一类,emd距离的计算比较费时,所以在对亿级数据处理的时候,提升计算速度是程序执行的关键,我的解决方案就是并行加上优化emd的算法。本文首先介绍下的文章讲解对牌组聚类的方法,文章后面附优化后的就算emd距离的代码。

在这里插入图片描述

分类思路简介

对牌组的分类,有四种不同的情况 ,对应的是 hand,flop,turn,river。 常见的牌组分类方法就是把在仅考虑牌组打到river时胜率相近的牌组归为同一类别,即expected hand strength(EHS) metric 方法 。举例来说,如果一个玩家有对A作为手牌,那么发到河牌他获胜的概率是84.93%,打平的概率是0.55%,那么给予对A的评分是0.852。同样的对K的胜率是0.824, 这两手牌得分类似,因此把他们归类为同一类别。但是这种方法没有考虑一手牌的发展情况。忽略了某些手牌虽然初始胜率低,但是潜力大的情况。number of clusters, using the EMD 在德扑领域,前沿的分类方法是,首先,对于翻前手牌不抽象,对于翻后和转牌,根据发到河牌的胜率分布的情况进行Kmeans聚类,但是这种方法,被未考虑整个分布随着发牌的变化,因此更好的方法是首先对河牌分类,然后转牌的牌组,根据分布到下一轮可能的概率分布进行分类,翻后的牌组,根据下一轮可能分到的转牌类别的概率分布进行分类,手牌不抽象。下图展示了翻后牌组在河牌的概率分布,和对下一轮转牌的概率分布的情况,对于 5c9d和TcQd,他们收到的翻牌是7h9hQh,可以看出在河牌上这两手牌分布类似,但是对于下一轮转牌的分布就明显不同,所以要考虑下一步发牌后的分布,来进行分类。

在这里插入图片描述

代码

普通的emd算法计算速度,并不适用于德扑的分类,如python里面的pyemd包,平均计算一次要在ms的级别,文章介绍了一种emd的算法,适用于德扑的emd计算,因为德扑的分布矩阵大都是稀疏矩阵,有一定特殊性,可以提高算法的运行速度,我初步试了下分成100种的情况下,可以提高计算速度6倍,除了算法的优化,后期还可以multiprocessing并行的方法提高计算速度。

这个算法在计算emd之前多了一步,就是
给定一组质心mean的分布meanarr,那么的的分布的每个下标i就是对应的下一回合对应的类别,meanarr[i]就是分布到下一回合i的概率,因为meanarr很稀疏,他有很多的0,预先计算sortedDistances,sortedDistances[i][j]就是与分布到下一回合的i集合第j相邻的meanarr非零的集合的距离 orderedClusters[i][j] 就是i集合第j相邻的meanarr非零的集合的index。计算sortedDistances的代码的函数calOrderedCluster如下:


meanarr=[0,0,5,0,3,0,0,0]
pointarr=[2,0,2,0,3,0,1,0]
def calOrderedCluster(meanarr,pointarr):
    arrQ=[index for index,i in enumerate(meanarr) if i!=0]
    distant=np.zeros( (len(pointarr),len(arrQ)) )
    martix=np.zeros( (len(pointarr),len(arrQ)),dtype=np.int32 )
    for idealCluster in range(len(pointarr)):
        arrtemp=[i-idealCluster for i in arrQ]
        distancearr=list(map(lambda x:abs(x),arrtemp))
        sortedDistances[idealCluster,:]=np.sort(distancearr)
        s= np.argsort(distancearr)
        orderedClusters[idealCluster,:]=[arrQ[i] for i in s ]
    return orderedClusters,sortedDistances

Alt

计算emd的函数代码如下:


def calEmd(meanarr,pointarr,orderedClusters,sortedDistances):
    targets=pointarr.copy()
    meanRemaining=meanarr.copy()
    done=[False]*len(pointarr)
    totCost=0
    for i in range(orderedClusters.shape[1]):
        for j in range(len(pointarr)):
            if done[j] :
                continue
            pointCluster=j
            meanCluster=orderedClusters[pointCluster][i]
            amtRemaining=meanRemaining[meanCluster]
            if amtRemaining == 0:
                continue
            d=sortedDistances[pointCluster][i]
            if amtRemaining<targets[j]:
                totCost += amtRemaining * d
                targets[j] -= amtRemaining
                meanRemaining[meanCluster]=0
            else:
                totCost += targets[j] * d
                targets[j]=0
                meanRemaining[meanCluster] -= targets[j]
                done[j]=True
    return totCost

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值