TF:机器学习射击篮球框

在本文中,我们将深入研究如何使用Unity3DTensorFlow教AI执行简单的游戏任务:将篮球射进框(不会动的某军事基地)。


游戏介绍

有一种游戏,玩家的主要目标是:将球放入篮筐。听起来并不难,但是当您的血液在抽动,您的心脏在跳动,人群在欢呼时,好吧,要开枪很难。我在说经典的美国篮球比赛吗?不,从未听说过。我说的是经典的Midway街机游戏NBA Jam

如果您曾经玩过NBA Jam或它所启发的任何游戏(包括现实生活中的NBA联赛,我认为是在NBA Jam之后出现的),那么从球员的角度来看,投篮的技巧就非常简单。以合适的时机按住并释放拍摄按钮。您是否曾经想过从游戏的角度来看如何拍摄如何选择球的弧度?球有多硬?电脑如何知道射击角度?如果您是一个聪明,有数学倾向的人,您也许可以用笔和纸找出这些答案,但是此博客文章的作者未通过8年级代数,因此……那些“聪明人”的答案就不成问题了。我将需要以其他方式进行处理。与其采取更简单,更快,更有效的方法进行射击所需的数学运算,我们不去看看兔子洞的深度,学习一些简单的TensorFlow,并尝试射击一些令人毛骨悚然的篮球。

入门

  1. 我们需要少量的内容来完成这个项目。

  2. 篮球模拟与物理的统一
  3. Node.jsTensorFlow.js用于训练我们的模型
  4. TensorFlowSharp用于通过ML-Agents资产包将我们的模型嵌入Unity
  5. tsjs-converter,用于将TensorFlow.js模型转换为可在Unity中使用的图形。
  6. Google表格可轻松显示线性回归
下载项目

我不会尝试一步一步地重新创建该项目,因此建议在Github上下拉源代码,并在解释发生的情况时紧随其后。后台留言即可获得下载资源。

我们的目标是什么?


为使事情简单,我们对该项目的期望结果将非常简单。我们要解决的问题:如果射手距离篮筐X距离,则用力射门而已!我们不会试图瞄准球或其他任何花哨的东西。我们只是想弄清楚投篮有多难。如果您对如何在Unity中制作更复杂的AI感兴趣,则应该从Unity 签出更完整的ML-Agents项目。我将在这里讨论的方法被设计为简单,易上手,并且不一定指示最佳实践(我也在学习!)基于对TensorFlow,机器学习和数学的有限知识。因此,一点点了解,当然这一切都是为了好玩。

篮子和球

我们已经讨论了我们目标的要点:投篮。要将球射入篮筐,您需要一个篮筐,然后……一个球。这就是Unity的来历。

如果您不熟悉Unity,那就知道它是一个游戏引擎,可让您为所有平台构建2D和3D游戏。它具有内置的物理特性,基本的3D建模以及出色的脚本运行时(Mono),可让我们用C#编写游戏

我不是艺术家,但是我拖了一些街区,把这个场景放在一起。

0_1zsfBiJPlXBxl5wx.png

那个红色方块显然是我们的玩家。箍圈设置有不可见的触发器,使我们能够检测物体(球)何时穿过球筐。在Unity编辑器中,您可以看到以绿色概述的不可见触发器。您会注意到有两个触发器。这样一来,我们可以确保只计算球从上到下落下的篮筐。如果我们看一下中的OnTriggerEnter方法/Assets/BallController.cs(我们篮球的每个实例将具有的脚本),您将看到如何将这两个触发器一起使用。让我们尝试运行所有这些,看看我们的全明星射手的表现如何。您可以在Unity编辑器中点击▶️(播放)按钮,我们将看到…

0_i_AdthwJ3tdBZZCZ.gif

答案就在一行中Assets/BallController.cs它说float force = 0.2f这条线大胆地宣称每一枪都应该完全一样。您会注意到,Unity非常从字面上看待这个“完全相同”的事情。具有相同作用力的相同物体一次又一次地重复,将始终以完全相同的方式反弹。整齐。


当然,这不是我们想要的。

随机化扔,收集数据

我们可以通过简单地将力更改为随机值来引入一些随机噪声,也就是随机值,随机投。



0_FUgZvuZbZu_er5Eg.gif


ok 终于进了一个。但这纯粹是运气。没关系。在这一点上,任何拍摄都是我们可以使用的数据点。稍后我们将解决这个问题。

同时,我们不希望仅从一个位置投球。我们希望Red(红色的投球器)在任何距离都能成功投球(当他足够幸运时)。在中Assets/BallSpawnController.cs,查找这些行和注释MoveToRandomDistance()

