WEBVTT

00:00.240 --> 00:02.550
大家好, 欢迎学习本教程｡ 

00:02.580 --> 00:07.680
在上一个教程中, 我们初始化了地图, 现在是时候开始激动人心的工作了｡ 

00:07.680 --> 00:11.190
我们创建了核心, 然后用类来实现｡ 

00:11.190 --> 00:18.120
当然, 你会发现这个类非常实用, 可以创建很多属性, 因为正如你所看到的,

00:18.120 --> 00:24.390
我不仅为我的车定义了一些变量, 还定义了一些函数, 当然, 这些函数可以让车向左,

00:24.390 --> 00:30.000
向右, 或者直行.

00:30.480 --> 00:34.920
因此, 我们有几个变量对描述环境非常重要｡ 

00:34.920 --> 00:42.120
例如, 我们有角度, 它是x轴和汽车方向轴之间的角度｡

00:42.480 --> 00:51.240
然后是旋转, 这是它的最后一次旋转, 它会记住0度, 20度或-20度｡

00:51.330 --> 00:57.660
然后我们有速度, 速度向量的x坐标和速度向量的Y坐标,

00:57.660 --> 01:02.610
然后是速度X和速度y的向量｡

01:03.240 --> 01:07.110
然后我们有传感器和信号, 这非常重要｡ 

01:07.140 --> 01:13.080
我们正在制造的汽车将有三个传感器, 因为一个传感器2和传感器3｡ 

01:13.200 --> 01:18.090
一号传感器会探测车前是否有气味｡ 

01:18.240 --> 01:24.060
然后传感器2是将检测是否有任何气味在汽车的左边的传感器｡ 

01:24.180 --> 01:29.550
第三个传感器是用来探测车右侧是否有气味的传感器｡ 

01:29.700 --> 01:37.050
然后从这三个传感器中, 我们得到信号, 即每个传感器接收到的信号｡

01:37.050 --> 01:40.140
因此, 信号1是由传感器1接收的信号｡ 

01:40.140 --> 01:46.130
信号二是由传感器二接收的信号, 信号三是由传感器三接收的信号｡ 

01:46.140 --> 01:47.550
那么它是如何工作的呢？

01:47.580 --> 01:51.660
信号1是传感器1周围的发送密度｡ 

01:51.660 --> 01:57.900
信号二是传感器二周围的气味密度, 信号三是传感器三周围的沙子密度｡

01:58.020 --> 02:00.500
我们如何计算沙子的密度？

02:00.510 --> 02:01.650
这很简单

02:01.650 --> 02:05.910
我们在每个传感器周围画一些大方块｡ 

02:05.910 --> 02:08.790
这些实际上是200乘200的正方形｡ 

02:08.790 --> 02:14.340
对于每个正方形, 我们用正方形中1的个数除以正方形中单元格的总数,

02:14.340 --> 02:17.790
即20乘以20等于400｡

02:17.790 --> 02:22.320
这就给出了沙子的密度, 因为这些密度对应着沙子的密度｡ 

02:22.350 --> 02:27.720
我们对每个传感器都这样做, 这样就得到了每个传感器周围沙子的密度｡ 

02:27.720 --> 02:29.070
那就是信号｡ 

02:29.460 --> 02:29.820
好吧, 我会的

02:29.820 --> 02:35.250
所以现在我们有了检测沙子的一切, 然后我们有了移动功能｡ 

02:35.310 --> 02:41.280
当然, 移动函数允许内核向左､ 直行或向右移动｡

02:41.730 --> 02:43.140
所以让我们快速浏览一下｡ 

02:43.140 --> 02:52.320
我们这里更新了核心的位置, 它的最后位置, 也就是经过这里的self和速度矢量｡

02:52.320 --> 02:58.440
因此, 由于速度矢量, 位置将在速度矢量的方向上更新｡ 

02:58.710 --> 03:05.040
然后我们得到了旋转, 我们将在下面的代码中得到它｡ 

03:05.160 --> 03:11.010
旋转等于动作到旋转动作, 在这里我们将选择动作, 然后获得旋转｡ 

03:11.100 --> 03:15.090
所以这个自旋转等于旋转｡ 

03:15.090 --> 03:21.690
这是一个旋转, 我们知道如何旋转, 向左或向右的核心｡

03:22.230 --> 03:29.220
然后我们更新角度, 我提醒你, 这个角度是x轴和核心方向轴之间的角度｡

03:29.340 --> 03:35.280
一旦内核移动, 我们就必须更新传感器和信号,

