欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

pytorch 使用笔记

程序员文章站 2022-03-19 22:16:04
...

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.LogSoftmaxnn.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之后程序执行完就可以正常退出。