Pytorch常用函数之一_数据类型

编程语言和自然语言一样,不理解的词越多,对全文的理解就越差。掌握必要的基础知识,让后期看代码更加流畅。

机器学习需要掌握数据处理工具Pandas、Numpy,同理,深度学习也需要掌握相应的工具,在Pytorch中数据存储在Tensor之中,本篇将介绍它们的基本用法以及与之相关的常用函数。

查看版本信息

包含头文件

1.  import torch  

1.查看torch版本

1.  print(torch.__version__)  

2.查看CUDA版本

1.  print(torch.version.cuda)  

GPU相关操作

1. 查看当前是否支持GPU

1.  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')  

2.GPU相关的数据转换

1.  a = torch.Tensor([5])  
2.  b = a.to('cuda') # 转成在 GPU 上运行的类型  
3.  b = a.cuda() # 同上  
4.  c = b.to('cpu') # 转成在 CPU 上运行的类型  
5.  c = b.cpu() # 同上  

3. 查看GPU状态

1.  print(torch.cuda.device_count()) # 查看可用 GPU 个数  
2.  print(torch.cuda.current_device()) # 查看当前使用的 GPU ID  
3.  print(torch.cuda.get_device_capability(0)) # 查看 ID 为 0 的 CUDA 容量  
4.  print(torch.cuda.get_device_name(0)) # 查看设备名

4. 清空GPU缓存

1.  print(torch.cuda.empty_cache()) # 清空缓存  

Tensor

Tensor用于表示矩阵(多维数据),类似Numpy的ndarray,它可以使用GPU加速。从Pytorch 0.4.0之后,Variable与Tensor合并(Variable仍存在,但很少使用)。
创建Tensor时参数requires_grad默认为False,若设为True,则可实现自动求导的功能,梯度保存在其内部变量grad中,计算梯度的方法存储在grad_fn中。

1.生成Tensor

用Tensor方法将其它格式数据转换成张量,转换内容一般是list或数组格式:

1.  a = torch.Tensor([[1,2],[3,4],[5,6]]) # 生成 3,2 维Tensor    
2.  b = torch.zeros(3,5) # 生成内容为全0的 3,5 维Tensor    
3.  c = torch.rand(3,5) # 生成内容为 0-1 随机数的 3,5 维Tensor    
4.  d = c.clone() # 将c中内容复制到 d, 新旧内容指向不同的地址空间  

2.修改Tensor
用赋值的方法即可修改张量,比如将上面生成张量中位置1,1的元素赋值成50。

1.  a[1,1]=50  

3. 查看Tensor状态
查看Tensor数据类型,大小及元素个数

1.  a = torch.Tensor([5])    
2.  print(a.type()) # torch.FloatTensor,默认类型为FloatTesor     
3.  print(a.size()) # torch.Size([1])    
4.  print(a.shape)  # torch.Size([1])    
5.  print(a.numel()) # 1,查看元素个数  
6.  print(a.dim()) # 1, 查看维度  

4.类型转换
Tensor与其它数据类型相互转换

1.  a = torch.Tensor([5]) # tensor([5.])
2.  b = a.numpy()  # 转换成numpy.array类型 [5.]  
3.  c = a.item() # 转换成单个值 5.0  
4.  d = torch.from_numpy(b)  # 转换成Tensor tensor([5.])  
5.  e = d.int() # 转换成 IntTensor tensor([5], dtype=torch.int32)
6.  f = d.tolist() # 转换成list [5.0]  

维度变换

1.增加维度

在深度学习过程中,现有的数据格式和模型要求的格式往往不同,层与层之间的数据也需要转换后才能对接,维度转换是最常用的方法。
squeeze意为压缩,即去掉维度,unsqueeze则相反,为添加维度。

1.  unsqueeze(input, dim, out=None)   

用于增添第dim维度为1。具体用法见以下示例:

1.  a = torch.Tensor([1,2,3])  
2.  print(a, a.shape)  # tensor([1., 2., 3.]) torch.Size([3])  
3.  b = torch.unsqueeze(a, 1)  
4.  print(b, b.shape)  # tensor([[1.],[2.],[3.]]) torch.Size([3, 1])  
5.  c = torch.unsqueeze(a, 0)  
6.  print(c, c.shape)  # tensor([[1., 2., 3.]]) torch.Size([1, 3])  

2.减小维度

1.  squeeze(input, dim=None, out=None)   

用于删除第dim个维度,如果当前不包括指定的维度,则不会删除。如果不指定dim,函数将删除值为1的维度。
本例中延用上例中的数据:

1.  print(torch.squeeze(c,0))  # tensor([1., 2., 3.])  
2.  print(torch.squeeze(b,1))  # tensor([1., 2., 3.])  
3.  print(torch.squeeze(b))  # tensor([1., 2., 3.])  

3.转换维度
比squeeze和unsqueeze更简单的方法是直接把张量转换成指定维度,使用view函数实现,它类似于numpy的reshape,Tensor也提供reshape方法。

1.  view(*shape)   

将张量转换成指定的形状,示例:

1.  x = torch.Tensor([1,2,3,4])  
2.  print(x.view(2,2))  # tensor([[1., 2.], [3., 4.]])  
3.  print(x.view(1,4))  # tensor([[1., 2., 3., 4.]])  
4.  print(x.view(1,-1)) # 设为-1时自动计算该维度大小 tensor([[1., 2., 3., 4.]])  
5.  print(x.view(4))  # tensor([1., 2., 3., 4.])  

