簡單的統計學:如何用Python計算撲克概率

2020-12-11 deephub

介紹

在本文中,我們展示了如何在Python中表示基本的撲克元素,例如「手」和「組合」,以及如何計算撲克賠率,即在無限額德州撲克中獲勝/平局/失敗的可能性。

我們根據《拉斯維加斯威尼斯之夜》中的真實故事提供實用的分析。

我們將使用poker包來表示手牌,連擊和範圍。 我已經擴展了來自Kevin Tseng的撲克賠率計算器,因此它除了能夠計算單個手牌之外,還可以基於範圍(可能的手牌)來計算撲克概率。

from poker import Rangefrom poker.hand import Comboimport holdem_calcimport holdem_functionsimport numpy as npimport pandas as pdimport matplotlib.pyplot as pltfrom IPython.core.display import display, HTMLhero_odds = []hero_range_odds = []

翻牌圈

我的手牌為K和J(KJ),我使用來自poker.hand的Combo類構造我的手牌。

# my hand = King of spades and Jack of clubshero_hand = Combo('KsJc')print(hero_hand)

我記不清翻牌前發生的事情以及我的位置。 但是,我確實記得翻牌前有加注,而翻牌後只剩下兩名選手:我和對方。

我們現在要注意。 翻牌圈出現梅花Q,紅桃10和梅花J。 是的,我翻到了順子!

讓我們假設沒有對方撲克的先驗知識來計算翻牌後的賠率,即在翻牌後,我們將計算出我的牌勝過隨機的一對牌的可能性。

flop = ["Qc", "Th", "9s"] # the flopboard = flop # the board equals the flopvillan_hand = None # no prior knowledge about the villanexact_calculation = True # calculates exactly by simulating the set of all possible handsverbose = True # returns odds of making a certain poker hand, e.g., quads, set, straightnum_sims = 1 # ignored by exact_calculation = Trueread_from_file = None # we are not reading hands from fileodds = holdem_calc.calculate_odds_villan(board, exact_calculation, num_sims, read_from_file , hero_hand, villan_hand, verbose, print_elapsed_time = True)

Holdemcalc中的函數calculateodds_villan可以計算出特定的德州撲克贏手的概率。 通過運行蒙特卡洛方法可以估算出該概率,也可以通過模擬所有可能的情況來準確地計算出該概率,快速計算翻牌後的確切賠率。因此在這裡我們不需要蒙特卡洛近似值。 這是我們的賠率:

odds[0]{'tie': 0.04138424018164999, 'win': 0.9308440557284221, 'lose': 0.027771704089927955}

此時,我感覺還不錯。 在隨機的情況下,我只有2.77%的機會輸,獲勝的機會超過93%。 這很樂觀。

考慮到翻牌前有加注,而只有我和對方在翻牌後才離開,所以對方有一些手牌,對吧? 我們稱這種可能的手為範圍。 這是我們根據幾個因素(包括對方的舉止,位置,下注大小等)做出的推論。該推論導致我們假設對方可能擁有一組手牌。 在這一點上,我認為對方有:

一對7或更好A /10或更好K/J或更好我們可以使用「類別範圍」來表示該範圍,如下所示:

villan_range = Range('77+, AT+, KJ+')display(HTML(villan_range.to_html()))print("#combo combinations:" + str(len(villan_range.combos)))

這使對方手牌組合從總共51 * 52–1 = 2651個可能減少到144種可能。 現在假設對方手牌的範圍來計算我的賠率。

items = [holdem_calc.calculate_odds_villan(board, exact_calculation, num_sims, read_from_file , hero_hand, villan_hand, verbose, print_elapsed_time = False) for villan_hand in villan_range.combos]odds = {}[odds.update({odd_type: np.mean([res[0][odd_type] for res in items if res])}) for odd_type in ["tie", "win", "lose"]]

{'tie': 0.11423324150596878, 'win': 0.8030711151923272, 'lose': 0.08269564330170391}

在假定的範圍內,我的獲勝機率從93%下降至80%。 但是,我仍然很可能損失8.2%。 在這一點上,我很明確。 但是我應該繼續嗎? 我絕對希望對方繼續比賽並且不棄牌。 但是他在翻牌後有個好牌的可能性有多大? 讓我們看看如果我們繼續玩到最後,他伸手的機率是多少。

for hand_ranking in holdem_functions.hand_rankings:print(hand_ranking +": " + str(np.mean([res[1][1][hand_ranking] for res in items if res])))

