大家好, 欢迎学习本Python教程｡
好了, 我们还有最后一个函数要在重放内存类中实现｡
这是一个简单的函数｡
当然, 这是为了从我们的记忆中随机抽取一些样本｡
因此, 这个函数将返回这些随机样本｡
好吧, 我会的
所以让我们来实现它｡
我们要称之为样品｡
我们走吧｡
这个函数接受两个参数作为输入｡
第一个人, 像往常一样, 自我｡
我们的重播内存类的未来对象｡
第二个论点是, 你能猜猜看吗？
我们要取一些样品, 尺寸是固定的, 因此我们需要为样品选择一个尺寸｡
更准确地说, 我们称之为批量大小｡
这就是我们要给予第二个参数命名的, 批大小｡
好了
我们有了两个参数, 现在可以实现示例函数了｡
所以现在我只想警告你们, 这会有点技术性, 但我会尽我所能解释｡
我们将从创建samples变量开始｡
这只是一个包含内存样本的变量｡
好吧, 我会的
所以样本相等｡
那么现在我们要怎么得到这些样本呢？
首先, 我们要提取记忆, 因为我们从记忆中提取样本.
然后, 我们可能需要批量, 因为我们想要获得的样本包含批量元素｡
所以我们需要内存, 需要批处理大小, 然后我们需要一些PyTorch或Python技巧来获得这些样本的良好格式｡
我接下来要做的是, 写好这行代码, 然后一个元素一个元素地解释.
那就开始吧｡
我从一个zip函数开始｡
我很快就会解释它的作用｡
在这个zip函数里面, 我会加一个星星｡
我也要扩展一下｡
星星和随机点样本｡
正如你可能已经猜到的, 我们在这里导入的随机库是随机的｡
所以这就是我们必须导入这个随机库的主要原因, 因为我们是随机抽取样本的｡
在这个随机库中, 我们将使用sample函数｡
这是变量, 这是函数.
所以我要加一些括号｡
现在你可以看到, sample是一个函数, 我们必须输入一些参数｡
正如你所看到的, 第一个论证是self｡
实际上说到self, 这对应于self内存, 未来实例的内存, 重放内存类的对象｡
所以我要在这里加上这个记忆｡
第二个参数是, 你们可能已经猜到了, 我们要从内存中随机抽取的批大小,
我们给它取了一个名字, 叫做批大小.
第二个参数是批处理大小｡
好吧, 我会的
这行代码已经输入好了, 现在我来解释一下它的作用.
首先, 使用这个随机样本函数, 我们从内存中随机抽取一些样本,
这些样本的批量大小是固定的｡
所以这是可以理解的｡
但是这个zip存储函数有什么作用呢？
这并不神秘｡
它就像一个重塑功能｡
比如说, 我在这里加一个common来解释我将要删除它｡
比如说, 我们有一个包含以下元素的列表｡
例如, 首先是一, 二, 三, 然后是第二个元素, 四, 五, 六｡
所以我们有一个三个元素的两个元组的列表, 一, 二, 三和四, 五, 六｡
那么如果我用一个带星星的zip函数, 它会变成什么呢？
所以zip星星list将等于一个新的list, 但是形状不同｡
这个不同的形状是一个四, 然后是二, 三, 然后是五, 六｡
好吧, 我会的
所以这就是它的作用｡
它只是重塑了你的清单｡
好吧, 我会的
既然你已经了解了这个zip星星列表的作用, 那么, 现在让我们来解释一下为什么我们必须这样做｡
正如你们所理解的, 我们要把事件添加到记忆中, 这些事件有形式, 首先是状态,
然后是行动, 最后是奖励｡
但是对于我们的算法, 我们不需要这种格式｡
实际上, 我们希望我们的样本具有以下格式, 该格式由三个样本组成, 一个样本用于状态,
一个样本用于动作, 一个样本用于奖励｡
举个例子, 我们假设1到3是状态1, 动作1, 奖励1, 然后状态到动作,
奖励2｡
我们需要的是, 每一批一个状态一个行动二个行动一个第三批奖励一.
我们只有两个人｡
这正是我们接下来要考虑的格式, 因为我们会将这些批处理包装到PyTorch变量中｡
记住, python变量是一个同时包含张量和梯度的变量｡
为了能够对张量进行微分, 为了能够对张量进行微分,
我们需要一个包含张量和梯度的变量结构｡
再说一遍, 这就是PyTorch的工作原理｡
总结一下, 我们为每个状态, 动作和奖励创建一个批处理,
然后我们将把这些批处理分别放入一些PyTorch变量中, 每个变量都将得到一个梯度,
这样我们最终就可以区分它们｡
好吧, 我会的
这就是这个函数的目的｡
所以让我删除这条评论｡
现在我们唯一要做的就是把样品还回去｡
所以正如我刚才解释的, 我们不能直接返回样本, 原因很简单,
我们想把样本放入PyTorch变量中｡
为了对每一个样本都这样做,
我们将使用映射函数, 这个映射函数将从样本映射到包含张量和梯度的触摸变量｡
如你所见, 这个map函数有几个参数｡
第一个参数是一个函数, 该函数将把样本转换为一些示教变量｡
第二个参数是我们要应用这个函数的对象｡
这就是这个函数的参数｡
那么, 它会是什么呢？
这当然是样品｡
这里的第二个参数是样本, 然后我们定义要应用每个样本的函数｡
为了定义一个函数, 我们需要先给予它命名, 我们称之为Lambda｡
这只是一个名字, 先给lambda, 然后给x, 它是这个函数的变量｡
这就是我给变量起的名字, 然后是冒号.
并给予了该函数的表达式｡
这就是我们希望lambda函数返回的结果｡
所以它应该是, 它应该是一个可以转换或者采样到火炬变量的东西｡
为了做到这一点, 我们已经在之前的教程中提到过, 我们有变量函数｡
变量函数将从火炬张量转换为包含该张量和梯度的变量｡
所以我首先要加的是变量variable, 我会在里面转换X, 因为一旦lambda被应用到样本上,
X就是样本了｡
但这还不是全部｡
还有最后一个技术问题需要解决｡
事实上, 对于包含在样本中的每个批次,
例如, 动作一､ 二､ 三和其他动作的批次,
我们必须相对于对应于状态的第一维将其连接｡
为什么我们要做这样的连接呢？
这只是为了让一切都很好地协调一致｡
也就是说, 在每一行中, 状态､ 动作和奖励对应于相同的时间｡
所以最终我们得到了一个批处理列表, 所有的批处理都是对齐的, 每个批处理都是一个pytorch变量｡
那么, 我们如何进行这种连接呢？
我们需要使用torch库中的cat函数｡
所以我们在这里加上torch, 再加上cat, 适用于X｡
但是在这个cat函数中, 我们需要指定我们要进行连接的维｡
正如我刚才提到的, 这是第一个索引为零的维度｡
我们开始吧｡
我们已经准备好了｡
这个lambda函数将获取样本,
将它们相对于第一维连接起来, 然后最终我们将传感器转换为一些包含传感器和梯度的火炬变量,
这样当我们稍后在这个意义上应用随机网格时, 我们将能够进行微分以更新权重｡
好了, 这个功能准备好了｡
然后这里是map函数的第二个参数, 我们需要指定我们想把这个lambda函数应用到什么上, 也就是我们要去的所有样本上,
我们将把这个lambda函数应用到所有的样本上, 这样最终我们得到一个批处理列表,
每个批处理都是一个pytorch变量｡
好吧, 我会的
所以这是相当技术性的, 但现在至少一切都可以工作了｡
好吧, 我们以后不会再用这种方法了｡
我们只在这里用｡
所以, 如果您不想深入了解这里的技术细节, 那也没关系｡
您可以复制这三行代码来对内存进行采样｡
如果你想用PyTorch做一个人工智能, 那就如你所愿｡
但现在好消息是, 我们已经完成了这个回放内存类体验回放现在已经实现, 我们可以进入下一个也是最后一个类,
这将是整个深度学习模型｡
所以在这个深度学习模型中, 我们当然会有我们的网络, 它会添加经验, 重放,
然后是深度学习算法的所有其他部分｡
所以这将是一个更大的类｡
我们将创建大约十个函数, 但这只是因为我们是一步一步地做, 这样你就可以更好地理解正在发生的事情｡
所以我迫不及待地要实施我们的深度学习模式｡
在那之前, 好好享受我｡