如果我们这样做,每次射门后,Red都会在球场上热情地跳跃。

0_bbr9n4cp5WuGooYe.gif

随机运动和随机力的这种结合创造了一个非常奇妙的东西:数据。如果您查看Unity中的则随着成功尝试的进行,您将看到每次投射的数据。

微信截图_20200109152417.png


每次成功的射击都将统计到目前为止成功射击的次数,距篮筐的距离以及进行射击所需的力量事成功的关键。虽然这很慢,但让它逐渐增加。返回到添加MoveToRandomDistance()呼叫的位置,并将0.3f(每次发射300毫秒0.05f的延迟)更改为(50毫秒的延迟)。现在点击播放,观看我们成功拍摄的动态图。数据量更大。



现在,这是一个很好的培训制度!我们可以从后面的柜台看到,我们成功得分约6.4%。斯蒂芬·库里(Steph Curry),不是。说到培训,我们实际上从中学到了什么吗?TensorFlow在哪里?为什么这很有趣?好吧,这就是下一步。现在,我们准备将这些数据从Unity中提取出来,并建立一个模型来预测所需的力量。


预测,模型和回归

检查我们在表格中的数据,在深入研究TensorFlow之前,我想看一下数据,以便让Unity运行直到Red成功完成约50张照片为止。如果查看Unity项目的根目录,则应该看到一个新文件successful_shots.csv这是Unity每次成功拍摄后的原始转储!我将Unity导出,以便可以在电子表格中轻松对其进行分析。.csv文件只有三行indexdistanceforce将此文件导入了Google表格,并创建了一个具有趋势线散点图这使我们可以了解数据的分布情况。

0_zlc5Gb__XqxuUzX3.png

该图显示了一系列点,这些点基于射击的力沿Y轴定位,基于射击的距离沿X轴定位。我们看到的是所需的力量与射击距离之间的非常明显的关联(有一些随机的例外,发生了疯狂的反弹)。实际上,您可以将其读为“ TensorFlow擅长于此。”

尽管此用例很简单,但TensorFlow的一大优点是,如果愿意,我们可以使用类似的代码构建更复杂的模型。例如,在一个完整的游戏中,我们可以包括一些功能(例如其他比赛的位置,以及他们过去几次盖帽的统计数据),以确定我们的球员应该投篮还是传球。

创建我们的模型TensorFlow.jstsjs/index.js在您喜欢的编辑器中打开文件。该文件与Unity无关,只是一个脚本,用于根据中的数据训练我们的模型successful_shots.csv这是训练和保存模型的整个方法……

如您所见,只是没有太多。我们从.csv文件中加载数据,并创建一系列X点和Y点(听起来很像上面的表格!)。从那里,我们要求模型“拟合”此数据。之后,我们将保存模型以供将来使用!

可悲的是,TensorFlowSharp并没有期望Tensorflow.js可以保存到的格式的模型。因此,我们需要进行一些神奇的翻译,才能将模型引入Unity。我提供了一些实用程序来帮助解决此问题。一般的过程是,我们将模型转换TensorFlow.js FormatKeras Format可以建立检查点的位置,并与我们合并Protobuf Graph Definition以获得Frozen Graph Definition可以放入Unity 的检查点幸运的是,如果您想一起玩,可以跳过所有内容,然后运行tsjs/build.sh,如果一切顺利,它将自动完成所有步骤,并将冻结的模型放入Unity。内部团结的,大家可以看一下GetForceFromTensorFlow()Assets/BallSpawnController.cs看到我们的模型看起来像什么互动。进行图形定义时,您要定义一个复杂的系统,该系统具有多个步骤。在我们的案例中,我们将模型定义为单个密集层(具有隐式输入层),这意味着我们的模型接受单个输入并提供一些输出。在TensorFlow.js中使用model.predict时,它将自动将输入提供给正确的输入图节点,并在计算完成后为您提供来自正确节点的输出。但是,TensorFlowSharp的工作方式不同,要求我们通过它们的名称直接与图节点交互。

考虑到这一点,将输入数据转换为图形期望的格式,然后将输出发送回Red即可。

今天是比赛日!

使用上面的系统,我在模型上创建了一些变体。这是使用仅受过500次成功训练的模型进行的红色射击。我们看到制成的篮子增加了10倍!如果我们训练Red几个小时并获得10k或100k成功的镜头,会发生什么?当然,这将进一步改善他的比赛!如果你能击败了60%的成功率(扰流:跳动的60%是100%的可能,回去看一下第一个GIF看到的只是你能有多好培养红!)



sitemap