feat: ISMCTS q-value as training label
C#: TrainingCollector新增q_value列, IsmctsBot传入winRate CSV: reward→q_value, ISMCTS状态带真实评估值, Neural填0 Python: 优先取ISMCTS状态+评估值训练, 无q_value的Neural状态跳过 旧CSV格式(reward)自动fallback到Neural-only过滤 信号从'这局谁赢'改为'ISMCTS评估这步有多好'
This commit is contained in:
@ -392,7 +392,7 @@ namespace PdkFriendServer.Logic
|
||||
int totalSims = allCandidates.Count * fastSims
|
||||
+ scoredCandidates.Count(c => c.winRate > 0.3) * (simsPerCandidate - fastSims);
|
||||
Console.WriteLine($"[ISMCTS pos{view.MyPos}] {totalSims}sims => {desc}");
|
||||
TrainingCollector.Record(view, _tracker, TrainingCollector.ActionToIdx(best.play), view.MyPos-1);
|
||||
TrainingCollector.Record(view, _tracker, TrainingCollector.ActionToIdx(best.play), view.MyPos-1, (float)best.winRate);
|
||||
return best.play;
|
||||
}
|
||||
|
||||
|
||||
@ -7,8 +7,8 @@ using GameMessage.PaoDeKuaiF;
|
||||
namespace PdkFriendServer.Logic
|
||||
{
|
||||
/// <summary>
|
||||
/// 训练数据收集器 — 记录 (state, action, result) 三元组供 Python 训练。
|
||||
/// 状态编码与 Python trainer 完全一致:13rank×4suit×7ch=364 float。
|
||||
/// 训练数据收集器 — 记录 (state, action, q_value, player) 四元组供 Python 训练。
|
||||
/// q_value: ISMCTS 对选出动作的胜率评估 (0~1), NeuralBot 填游戏结果(-1/0/1)
|
||||
/// </summary>
|
||||
public static class TrainingCollector
|
||||
{
|
||||
@ -25,14 +25,15 @@ namespace PdkFriendServer.Logic
|
||||
{
|
||||
public float[] State;
|
||||
public int Action; // 0-12 = rank index, 13 = pass
|
||||
public float QValue; // ISMCTS 评估值 (0~1) 或 NeuralBot 用游戏结果
|
||||
public int Player;
|
||||
}
|
||||
|
||||
public static void Record(PdkBotView view, CardTracker tracker, int actionIdx, int player)
|
||||
public static void Record(PdkBotView view, CardTracker tracker, int actionIdx, int player, float qValue = 0f)
|
||||
{
|
||||
if (!Enabled) return;
|
||||
var state = EncodeState(view, tracker);
|
||||
_records.Add(new TrainingRecord { State = state, Action = actionIdx, Player = player });
|
||||
_records.Add(new TrainingRecord { State = state, Action = actionIdx, QValue = qValue, Player = player });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -45,12 +46,11 @@ namespace PdkFriendServer.Logic
|
||||
var path = $"training_data/game_{gameId:D5}.csv";
|
||||
System.IO.Directory.CreateDirectory("training_data");
|
||||
using var w = new System.IO.StreamWriter(path);
|
||||
w.WriteLine("state,action,reward,player");
|
||||
w.WriteLine("state,action,q_value,player");
|
||||
foreach (var r in _records)
|
||||
{
|
||||
float reward = r.Player >= 0 && r.Player < rewards.Length ? rewards[r.Player] : 0;
|
||||
var stateStr = string.Join(",", r.State.Select(f => f.ToString("F6")));
|
||||
w.WriteLine($"\"{stateStr}\",{r.Action},{reward:F3},{r.Player}");
|
||||
w.WriteLine($"\"{stateStr}\",{r.Action},{r.QValue:F3},{r.Player}");
|
||||
}
|
||||
// 游戏结果摘要 — 方便不中断训练即可评估模型进化
|
||||
w.WriteLine($"#RESULT,winner={winnerPos},bots={string.Join(",", botTypes ?? new[]{"ISMCTS","ISMCTS","ISMCTS"})}");
|
||||
|
||||
Reference in New Issue
Block a user