4.cat拼接
cat函数用于在指定维度上拼接多个张量。

1.  cat(tensors, dim=0, out=None)   

将tensors中的多个张量按dim指定的维度拼接成一个张量,拼接后总维数不变。

1.  x = torch.Tensor([[1,2],[3,4]])  
2.  y = torch.Tensor([[5,6],[7,8]])  
3.  print(torch.cat((x,y),0))  
4.  # tensor([[1., 2.],  
5.  #        [3., 4.],  
6.  #        [5., 6.],  
7.  #        [7., 8.]])  
8.  print(torch.cat((x,y),1))  
9.  # tensor([[1., 2., 5., 6.],  
10. #        [3., 4., 7., 8.]])  

一般面对的数据最多三维,并以一两维居多,可将其理解为横向加或者纵向加。

5.stack拼接
与cat拼接不同的是,stack拼接后维度增加,其用法如下:

1.  stack(tensors, dim=0, out=None)  

示例:

1.  x = torch.Tensor([1,2])  
2.  y = torch.Tensor([3,4])  
3.  print(torch.stack((x,y),dim=0))  
4.  # tensor([[1., 2.],  
5.  #         [3., 4.]])  
6.  print(torch.stack((x,y),dim=1))  
7.  # tensor([[1., 3.],  
8.  #         [2., 4.]])  

从输出内容可以看到,拼接后张量变成了两维,dim=0是最常用的方法,它直接把两个张量拼在一起,当dim=1时,拼接时转换了位置。

6.transpose两维度互换

1.  transpose(input, dim0, dim1)  

互换dim0, dim1两个维度,具体用法如下:

1.  x = torch.Tensor([[1,2],[3,4]])  
2.  print(torch.transpose(x,0,1))  
3.  # tensor([[1., 3.],  
4.  #        [2., 4.]])  

7.perumute多维度互换
permute与transpose功能类似,但更加灵活,它可以指定多个维度互换。

1.  x = torch.Tensor([[1,2],[3,4]])  
2.  print(torch.transpose(x,0,1))  
3.  # tensor([[1., 3.],  
4.  #        [2., 4.]])  

用于将张量转换成dim指定的维度。

1.  x = torch.rand(2,3,4)  
2.  print(x.shape, x.permute(2,1,0).shape)  
3.  # torch.Size([2, 3, 4]) torch.Size([4, 3, 2])  

本例先产生了一组3维的随机数,每个维度的元素个数分别是2,3,4,然后使用permute将其第2维转成第0维,第1维不变,第0维转成第2维,从打印信息可以看到各维元素个数的变化。permute常用于对转换图片格式。

8.维度扩展
增加Tensor中元素的个数,其内容与被扩展的内容一致。

1.  a = torch.Tensor([5])  
2.  print(a.expand(1, 2)) # tensor([[5., 5.]])  

求导

下例中使用了torch.tensor而非torch.Tensor,torch.Tensor是Pytorch中的类,确切地说是FloatTensor的别名;而torch.tensor()是函数,它更加灵活,使用方法如下:

1.  torch.tensor(data, dtype=None, device=None, requires_grad=False)  

它可以创建各种类型的Tensor数据。
下面声明三个变量x,a,b,用它们计算变量y,之后用y.backward()求y对x,a,b三个变量的偏导数,这是深度学习中常说的“反向”过程。结果存储在变量的grad元素中,如x.grad。

1.  x = torch.tensor([1.0], requires_grad=True)    
2.  a = torch.tensor([2.0], requires_grad=True)    
3.  b = torch.tensor([3.0], requires_grad=True)    
4.  y = a * x + b  
5.  y.backward()    
6.  print(x.grad) # 输出结果: tensor([2.])    
7.  print(a.grad) # 输出结果: tensor([1.])    
8.  print(b.grad) # 输出结果: tensor([1.])    
9.  print(b.data) # 输出结果: tensor([3.])    

从输出结果可以看到,Tensor包含两个元素,data是它的Tensor值,grad保存的是求得的偏导数。

剥离无梯度变量

detach方法用于从普通Tensor中剥离出无梯度的变量。下面延用上例求导后有梯度的数据b。

1.  print(b) # tensor([3.], requires_grad=True)  
2.  print(b.detach()) # tensor([3.])  
3.  print(b.detach_()) # tensor([3.])  

detach和detach_的区别是detach获取b的data数据,而detach_则是将b中的grad_fn设置为None,requires_grad设置为False,从而改变了b的内容。

Parameter

一般模型参数都是torch.nn.parameter.Parameter类型的数据,它继承了Tensor,主要不同是requires_grad默认为True,以便于模型调参。
常在两种场景中使用Parameter,一种是fine-tune精调时冻结模型中某些层的参数;另一种是自己实现一些特殊的结构,如构建Attention时,用Parameter创建需要调节的参数。

1.创建Parameter数据

1.  p = torch.nn.Parameter(torch.randn(2))   
2.  print(p) # tensor([1.2087, 1.2607], requires_grad=True)  

2. 查看模型的Parameter参数,大小及冻结情况

Pytorch模型的基类是Module,其中维护一个名为_parameters的字典,它包含每一个子元素的名字(key)和value参数(value)。如需要冻结某层,将其require_grad设为False即可。

1.  model = torch.nn.Linear(1,1)  
2.  for name, param in model.named_parameters():    
3.      print(name, param.size(), param.requires_grad)    
4.  # 输出结果:  
5.  # weight torch.Size([1, 1]) True  
6.  # bias torch.Size([1]) True  
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354