03:35.280 --> 03:41.340
因为内核刚刚旋转, 而传感器也在旋转, 因此我们需要使用rotate函数旋转传感器,

03:41.340 --> 03:45.420
并将新位置添加到其中｡

03:45.480 --> 03:48.870
为什么我们会有这个矢量300？

03:48.870 --> 03:53.910
这是因为30是核心和传感器之间的距离｡ 

03:53.910 --> 03:58.380
你知道, 它是核心和核心探测到的东西之间的距离｡ 

03:58.980 --> 04:04.050
一旦传感器被更新, 那么就该更新信号了｡ 

04:04.050 --> 04:07.020
所以这里我们完全按照我解释的来计算信号｡ 

04:07.020 --> 04:12.840
我们得到传感器的X坐标, 然后我们把所有的细胞从负10到正10｡ 

04:13.170 --> 04:18.840
然后我们对Y坐标做同样的处理, 把所有的单元格从-10取到+10｡ 

04:18.840 --> 04:28.020
因此, 我们得到了传感器周围20 × 20像素的正方形, 在这个正方形内, 我们将所有的像素相加｡

04:28.020 --> 04:32.820
所以基本上我们把所有的单元格加起来, 因为这些单元格要么包含0, 要么包含1｡ 

04:32.820 --> 04:37.950
因为在20乘20的平方里有20乘20等于400个细胞｡ 

04:37.950 --> 04:43.230
我们把它除以400, 得到正方形内一次的密度｡ 

04:43.230 --> 04:48.300
这就是我们如何获得传感器周围细胞密度的信号｡ 

04:48.300 --> 04:54.840
我们对第二个传感器和第三个传感器做了同样的操作, 以获得第二个信号和第三个信号｡

04:54.960 --> 04:55.190
好吧, 我会的

04:55.290 --> 04:56.760
所以这就是检测的意义｡ 

04:56.760 --> 05:00.060
这里的三行代码非常重要｡ 

05:00.060 --> 05:06.060
这是另一个糟糕的奖励, 我们想给予我们的车时, 它是达到地图的边缘之一｡

05:06.390 --> 05:14.250
我们不想让车撞到墙上, 所以我们想惩罚它, 当它太靠近墙的时候惩罚它.

05:14.400 --> 05:16.230
因此, 这就是我们在这里所做的｡ 

05:16.410 --> 05:25.110
如果第一个传感器大于longer-10, 它就大于这里因为这里的距离更长｡

05:25.110 --> 05:27.360
再长一点, 负10就在这里｡ 

05:27.360 --> 05:34.110
所以如果传感器1x大于, -10,

05:34.110 --> 05:41.470
表示所有点都在这里, 也就是说, 如果汽车越来越靠近地图的右边缘, 或者传感器1x小于10.

05:41.490 --> 05:42.420
就是这里｡ 

05:42.420 --> 05:51.810
如果汽车越来越靠近地图的左边缘, 或者如果传感器Y大于-10, 那就是地图的上边缘｡

05:51.870 --> 05:57.960
和/或如果自传感器y小于10, 则其为地图的下边缘｡ 

05:58.470 --> 06:06.360
如果第一个传感器到达这四个边缘中的任何一个, 那么, 我们将把传感器的信号｡

06:06.360 --> 06:08.430
信号一是传感器一的信号｡ 

06:08.550 --> 06:10.260
我们将其设置为1｡ 

06:10.260 --> 06:11.400
这是什么意思？

06:11.400 --> 06:15.330
这意味着完全发送, 像一个完整的气味密度｡ 

06:15.360 --> 06:17.100
这是你能得到的最糟糕的东西｡ 

06:17.100 --> 06:19.440
它会让你的车停下来｡ 

06:19.440 --> 06:23.940
所以信号是1, 所以车会得到一个非常糟糕的奖励｡ 

06:24.300 --> 06:24.720
好吧, 我会的

06:24.720 --> 06:29.520
然后我们对来自传感器2和传感器3的信号2和信号3进行了同样的处理｡ 

06:30.280 --> 06:30.730
好吧, 我会的

06:30.730 --> 06:32.950
然后我们创建游戏类｡ 

06:32.950 --> 06:38.050
这就是创建游戏的类因为到目前为止我们只创建了汽车.

06:38.200 --> 06:44.380
当然, 现在我们必须创建地图, 我们必须创建游戏本身, 所以我们不会玩游戏｡

