京东电子商务网站建设,深圳招聘网官方网站,西北电力建设甘肃工程公司网站,成都哪些公司做网站好文章目录 前言数据结构-张量max函数索引函数赋值函数拼接函数 前言
由于不经常动手写代码#xff0c;所以对于python语言中的常见数据结构的用法也不是很熟悉#xff0c;对于pytorch中的数据结构就更加不熟悉了。之前的代码基础是基于C语言的#xff0c;属性都是自己定义所以对于python语言中的常见数据结构的用法也不是很熟悉对于pytorch中的数据结构就更加不熟悉了。之前的代码基础是基于C语言的属性都是自己定义值传递或者引用传递都是自己定义而在python中就没有区分的这么清楚所以让我对一些概念或者数据结构用法存在疑惑尤其是使用pytorch的过程中所以专门做个笔记。
ChatGPT有句话说的很好“小心使用以确保结果符合您的预期。”为了确保结果符合我们心中的预期所以在编写代码的过程中需要对每个函数的输入与输出进行验证而在每个函数中我们又使用了别的API函数层层嵌套所以我们要想验证一个函数的输入输出符合预期就需要对输入输出进行验证。每一步都是为了结果符合预期。
数据结构-张量
max函数
torch.max函数对于一个二维张量size(a,b)的效果为
torch.max(next_q_values,dim1)
#返回值
torch.return_types.max(
valuestensor([0.1055, 0.0693, 0.1055, 0.1071, 0.0456, 0.0544, 0.0671, 0.0859, 0.0946,0.0770]),
indicestensor([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]))
#后面加上索引1
torch.max(next_q_values,dim1)[1]
#结果
tensor([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])也就是说torch.max函数当参数dim为多少时它的取极大值的过程就是针对这个维度进行的让其他维度保持不变的情况下取max然后让其他维度递增再取max。
索引函数
对于张量来说索引加括号与不加括号差别也很大。使用加括号的形式叫做花式索引花式索引Fancy Indexing是一种在NumPy和其他类似的数组库比如Pytorch中常见的索引方式它允许您使用一个数组来索引另一个数组的元素。常见的索引方式就是给每个维度赋值然后索引D[a,b]花式索引就是在每个维度的位置上用数组来赋值D[[ ],[ ]]可以把第一个维度当作希望生成的形状并且把对应元素的行标上去然后第二个维度的形状不用发生变化只用把对应元素的列标上去即可比如说我们想从原始数据中生成一个新的数组尺寸为(2,3)新数组B中各个位置的元素与原数组A的关系为 那么我们可以使用如下的命令A[[[2,1,2],[1,0,0]],[[1,1,2],[1,2,1]]]。注意我们的索引第一个维度就是每个元素所对应的行的重新排列索引的第二个维度就是每个元素所对应的列的重新排列。同时需要注意这种索引形式得到的值都是相当于值引用。如果我们对索引出来的值进行赋值操作就会导致原来数组中的元素发生变化因为它就相当于索引赋值。
提起索引不得不提到Python中臭名昭著的赋值语句赋值语句时常让我迷惑他究竟是值传递还是引用传递。目前看来只有整数和浮点数数据类型是值传递其他的一律是引用传递哪怕是GPT宣称列表也是值传递也是假的列表也是引用传递。比如 对于非整数或者浮点数的合成数据类型就更是引用传递了哪怕是torch.tensor(1)也是引用传递。 对于Pytorch中的张量数组来说也是这样
btorch.tensor([[1.1,2.2,3.3,4.4],[0.1,0.2,0.3,0.4],[-1,-2,-3,-4]])
print(b[0,1].shape)
#结果 torch.Size([])
print(b[[0],[1]].shape)
#结果 torch.Size([1])
print(b[[0,1],[1,0]].shape)
#结果 torch.Size([2])其实引用传递往往要与原地修改相辅相成如果两个变量是同一引用但是其中一个变量修改的时候并不是原地修改就不会导致另一个变量发生同步变化。所以要想同步改变我们就要使用原地修改。
原地修改的常见类型有索引赋值简写递推、-、*、/等。
如果我们不希望同步变化那么我们有两种办法第一不使用引用或者说使用引用克隆第二不使用原地修改对于指向同一引用的对象在更新对象的值时不使用原地修改的函数。第二种方法稍微难做一点因为我们在pytorch中处理张量数据时很容易就会对张量进行索引赋值而这种方式恰恰是会造成原地修改的也就是会导致同步变化的。所以在保存变量时尽量保存变量的克隆这样就会避免同步变化。
在pytorch中不使用引用可以分为两种情况。第一种是不保存梯度的detach()方法但是数据区共享所以还是有引用的只不过没有梯度了第二种数据区也不共享梯度也不保存的是clone()方法数据区不共享梯度应该也不会受到影响。可以是
赋值函数
赋值函数或者可以叫做索引函数毕竟是先找到位置才能进行赋值的。对于张量来说对第一个维度进行索引就会得到第一个维度所对应的那些数据。如果我们在两个维度都用列表来索引得到的就是单个元素所拼接的张量 对于一个二维张量size(a,b)相对其中某些位置上的元素进行赋值的操作为
target_q_values[range(batch_size),actions]rewards0.9*(1-dones)*torch.max(next_q_values,dim1)[0]其实为了分清楚究竟是引用传递还是值传递我们应该用这样的提示词进行搜索python中数组的原地修改的操作有哪些python中numpy数组的原地修改的操作有哪些pytorch的tensor张量的原地修改操作有哪些 以下是chatGPT的回答 在PyTorch中张量tensor是核心数据结构提供了许多原地修改的操作。以下是一些常见的原地修改操作 索引赋值运算 直接对张量的元素进行赋值操作会原地修改张量。 import torchmy_tensor torch.tensor([1, 2, 3])my_tensor[0] 4 # 原地修改不创建新对象add_()、sub_()等方法 类似于赋值运算这些方法在原地执行加法、减法等操作。 import torchmy_tensor torch.tensor([1, 2, 3])
my_tensor.add_(1) # 原地修改不创建新对象等价于
my_tensor 1 mul_()、div_()等方法 类似于add_()这些方法在原地执行乘法、除法等操作。 import torchmy_tensor torch.tensor([1, 2, 3])
my_tensor.mul_(2) # 原地修改不创建新对象zero_()方法 将张量所有元素设为零。 import torchmy_tensor torch.tensor([1, 2, 3])
my_tensor.zero_() # 将所有元素设为零原地修改fill_()方法 将张量所有元素填充为指定值。 import torchmy_tensor torch.tensor([1, 2, 3])
my_tensor.fill_(5) # 将所有元素填充为5原地修改这些方法都是在原地修改PyTorch张量而不是创建新的张量对象。原地操作可以有效地减少内存开销并提高代码的执行效率。
所以在代码中我们需要注意哪些是引用传递对然后注意引用传递对中变量的运算是不是原地修改如果不是就需要再修改。
拼接函数
拼接函数torch.cat作用是把列表list中的张量按照第一个维度拼在一起。不论列表中第一个张量的第一个维度是多少拼接的时候总是在第一个张量的第一个维度后拼接按照顺序每个张量的第一个维度的值都是累加的。