WEBVTT

00:00.270 --> 00:02.730
大家好, 欢迎学习本Python教程｡ 

00:03.000 --> 00:08.580
好的, 在本教程中, 我们将创建一个函数, 每次都能选择正确的动作｡

00:08.580 --> 00:14.430
所以基本上, 我们要实现的部分, 将使汽车做正确的移动,

00:14.430 --> 00:20.520
在每一次是向左走, 直行或向右走, 以达到目标, 并避免障碍物下降｡

00:20.730 --> 00:22.200
所以我们现在就开始吧｡ 

00:22.200 --> 00:28.260
像往常一样, 我们先用def定义一个函数, 然后给予这个函数命名,

00:28.260 --> 00:30.360
我们称之为select.

00:31.170 --> 00:31.830
开始行动

00:32.370 --> 00:37.320
然后加上一些括号, 这个选择操作函数将有两个参数｡ 

00:37.320 --> 00:41.130
第一种是自我象平常一样地指称客体｡ 

00:41.130 --> 00:46.020
第二个论点, 你认为是哪一个？

00:46.170 --> 00:47.580
那会是什么呢？

00:47.610 --> 00:53.520
如果你想一想, 我们选择的行动来自神经网络的输出,

00:53.520 --> 00:59.340
因为神经网络的输出是三种可能行动中每一种的线索值,

00:59.340 --> 01:05.550
因此我们所做的行动, 将成为神经网络输出的行动, 取决于输入状态｡

01:05.550 --> 01:11.340
而输入状态正是我们需要的select action函数的第二个参数｡ 

01:11.670 --> 01:16.260
这是因为我们实际上是要获取神经网络的输出｡ 

01:16.260 --> 01:22.140
当然, 神经网络的输出直接取决于神经网络的输入｡ 

01:22.140 --> 01:23.970
这就是我们的论点｡ 

01:23.970 --> 01:26.430
现在我们可以给它取任何名字｡ 

01:26.430 --> 01:33.870
我们称之为状态, 因为神经网络的输入是输入状态, 由一个五维向量编码,

01:33.870 --> 01:39.810
三个信号, 方向和负方向｡

01:39.810 --> 01:41.940
所以现在事情就简单了｡ 

01:41.940 --> 01:49.320
我们将把输入状态输入到神经网络中, 就是我们在上面构建的, 这里的网络类.

01:49.320 --> 01:55.950
然后我们将得到输出, 这是三个可能动作中每一个的提示值｡

01:55.950 --> 02:02.640
然后使用一个软max方法, 我会在本教程中解释, 我们将播放最后一个动作｡

02:03.030 --> 02:04.290
所以我们开始吧｡ 

02:04.290 --> 02:07.740
让我们进入函数, 实现所有这些｡ 

02:08.220 --> 02:13.020
我们首先要讲的是我刚才提到的填充物｡ 

02:13.020 --> 02:24.480
最大化软最大化的思想是我们每次都要尝试最好的动作, 但同时我们也要探索不同的动作｡

02:24.720 --> 02:25.890
我们怎么才能做到呢？

02:25.890 --> 02:30.990
我们如何才能在探索其他动作的同时获得最佳的动作？

02:30.990 --> 02:38.850
我们使用了软最大值的概念, 它包括为每个Q值, Q状态行为,

02:38.850 --> 02:41.880
生成一个概率分布｡

02:41.880 --> 02:44.970
你知道, 我们对每个动作都有一个Q值｡ 

02:44.970 --> 02:46.590
向左走, 直走或向右走｡ 

02:46.590 --> 02:49.470
但此Q值还取决于输入状态｡ 

02:49.470 --> 02:52.650
这就是你们看到的Q函数和直觉课｡ 

02:52.650 --> 02:55.980
该Q函数是状态和动作的函数｡ 

02:56.010 --> 03:02.460
因为我们这里有一个输入状态, 也就是这里的状态, 和三个可能的动作, 我们有三个｡

03:02.460 --> 03:03.270
Q值｡ 

03:03.270 --> 03:04.470
问：国家行动一｡ 

03:04.470 --> 03:07.230
Q状态动作二和Q状态动作三｡ 

03:07.230 --> 03:13.710
我们将生成一个关于这三个Q值的概率分布｡ 

03:13.710 --> 03:18.900
也就是说, 第一个Q值有一个概率, 第二个Q值有一个概率,

03:18.900 --> 03:22.590
第三个Q值有一个概率｡