06:44.380 --> 06:46.690
是我们的人工智能在玩游戏｡ 

06:46.690 --> 06:52.030
这个游戏实际上是要避开障碍物, 从机场到市中心, 反之亦然｡ 

06:52.270 --> 07:01.690
所以在这个博弈类中, 我们需要创建一些像汽车这样的对象, 然后我们需要定义更新函数, 这是最重要的｡

07:01.690 --> 07:06.880
实际上, 我们现在将重点关注这一点, 因为这是在这个更新功能中,

07:06.880 --> 07:12.040
我们将选择汽车在每次完成其目标时必须执行的操作｡

07:12.040 --> 07:20.470
而这个动作正是我们的神经网络的输出, 这个神经网络将是我们人工智能的核心｡

07:20.770 --> 07:27.020
所以这个动作是由汽车的大脑返回的, 我提醒一下, 它是我们当前类的对象,

07:27.040 --> 07:29.620
将在我们的AI文件中生成｡

07:29.650 --> 07:37.120
这个对象有一个叫做update的方法, 它把最后一个奖励和最后一个信号作为输入｡

07:37.390 --> 07:40.930
所以最后的奖励当然是, 最后的奖励是由汽车获得的｡ 

07:40.930 --> 07:45.490
而最后一个信号当然是三个传感器的最后一个信号｡ 

07:45.490 --> 07:51.160
来自传感器1的信号1来自传感器2的信号2来自传感器3的信号3｡ 

07:51.160 --> 07:56.710
然后我添加了另外两个输入, 即汽车相对于目标的方向｡ 

07:56.710 --> 08:01.510
例如, 如果汽车正朝着目标前进, 那么方向将等于零｡ 

08:01.510 --> 08:06.550
如果它稍微向右, 则方向将接近45度｡ 

08:06.640 --> 08:11.200
如果它稍微向左, 方向将接近-45度｡ 

08:11.710 --> 08:15.160
这是我们输入状态的第四个输入｡ 

08:15.160 --> 08:18.760
最后一个输入是负方向｡ 

08:18.760 --> 08:22.480
因此, 通常神经网络的输入是独立的｡ 

08:22.480 --> 08:29.230
没有线性, 但如果我们加上它也没关系, 因为神经网络会用权重来修正它｡

08:29.230 --> 08:35.200
但我还是注意到, 通过增加这个负方向, 好吧, 这使得汽车, 汽车的训练,

08:35.200 --> 08:37.750
以稳定的探索｡

08:37.750 --> 08:42.550
你知道, 我们这样做是为了让人工智能不总是朝着同一个方向探索｡ 

08:42.550 --> 08:48.640
通过添加这个负方向, 我们确保它在两个方向上探索, 右或左｡ 

08:48.640 --> 08:55.720
所以这三个信号, 加上方向和减去方向, 是我们编码向量的五个输入,

08:55.720 --> 08:58.810
它们将进入网络｡

08:58.810 --> 09:02.380
这是我们的输入向量, 将进入网络｡ 

09:02.620 --> 09:10.450
当它进入网络后, 网络会返回输出, 这就是每次要执行的动作｡

09:10.450 --> 09:16.450
而输出由这个更新函数返回, 它包含网络本身和网络的输出｡

09:16.720 --> 09:22.060
因此, 这就是为什么我们必须输入最后一个信号, 也就是输入状态和较少的奖励,

09:22.060 --> 09:26.110
因为要玩的动作也取决于较少的奖励｡

09:26.820 --> 09:27.180
好吧, 我会的

09:27.180 --> 09:33.810
然后我们更新病房的平均分数, 更新旋转,

09:33.810 --> 09:37.230
我们使用移动功能根据所选的操作旋转汽车｡

09:37.230 --> 09:43.410
我们更新了汽车到目标的距离, 我们更新了传感器的位置｡ 

09:43.410 --> 09:48.270
一个球､ 二个球和三个球都对应于将在地图上表示传感器的球｡ 

09:48.270 --> 09:49.770
你很快就会明白的｡ 

09:50.400 --> 09:56.190
这一部分非常重要, 因为如果车撞上沙地,

09:56.190 --> 10:04.000
我们就惩罚它, 正如你所看到的, 这意味着如果车撞上沙地, 它会减速.

10:04.020 --> 10:06.350
这就是我们降低它的速度的地方｡ 

10:06.360 --> 10:09.900
你知道, 它的速度通常是6, 就像你在这里看到的｡ 

10:09.900 --> 10:12.570
如果它落在沙子上, 它就会是一个｡ 

