彈目標(biāo)選擇:從MDP建模到PyTorch實(shí)現(xiàn)與調(diào)參避坑)
簡(jiǎn)介本資源面向計(jì)算機(jī)、自動(dòng)化等專業(yè)的學(xué)生與開(kāi)發(fā)者提供基于Python與DQN強(qiáng)化學(xué)習(xí)實(shí)現(xiàn)海防場(chǎng)景導(dǎo)彈目標(biāo)選擇任務(wù)的完整項(xiàng)目方案適用于畢業(yè)設(shè)計(jì)、課程設(shè)計(jì)及項(xiàng)目開(kāi)發(fā)參考。任務(wù)中敵方艦艇以固定陣型排列我方18枚導(dǎo)彈需依次選擇攻擊目標(biāo)并沿直線軌跡飛行進(jìn)入防御艦艇防御半徑后存在被攔截概率艦艇被命中一定次數(shù)后死亡且可通過(guò)調(diào)整不同艦艇價(jià)值改變攻擊側(cè)重點(diǎn)核心在于合理規(guī)劃攻擊目標(biāo)與順序以實(shí)現(xiàn)期望傷害最大化。資源包共474個(gè)文件約80.7MB包含15個(gè)Python源碼文件、108組模型checkpoint與data分片、6個(gè)yml配置、2張png示意圖、1個(gè)mp4演示視頻及md項(xiàng)目文檔覆蓋訓(xùn)練權(quán)重、配置與說(shuō)明材料。已有40人學(xué)習(xí)下載讀者可獲取可運(yùn)行源碼、算法解析文檔與演示視頻并在此基礎(chǔ)上延伸改造。1. 導(dǎo)彈目標(biāo)選擇任務(wù)為什么適合用 DQN 入門(mén)強(qiáng)化學(xué)習(xí)導(dǎo)彈目標(biāo)選擇本質(zhì)是在多目標(biāo)、多威脅、多約束的戰(zhàn)場(chǎng)態(tài)勢(shì)里讓導(dǎo)彈在飛行中動(dòng)態(tài)決定“打誰(shuí)、先打誰(shuí)、要不要換目標(biāo)”。傳統(tǒng)做法是寫(xiě)死優(yōu)先級(jí)規(guī)則比如“先打距離最近”或“先打威脅值最高”但真實(shí)場(chǎng)景里目標(biāo)會(huì)機(jī)動(dòng)、威脅會(huì)變化、攔截概率會(huì)波動(dòng)規(guī)則一多就互相打架。DQNDeep Q-Network把這件事建模成序貫決策狀態(tài)是當(dāng)前態(tài)勢(shì)動(dòng)作是選擇某個(gè)目標(biāo)獎(jiǎng)勵(lì)綜合命中概率、威脅削減和資源消耗讓網(wǎng)絡(luò)自己學(xué)出策略。Python 生態(tài)里 PyTorch 或 TensorFlow 都能快速搭出可訓(xùn)練的 DQN配合仿真環(huán)境就能跑通從環(huán)境封裝、經(jīng)驗(yàn)回放到目標(biāo)網(wǎng)絡(luò)更新的完整鏈路。這套東西適合畢業(yè)設(shè)計(jì)、課程設(shè)計(jì)里需要“有算法、有代碼、有可視化”的題目也適合想從零理解強(qiáng)化學(xué)習(xí)落地流程的開(kāi)發(fā)者——它比打游戲更貼近工程約束又比真實(shí)火控系統(tǒng)簡(jiǎn)單到能在一臺(tái)筆記本上復(fù)現(xiàn)。2. 把導(dǎo)彈目標(biāo)選擇建模成 MDP狀態(tài)、動(dòng)作、獎(jiǎng)勵(lì)怎么定2.1 狀態(tài)空間設(shè)計(jì)別把原始坐標(biāo)直接塞給網(wǎng)絡(luò)狀態(tài)設(shè)計(jì)是 DQN 能不能收斂的第一道坎。常見(jiàn)做法是把每個(gè)目標(biāo)的信息整理成固定長(zhǎng)度的向量再拼上導(dǎo)彈自身狀態(tài)。假設(shè)場(chǎng)景里有 N 個(gè)目標(biāo)每個(gè)目標(biāo)提取 6 個(gè)特征相對(duì)距離、相對(duì)方位角、相對(duì)速度、威脅等級(jí)、目標(biāo)類型編碼、是否已被分配。導(dǎo)彈自身狀態(tài)包括剩余燃料、當(dāng)前速度、當(dāng)前高度。這樣狀態(tài)維度就是6 * N 3。如果 N 會(huì)變化要么固定最大目標(biāo)數(shù)并用掩碼標(biāo)記無(wú)效目標(biāo)要么用注意力機(jī)制但入門(mén)階段建議固定 N比如 N5先把流程跑通。import numpy as np def build_state(missile, targets, max_targets5): missile: dict, 包含 fuel, speed, altitude targets: list of dict, 每個(gè)目標(biāo)含 dist, angle, rel_speed, threat, type_id, assigned 返回: np.array, shape (6 * max_targets 3,) state [] for i in range(max_targets): if i len(targets): t targets[i] state.extend([ t[dist] / 10000.0, # 歸一化到 0~1 附近 t[angle] / np.pi, # 角度歸一化 t[rel_speed] / 1000.0, t[threat] / 10.0, t[type_id] / 5.0, 1.0 if t[assigned] else 0.0 ]) else: state.extend([0.0] * 6) # 無(wú)效目標(biāo)補(bǔ)零 state.extend([ missile[fuel] / 100.0, missile[speed] / 2000.0, missile[altitude] / 15000.0 ]) return np.array(state, dtypenp.float32)這段代碼的關(guān)鍵是歸一化。距離除以 10000、速度除以 1000 這類操作不是可選項(xiàng)而是必須做——DQN 對(duì)輸入尺度敏感未歸一化的特征會(huì)讓梯度更新方向被大數(shù)值主導(dǎo)表現(xiàn)為 loss 震蕩不降。assigned字段用來(lái)標(biāo)記該目標(biāo)是否已經(jīng)被其他導(dǎo)彈鎖定避免多彈重復(fù)打同一個(gè)目標(biāo)這是多導(dǎo)彈協(xié)同里常見(jiàn)的約束。如果目標(biāo)數(shù)少于 max_targets補(bǔ)零并配合動(dòng)作掩碼防止網(wǎng)絡(luò)選到無(wú)效目標(biāo)。2.2 動(dòng)作空間與獎(jiǎng)勵(lì)函數(shù)稀疏獎(jiǎng)勵(lì)是最大的坑動(dòng)作空間最直接的設(shè)計(jì)是離散化動(dòng)作 選擇第 i 個(gè)目標(biāo)i 從 0 到 N-1再加上一個(gè)“保持當(dāng)前目標(biāo)”的動(dòng)作總共 N1 個(gè)離散動(dòng)作。這樣 DQN 的輸出層就是 N1 個(gè) Q 值取 argmax 即可。不要一上來(lái)就做連續(xù)動(dòng)作空間那需要 DDPG 或 SAC復(fù)雜度翻倍畢業(yè)設(shè)計(jì)周期內(nèi)很難調(diào)穩(wěn)。獎(jiǎng)勵(lì)函數(shù)決定策略長(zhǎng)什么樣。一個(gè)可用的獎(jiǎng)勵(lì)結(jié)構(gòu)是命中目標(biāo)100同時(shí)按目標(biāo)威脅值加成比如100 threat * 10導(dǎo)彈被攔截或燃料耗盡-50每步時(shí)間懲罰-0.1鼓勵(lì)盡快決策切換目標(biāo)懲罰-1避免頻繁換目標(biāo)導(dǎo)致震蕩選中已分配目標(biāo)-5懲罰重復(fù)分配def compute_reward(missile, target, done, hit, fuel_out, switched, already_assigned): reward -0.1 # 每步基礎(chǔ)懲罰 if hit: reward 100 target[threat] * 10 if fuel_out: reward - 50 if switched: reward - 1 if already_assigned: reward - 5 return reward血淚經(jīng)驗(yàn)是稀疏獎(jiǎng)勵(lì)下 DQN 幾乎學(xué)不動(dòng)。如果只有命中才給獎(jiǎng)勵(lì)前期隨機(jī)探索很難碰到命中Q 值長(zhǎng)期為 0網(wǎng)絡(luò)輸出退化為常數(shù)。解決辦法是加中間獎(jiǎng)勵(lì)比如“距離縮短”給小額正獎(jiǎng)勵(lì)“威脅值降低”也給正獎(jiǎng)勵(lì)讓 agent 有梯度可爬。但中間獎(jiǎng)勵(lì)不能太大否則 agent 會(huì)刷獎(jiǎng)勵(lì)而不去命中這就是 reward hacking。我一般把中間獎(jiǎng)勵(lì)控制在每步 ±0.5 以內(nèi)命中獎(jiǎng)勵(lì)保持 100 量級(jí)比例大約 200:1。3. 用 PyTorch 搭 DQN網(wǎng)絡(luò)結(jié)構(gòu)、經(jīng)驗(yàn)回放和目標(biāo)網(wǎng)絡(luò)3.1 Q 網(wǎng)絡(luò)結(jié)構(gòu)兩層全連接夠用別堆太深導(dǎo)彈目標(biāo)選擇的狀態(tài)維度通常在 30 到 50 之間動(dòng)作數(shù)在 6 到 10 之間這種規(guī)模用兩層 128 維全連接加 ReLU 就足夠。層數(shù)太深反而容易過(guò)擬合訓(xùn)練慢且難調(diào)。輸出層不加激活函數(shù)直接輸出 Q 值。import torch import torch.nn as nn class QNetwork(nn.Module): def __init__(self, state_dim, action_dim, hidden128): super().__init__() self.net nn.Sequential( nn.Linear(state_dim, hidden), nn.ReLU(), nn.Linear(hidden, hidden), nn.ReLU(), nn.Linear(hidden, action_dim) ) def forward(self, x): return self.net(x)state_dim由上一章的6 * max_targets 3決定action_dim是max_targets 1。hidden 取 128 是經(jīng)驗(yàn)值64 可能欠擬合256 在幾千條經(jīng)驗(yàn)的數(shù)據(jù)量下容易過(guò)擬合。如果訓(xùn)練 loss 下降但評(píng)估回報(bào)不漲優(yōu)先檢查是不是網(wǎng)絡(luò)太大記住了訓(xùn)練樣本。3.2 經(jīng)驗(yàn)回放與目標(biāo)網(wǎng)絡(luò)兩個(gè)穩(wěn)定訓(xùn)練的關(guān)鍵組件DQN 相比普通 Q-learning 的核心改進(jìn)就是經(jīng)驗(yàn)回放和目標(biāo)網(wǎng)絡(luò)。經(jīng)驗(yàn)回放把(state, action, reward, next_state, done)存進(jìn)緩沖區(qū)訓(xùn)練時(shí)隨機(jī)采樣打破時(shí)間相關(guān)性。目標(biāo)網(wǎng)絡(luò)是 Q 網(wǎng)絡(luò)的副本每隔 C 步同步一次參數(shù)用來(lái)計(jì)算 TD 目標(biāo)避免“自己追自己”導(dǎo)致發(fā)散。import random from collections import deque class ReplayBuffer: def __init__(self, capacity10000): self.buffer deque(maxlencapacity) def push(self, state, action, reward, next_state, done): self.buffer.append((state, action, reward, next_state, done)) def sample(self, batch_size): batch random.sample(self.buffer, batch_size) states, actions, rewards, next_states, dones zip(*batch) return (np.stack(states), np.array(actions), np.array(rewards, dtypenp.float32), np.stack(next_states), np.array(dones, dtypenp.float32)) def __len__(self): return len(self.buffer)容量設(shè) 10000 到 50000 都常見(jiàn)。太小則樣本重復(fù)率高容易過(guò)擬合近期經(jīng)驗(yàn)太大則早期差經(jīng)驗(yàn)長(zhǎng)期污染緩沖區(qū)。我一般從 10000 起步訓(xùn)練穩(wěn)定后如果發(fā)現(xiàn)策略退化再考慮減小容量或加優(yōu)先級(jí)采樣。目標(biāo)網(wǎng)絡(luò)同步步數(shù) C 通常取 100 到 500環(huán)境步數(shù)多就取大一點(diǎn)。同步太頻繁等于沒(méi)有目標(biāo)網(wǎng)絡(luò)同步太慢則目標(biāo)滯后嚴(yán)重TD 誤差長(zhǎng)期偏大。3.3 訓(xùn)練循環(huán)epsilon 衰減和梯度裁剪訓(xùn)練循環(huán)里兩個(gè)參數(shù)最影響成敗epsilon 衰減和梯度裁剪。epsilon 控制探索率從 1.0 線性或指數(shù)衰減到 0.05 左右。衰減太快則探索不足策略早熟衰減太慢則訓(xùn)練前期大量隨機(jī)動(dòng)作收斂慢。梯度裁剪用torch.nn.utils.clip_grad_norm_限制梯度范數(shù)防止個(gè)別 batch 的 TD 誤差過(guò)大把網(wǎng)絡(luò)打飛。def train_step(q_net, target_net, optimizer, buffer, batch_size, gamma): if len(buffer) batch_size: return None states, actions, rewards, next_states, dones buffer.sample(batch_size) states torch.FloatTensor(states) actions torch.LongTensor(actions) rewards torch.FloatTensor(rewards) next_states torch.FloatTensor(next_states) dones torch.FloatTensor(dones) q_values q_net(states).gather(1, actions.unsqueeze(1)).squeeze(1) with torch.no_grad(): next_q target_net(next_states).max(1)[0] target rewards gamma * next_q * (1 - dones) loss nn.MSELoss()(q_values, target) optimizer.zero_grad() loss.backward() torch.nn.utils.clip_grad_norm_(q_net.parameters(), max_norm10.0) optimizer.step() return loss.item()gamma取 0.95 到 0.99。導(dǎo)彈目標(biāo)選擇是回合制任務(wù)一個(gè)回合可能幾十步gamma 取 0.95 意味著約 20 步外的獎(jiǎng)勵(lì)衰減到一半比較合理。max_norm10.0是常用值如果 loss 出現(xiàn) NaN先降到 1.0 試試。訓(xùn)練時(shí)每 C 步執(zhí)行target_net.load_state_dict(q_net.state_dict())C 取 200 左右。4. 仿真環(huán)境搭建與訓(xùn)練調(diào)參從零跑通第一個(gè)回合4.1 用 Gym 風(fēng)格封裝環(huán)境reset 和 step 的邊界為了復(fù)用 DQN 訓(xùn)練代碼環(huán)境最好按 Gym 接口封裝reset()返回初始狀態(tài)step(action)返回(next_state, reward, done, info)。導(dǎo)彈目標(biāo)選擇的仿真不需要真實(shí)物理引擎用簡(jiǎn)化的運(yùn)動(dòng)學(xué)模型即可目標(biāo)按預(yù)設(shè)軌跡移動(dòng)導(dǎo)彈按當(dāng)前目標(biāo)方向飛行每步更新距離和角度。class MissileEnv: def __init__(self, max_targets5, max_steps100): self.max_targets max_targets self.max_steps max_steps self.reset() def reset(self): self.step_count 0 self.missile {fuel: 100.0, speed: 800.0, altitude: 8000.0} self.targets [self._random_target() for _ in range(self.max_targets)] self.current_target None return build_state(self.missile, self.targets, self.max_targets) def step(self, action): self.step_count 1 switched False if action self.max_targets: if self.current_target ! action: switched True self.current_target action # 簡(jiǎn)化運(yùn)動(dòng)學(xué)更新 self.missile[fuel] - 0.5 for t in self.targets: t[dist] - self.missile[speed] * 0.1 hit any(t[dist] 0 for t in self.targets) fuel_out self.missile[fuel] 0 done hit or fuel_out or self.step_count self.max_steps reward compute_reward(self.missile, self.targets[0], done, hit, fuel_out, switched, False) next_state build_state(self.missile, self.targets, self.max_targets) return next_state, reward, done, {}max_steps100是回合上限防止 agent 無(wú)限繞圈。fuel每步減 0.5100 步耗盡和 max_steps 對(duì)齊。目標(biāo)距離每步減speed * 0.1這是把速度單位換算成“每步飛行距離”的簡(jiǎn)化。真實(shí)項(xiàng)目里可以用更細(xì)的積分步長(zhǎng)但入門(mén)階段這個(gè)精度足夠驗(yàn)證算法。注意done的判斷順序先判命中再判燃料最后判步數(shù)避免命中時(shí)被步數(shù)截?cái)唷?.2 超參數(shù)表與訓(xùn)練曲線判讀下面這張表是我調(diào)過(guò)幾輪后比較穩(wěn)的起點(diǎn)不是唯一解但能讓你第一輪就跑出下降的 loss 和上升的回報(bào)。參數(shù)取值說(shuō)明學(xué)習(xí)率1e-3Adam 優(yōu)化器太大易震蕩太小收斂慢batch_size64經(jīng)驗(yàn)回放采樣批量gamma0.95折扣因子回合約 100 步epsilon 起始1.0完全隨機(jī)探索epsilon 終止0.05保留少量探索epsilon 衰減步數(shù)5000線性衰減目標(biāo)網(wǎng)絡(luò)同步每 200 步硬更新回放緩沖區(qū)10000經(jīng)驗(yàn)容量梯度裁剪10.0范數(shù)上限訓(xùn)練曲線判讀有幾個(gè)典型模式。Loss 持續(xù)下降但評(píng)估回報(bào)不漲多半是過(guò)擬合或獎(jiǎng)勵(lì)設(shè)計(jì)有問(wèn)題。Loss 震蕩劇烈檢查學(xué)習(xí)率是否太大或 batch_size 是否太小?;貓?bào)曲線先升后降常見(jiàn)于 epsilon 衰減太快導(dǎo)致策略早熟或者目標(biāo)網(wǎng)絡(luò)同步太頻繁。我一般每 100 回合跑一次評(píng)估評(píng)估時(shí) epsilon 設(shè)為 0看純貪心策略的表現(xiàn)避免探索噪聲干擾判斷。5. 避坑與排查導(dǎo)彈目標(biāo)選擇 DQN 訓(xùn)練中最容易翻車的 5 個(gè)點(diǎn)5.1 現(xiàn)象Q 值爆炸成 NaNloss 直接變 inf原因通常是獎(jiǎng)勵(lì)量級(jí)過(guò)大或梯度未裁剪。命中獎(jiǎng)勵(lì) 100 加上威脅加成可能到 200TD 目標(biāo)里reward gamma * max Q在 Q 值本身已經(jīng)偏大時(shí)進(jìn)一步放大幾輪更新后超出浮點(diǎn)范圍。解決方法是先把獎(jiǎng)勵(lì)整體除以 100讓命中獎(jiǎng)勵(lì)回到 1 量級(jí)同時(shí)確認(rèn)clip_grad_norm_已啟用且 max_norm 不超過(guò) 10。如果仍然 NaN把學(xué)習(xí)率降到 1e-4 再試。5.2 現(xiàn)象agent 學(xué)會(huì)原地不動(dòng)或反復(fù)選同一個(gè)目標(biāo)這是 reward hacking 的典型表現(xiàn)。如果“保持當(dāng)前目標(biāo)”有隱性正獎(jiǎng)勵(lì)或者切換懲罰過(guò)大agent 會(huì)發(fā)現(xiàn)不動(dòng)最安全。檢查獎(jiǎng)勵(lì)函數(shù)里是否有未預(yù)期的正項(xiàng)比如距離縮短獎(jiǎng)勵(lì)在目標(biāo)不動(dòng)時(shí)也持續(xù)給。解決辦法是給“保持當(dāng)前目標(biāo)”加微小時(shí)間懲罰或者把切換懲罰從 -1 降到 -0.2讓 agent 有動(dòng)力重新評(píng)估。5.3 現(xiàn)象訓(xùn)練回報(bào)波動(dòng)極大同一策略兩次評(píng)估差一倍多半是環(huán)境隨機(jī)性太強(qiáng)或評(píng)估回合數(shù)太少。目標(biāo)初始位置、速度如果每次 reset 都大幅隨機(jī)策略很難穩(wěn)定。把隨機(jī)范圍收窄比如距離在 5000 到 10000 之間而不是 1000 到 20000。評(píng)估時(shí)至少跑 20 個(gè)回合取平均單回合結(jié)果沒(méi)有參考價(jià)值。另外檢查回放緩沖區(qū)是否太小導(dǎo)致采樣方差大。5.4 現(xiàn)象loss 正常下降但 agent 從不命中目標(biāo)這是稀疏獎(jiǎng)勵(lì)下探索不足的經(jīng)典問(wèn)題。epsilon 衰減太快agent 還沒(méi)碰到過(guò)命中就進(jìn)入利用階段Q 網(wǎng)絡(luò)對(duì)命中動(dòng)作的估值始終是隨機(jī)初始值。解決辦法是延長(zhǎng) epsilon 衰減步數(shù)到 10000 以上或者加中間獎(jiǎng)勵(lì)引導(dǎo)。另一個(gè)檢查點(diǎn)是動(dòng)作掩碼如果無(wú)效目標(biāo)的 Q 值沒(méi)有被屏蔽agent 可能一直選無(wú)效動(dòng)作表現(xiàn)為“不命中也不報(bào)錯(cuò)”。5.5 現(xiàn)象換一臺(tái)機(jī)器或換隨機(jī)種子后結(jié)果完全不可復(fù)現(xiàn)DQN 對(duì)隨機(jī)種子敏感是常態(tài)。要復(fù)現(xiàn)結(jié)果需要固定 Python 的random.seed、NumPy 的np.random.seed、PyTorch 的torch.manual_seed還要設(shè)置torch.backends.cudnn.deterministic True。但即使這樣不同 GPU 上的浮點(diǎn)運(yùn)算順序差異仍可能導(dǎo)致微小偏差進(jìn)而影響策略。我的習(xí)慣是報(bào)告結(jié)果時(shí)跑 3 個(gè)不同種子取均值和標(biāo)準(zhǔn)差而不是只報(bào)最好的一次。6. 進(jìn)階技巧用動(dòng)作掩碼和優(yōu)先經(jīng)驗(yàn)回放把命中率再提一檔動(dòng)作掩碼解決的是“無(wú)效動(dòng)作被高估”的問(wèn)題。在導(dǎo)彈目標(biāo)選擇里已經(jīng)被分配的目標(biāo)、距離超出射程的目標(biāo)、燃料不足以到達(dá)的目標(biāo)都應(yīng)該在動(dòng)作選擇時(shí)屏蔽。實(shí)現(xiàn)方式是在 Q 網(wǎng)絡(luò)輸出后把無(wú)效動(dòng)作的 Q 值設(shè)為一個(gè)極小值再取 argmax。訓(xùn)練時(shí)計(jì)算 TD 目標(biāo)也要用掩碼后的 next Q否則目標(biāo)網(wǎng)絡(luò)會(huì)把無(wú)效動(dòng)作的估值傳播回來(lái)。def masked_q_values(q_values, valid_mask): q_values: tensor, shape (batch, action_dim) valid_mask: tensor, 1 表示有效, 0 表示無(wú)效 invalid_mask (valid_mask 0) q_values q_values.masked_fill(invalid_mask, -1e9) return q_values # 訓(xùn)練時(shí)計(jì)算 next_q with torch.no_grad(): next_q_all target_net(next_states) next_q_all masked_q_values(next_q_all, next_valid_masks) next_q next_q_all.max(1)[0]-1e9而不是-inf避免后續(xù)計(jì)算出現(xiàn) NaN。valid_mask 的構(gòu)造邏輯是目標(biāo)存在且未被分配且距離在射程內(nèi)則為 1否則為 0。這個(gè)掩碼在環(huán)境 step 里生成隨狀態(tài)一起返回。優(yōu)先經(jīng)驗(yàn)回放Prioritized Experience Replay讓 TD 誤差大的樣本被采樣概率更高。實(shí)現(xiàn)上可以用 SumTree 或者簡(jiǎn)化版給每個(gè)樣本存一個(gè)優(yōu)先級(jí)p |TD error| epsilon采樣時(shí)按 p 歸一化后的概率抽。簡(jiǎn)化版用 NumPy 的np.random.choice配合p數(shù)組即可不用手寫(xiě) SumTree。優(yōu)先級(jí)參數(shù) alpha 取 0.6重要性采樣權(quán)重 beta 從 0.4 線性升到 1.0。這套組合在導(dǎo)彈目標(biāo)選擇任務(wù)里通常能把命中率從 60% 左右提到 80% 以上但訓(xùn)練時(shí)間會(huì)增加約 30%。驗(yàn)證改進(jìn)是否有效不能只看訓(xùn)練回報(bào)。我一般固定 50 個(gè)測(cè)試場(chǎng)景每個(gè)場(chǎng)景跑 10 次取平均命中率和平均決策步數(shù)對(duì)比加掩碼前后、加優(yōu)先回放前后的數(shù)值。如果命中率提升但決策步數(shù)大幅增加說(shuō)明 agent 在猶豫需要檢查時(shí)間懲罰是否太小。最后說(shuō)個(gè)習(xí)慣每次改獎(jiǎng)勵(lì)函數(shù)或網(wǎng)絡(luò)結(jié)構(gòu)只改一個(gè)變量跑完對(duì)比再改下一個(gè)。同時(shí)改三四個(gè)地方結(jié)果好了也不知道是哪個(gè)起作用結(jié)果差了更不知道回退哪個(gè)。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取