03:22.590 --> 03:25.230
这三个概率加起来等于1｡ 

03:25.440 --> 03:33.420
所以我们将用软最大值来做这一切, 软最大值将把大概率归因于最高的Q值｡

03:33.570 --> 03:41.220
这就是为什么self max的替代方法是简单的max, 直接取Q值的最大值｡

03:41.220 --> 03:44.640
但在这种情况下, 我们不探索其他行动｡ 

03:44.850 --> 03:51.690
多亏了这些概率, 我们可以用一个温度参数来探索其他地方, 我们很快就会看到｡

03:51.990 --> 03:55.740
我们仍然可以通过配置此温度参数来探索它们｡ 

03:55.770 --> 04:03.060
这就是为什么一般来说, 对于深度学习, 我强烈建议使用soft max而不是简单的arg max｡

04:03.240 --> 04:05.130
好的, 我们来实现软最大化｡ 

04:05.130 --> 04:10.980
因此, 正如你们所理解的,

04:10.980 --> 04:20.160
由于Soft Max返回了三个可能行为的三个Q值中的每一个的概率, 那么, 我们要创建的第一个变量是probs, 当然是指这些概率｡

04:20.160 --> 04:22.080
所以道具等于｡ 

04:22.080 --> 04:24.660
现在我们来看看软极大函数｡ 

04:24.810 --> 04:27.930
根据你的说法, 我们要从哪里拿呢？

04:28.050 --> 04:29.490
好吧, 当然了｡ 

04:29.490 --> 04:35.730
请记住, 我们导入了torch dot和dot功能子模块, 我提醒一下,

04:35.730 --> 04:39.630
这是包含了实现神经网络的大多数操作的模块｡

04:39.630 --> 04:40.830
我们给了它捷径｡ 

04:40.830 --> 04:46.920
这就是我们要从这个函数子模块中得到的self max函数｡ 

04:47.070 --> 04:56.010
但是因为我们给了它一个捷径f, 所以我们从一个F表示的泛函开始, 从这个泛函中我们得到软极大函数｡

04:56.010 --> 04:56.730
在这里｡ 

04:56.730 --> 04:57.990
这是第一个｡ 

04:57.990 --> 04:59.250
和括号｡ 

04:59.580 --> 05:00.030
好吧, 我会的

05:00.030 --> 05:03.840
现在我们需要在这个self max函数中输入什么呢？

05:03.840 --> 05:09.900
当然, 这就是我们想要生成概率分布的实体｡ 

05:09.900 --> 05:11.400
这些实体是什么？

05:11.400 --> 05:13.590
当然, 这些是Q值｡ 

05:13.590 --> 05:16.710
现在的问题是, 我们如何得到Q值？

05:16.710 --> 05:20.970
当然, Q值是神经网络的输出｡ 

05:20.970 --> 05:24.420
为了得到这些神经网络的输出, 好了, 我们开始吧｡ 

05:24.420 --> 05:26.880
我们需要神经网络｡ 

05:26.880 --> 05:30.420
但事实上, 我们已经有了它, 因为这就是｡ 

05:30.910 --> 05:41.350
在init函数中初始化我们创建了self点模型, 它就是我们的神经网络, 因为它是网络类的一个对象｡

05:41.350 --> 05:42.600
所以这是完美的｡ 

05:42.610 --> 05:48.970
我们可以把我们的模型放在这里, self max把这个模型应用到输入状态, 这是这里的参数,

05:48.970 --> 05:52.870
它会返回我们要找的输出｡

05:52.900 --> 05:54.280
这就是Q值｡ 

05:54.280 --> 06:00.730
所以现在你的直觉, 为什么我们必须把这个模型引入到init函数中, 可能会更好｡

06:00.730 --> 06:06.550
对于那些从面向对象编程开始的人来说, 你会看到这一切都会变得很自然｡

06:06.940 --> 06:08.680
那么自我最大化｡ 

06:08.680 --> 06:16.660
所以我们用self点模型, 因为这一定是我们在这里创建的对象的模型｡ 

06:16.990 --> 06:23.860
但是我们需要得到神经网络模型的输出, 所以我们要在这里加上一些括号, 我们要在其中输入well,

06:23.860 --> 06:30.340
这里的输入状态称为state｡

06:30.340 --> 06:37.690
所以我们一开始要做的是进入状态, 但现在我们必须小心一些｡ 