10:12.570 --> 10:14.250
所以它会被减速到1｡ 

10:14.250 --> 10:17.550
你会看到汽车一旦进入沙地上是如何减速的｡ 

10:17.850 --> 10:21.720
所以它慢了下来, 而且, 它得到了一个坏的奖励｡ 

10:21.720 --> 10:23.670
它得到一个负一的奖励｡ 

10:23.670 --> 10:25.950
而这实际上是你能得到的最糟糕的奖励｡ 

10:25.950 --> 10:27.510
最好的奖励是一个｡ 

10:27.540 --> 10:31.770
最差的奖励是负一, 奖励在负一和正一之间｡ 

10:32.400 --> 10:39.150
否则, 如果车没有撞到沙子上, 它会保持正常速度, 速度为6.

10:39.270 --> 10:40.890
然后我们再加些别的东西｡ 

10:40.890 --> 10:45.660
如果它离目标越来越近, 那么它会得到一个稍微积极的奖励｡ 

10:45.660 --> 10:52.530
如果它离目标越来越远, 那么, 它会得到一个轻微的负奖励, -0｡  2.

10:53.380 --> 10:57.180
然后是最后一个与奖励有关的条件｡ 

10:57.190 --> 11:02.710
这是因为核心太靠近其中一个边了, 就像我们之前说的那样｡ 

11:02.740 --> 11:04.920
还记得我们说过满沙吗？

11:04.930 --> 11:11.000
好吧, 如果核心离地图的左边太近, 它会得到负一的奖励｡ 

11:11.020 --> 11:15.250
如果它太靠近地图的右边缘, 它得到的奖励是2减1｡ 

11:15.400 --> 11:20.050
如果它太靠近地图的底部边缘, 它会得到减一的奖励｡ 

11:20.050 --> 11:25.150
如果它离地图左上角太近, 它的奖励就减一｡ 

11:25.150 --> 11:27.360
所以这是一个可怕的惩罚｡ 

11:27.370 --> 11:31.180
所以你会看到它如何快速学会不匆忙进入其他东西｡ 

11:31.750 --> 11:32.170
好吧, 我会的

11:32.170 --> 11:36.430
然后在目标达到时更新目标｡ 

11:36.430 --> 11:40.930
所以, 你知道, 当汽车到达机场,

11:40.930 --> 11:45.970
这是第一个目标, 这是地图的左上角, 而目标改变到地图的右下角, 这是市中心,

11:45.970 --> 11:47.470
这正是我们在这里做的｡

11:47.470 --> 11:55.030
我们更新目标的X坐标和Y坐标, 然后更新汽车到目标的距离｡

11:55.720 --> 11:56.170
好吧, 我会的

11:56.170 --> 11:58.180
那就不那么重要了｡ 

11:58.180 --> 12:05.290
这只是一个类, 它会添加绘画工具, 让我们能够在地图上画出一些道路或障碍物,

12:05.290 --> 12:08.020
这与洞穴更相关｡

12:08.050 --> 12:09.400
你想看的话可以看一下｡ 

12:09.400 --> 12:17.320
我将提供此代码的推荐版本, 如果您想更深入地了解如何使用Sky V, 我将提供一些参考｡

12:17.320 --> 12:22.510
但我们离人工智能越来越远了, 所以我不打算深入讨论它的细节｡

12:22.600 --> 12:26.860
这与汽车应用类的最后一段代码相同｡ 

12:26.860 --> 12:31.240
这只是添加API按钮, 清除, 保存和加载｡ 

12:31.240 --> 12:32.710
这就是我们要做的｡ 

12:32.710 --> 12:34.720
清除画布保存｡ 

12:34.720 --> 12:36.010
这一点非常重要｡ 

12:36.010 --> 12:43.150
这是为了我们能够保存AI, 保存大脑, 这样你以后可以通过取加载功能来重复使用它,

12:43.150 --> 12:48.160
这是我们在地图上添加的另一个工具来加载汽车的大脑, 也就是加载汽车的记忆,

12:48.160 --> 12:51.730
如何在地图中导航｡

12:52.000 --> 13:00.430
最后是最后一段代码, 它运行整个程序, 运行地图和人工智能本身｡

13:00.700 --> 13:03.280
事实上, 这就是我们现在要做的｡ 

13:03.310 --> 13:06.730
让我们来看看我们在这段代码中创建的所有内容｡ 

13:06.730 --> 13:10.300
所以现在人工智能还没有实现｡ 

