pytorch 使用笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yanhe156/article/details/83413395

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

猜你喜欢

转载自blog.csdn.net/yanhe156/article/details/83413395