High Card: 0.06978879706152433 Pair: 0.3662891541679421 Two Pair: 0.23085399449035812 Three of a Kind: 0.09733700642791548 Straight: 0.18498112437506367 Flush: 0.0040608101214161816 Full House: 0.04205693296602388 Four of a Kind: 0.004560759106213652 Straight Flush: 2.0406081012141617e-05 Royal Flush: 5.101520253035404e-05

如果我們繼續玩,對方很有可能做出一對(36%)或兩對(23%)。 他極有可能直接命中(18%)甚至打出盤(9.7%)或滿堂(4%)。 由於對方很有可能擁有合理的手牌,因此我決定下高注,大約底池的2/3。

轉牌

到轉牌了,是方片2(2)。 基本上,這是一張空白牌,也就是說,它對我們的遊戲沒有太大影響。

turn= ["2d"]board = flop + turnvillan_hand = Noneodds = holdem_calc.calculate_odds_villan(board, exact_calculation, num_sims, read_from_file , hero_hand, villan_hand, verbose, print_elapsed_time = True)hero_odds.append(odds[0]['win'])print(odds[0])

{'tie': 0.0233201581027668, 'win': 0.9677206851119895, 'lose': 0.008959156785243741}

假設對方的牌是隨機的,那麼我現在有96%的獲勝機率。

但是,考慮到我假定的對方手牌範圍,我的獲勝機率現在從翻牌時的80%上升到86%。 我再次下注,對方跟注,河牌來了。

items = [holdem_calc.calculate_odds_villan(board, exact_calculation, num_sims, read_from_file , hero_hand, villan_hand, verbose, print_elapsed_time = False) for villan_hand in villan_range.combos]odds = {}[odds.update({odd_type: np.mean([res[0][odd_type] for res in items if res])}) for odd_type in ["tie", "win", "lose"]]

{'tie': 0.10123966942148759, 'win': 0.8615702479338843, 'lose': 0.0371900826446281}

河牌

是梅花K(K)。 這使對方更容易勝利。 所以這對我來說是個壞消息。

river = ["Kc"]board = flop + turn + river verbose = Truevillan_hand = Noneodds = holdem_calc.calculate_odds_villan(board, exact_calculation, num_sims, read_from_file , hero_hand, villan_hand, verbose, print_elapsed_time = True)hero_odds.append(odds[0]['win'])print(odds[0])

{'tie': 0.11818181818181818, 'win': 0.8696969696969697, 'lose': 0.012121212121212121}

現在,我對隨機牌的獲勝機率從96%降至約87%。 但我仍然只以1.2%的極低概率輸掉。 好吧,那條壞的河牌不是那麼糟吧?

好吧,還有另外一個因素。 對方在翻牌圈和河牌圈都跟我有大賭注。 他可能比我想像的要好...對嗎? 然後,我應該調整我的假定範圍。

現在,我認為對方不再擁有77或88的一對,否則,鑑於我的高賭注,他不會跟下去。 我認為他可能有一對9或更好的一對,才能與99、10或QQ配對。 他可能還會有JJ從而導致平局。 或KK和AA,直到轉牌時都是頭對。 我決定保持10和K或更好的牌,因為有所謂的隱含賠率。 隱含賠率是對您打出的一筆錢可以從投注中贏取多少錢的估計。 因此,對方可能會等待中獎(他可能剛剛中了?)。 因此,我將對方的更新範圍定義如下:

villan_range = Range('99+, AT+, KJ+') display(HTML(villan_range.to_html()))print("#combo combinations:" + str(len(villan_range.combos)))

現在,對方的連擊數從144降低到了132。讓我們計算更新後的賠率。

items = [holdem_calc.calculate_odds_villan(board, exact_calculation, num_sims, read_from_file , hero_hand, villan_hand, verbose, print_elapsed_time = False) for villan_hand in villan_range.combos]odds = {}[odds.update({odd_type: np.mean([res[0][odd_type] for res in items if res])}) for odd_type in ["tie", "win", "lose"]]

{'tie': 0.12, 'win': 0.72, 'lose': 0.16}

現在,我有72%的機會獲勝(從86%下降的),而我在轉牌時的失利機率從3.7%增加到16%。 我決定慎重一下,對方則全押,下注大約70%的彩池。

基本的河牌戰略可以告訴您以下內容:

用你最小的牌作為河牌利用您最強的資產押注以中等強度的攤牌值檢查手牌,以期達到攤牌for hand_ranking in holdem_functions.hand_rankings: print(hand_ranking +": " + str(np.mean([res[1][1][hand_ranking] for res in items if res])))

High Card: 0.0 Pair: 0.5066666666666667 Two Pair: 0.08 Three of a Kind: 0.13333333333333333 Straight: 0.28 Flush: 0.0 Full House: 0.0 Four of a Kind: 0.0 Straight Flush: 0.0 Royal Flush: 0.0

從賠率直方圖中,我們可以將對方的可能手牌分為3種類型:

虛張聲勢:他拿著{好牌,成對}的機率為60.66%中強度牌:他以{0.8}的機率拿著{Two Pair}價值下註:他以41.33%的機率持有{三種牌}對方的全押是有道理的,他持有好牌的概率太低而無法檢查。 所以在這裡我在想他要麼因為虛弱而虛張聲勢,要麼他發瘋了,這是一個有價值的選擇。 如果您的持牌量最差,那麼會虛張聲勢;如果您的牌很強,則進行價值下注的基本策略有時被稱為兩極分化下注。 那就是對方在這裡所做的。

回顧每種類型的概率(虛張聲勢,中等強度的手牌,價值下注),我基本上應該至少有60.66%的勝率,這是一個保守的衡量標準,因為對方可能會押注三分之一。 但是我應該跟進嗎?

這是另一個稱為底池賠率的概念。 底池賠率是指相對於底池大小進行下注的價格。 總而言之,如果我贏得底池的概率大於底池限注價格和底池大小之間的比率,我應該跟注。 讓我們做一些數學運算:

贏取機會≥60.66%(保守估計)底池價格= 0.7 *底池大小預測底池大小=(1 + 0.7 + 0.7)*底池大小底池賠率=底池價格/預測底池大小= 29%我獲勝的機會至少是底池賠率的兩倍。 因此,我繼續跟進。 結果呢? 對方轉過牌。 桌子一度安靜,卻凝視著桌子上的Ace Jack。

討論和結論

在本文中,我展示了如何表示基本的撲克元素(例如手牌和組合),以及如何在講述威尼斯人夜晚的故事的同時,假設Python中的隨機手牌和範圍來計算撲克賠率。

我們展示了撲克有多麼令人興奮(概率上很有趣)。 在下面,我展示了我的獲勝賠率是如何從翻牌到轉牌,然後是河牌的改變過程,假設對方的隨機牌以及推斷範圍。

我們觀察到,即使最終結果不利於我,我還是贏得這一單挑局的主要人選。 這就是為什麼撲克玩家說

您應該專注於做出決定,而不關注所取得的結果。

當然,本文中的所有分析都假設了一些範圍和基本的撲克策略,這些策略和基本的撲克策略構成了我在玩遊戲時的思維模型,並在本文中以Python實現。 我不是職業撲克玩家,還有很多方法。 我相信我犯了一些錯誤,例如,低估了對方在翻牌前加注時持有A和J的可能。

我很好奇,其他人將如何使用此處使用的Python框架來分析手牌。

作者:Thársis Souza, PhD

deephub翻譯組:孟翔傑

