什么是強化學(xué)習(xí)?
在機器學(xué)習(xí)的大家庭里,強化學(xué)習(xí)(RL)是那個總是在玩“打怪升級”游戲的孩子。這個孩子不斷嘗試各種策略,尋找最優(yōu)的游戲路線,在失敗中學(xué)習(xí),在成功中積累經(jīng)驗,最終成為一名“游戲高手”。在現(xiàn)實世界中,強化學(xué)習(xí)算法通過與環(huán)境的交互,逐漸優(yōu)化策略,以最大化其長期收益。這種學(xué)習(xí)方式有點像訓(xùn)練一只小狗,經(jīng)過不斷的嘗試和獎勵,小狗學(xué)會了坐下、握手、甚至是跳圈。
強化學(xué)習(xí)的核心思想是通過“試錯”來學(xué)習(xí)。模型(即智能體)在每一步行動后,都會從環(huán)境中得到一個反饋(獎勵或懲罰),這個反饋幫助模型調(diào)整其策略,以便在未來獲得更大的獎勵。最終目標是找到一個策略,使得在長期內(nèi)累積的獎勵最大化。
強化學(xué)習(xí)與監(jiān)督學(xué)習(xí)、無監(jiān)督學(xué)習(xí)的比較
要理解強化學(xué)習(xí),我們先來對比一下它與監(jiān)督學(xué)習(xí)和無監(jiān)督學(xué)習(xí)的不同之處。
監(jiān)督學(xué)習(xí)
監(jiān)督學(xué)習(xí)就像一個勤奮的學(xué)生,他總是有現(xiàn)成的答案可以參考(有標簽的數(shù)據(jù))。他通過不斷地學(xué)習(xí)這些答案,來預(yù)測新問題的答案。監(jiān)督學(xué)習(xí)的目標是找到輸入與輸出之間的映射關(guān)系,比如根據(jù)一個人的身高和體重來預(yù)測他是否適合當(dāng)模特。這里,學(xué)生每次答題后都會知道自己對錯,而強化學(xué)習(xí)則是在“玩游戲”的過程中不斷積累經(jīng)驗,沒有現(xiàn)成的答案。
無監(jiān)督學(xué)習(xí)
無監(jiān)督學(xué)習(xí)更像是一個在迷宮里探索的小孩,他沒有現(xiàn)成的路徑圖(沒有標簽的數(shù)據(jù)),只能通過觀察和摸索來理解這個迷宮的結(jié)構(gòu)。無監(jiān)督學(xué)習(xí)的目標是發(fā)現(xiàn)數(shù)據(jù)的內(nèi)在模式,比如將相似的物品分成同一類。強化學(xué)習(xí)與無監(jiān)督學(xué)習(xí)不同的是,它不僅僅是發(fā)現(xiàn)數(shù)據(jù)中的模式,還要根據(jù)這些模式采取行動,并根據(jù)行動的結(jié)果進行調(diào)整。
強化學(xué)習(xí)
強化學(xué)習(xí)與上述兩種學(xué)習(xí)方法的不同之處在于,它不僅學(xué)習(xí)如何做出正確的決策,還要學(xué)習(xí)如何在一系列決策中最大化長期收益。它沒有監(jiān)督學(xué)習(xí)中的“標準答案”,也不像無監(jiān)督學(xué)習(xí)那樣只是探索數(shù)據(jù)的結(jié)構(gòu)。強化學(xué)習(xí)是一個更加動態(tài)的過程,智能體通過與環(huán)境的不斷交互,逐漸摸索出一套能夠獲得最大化回報的策略。就像訓(xùn)練一只小狗,你需要通過不斷地給它獎勵,讓它明白哪些行為是正確的。
常用的強化學(xué)習(xí)算法
強化學(xué)習(xí)的算法種類繁多,每種算法都有其獨特的適用場景和特點。我們來聊聊幾種常見的強化學(xué)習(xí)算法,用最簡單的語言讓你明白它們的工作原理。
Q學(xué)習(xí)(Q-Learning)
Q學(xué)習(xí)是強化學(xué)習(xí)中的一個經(jīng)典算法,它的核心思想是建立一個“Q表”,記錄每個狀態(tài)-動作對的價值。想象一下你在玩迷宮游戲,每到一個十字路口(狀態(tài)),你有幾個方向可以選擇(動作),Q學(xué)習(xí)會記錄下你每次選擇的結(jié)果——你是到了死胡同,還是找到了出路。隨著游戲的進行,Q表不斷更新,最終幫助你選擇最優(yōu)的路線。在具體實現(xiàn)中,Q學(xué)習(xí)通過不斷更新Q值來逼近最優(yōu)策略,這個過程不需要環(huán)境的模型,因此也被稱為無模型(model-free)算法。
深度Q學(xué)習(xí)(Deep Q-Learning, DQN)
Q學(xué)習(xí)雖然簡單,但在復(fù)雜環(huán)境中,Q表的大小會急劇膨脹,無法處理高維狀態(tài)空間。為了解決這個問題,深度Q學(xué)習(xí)引入了神經(jīng)網(wǎng)絡(luò)來代替Q表,直接從圖像、視頻等高維數(shù)據(jù)中提取特征,計算每個動作的Q值。DQN的出現(xiàn)使得強化學(xué)習(xí)能夠在復(fù)雜的游戲、機器人控制等任務(wù)中大顯身手,像“阿爾法狗”這樣的AI正是借助了類似的技術(shù)。
策略梯度(Policy Gradient)
策略梯度方法直接優(yōu)化策略,而不是像Q學(xué)習(xí)那樣間接優(yōu)化Q值。它的工作原理是通過計算梯度來逐步調(diào)整策略參數(shù),使得在給定環(huán)境下的期望回報最大化。想象一下你在爬山,每次你都會根據(jù)當(dāng)前的坡度調(diào)整前進的方向,策略梯度方法就是通過這種方式找到最佳策略。在策略梯度中,智能體不再需要記錄每個狀態(tài)的具體價值,而是直接調(diào)整策略,往往在處理高維連續(xù)動作空間時表現(xiàn)出色。
演員-評論家(Actor-Critic)
演員-評論家方法結(jié)合了策略梯度和Q學(xué)習(xí)的優(yōu)點。這個方法將智能體分為兩個部分:演員(Actor)和評論家(Critic)。演員負責(zé)生成動作(類似于策略梯度),而評論家則根據(jù)當(dāng)前狀態(tài)和動作給出評價(類似于Q學(xué)習(xí)中的Q值)。評論家的評價幫助演員調(diào)整策略,使得智能體能夠更快地找到最優(yōu)策略。這種方法通過將策略學(xué)習(xí)與價值評估分開處理,使得算法能夠更高效地學(xué)習(xí)復(fù)雜的策略。
蒙特卡洛樹搜索(Monte Carlo Tree Search, MCTS)
蒙特卡洛樹搜索是一種用于決策過程中的算法,尤其在策略類游戲中表現(xiàn)突出。它通過構(gòu)建一個決策樹,模擬未來可能的決策路徑,并通過蒙特卡洛模擬(即隨機取樣)來評估這些路徑的價值。MCTS不需要完整的環(huán)境模型,通過多次模擬來逐步逼近最優(yōu)決策。比如在圍棋或國際象棋中,MCTS可以模擬數(shù)千次可能的棋局變化,從中選擇最佳的下一步棋。
強化學(xué)習(xí)的應(yīng)用領(lǐng)域
強化學(xué)習(xí)因為其獨特的學(xué)習(xí)方式,在多個領(lǐng)域得到了廣泛應(yīng)用。讓我們來看看它在哪些領(lǐng)域“大顯身手”。
游戲AI
強化學(xué)習(xí)在游戲AI領(lǐng)域的表現(xiàn)可謂是“如魚得水”。從早期的“吃豆人”到后來風(fēng)靡全球的“阿爾法狗”,強化學(xué)習(xí)幫助這些AI在游戲中找到了最優(yōu)策略。它不僅可以擊敗人類頂尖棋手,還可以在復(fù)雜的策略類游戲中展示出驚人的決策能力。通過不斷模擬和試錯,強化學(xué)習(xí)使得游戲AI越來越聰明,甚至讓人類感到“不可戰(zhàn)勝”。
機器人控制
機器人控制是強化學(xué)習(xí)的另一個重要應(yīng)用領(lǐng)域。在這里,強化學(xué)習(xí)幫助機器人學(xué)習(xí)如何行走、抓取物體、平衡等復(fù)雜任務(wù)。與傳統(tǒng)的控制方法相比,強化學(xué)習(xí)可以通過與環(huán)境的交互,自主學(xué)習(xí)最優(yōu)的控制策略,而不需要依賴于精確的物理模型。這種自主學(xué)習(xí)能力使得強化學(xué)習(xí)在機器人領(lǐng)域展現(xiàn)出了巨大的潛力,從工業(yè)自動化到家庭服務(wù)機器人,應(yīng)用場景廣泛。
自動駕駛是一項高度復(fù)雜且具有挑戰(zhàn)性的任務(wù),涉及大量的感知、決策和控制。強化學(xué)習(xí)在這一領(lǐng)域的應(yīng)用主要體現(xiàn)在決策和控制上。通過與虛擬環(huán)境中的模擬駕駛互動,強化學(xué)習(xí)算法可以逐步學(xué)習(xí)如何在各種交通場景中做出安全、有效的決策。雖然目前自動駕駛還處于發(fā)展階段,但強化學(xué)習(xí)的引入無疑為這一領(lǐng)域帶來了新的可能性。
智能推薦系統(tǒng)
推薦系統(tǒng)的核心任務(wù)是根據(jù)用戶的行為數(shù)據(jù),預(yù)測他們可能感興趣的內(nèi)容。在傳統(tǒng)推薦系統(tǒng)中,監(jiān)督學(xué)習(xí)方法通過已知的用戶評分來訓(xùn)練模型,而強化學(xué)習(xí)則通過不斷調(diào)整推薦策略,使得用戶的長期滿意度最大化。例如,視頻網(wǎng)站可以利用強化學(xué)習(xí)不斷優(yōu)化推薦算法,使得用戶在瀏覽時更容易找到他們喜歡的視頻內(nèi)容,從而提高用戶粘性。
金融交易
在金融交易領(lǐng)域,市場環(huán)境變化多端且充滿不確定性。強化學(xué)習(xí)通過模擬不同的交易策略,找到在復(fù)雜市場條件下的最優(yōu)交易方案。例如,通過強化學(xué)習(xí)模型,交易系統(tǒng)可以自主學(xué)習(xí)如何在不同的市場條件下進行買賣操作,以最大化長期收益。盡管金融市場中充滿了隨機性和風(fēng)險,但強化學(xué)習(xí)為智能交易系統(tǒng)提供了一個強有力的工具,幫助其在高風(fēng)險環(huán)境中找到平衡。
醫(yī)療健康
強化學(xué)習(xí)在醫(yī)療健康領(lǐng)域的應(yīng)用也在逐步擴大,尤其是在個性化治療和藥物開發(fā)方面。例如,在個性化治療中,強化學(xué)習(xí)可以根據(jù)病人的歷史數(shù)據(jù),優(yōu)化治療方案,使其在特定的病情下獲得最優(yōu)治療效果。此外,強化學(xué)習(xí)還可以用于藥物開發(fā)中的虛擬篩選過程,通過模擬不同的藥物組合,找到效果最佳的藥物配方,縮短研發(fā)時間。
強化學(xué)習(xí)作為機器學(xué)習(xí)中的一個重要分支,通過與環(huán)境的互動,不斷優(yōu)化策略,最大化長期收益。在與監(jiān)督學(xué)習(xí)和無監(jiān)督學(xué)習(xí)的比較中,強化學(xué)習(xí)展現(xiàn)出了其獨特的動態(tài)決策能力。無論是在游戲AI、機器人控制、自動駕駛,還是在推薦系統(tǒng)、金融交易和醫(yī)療健康等領(lǐng)域,強化學(xué)習(xí)都展現(xiàn)出了廣泛的應(yīng)用前景。
盡管強化學(xué)習(xí)目前仍然面臨著一些挑戰(zhàn),如學(xué)習(xí)效率、穩(wěn)定性和安全性問題,但隨著算法的不斷改進和硬件性能的提升,強化學(xué)習(xí)的應(yīng)用將會越來越廣泛。無論你是機器學(xué)習(xí)領(lǐng)域的新手還是老手,強化學(xué)習(xí)都是一個值得深入探索的方向。
強化學(xué)習(xí)算法示例
我們用代碼來展示幾個常見的強化學(xué)習(xí)算法:
Q學(xué)習(xí)(Q-Learning)
比如現(xiàn)在有一條結(jié)了冰的河流,一個人想從冰面走過到對岸,冰面上有些地方很結(jié)實,有些地方一踩上去就會掉進冰窟窿。這個人現(xiàn)在的任務(wù)是通過冰面走到對岸,從起點走到終點,并且不能掉進冰窟窿。此人如何走到對面岸邊呢?我們可以用強化學(xué)習(xí)中的Q學(xué)習(xí)算法來教“自己”走到終點。
此處示例代碼我們使用的是OpenAI Gym中的FrozenLake環(huán)境。在這個環(huán)境中,冰面被分成了一個4x4的網(wǎng)格,每個格子可以是:
起點(S)
終點(G)
正常的冰面(F)
會掉下去的冰窟窿(H)
我們的目標就是讓人(智能體/agent)學(xué)會從起點(S)走到終點(G),而避免掉進冰窟窿(H)。
Q學(xué)習(xí)是一種強化學(xué)習(xí)算法,它的核心思想是讓智能體通過試錯(trial and error)來學(xué)習(xí)每一個狀態(tài)(比如說智能體站在哪個格子)下采取什么行動(上下左右移動)最優(yōu)。為了做出這個決定,Q學(xué)習(xí)使用了一個叫做“Q表”的東西。這個Q表記錄了在每個狀態(tài)下,采取每個行動的“價值”有多大。
每次智能體采取行動并收到反饋(例如掉進冰窟窿,成功到達終點等),Q表會更新,這樣智能體就逐漸學(xué)會了如何更好地行動。
下面我們使用代碼演示此算法:
import gym
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap, BoundaryNorm
# 創(chuàng)建FrozenLake環(huán)境
env = gym.make("FrozenLake-v1", is_slippery=True, render_mode='rgb_array') # 使用FrozenLake-v1
# 初始化Q表
state_space_size = env.observation_space.n
action_space_size = env.action_space.n
Q = np.zeros((state_space_size, action_space_size))
# 超參數(shù)
alpha = 0.1 # 學(xué)習(xí)率
gamma = 0.99 # 折扣因子
epsilon = 1.0 # 初始探索率
epsilon_decay = 0.995 # 探索率衰減
epsilon_min = 0.01 # 最小探索率
num_episodes = 2000 # 總回合數(shù)
# 用于記錄每輪的總獎勵
rewards = []
def get_action(state, epsilon):
if np.random.random() < epsilon:
return env.action_space.sample()
else:
return np.argmax(Q[state])
# Q學(xué)習(xí)算法
for episode in range(num_episodes):
state, _ = env.reset()
total_reward = 0
done = False
while not done:
action = get_action(state, epsilon)
next_state, reward, done, truncated, _ = env.step(action)
# Check if the episode is done either through completion or termination
done = done or truncated
# 更新Q值
best_next_action = np.argmax(Q[next_state])
td_target = reward + gamma * Q[next_state, best_next_action]
td_error = td_target - Q[state, action]
Q[state, action] += alpha * td_error
total_reward += reward
state = next_state
# 更新探索率
epsilon = max(epsilon_min, epsilon * epsilon_decay)
rewards.append(total_reward)
if episode % 100 == 0:
print(f"Episode {episode}: Total Reward: {total_reward}, Epsilon: {epsilon}")
# 打印最終Q表
print("Final Q-Table Values")
print(Q)
# 繪制獎勵隨時間變化圖
plt.plot(rewards)
plt.xlabel('Episode')
plt.ylabel('Total Reward')
plt.title('Reward Over Time')
plt.show()
# 使用matplotlib繪制方格圖并畫出最終路線
def plot_frozen_lake(Q):
grid_size = env.unwrapped.nrow
grid = np.zeros((grid_size, grid_size))
fig, ax = plt.subplots()
cmap = ListedColormap(['white', 'black', 'blue', 'green'])
norm = BoundaryNorm(boundaries=[-0.5, 0.5, 1.5, 2.5, 3.5], ncolors=4)
for i in range(grid_size):
for j in range(grid_size):
state = i * grid_size + j
if env.unwrapped.desc[i, j] == b'S':
grid[i, j] = 2
ax.text(j, i, 'S', ha='center', va='center', color='black')
elif env.unwrapped.desc[i, j] == b'G':
grid[i, j] = 3
ax.text(j, i, 'G', ha='center', va='center', color='black')
elif env.unwrapped.desc[i, j] == b'H':
grid[i, j] = 1
ax.text(j, i, 'H', ha='center', va='center', color='black')
elif env.unwrapped.desc[i, j] == b'F':
grid[i, j] = 0
ax.text(j, i, 'F', ha='center', va='center', color='black')
ax.imshow(grid, cmap=cmap, norm=norm)
state, _ = env.reset()
path = [state]
directions = ['↑', '→', '↓', '←']
while True:
action = np.argmax(Q[state])
next_state, reward, done, truncated, _ = env.step(action)
path.append(next_state)
i, j = state // grid_size, state % grid_size
if state != next_state: # 不在同一個狀態(tài)上畫箭頭
ax.text(j, i, directions[action], ha='center', va='center', color='red')
state = next_state
if done or truncated:
break
plt.show()
# 經(jīng)過訓(xùn)練后,利用最終Q表繪制方格圖并演示智能體的最終路線
plot_frozen_lake(Q)
#?輸出
Episode 0: Total Reward: 0.0, Epsilon: 0.995
Episode 100: Total Reward: 0.0, Epsilon: 0.6027415843082742
Episode 200: Total Reward: 0.0, Epsilon: 0.36512303261753626
Episode 300: Total Reward: 0.0, Epsilon: 0.2211807388415433
Episode 400: Total Reward: 0.0, Epsilon: 0.13398475271138335
Episode 500: Total Reward: 0.0, Epsilon: 0.0811640021330769
Episode 600: Total Reward: 0.0, Epsilon: 0.04916675299948831
Episode 700: Total Reward: 0.0, Epsilon: 0.029783765425331846
Episode 800: Total Reward: 1.0, Epsilon: 0.018042124582040707
Episode 900: Total Reward: 0.0, Epsilon: 0.010929385683282892
Episode 1000: Total Reward: 1.0, Epsilon: 0.01
Episode 1100: Total Reward: 1.0, Epsilon: 0.01
Episode 1200: Total Reward: 1.0, Epsilon: 0.01
Episode 1300: Total Reward: 1.0, Epsilon: 0.01
Episode 1400: Total Reward: 0.0, Epsilon: 0.01
Episode 1500: Total Reward: 1.0, Epsilon: 0.01
Episode 1600: Total Reward: 0.0, Epsilon: 0.01
Episode 1700: Total Reward: 1.0, Epsilon: 0.01
Episode 1800: Total Reward: 1.0, Epsilon: 0.01
Episode 1900: Total Reward: 1.0, Epsilon: 0.01
Final Q-Table Values
[[5.44268685e-01 4.69096295e-01 4.82892049e-01 4.79534135e-01]
[1.37398190e-01 1.62239900e-01 1.41869750e-01 4.86489428e-01]
[3.85222751e-01 1.07776060e-01 1.20971350e-01 1.31364319e-01]
[1.61018062e-03 5.15108692e-02 7.38985361e-04 9.63652587e-04]
[5.58640044e-01 4.45894208e-01 4.24832915e-01 4.05942688e-01]
[0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[2.46020726e-01 4.95482787e-02 9.58877618e-02 6.20800888e-02]
[0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[3.33051441e-01 2.94682152e-01 3.28286414e-01 5.93740756e-01]
[3.66880719e-01 6.75596165e-01 1.83187573e-01 4.01768922e-01]
[6.29869042e-01 2.03088211e-01 1.96117532e-01 2.41455667e-01]
[0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[1.96948367e-01 3.14519066e-01 7.95832287e-01 3.81453214e-01]
[4.77829487e-01 8.97068795e-01 6.42640553e-01 6.42877028e-01]
[0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
蒙特卡洛樹搜索(MCTS)
蒙特卡洛樹搜索 (MCTS) 是一種用于決策過程的算法,特別適用于游戲領(lǐng)域(如圍棋、國際象棋等)。MCTS 通過在可能的決策樹中隨機采樣來逐漸改進決策,它在不需要完全遍歷樹的情況下找到好的決策。MCTS 的主要步驟如下:
選擇 (Selection): 從根節(jié)點開始,根據(jù)樹中現(xiàn)有的信息選擇一個需要擴展的節(jié)點。常用的選擇策略是 UCT (Upper Confidence bounds for Trees),它平衡了探索和利用。
擴展 (Expansion): 如果選擇的節(jié)點是非終止節(jié)點,且還沒有完全展開它的子節(jié)點,則從該節(jié)點擴展出一個或多個子節(jié)點。
模擬 (Simulation): 從新擴展的節(jié)點開始,進行隨機模擬,直到達到終止狀態(tài)。這一步的目的是估計該節(jié)點的價值。
反向傳播 (Backpropagation): 將模擬結(jié)果反向傳播到經(jīng)過的所有節(jié)點,以更新它們的統(tǒng)計信息。
MCTS 往往在多次迭代后逐步收斂到最優(yōu)解。
為了更好地理解MCTS算法,我們可以設(shè)計一個簡單的游戲,例如“猜數(shù)字”游戲。這個游戲規(guī)則如下:
游戲在一個有限的范圍內(nèi)隨機選擇一個目標數(shù)字。
玩家需要通過猜測來找到這個目標數(shù)字。
每次猜測后,玩家會得到提示:猜測的數(shù)字是“太高”還是“太低”。
游戲結(jié)束時,玩家找到目標數(shù)字。
我們可以使用MCTS算法來模擬玩家的猜測過程。假設(shè)我們本次給出的數(shù)字是88,以下是具體的實現(xiàn)步驟和代碼:
import numpy as np
import random
import matplotlib.pyplot as plt
class GuessNumberGame:
def __init__(self, lower_bound=1, upper_bound=100):
self.lower_bound = lower_bound
self.upper_bound = upper_bound
self.target = 88
self.current_guess = None
def make_guess(self, guess):
self.current_guess = guess
if guess < self.target:
return -1 # Too low
elif guess > self.target:
return 1 # Too high
else:
return 0 # Correct
def get_possible_guesses(self):
return list(range(self.lower_bound, self.upper_bound + 1))
def is_correct_guess(self):
return self.current_guess == self.target
class Node:
def __init__(self, state, parent=None):
self.state = state
self.parent = parent
self.children = []
self.visits = 0
self.total_reward = 0
def add_child(self, child_state):
child = Node(child_state, self)
self.children.append(child)
return child
def update(self, reward):
self.visits += 1
self.total_reward += reward
def ucb1(self, c=1.41):
if self.visits == 0:
return float('inf')
return self.total_reward / self.visits + c * np.sqrt(np.log(self.parent.visits) / self.visits)
def selection(node):
while node.children:
node = max(node.children, key=lambda n: n.ucb1())
return node
def expansion(node):
possible_guesses = node.state.get_possible_guesses()
for guess in possible_guesses:
new_state = GuessNumberGame(node.state.lower_bound, node.state.upper_bound)
new_state.target = node.state.target
new_state.make_guess(guess)
node.add_child(new_state)
def simulation(state):
game = GuessNumberGame(state.lower_bound, state.upper_bound)
game.target = state.target
while not game.is_correct_guess():
possible_guesses = game.get_possible_guesses()
guess = random.choice(possible_guesses)
game.make_guess(guess)
if game.is_correct_guess():
return 1 # Correct guess
return 0
def backpropagation(node, reward):
while node:
node.update(reward)
node = node.parent
def mcts(root, iterations):
for _ in range(iterations):
node = selection(root)
if not node.children:
expansion(node)
reward = simulation(node.state)
backpropagation(node, reward)
# 可視化函數(shù)
def visualize_guesses(game, guesses):
plt.figure(figsize=(10, 6))
plt.plot(guesses, 'bo-', label='Guesses')
plt.axhline(y=game.target, color='r', linestyle='-', label='Target')
plt.xlabel('Iteration')
plt.ylabel('Guess Value')
plt.title('MCTS Guessing Process')
plt.legend()
plt.show()
# 測試
game = GuessNumberGame()
root = Node(game)
mcts(root, 1000)
# 選擇最佳猜測
best_guess_node = max(root.children, key=lambda n: n.visits)
best_guess = best_guess_node.state.current_guess
print("Target number:", game.target)
print("Best guess:", best_guess)
# 可視化猜測過程
guesses = [child.state.current_guess for child in root.children]
visualize_guesses(game,?guesses)
# 輸出
Target number: 88
Best guess: 1