06:37.690 --> 06:43.930
现在状态看起来是一个简单的状态, 但记住状态实际上是一个火炬张量,

06:43.930 --> 06:51.040
因为稍后我们会用这个无自态, 把它作为选择作用函数的自变量,

06:51.040 --> 06:57.280
这里的状态自变量实际上会变成这个无自态｡

06:57.430 --> 07:02.590
因为这是一个火炬张量, 模型会接受它, 所以没问题｡ 

07:02.590 --> 07:04.720
但现在我们可以改进算法了｡ 

07:04.870 --> 07:08.290
正如你所理解的, State是一个火炬张量｡ 

07:08.290 --> 07:15.250
正如我们之前所说的, 大多数传感器都被包装到一个变量中, 这个变量也包含一个梯度｡ 

07:15.430 --> 07:22.540
所以现在我们要做的第一件事就是把这个输入状态, 一个张量, 包装成一个火炬变量｡ 

07:22.570 --> 07:27.910
但由于这是输入状态, 所以不会有什么区别｡ 

07:27.910 --> 07:33.610
在计算中, 我们将不使用该状态向变量的梯度｡ 

07:33.610 --> 07:42.700
所以我们现在要做的是, 把火炬张量状态, 转化成火炬变量｡ 

07:44.670 --> 07:45.480
就像这样｡ 

07:45.600 --> 07:52.320
但是, 为了说明, 我们不希望在PN模块的所有计算的图中出现梯度｡

07:52.320 --> 07:57.660
我们在这里加一句, volatile等于true.

07:57.930 --> 08:03.120
所以现在我们把火炬张量状态转化为火炬变量｡ 

08:03.210 --> 08:10.500
但是由于这个volatile equals true参数,

08:10.500 --> 08:16.380
我们不会把与这个输入状态相关的梯度包括到模块的所有计算的图中｡

08:16.650 --> 08:18.390
这是另一个技术诀窍｡ 

08:18.390 --> 08:22.920
这将为我们节省一些内存, 从而提高性能｡ 

08:22.920 --> 08:27.690
所以我强烈建议你这样做, 现在我们要添加一些更有趣的东西｡ 

08:27.690 --> 08:30.600
它是关于我刚才提到的温度参数｡ 

08:30.600 --> 08:39.960
所以这个温度参数是一个参数, 它可以让我们调整神经网络如何确定它应该决定采取什么行动｡

08:39.960 --> 08:49.500
所以这个温度参数会是一个正数, 它越接近零, 神经网络在玩一个动作时就越不确定｡

08:49.500 --> 08:56.400
而这个温度参数越高, 神经网络就越能确定它决定要采取的行动｡

08:56.670 --> 09:05.100
为了添加此参数, 我将输出（即cue值）乘以此温度参数｡

09:05.250 --> 09:13.230
比如说, 从7开始, 我在这里指定一个小注释T等于7.

09:13.350 --> 09:17.010
这就是我设置的温度参数, 等于7｡ 

09:17.010 --> 09:22.320
我们会尝试其他的, 但我只想从一个小的开始, 因为你会看到这个小的.

09:22.320 --> 09:25.680
我们的车还是会像昆虫一样｡ 

09:25.680 --> 09:30.180
但是通过增加这个温度参数, 我们的代码看起来会更像一辆汽车｡ 

09:30.180 --> 09:33.990
此外, 电池驱动会更好｡ 

09:34.200 --> 09:41.670
这是有意义的, 因为温度参数越高, Q值获胜的概率就越高｡

09:42.000 --> 09:49.410
因为, 例如, 如果我们有Q值的软最大值, 让我们取一些简单的数字｡ 

09:49.410 --> 09:51.660
一, 二, 三, 一, 二, 三

09:52.020 --> 10:00.930
例如, 如果1到3的填充最大值等于0｡  04, oh点11和0｡  85.

10:01.020 --> 10:07.260
然后再升高温度, 现在温度等于1.

10:07.350 --> 10:10.320
通过取一个更高的温度, 比如说, 2｡ 

10:10.350 --> 10:11.910
太软了｡ 

10:13.020 --> 10:15.810
我们把这个复制一下, 然后乘以｡ 

10:15.810 --> 10:23.940
例如, 两个或三个填充的Mac具有相同的Q值, 但乘以此温度参数3｡

10:24.060 --> 10:30.900
我们会得到第一个Q值为零的结果, 因为这个概率非常低｡ 