相關焦點

  • 德州撲克獲勝概率計算的方法!
    概率計算所謂德克薩斯撲克的概率,簡單說,就是等來某種獲勝牌型的可能性(成牌概率),與底池提供籌碼(底池概率)之間的比較,如果底池籌碼足夠多
  • 德州撲克講堂:如何將概率運用在行動下註上
    原標題:德州撲克講堂:如何將概率運用在行動下註上   概率,第五期內容介紹了德州撲克的經典速算法則——42法則,及玩家在翻牌圈將抽牌X4、在轉牌圈將抽牌X2便可大略算出勝率。本期將會結合前五期介紹的概率相關內容講解如何將概率運用在行動下註上面。
  • 專業大神教你德州撲克的概率表
    理解基本的概率將為你玩德扑打下更堅實的基礎,這篇文章討論你應該知道的有關概率的所有重要的和有趣的內容。充分了解德撲的規則才能更好的進行比賽。德撲究竟怎麼玩呢?概率是指某個事件會發生的確定程度,傳統的定義是:「一個事件的概率是特定事件發生的數量和所有可能事件發生數量的比率,且每個單位事件發生的可能性均相等,這使得它們的可能性是相同的。」因此,投硬幣翻中頭的概率是1:2或50%。對於撲克玩家來說,隨機學是研究概率中最有趣的部分,隨機性關係到以頻率為基礎的可能性。組合學(牌的組合)、統計學(樣本大小)和其它的分支學科都是隨機學的組成部分。
  • 統計學知識大梳理(終極篇)
    概率與概率分布稍微關注過統計學的人,可能會這麼一個疑問。為什麼大學裡會有這樣兩門課,《概率論與數理統計》,《統計學》,它們有什麼區別?不確定性事件唯一的規律就是概率,獨立隨機事件我們沒辦法預測或控制它在某個時刻一定會發生,但卻可以用概率來描述它發生的可能性。以概率論作為理論基礎,為我們提供了認識不確定世界的方法。
  • 統計學公開課大盤點
    課程本身深入淺出的介紹了統計學的大多數基本概念,只要認真回答每節課的小問題,同時認真完成homework, 包括用python寫個小的統計程序,應該會大有收穫。 MOOC學霸@wzyer對這門課程的評價是:課程本身內容很不錯,涵蓋了統計基本的知識點。不過也許是Udacity風格的問題吧,聽完之後感覺有些不夠系統。
  • 統計學小例子
    統計與概率論本身與數據分析的關聯度非常的高而且掌握的程度也可以很好的反映出從業者的投入程度。接下來我們通過一些例子,來體驗概率論思維。扔十次硬幣,真的會有五次朝上?直覺上,我們知道拋硬幣正反兩面朝上的概率各一半,如果你真的現在去拋十次硬幣,真的有5次正面向上的情況出現麼?其實這種可能性只有1/4左右,顯然和大多數人的直覺完全不同了。我們都知道,統計學的規律只有經過了大量隨機試驗才能得出,也才有意義。但是隨機試驗得到的結果,和我們用古典概率算出來的結論可能是兩回事。
  • 職場人士如何一小時學會從0到1用Python
    從cmd命令行到IDLE:進行語法練習+簡單腳本的編寫與運行如果說在上面的命令框裡寫一兩行簡單的代碼還行,當要開始寫函數,寫一些條件語句、循環語句時,命令框就顯得有點施展不開了。這個時候我們就可以開始用安裝python環境時自帶的開發環境——IDLE了(可以在開始菜單欄裡找到,叫「IDLE (Python 3.x 64-bit)」。
  • 如何在實戰中真正運用概率思考
    如果你經常關注紙牌類遊戲就能發現,那些賭術高超的職業賭徒都是統計學和概率學的忠實信仰者。無論是21點,德州撲克,還是我們接觸較多的鬥地主、麻將等牌類遊戲,都無時無刻不在談論概率。安妮.杜克是唯一一位同時獲得世界撲克系列賽冠軍和美國NBC全國單挑撲克冠軍的女性選手。
  • 要用統計學來思考
    如何在防治疫情和恢復之間找到平衡點,會成為目前乃至今後一段時間內的難題。至於解題的關鍵,就是需要來精準計算不同措施的綜合成本和各種情況的概率。從根本上看,傳染病其實是個隨機事件,所以在防治疫情的過程中,我們需要運用更多統計學的概念,來幫助各方面理性對待各種隨機現象,從而避免過度恐慌,做出正確的判斷和決策。下面我們舉兩個例子。
  • 大數據下的「應用統計學」與「經濟統計學」,如何抉擇?
    本文,將對與統計學有關的「應用統計學」與「經濟統計學」兩個專業進行對比分析。一、源於數學,各有側重統計學是一門很古老的學科,單從字面上來分析「統計」一詞的含義,一言以蔽之,「統」指「統括」,「計」指「計算」,這兩個動詞合二為一,意思是對某一現象有關的數據進行搜集、整理、計算以及分析,通過這樣的手段以達到整理所測對象數據、推斷關注對象的本質、甚至預測對象未來的目的。
  • 使用python實現一個簡單計算器
    但是並沒有做過什麼實際的案例,主要原因是因為使用tikinter做界面比較麻煩,沒有可視化的設計來的快,就像我之前用的QT設計工具,就非常方便。如果做一些簡單的界面,使用tkinter還是很方便的,畢竟是python自帶的庫。
  • 都是10G的大數據計算,Python與PHP誰算的速度更快?正面PK硬剛
    系統居然還是沒有python命令。這兩天剛看到一個CentOS Linux 8的命令alternatives,這個是用來控制一個系統裡面多個軟體版本的情況用的。編寫Mapper程序用Hadoop用戶執行以下命令:su hadoopmkdir -p /wwwroot/hadoop/pythoncd /wwwroot/hadoop/python
  • 數據分析必備——統計學入門基礎知識
    但是,統計學的知識包括了圖形信息化、數據的集中趨勢、概率計算、排列組合、連續型概率分布、離散型概率分布、假設檢驗、相關和回歸等知識,對於具體的知識點,本文就不一一介紹了,感興趣的同學請參考《深入淺出統計學》、《統計學:從數據到結論》等專業書籍。 統計學分為描述性統計學和推斷性統計學。
  • 100%讓你在10分鐘內學會如何用python將數據批量地插入到資料庫
    本文基於python, 使用pandas, pymysql等三方庫實現了向資料庫中高效批量插入數據,一方面提供被網上很多瞎轉載的答案給坑蒙了的人(因為我也是),一方面自己也做個筆記,以後方便查閱。01需求原因最近在處理一個需求,有關批量往資料庫插入數據的,描述如下:原來的程序是基於sql的存儲過程進行數據的更新修改操作,由於數據量較大,導致對資料庫壓力太大,於是需要將程序重構為用python
  • python如何計算環比增長率
    從上學的時候就有很多小夥伴搞不清楚這兩個增長率之間的區別,這裡簡單直白的解釋一下:同比增長率從名字上就比較容易理解,指的是同期相比增長情況如何,比如今年一季度和去年一季度相比業務增長情況就可以用同比增長率來衡量,具體的計算公式為(今年一季度數據 - 去年一季度數據)/去年一季度數據。
  • Python 優秀函數庫組成的最佳陣容
    下文簡單介紹一下 python 的幾個最為重要的數據分析模塊。Numpy 是 Python 提供數值計算的基礎模塊,也是 Python 生態中歷史最為悠久的模塊。SciPy 是基於 Numpy 開發的高級模塊,它用於解決科學計算中的一些標準問題。例如數值積分和微分方程求解,擴展的矩陣計算,最優化,概率分布和統計函數,甚至包括信號處理。
  • 白話統計學05—標準化和z分布(學習分享)
    在這一小節中,我們就來看看如何利用數據的正態分布這一屬性。設想在一次期末考試中,你的生物學課程成績為65分,滿分是100分,統計學課程的成績為42分,滿分是200分。哪門課程的分數「更好」呢?這個問題表面看上去很容易回答,其實則不然。首先,必須界定一個標準,「更好」究竟意味著什麼。如果「更好」意味著考試中正確回答的比例,那麼顯然生物學考得更好。
  • 世界撲克冠軍:用對賭思維提升決策質量
    以下為該文的中譯版摘錄:安妮·杜克:世界撲克冠軍教你如何做決策作者:沈佩玉她是一名認知心理學博士,畢業於常青藤大學,現在是一位著名的演說家和決策專家。她也是四個孩子的母親。而她最引人注目的身份,卻是一名世界級的撲克冠軍,在撲克錦標賽比賽中贏得了超過400萬美元,還贏得了世界撲克手環系列賽金手鐲、世界撲克錦標賽冠軍和全國廣播公司全國撲克錦標賽。
  • 【德州撲克計算器】小程序上線,用它算手牌勝率更方便!
    )現在就讓葫蘆娃來教大家怎麼用它來計算手牌勝率。如何添加【德州撲克計算器】小程序首先你要確保你的微信版本已經更新到最新版本。以後要用的時候,在微信底部的的【發現】-【小程序】頁面就能再次找到:以前在公眾號裡查手牌勝率你需要進行四步操作:1、點開微信→ 2、點開訂閱號→ 3、點開「德州撲克跟我學」公眾號→ 4、點開菜單欄的【勝率計算】而現在,只要一步:直接在手機桌面上點開【德州撲克計算器】就能用了。
  • 從統計學的角度觀察數字貨幣挖礦
    為了便於說明,假設您提供了1 EH/s的哈希算力,而網絡中的總哈希算力是100 EH/s,那麼您將獲得100張彩票其中的1張,即中獎概率是1%。所以每發現100個區塊,按照統計學計算你也會找到其中的1個區塊。上面的描述應該使你有一個基本了解,但是如果你想深入了解它,請繼續閱讀以下內容!一個礦池是由一組礦工組成,礦工共同努力以減少回報的波動性。