読者です 読者をやめる 読者になる 読者になる

UCI Machine Learning RepositoryよりPoker Hand

UCI Machine Learning Repository: Poker Hand Data Set

ポーカーの手の判定。プログラミングの課題でよくあるけど、統計的な分類で判定します。

> head(df)
  C 1 C 2 C 3 C 4 C 5 C 6 C 7 C 8 C 9 C 10 C 11
1   3  12   3  11   3  13   3  10   3    1    9
2   4  10   4  11   4   1   4  13   4   12    9
3   4   1   4  13   4  12   4  11   4   10    9
4   1   2   1   4   1   5   1   3   1    6    8
5   1   9   1  12   1  10   1  11   1   13    8
6   2   1   2   2   2   3   2   4   2    5    8

0: Nothing in hand; not a recognized poker hand 
1: One pair; one pair of equal ranks within five cards 
2: Two pairs; two pairs of equal ranks within five cards 
3: Three of a kind; three equal ranks within five cards 
4: Straight; five cards, sequentially ranked with no gaps 
5: Flush; five cards with the same suit 
6: Full house; pair + different rank three of a kind 
7: Four of a kind; four equal ranks within five cards 
8: Straight flush; straight + flush 
9: Royal flush; {Ace, King, Queen, Jack, Ten} + flush 


役の分布 N=25008 
0     1     2     3     4     5     6     7     8     9 
12493 10599  1206   513    93    54    36     6     5     3 

ロイヤルフラッシュは0.0001199616 !1/一万

元の特徴量はカードのスートと数で、1-9の役を目的変数として(C11,当然質的変数に直して)、そのままやっても上手くいくハズはないので、 1.カードの重複枚数の1番大きい数 2.カードの重複枚数の2番目に大きい数 3.スートが5つ揃っていらTrueそうでなければFalse 4.ストレートの判定 5.ストレートフラッシュの判定

と特徴量を直して、randomForestで分類。

こんなに追加したら普通に判定するのと大して変わらないような気もするのですが、該当部分は23行で書けているのでいいのかなと。モノ的にエラー率0%じゃないとダメでしょうし。 forの中でソートを2回しているのはスルーしてくださいw

df=read.csv("https://archive.ics.uci.edu/ml/machine-learning-databases/poker/poker-hand-training-true.data")
colnames(df)=paste("C",as.character(1:11))


#特徴量の追加
ncard1=c()
ncard2=c()
suit=c()
straight=c()
sf=c()
for(i in 1:N){
  dsuit=df[i,c(1,3,5,7,9)]
  d=df[i,c(2,4,6,8,10)]
  hoge=sort(table(as.numeric(d)),decreasing = T)
  d1=hoge[1]
  d2=hoge[2]
  ncard1=c(ncard1,d1)
  ncard2=c(ncard2,d2)
  #スート
  if(length(unique(as.numeric(dsuit)))==1){
    same_suit=1
  }else{
    same_suit=0
  }
  suit=c(suit,same_suit)
  
  d=sort(d)
  if(d[5]-d[1]==4 || setequal(d,c(1,10,11,12,13))){
    st=T
  }else{
    st=F
  }
  straight=c(straight,st)
  hoge=ifelse(max(d)==13 && min(d)==1 && st,T,F)
  sf=c(sf,hoge)
}

df2=cbind(ncard1,ncard2,suit,straight,sf)
df2=data.frame(df2)
df2$straight=factor(df2$straight)
df2$sf=factor(df2$sf)

df2=cbind(df2,y=df[,11])

df2$y=factor(df2$y)
df2$suit=factor(df2$suit)
rownames(df2)=as.character(1:N)


N=nrow(df2)
trn=sample(N,floor(N)*0.7)
train=df2[trn,]
test=df2[-trn,]


library(randomForest)
tuneRF(y = train[,6],x=train[,-6],type="classification")

rf=randomForest(y~.,data=train,mtry=5,type="classification")

pred=predict(rf,newdata=test)
cm=table(test$y,pred)
print(cm)

   pred
       0    1    2    3    4    5    6    7    8    9
  0 3824    0    0    0    0    0    0    0    0    0
  1    0 3121    0    0    0    0    0    0    0    0
  2    0    0  352    0    0    0    0    0    0    0
  3    0    0    0  156    0    0    0    0    0    0
  4    0    0    0    0   18    0    0    0    0    0
  5    0    0    0    0    0   17    0    0    0    0
  6    0    0    0    0    0    0    8    0    0    0
  7    0    0    0    0    0    0    0    4    0    0
  8    0    0    0    0    0    0    0    0    2    0
  9    0    0    0    0    0    0    0    0    0    1