13:10.300 --> 13:13.780
所以代码会有一个非常随机的运动｡ 

13:13.780 --> 13:15.850
它看起来就像一只昆虫｡ 

13:15.850 --> 13:17.590
但别担心, 我们会解决的｡ 

13:17.590 --> 13:26.320
我们不仅要训练它像真实的汽车一样移动, 还要训练它沿着一些道路导航, 避开一些障碍｡

13:26.320 --> 13:27.550
所以我们开始吧｡ 

13:27.550 --> 13:32.230
我将选择所有内容并执行｡ 

13:32.230 --> 13:35.050
这是地图这是车｡ 

13:35.530 --> 13:35.980
好吧, 我会的

13:35.980 --> 13:41.380
这是一个小东西, 你可以看到它看起来像一只昆虫, 这就是我们的车｡ 

13:41.380 --> 13:45.940
所以就像我告诉你的, 这些动作完全是随机的｡ 

13:45.940 --> 13:53.530
所以每次汽车在行动中随机选择是向左直行还是向右直行｡ 

13:53.680 --> 13:58.720
这就是为什么它在做一些无意义的运动, 这就是为什么它看起来像一只昆虫｡ 

13:59.170 --> 14:01.420
当然, 我们会解决这个问题｡ 

14:01.420 --> 14:08.050
当然, 由于人工智能是激活的, 嗯,

14:08.050 --> 14:12.910
它不会去, 这是机场在这里或市中心在地图的右下角｡

14:13.520 --> 14:21.500
我们将通过制作I来解决所有这些问题, 这样我们就可以在这个核心或这个昆虫中实现人工智能｡ 

14:21.500 --> 14:26.350
你可以看到这三个球, 黄色的, 红色的和白色的｡ 

14:26.360 --> 14:28.070
这是我们的三个传感器｡ 

14:28.070 --> 14:32.480
所以它能探测到周围是否有气味｡ 

14:32.480 --> 14:35.480
说到气味, 好吧, 让我们扔一些｡ 

14:35.480 --> 14:41.540
因此, 要做到这一点, 我只需要做一个点击左这里和｡ 

14:42.440 --> 14:45.220
你知道, 画一些发送仍然点击左｡ 

14:45.230 --> 14:50.000
所以现在我加了一些沙子, 我们可以再加一些｡ 

14:50.000 --> 14:55.370
所以每次我添加沙子的时候, 正如你所看到的, 这就是在沙子数组中添加1｡ 

14:55.370 --> 14:59.780
那是沙阵, 那是零零坐标的原点｡ 

14:59.900 --> 15:01.850
这里有很多｡ 

15:01.850 --> 15:03.920
如你所见, 这很好｡ 

15:03.920 --> 15:07.130
汽车刚驶入沙地就减速了｡ 

15:07.400 --> 15:14.780
正如你现在看到的, 它的速度确实慢了下来因为它正向沙滩前进, 现在它正试图逃跑.

15:16.130 --> 15:23.900
所以我们要做的就是画一些路我们要画一些从机场到市中心的路, 我们要训练汽车保持在路上,

15:23.900 --> 15:27.890
避开障碍物｡

15:28.310 --> 15:28.760
好吧, 我会的

15:28.760 --> 15:31.940
正如你所看到的, 有一个清除按钮来清除沙子｡ 

15:31.970 --> 15:37.100
还有就是保存扣救车的脑子｡ 

15:37.100 --> 15:42.740
事实上, 我们所说的分数曲线可以节省眼睛, 节省你的模型, 实际上,

15:42.740 --> 15:44.570
节省你的汽车大脑｡

15:44.780 --> 15:50.870
然后你可以知道, 当你离开你的代码或关闭你的电脑,

15:50.870 --> 15:57.710
你想再回到它, 你可以使用加载按钮来加载你的模型, 这是加载大脑,

15:57.710 --> 16:01.010
这将得到你的车训练有素的眼睛｡

16:01.640 --> 16:02.150
好吧, 我会的

16:02.150 --> 16:05.930
所以现在我等不及要开始做I了｡ 

16:05.960 --> 16:07.300
这会很有趣的｡ 

16:07.310 --> 16:13.850
我们将建立神经网络, 一旦汽车不按我们的要求工作, 我们将惩罚它｡ 

16:13.880 --> 16:16.160
我们从下一个教程开始｡ 

16:16.160 --> 16:17.770
在那之前, 好好享受吧｡ 

16:17.780 --> 16:18.320
一､ 
