最近在pytorch中使用的非常频繁。下面介绍一些pytorch中常用的张量运算。张量和数组之间的转换A=t.ones(3,4)#torch.tensor->numpy.ndarrayB=A.numpy()#numpy.ndarray->torch.tensorC=t.from_numpy(B)#注意:#A、B、C共享内存,修改其中任何一个,三者同时改变。#张量和数组的转换会很快从张量中取值A=t.ones(5)#B仍然是张量,只包含一个元素,也称为ScalarB=A[2]#Onlyatensorcontainingoneelement可以使用item函数#item返回的值就是值V=B.item()普通张量创建方法Tensor(sizes)基本构造函数tensor(data,)类似于np.arrayones(sizes)的构造函数all1Tensorzeros(sizes)all0Tensoreye(sizes)对角线为1,其他为0arange(s,e,step)从s到e,步长为steplinspace(s,e,steps)从s到e,均匀分为步骤rand/randn(*sizes)uniform/standarddistributionnormal(mean,std)/uniform(from,to)normaldistribution/uniformdistributionrandperm(m)随机排列如何复制数据#1.使用t.tensor()A=t.ones(5)#将A的数据复制到BB=t.tensor(A)#此时A和B不共享内存In[14]:id(A),id(B)Out[14]:(1751028332080,1751295611024)#2.使用克隆函数In[15]:c=A.clone()In[16]:id(A),id(c)Out[16]:(1751028332080,1751295519912)inplaceoperation#注意:#在pytorch中,所有以下划线结尾的函数#都会修改Tensor本身,如add_、t_、sub_等。在[18]中:A.cos_()Out[18]:tensor([[0.5403,0.5403,0.5403,0.5403],[0.5403,0.5403,-0.6536,0.5403],[0.5403,0.5403,0.5403,0.5403]])In[19]:A.add_(2)Out[19]:张量([[2.5403,2.5403,2.5403,2.5403],[2.5403,2.5403,1.3464,2.5403],[2.5403,2.5403,2.5403,2.5403]])In[20]:AOut[20]:tensor([[2.5403,2.5403,2.5403,2.5403],[2.541.03,4,2.5403],[2.5403,2.5403,2.5403,2.5403]])使用cuda#如果支持gpu,则使用gpuDevice=t.device("cuda"if.cuda.is_available()else"cpu")#将tensor转为In指定的device,x=x.to(device)y=y.to(device)增维和降维(unsqueeze/squeeze)#1.在指定位置添加一个新维度->unsqueezeIn[22]:A.shapeOut[22]]:torch.Size([2,1,4])#在A的第一个维度之前插入一个新的维度In[23]:B=A.unsqueeze(0)In[24]:B.shapeOut[24]:torch.Size([1,2,1,4])#在A的第三个维度之前插入一个新的维度In[25]:B=A.unsqueeze(2)In[26]:B.shapeOut[26]:torch.Size([2,1,1,4])#2.去掉指定位置的维度->unsqueeze#注意:一个维度中只能移除一个元素#移除B维度的第二部分In[27]:C=B.squeeze(1)In[28]:C.shapeOut[28]:torch.Size([2,1,4])#如果不指定参数,则除B以外的元素都将被移除维度DegreeIn[29]:C=B.squeeze()In[30]:C.shapeOut[30]:torch.Size([2,4])交换维度/改变维度顺序(transpose/permute)#1.transpose一次只能改变二维的位置。In[33]:B.shapeOut[33]:torch.Size([2,1,1,4])#交换B的第一维和第二维,B与C共享内存In[34]:C=B.transpose(0,1)In[35]:C.shapeOut[35]:torch.Size([1,2,1,4])#2.Permute可以同时改变多个维度的位置#重新调整B的维度顺序In[36]:B.shapeOut[36]:torch.Size([2,1,1,4])In[37]:C=B.permute(1,2,0,3)In[38]:C.shapeOut[38]:torch.Size([1,1,2,4])获取最大/最小值(max/min)In[42]:A=t.rand(7,4)#max函数返回指定维度的最大值和最大值的位置In[43]:t.max(A,0)Out[43]:torch.return_types.max(values=tensor([0.7347,0.9382,0.8176,0.9182]),indices=tensor([4,6,3,0]))#min函数类似于#...逻辑函数t.any和t.all#在pytorch中,all和any只支持uint8和bool类型张量#在numpy中,所有数值类型和bool类型数组都支持逻辑运算在[52]中:A=t.randint(0,5,(5,4)).type(t.uint8)In[53]:AOut[53]:张量([[0,4,1,3],[0,0,4,1],[3,0,2,1],[0,0,1,1],[2,0,1,4]],dtype=torch.uint8)#1.all沿着指定维度,只要有一个错误的(0),即False(0)In[54]:A.all(0)Out[54]:tensor([0,0,1,1],dtype=torch.uint8)#2.任意沿指定维度,只要有一个True(1),就是True(1)In[55]:A.any(0)Out[55]:tensor([1,1,1,1],dtype=torch.uint8)创建网格(meshgrid)#t.meshgrid第一个参数代表列,第二个参数代表行#正好和numpy相反>>>a,b=t.meshgrid(t.arange(5),t.arange(5))>>>atensor([[0,0,0,0,0],[1,1,1,1,1],[2,2,2,2,2],[3,3,3,3,3],[4,4,4,4,4]])>>>btensor([[0,1,2,3,4],[0,1,2,3,4],[0,1,2,3,4],[0,1,2,3,4],[0,1,2,3,4]])repeat(重复)重复操作到copythedata#In[63]:A=t.rand(3,2)#指定A的第一个维度重复两次,第二个维度重复两次In[64]:A.repeat(2,2)Out[64]:张量([[0.4932,0.4790,0.4932,0.4790],[0.2069,0.9966,0.2069,0.9966],[0.8775,0.1757,0.87757],[0.4932,0.4790,0.4790],9[0.4790],9[0.4790],0.20690]0.2069,0.9966],[0.8775,0.1757,0.8775,0.1757]])扩展维度(expand)的大小和repeat类似,都可以实现维度大小的扩展但需要注意的是,注意:expand并不是复制新的数据,而是在原有数据的基础上创建视图。所以在修改源张量的时候,会同时修改已有的张量In[20]:aOut[20]:tensor([[0.2521,0.1678,0.4995,0.5533]])#将第一维扩展为2,第二个维度扩展为4In[21]:b=a.expand(2,4)In[22]:bOut[22]:tensor([[0.2521,0.1678,0.4995,0.5533],[0.2521,0.1678,0.4995,0.5533]])#修改b也会修改aIn[23]:b[1,3]=3In[24]:aOut[24]:tensor([[0.2521,0.1678,0.4995,3.0000]])In[25]:bOut[25]:tensor([[0.2521,0.1678,0.4995,3.0000],[0.2521,0.1678,0.4995,3.0000]])条件查找(where)#1.根据条件修改值In[63]:A=t.rand(3,2)#where(condition,x,y)#如果满足条件则返回x,不满足则返回y#torch.where和numpy.where的区别在于参数xin#torch.where,y要求为tensorIn[72]:B=t.where(A>5,t.tensor([10]),t.tensor([0]))In[73]:BOut[73]:tensor([[10,0,0,0],[0,0,10,0],[0,0,10,10],[10,10,10,0],[10,0,10,10]])#2.获取满足条件的索引In[81]:t.where(A>4)Out[81]:(tensor([0,1,2,2,3,3,3,4,4,4,4]),张量([0,2,2,3,0,1,2,0,1,2,3]))In[82]:AOut[82]:张量([[8,2,3,2],[1,4,8,0],[4,0,9,9],[8,9,7,4],[9,5,8,7]])截断(clamp)#和torch.where功能类似,但是功能没有where丰富#torch.clamp(input,min,max,out=None)#对于input的所有值,从min和max两个位置截断#如果值小于min,设置为min;如果大于max的值设置为maxIn[82]:AOut[82]:tensor([[8,2,3,2],[1,4,8,0],[4,0,9,9],[8,9,7,4],[9,5,8,7]])#设置A中小于5的值为5,大于8的值为8[83]中:t.clamp(A,5,8)Out[83]:张量([[8,5,5,5],[5,5,8,5],[5,5,8,8],[8,8,7,5],[8,5,8,7]])Combination(stack/cat)#1.栈在一个新的维度上拼接,张量对应的维度必须相同In[97]:B=t.rand(3,4)In[98]:C=t.rand(3,4)#在第一个维度前添加一个新维度,在新维度上拼接In[99]:t.stack([B,C],1).shapeOut[99]:torch.Size([3,2,4])#2.猫在现有维度上拼接#在第一个维度上拼接In[107]:t.cat([B,C],0).shapeOut[107]:torch.Size([6,4])gather在one-hotencoding的处理中经常使用到根据维度索引取值.在[2]中:a=t.rand(3,4)在[3]中:aOut[3]:tensor([[0.6875,0.7594,0.4874,0.0156],[0.6033,0.8766,0.3650,0.7240],[0.3139,0.4568,0.8455,0.9149]])#在第二个维度上,取出index为(1,2,0)的值,#注意:除dim维度外,其他维度的index必须与a一致。比如dim=1,那么除了第一个维度,其他维度必须一致#输出维度与索引维度一致#index->[3,1],a->[3,4]In[4]:a.gather(dim=1,index=t.tensor([[1],[2],[0]]))Out[4]:tensor([[0.7594],[0.3650],#index->[1,4],a->[3,4]In[10]:a.gather(dim=0,index=t.tensor([[1,2,0,0]]))Out[10]:tensor([[0.6033,0.4568,0.4874,0.0156]])按维度索引分散设置值>>>atensor([[1,2,6,5],[6,7,9,0],[7,8,3,1],[2,8,0,6]])#指定要操作的张量的维度>>>dim=1#需要填充的值>>>val=0#indexisoutsideofdim维度需要保持一致>>>index=t.tensor([0,1,2,1]).unsqueeze(1)#可以看到,a[0,0],a[1,1],a[2,2]和a[3,1]修改为val>>>a.scatter(dim,index,val)tensor([[0,2,6,5],[6,0,9,0],[7,8,0,1],[2,0,0,6]])#既然可以设置指定的值,那么是否可以设置指定的张量呢?答案是肯定的#比如也可以这样,val和索引的维度一致>>>val=t.randint(10,100,(4,))>>>valtensor([59,39,76,99])>>>a.scatter(dim,index,val)张量([[59,2,6,5],[6,39,9,0],[7,8,76,1],[2,99,0,6]])scatterinlabelsmoothandlabeltransfer经常用到onehot矩阵,功能很强大