10:30.930 --> 10:39.180
所以第二个概率是0, 然后是很小的, 因为这个概率还是很低的.

10:39.180 --> 10:48.810
比如说, 0｡ 

10:48.810 --> 10:54.420
但是第三个概率是最大的, 也是相当高的,

10:54.420 --> 11:00.600
通过提高温度, 这个概率会更大因为我们会更确定这是对应于我们必须采取的行动的正确Q值.

11:00.600 --> 11:05.340
因此这将是一个类似于98点的数字｡ 

11:05.760 --> 11:11.760
现在通过增加温度参数,

11:11.760 --> 11:19.530
我们现在更加确定第三个动作应该是要进行的动作, 因为这个动作的Q值的概率不仅是最大的, 而且非常高｡

11:19.560 --> 11:22.470
这就是这个温度参数的意义所在｡ 

11:22.470 --> 11:26.880
这是关于我们应该决定采取哪种行动的确定性｡ 

11:27.180 --> 11:27.510
好吧, 我会的

11:27.510 --> 11:29.340
所以我要删除这条评论｡ 

11:29.340 --> 11:30.720
这只是解释｡ 

11:30.990 --> 11:33.150
现在开始行动吧｡ 

11:33.240 --> 11:35.310
那我们要怎么做呢？

11:35.310 --> 11:46.080
软最大值法的原理不仅是为每个Q值生成一个概率分布, 而且这是软最大值法的第二步｡

11:46.170 --> 11:51.630
我们从这个分布中随机抽取一个, 以获得我们的最终行动｡ 

11:51.780 --> 11:57.240
当然, 我们将有很大的机会得到对应于具有最高概率的Q值的动作,

11:57.240 --> 12:01.050
因为这正是分布的工作原理｡

12:01.500 --> 12:02.400
好了, 我们走吧｡ 

12:02.400 --> 12:03.930
我们开始行动吧｡ 

12:03.930 --> 12:07.860
所以我们要引入一个新的变量, 我们称之为动作｡ 

12:08.610 --> 12:17.160
这个动作是随机抽取我们之前在这条线上创建的概率分布｡

12:17.250 --> 12:19.980
那么, 我们如何获得这样一个随机抽奖呢？

12:19.980 --> 12:24.270
我们要计算每个Q值的概率｡ 

12:24.270 --> 12:32.160
我们先取props, 然后取点, 然后我们使用多名义函数,

12:32.160 --> 12:35.940
这样我们给予可以从props分布中随机抽取｡

12:35.940 --> 12:36.840
就这样了

12:36.840 --> 12:38.310
这就是我们行动的动力｡ 

12:38.310 --> 12:39.210
好极了｡ 

12:39.210 --> 12:44.580
当然, 现在我们要返回这个动作, 这里有一个小技巧｡ 

12:44.580 --> 12:51.300
事实上, 这个支持multiannual返回pytorch变量, 带有一个假的批,

12:51.300 --> 12:57.270
你知道这个假的维对应于批, 因此要得到我们想要的正确结果,

12:57.270 --> 13:00.390
那就是操作01或02｡

13:00.630 --> 13:08.490
我们只需要在这里加上数据, 然后加上一些括号, 我们要找的动作, 01或02,

13:08.490 --> 13:12.840
包含在索引中｡

13:13.410 --> 13:13.920
好吧, 我会的

13:13.920 --> 13:14.640
好了

13:14.640 --> 13:16.590
现在我们有我们的行动｡ 

13:16.740 --> 13:22.200
多亏了这个选择动作功能, AI现在可以知道每次要玩哪个动作｡ 

13:22.560 --> 13:23.370
好极了｡ 

13:23.370 --> 13:27.300
现在我们可以继续下一个函数, 也就是学习函数｡ 

13:27.300 --> 13:32.610
我们将在这里训练整个神经网络, 使用所有的前向传播,

13:32.610 --> 13:35.670
然后使用随机梯度下降法进行反向传播｡

13:35.670 --> 13:43.170
嗯, 基本上我们将实施深度学习模型的整个训练, 这是我们人工智能的核心｡

13:43.170 --> 13:44.610
所以我等不及要这么做了｡ 

13:44.610 --> 13:49.260
这将是一个令人兴奋的教程, 所以我会在下一个教程中看到你｡ 

13:49.260 --> 13:50.520
在那之前, 好好享受吧｡ 

13:50.520 --> 13:51.000
一､ 
