|
楼主 |
发表于 2022-12-25 14:46:24
|
显示全部楼层
本帖最后由 hyp7617 于 2022-12-25 14:56 编辑
准备训练数据
为了能够将数据提供给我们的模型,我们需要对其进行归一化并将我们之前看到的块元组转换为向量。
为了对元组进行编码,我们将分别对每个特征进行编码,将它们全部连接起来并将其提供给网络。我们将对块 ID 进行一次性编码,使其14变为:
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …]
复制代码 在编码位置之前,我们将转换为表示它相对于最后一个块的位置的向量,以便此块序列:
- [(14, 15, 5, 15, 0), (6, 14, 5, 16, 0)]
复制代码 变成这样:
- [(14, 0, 0, 0, 0), (6, -1, 0, 1, 0)]
复制代码 因为:
- [14, 5, 16] — [15, 5, 15] = [-1, 0, 1]
复制代码
最后,旋转也可以很容易地进行单热编码,因此旋转 0(北)变为:
我们连接所有这些数组,例如我们最终的块编码(6, -1, 0, 1, 0)是:
- [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, …, 0.47, 0.55, 0.63, 1, 0, 0, 0]
复制代码 对于拆分序列,我使用了回溯为 20 的滑动窗口方法,这意味着序列中的每个块都将具有它的前 20 个块的序列作为输入。我还对短于上述 20 的序列使用了 0 填充。
位置模型的一个样本的最终输入如下所示:
- [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, …, 0.39, 0.75, 0.13, 0, 0, 1, 0]
- [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, …, 0.45, 0.55, 0.24, 0, 0, 0, 1]
- [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, …, 0.09, 0.60, 0.38, 0, 1, 0, 0]
- ...
复制代码 对于块模型,我们只需要块 ID 的第一个编码,因为它只预测接下来可能放置的块类型。
生成新曲目
生成新轨道时,我们首先在地图上随机放置一个起始块。我们对这个长度为 1 的序列进行编码,并将其提供给块模型。在输出中,我们得到了下一个要放置的块类型的概率。我们将温度应用于此输出,然后进行采样。
之后,我们再次对位置网络的输入进行编码,通过网络运行它们并接收实值位置向量和旋转概率向量。
之后,我们在代码中执行一系列额外检查(如果轨道不超过地图大小等)以确保输出在一定程度上是正确的(毕竟,网络并不总是完美的)并重复再次处理,直到我们以块为单位达到所需的轨道长度。
在赛道的尽头,我们需要放置一个终点块,这样我们才能真正完成它。这是通过省略下图中的整个“块预测”步骤并仅要求位置网络预测完成块的位置来完成的:
最后,我们将所有位置向量转换为实际地图坐标,以便保存轨迹供游戏读取。
结果
在训练网络并解决我遇到的更多问题之后,生成的轨道通常可以由人类驾驶并且类似于“技术”风格。以下是一些生成的曲目的截图:
结论
我确信还有很大的改进空间(数据清理、更好的模型、超参数调整等等)。这是我的第一个 ML 项目,我学到了很多东西。总的来说,我真的很高兴结果如何。我跳过了这篇文章中的一些细节,以免读得太长,但我希望这至少对您来说是一本有趣的读物。
查看GitHub 上的项目,如果您有机会成为 TrackMania 播放器,请查看发布页面以获取下载或使用 TMTrackNN 生成的一些赛道。
谢谢阅读!
原文出处https://donadigo.com/tmtracknn
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|