pytorch 使用笔记
reshape
和numpy有点不同,numpy是reshape(),这里是view()
x = torch.randn(4,4)
x = x.view(-1,8)
x = x.view(8)
numpy和tensor转换
a = x.numpy()
x = torch.from_numpy(a)
转换时注意数据类型,tensor参与运算时,会对数据类型进行检查
To CPU or GPU
device = torch.device("cuda")
x = x.to(device)
y = torch.ones_like(x, device=device)
z = x+y
z = z.to("cpu", torch.double)
数据集加载
torch.utils.data.DataLoader(image_datasets[x], batch_size=4, shuffle=True, num_workers=4)
这里的 image_datasets[x] 是一个对象,有__init__()
, __len__()
, __getitem__()
三个函数,只要明确**__getitem__()
返回的是一个样本**就行了。
调用这个函数时不用再在意数据如何读取,shuffle。
多GPU
model = nn.DataParallel(model)
模型定义
定义后,找一个样本前向传播一下,看是否会mismatch。
注意模型接受的输入,对序列数据必须是三个维度的张量,三个维度依次表示sample数量,通道,特征。
对图像数据,必须是四个维度,依次表示sample数量,通道,行,列。
注意对单通道数据,需要手动加一个维度,通道数为1。
注意卷积层之后接全连接层时,需要自己写个函数进行flatten。
计算损失
不同损失函数的target.shape不同。
注意,计算损失时,MSELoss()
一个样本的target维度等于输出维度 。
CrossEntropyLoss()
的target只需要一个表示类别的值。注意target必须是1维向量,还要注意output不要经过softmax。因为计算损失有softmax。
注释里说了,这里的CrossEntropyLoss
是集合了nn.LogSoftmax
和nn.NLLLoss
。不是Andrew Ng公开课讲的交叉熵函数,但等价。
打开官方文档非常慢,参考这篇博客
![Screenshot from 2018-10-25 20-02-12](/home/yan/Pictures/Screenshot from 2018-10-25 20-02-12.png)
如何从dataloader中取一个样本查看?
dataiter = iter(dataloader)
one_sample = dataiter.next()
dataloader似乎没有__getitem__()
函数,但是支持迭代,所以需要这样才能访问。one_sample的具体形式取决于为自己所定义的数据类的__getitem__()
函数的返回值。官网的tutorial里出现了两种,可以为元组,也可以为字典。
如何查看parameters?
可以按上面dataloader那种方式查看,因为net.parameters()返回的是一个迭代器。
也可以使用list(net.parameters()) 得到一个列表。
SGD
一般深度学习库里的SGD指的是mini batch gradient decent。当然,如果batch=1,那就是真正的SGD。
数据类型问题
Expected object of type torch.DoubleTensor but found type torch.FloatTensor for argument #2 'weight'
我也是醉了,是我英语差到这都看不懂了???
这个错误事实上是说的是需要torch.FloatTensor,但是是torch.DoubleTensor。但是我看到这句话理解的正好相反了。
那么再来看条错误:
Expected object of type torch.LongTensor but found type torch.ByteTensor for argument #2 'target'
这个错误事实上是说需要LongTensor,我理解的没错。
再遇到类似问题,首先打印tensor的type()看一下。然后尝试一下相反的tensor类型。
同时要注意,np.float转换成tensor是DoubleTensor,np.float32转换成tensor才是FloatTensor。
参数初始化
自定义网络后,参数是有默认的初始化的,打印一下,可以看到不为0,查看源码可以看到卷积层默认使用的uniform初始化。似乎一般使用xavier初始化效果更好。
比如为Conv2d类型的层进行参数初始化,初始化为常量。
def weights_init(m):
if isinstance(m, nn.Conv2d):
nn.init.constant_(m.weight.data, 0.1)
nn.init.constant_(m.bias.data, 0)
net.apply(weights_init)
再比如这种
def weight_init(m):
if isinstance(m, nn.Conv2d):
n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
m.weight.data.normal_(0, math.sqrt(2. / n))
elif isinstance(m, nn.BatchNorm2d):
m.weight.data.fill_(1)
m.bias.data.zero_()
net.apply(weights_init)
程序执行完不退出
看到有人在python遇到这种情况是因为模块里有子线程,于是想到DataLoader()
的一个参数num_workers和线程有关,把它设成1,无效,看了函数的说明,num_works设成0表示不使用多线程,设为0之后程序执行完就可以正常退出。
推荐阅读
-
CorelDRAW使用钢笔工具绘制装饰画背景
-
Apple Watch 使用技巧和隐藏功能大全 应用之间快速切换教程
-
Android 数据存储之 FileInputStream 工具类及FileInputStream类的使用
-
Android使用Circular Reveal动画让页面跳转更炫酷
-
华硕笔记本截屏快捷键失灵怎么使用键盘截屏?
-
实例讲解使用HTML5 Canvas绘制阴影效果的方法
-
一点浏览器怎么设置右键快速关闭网页 一点浏览器右键快速关闭网页功能使用方法
-
Android 自动判断是电话,网址,EMAIL方法之Linkify的使用
-
Android变形(Transform)之Camera使用介绍
-
Android系统开发中log的使用方法及简单的原理