基础知识
魔术方法: P23
调试: P271
2import ipdb
ipdb.set_trace()
带下划线_的函数会修改Tensor本身,比如x.add_(y)和x.add(y)的区别
Tensor
Numpy与Tensor共享内存
b = a.numpy() # Tensor -> Numpy
a = t.from_numpy(a)# Numpy -> Tensor
x = x.cuda()
tensor的操作:torch.function,tensor.function.
普通索引共享内存
高级索引不共享内存
线性代数函数 P70
自动广播原则: unsqueese(view),expand(expand_as)
tensor=Tensor+Storage
持久化和加载: t.save(a,’a.pth’) b=t.load(‘a.pth’) P77
%timeit -n 10
Variable和autograd
from torch.autograd import Variable
三个属性
data: 对应Tensor
grad: 梯度,和data大小一样,也是Variable
grad_fn: 指向Function对象,用于构建计算图。用户创建对应叶子节点,grad_fn=None.记录的是它什么操作的输出。
Variable的构造函数的关键字参数:requires_grad(bool):是否需要求导; volatile(bool):True表示之上的计算图都不会求导1
2
3
4
5
6x = Variable(t.ones(2,2),requires_grad = True)
y = x.sum()
y.grad_fn
y.backward()
x.grad
x.grad.data.zero_() # 反向传播清零
variable.backward(grad_variable=None, retain_graph=None, create_graph=None)
假设用户输入的数据是真实的不需要求导的。
数值在前向传导过程成会保存成buffer,计算梯度之后自动清空。多次反向求导可以使用关键字参数retain_graph=True
retain_graph=True 实现多次反向传播????
反向传播过程中非叶子节点的导数在计算完之后就会清空,y=x*w,z=y.sum() 其中y.grad会清空。其对应的方法有两种,P92,t.autograd.grad(z,y)和hook
扩展Autograd Function:P95 自己实现前向和反向
nn.Module
1 | import torch.nn as nn |
nn.Sequential()
nn.ModuleList()
nn.ParameterList()
在优化器中为各层分别设置学习率
nn.functional对应nn.Module
参数初始化:
nn.Conv2d: nSamplesnChannelsHeight*Widh
单样本: input.unsqueeze(0)
model.train()
model.eval()
前向或者后向注册钩子函数,P125,可以查看中间层。
获取网络的模块属性:getattr(module)P128
保存模型:t.save(net.state_dict(), ‘net.pth’)
加载模型:net2=Net() net2.load_state_dict(t.load(‘net.pth’))
多个GPU并行操作
损失函数
1 | output = net(input) |
1 | net.zero_grad() |
优化器
1 | learning_rate=0.01 |
1 | import torch.optim as optim |
CIFAR-10分类
- 数据预处理:transform,trainset,trainloader,testset,testloader
- 定义网络:Net(nn.Module),super(Net,self).init(),forward()
- 定义损失函数和优化器
- 训练网络
- 输入数据
- 梯度清零
- 前向传播+反向传播
- 更新参数
数据处理
自定义的数据集需要继承Dataset类,并实现两个Python魔术方法
__getitem:返回一个样本。obj[index]=obj.getitem(index)
__len:返回样本数量。
transform=T.Compose()
trans=T.Lambda(lambda img:img.rotate(randonm()*360))
ImageFolder(root,transform,target_transform,loader)P139
self.class_to_idx了解label和文件夹名的映射关系
DataLoader()定义shuffle等P142
取样:P146
工具包:torchvision P147
- models:训练好模型
- dataset:数据集加载
- transforms:数据预处理操作,主要针对Tensor和PIL Image对象的操作
make_grid和save_img
可视化工具 Tensorboard和visdom
tensor_board和TensorboardX
visdom:env pane
%env LS_COLORS=None
!tree —charset ascii data/dogcat
Tensor—numpy:np.array(Tensor) torch.Tensor(np.darray)
PIL.image—numpy:np.asarray(PIL.image) image.fromarray(numpy.ndarray)
PIL.image—Tensor:trans = transforms.Compose([transforms.ToTensor()]) tens = trans(img) ToPILImage()
GPU
P158
with t.cuda.device(1):
t.cuda.set_device(1)
export CUDA_VISIVLE_DEVICES=1
b = t.load(‘a.pth’)
c = t.load(‘a.pth’,map_location=lamdba storage, loc: storage)
d = t.load(‘a.pth’,map_location={‘cuda:1’:’cuda:0’})
Module和Optimizer: state_dict
Dog.vs.Cat
checkpoints/ 中间模型
data/
- __init__.py
- dataset.py
- def init(self,root,transform=None, train=True, test=False):
- def getitem(self,index):
- def len(self):
- get_data.sh
models/ - __init__.py
- AlexNet.py
- BasicModule.py
- ResNet34.py
utils/ - __init__.py
- visualize.py
config.py
main.py
requirements.txt
README.md
main.py
- def train(**kwargs):
- def test(**kwargs):
- def val(model,dataloader):
- def help():
1 | if __name__=='main': |
pytorch 中文文档
https://pytorch-cn.readthedocs.io/zh/latest/package_references/functional/
PyTorch实战指南 第六章 Dog.VS.Cat
这是根据深度学习框架:PyTorch入门与实践这本书的第六章写的代码,是关于猫狗识别的,在这个过程中,一边看,一边写,刚开始是运行作者已经写好的代码,后来自己在jupyter上进行复制的复现,发现import无法导入ipynb文件,在使用了Ipynb_importer.py之后可以实现同一文件内导入ipynb模块,如果是在其他文件中进行导入,会有点费事,以下会记录Ipynb_importer.py的用法。因为费事,自己开始开始使用pycharm+jupyter的方式,直接自己根据作者提供的源码进行编写,在编写的过程中接受作者的思想。用pycharm的不方便的地方是无法直接运行测试,所以采取的是对自己不熟悉的模块或者方法,用jupyter进行测试,而直接编写则是pycharm。但是感觉pycharm还是没有那么好用,可能是自己用的少。我是按照data、model、util、main+config、requirement的顺序编写的。在编写函数的过程中,因为刚开始不理解各个模块是怎么组织起来的,所以都是从简单的开始,所以函数的位置和作者的不一样,其中对于model.save和model.load、vis.plot和vis.log的封装让我感觉很有意思,刚开始是编写的时候只能直接打上问号,因为不懂这么编写的意义,但在编写主函数main的时候才感觉到了这种编写的好处,基本把模型训练和对模型、结果的处理完全分离开,避免了耦合性很强的后果。
Ipynb_importer.py
我通过几次测试发现,import Ipynbimporter 只需要放在你的当前要运行的文件中即可,然后在其他文件下的init.py 中导入所有的当前文件夹中的Module,就像这样
/first/second/models/
——-_init.py
——————- None
——-BasicModule.ipynb
——-AlexNet.ipynb
—————from models.BasicModule import BasicModule
/first/main.py
import Ipynb_importer
from models import AlexNet
之所以在AlexNet中写models.BasicModule是因为直接导入BasicModule会报错,我根据dict的输出发现有问题,这一点和官网介绍的有一点区别,我没有实现官网说明的跨文件夹导入。因为如果改文件夹导入的话,models.BasicModule要接着换成相应的名字,与我预想的不一致,我预想的是不管在哪里导入,已经导入的应该不受影响才对。
ipynb-py.sh
之后发现了这个神器,可以把ipynb转化成.py,还是挺好用的,转化之后也没问题。
同时,借助这次实验,自己对python的掌握也更深了一点。
不过对于网络的构成还是有一些问题,那就是网络为什么这么写,这应该属于理论的东西。还需要进一步加强。
这次实验一共用了三天才完全搞懂,可以说其中涉及到的函数的用法基本都明白了。
本意是记录自己,不过如果有任何问题,欢迎交流。
PyTorch实战指南 第七章 DCGAN
这一次实现的也比较慢,用了小三天才做完,现在记录一下其中学到的几个东西。
__file__:
用来获取模块所在路径 可能是一个相对路径,可能是一个绝对路径,
如果当前文件包含在sys.path里面,那么,__file__返回一个相对路径!
也可以认为获取模块的名字
最后的落脚点一定是XX/XX.py
类没有这个属性
1 | In [1]: import numpy |
__name__:
__name__就是标识模块的名字的一个系统变量。这里分两种情况:假如当前模块是主模块(也就是调用其他模块的模块),那么此模块名字就是__main__,通过if判断这样就可以执行“__mian__:”后面的主函数内容;假如此模块是被import的,则此模块名字为文件名字(不加后面的.py),通过if判断这样就会跳过“__main__:”后面的内容。
这个模块可以是文件夹的名字,可以是类的名字,可以是__mian__”,XX的形式。
可以用于获取当前文件的文件名
通过上面方式,python就可以分清楚哪些是主函数,进入主函数执行;并且可以调用其他模块的各个函数等等。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19# test.py
## print(__file__)
## print(__name__)
# test2.py
## import test
## print(__file__)
## print(__name__)
H:\GitHub\pytorch_learn\Chapter7\test.py
test
test2.py
__main__
## from test import ccc
## print(ccc.__name__)
## print(__file__)
## print(__name__)
ccc
test2.py
__main__
type():
返回对象的类型
如果是module,则返回module
如果是类的实例,则返回类的名称,这个名称以XXX.XXX的形式返回,从import的第一个开始算起。
常用于判断数据类型,在pytorch中,用于返回模型名称,这个用法很巧妙,相当于返回了子类的类型名字
我觉得没有理解作者是怎么用的。在父类里的type(self) 返回的是子类的类名1
2
3
4
5
6
7
8
9
10
11
12In [1]: import numpy
In [2]: type(numpy)
Out[2]: module
In [3]: a = numpy.array(1)
In [4]: type(a)
Out[4]: numpy.ndarray
In [5]: type(numpy.array)
Out[5]: builtin_function_or_method1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29class A:
pass
class B(A):
pass
isinstance(A(), A) # returns True
type(A()) == A # returns True
isinstance(B(), A) # returns True
type(B()) == A # returns False
class A(object):
def __init__(self):
print(type(self))
pass
class B(A):
def __init__(self):
super(B,self).__init__()
print(type(self))
pass
import test
test.B()
<class 'test.B'>
<class 'test.B'>
__class__:
和type类似1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class A(object):
def __init__(self):
print(type(self))
print(self.__class__)
pass
class B(A):
def __init__(self):
super(B,self).__init__()
print(type(self))
print(self.__class__)
pass
<class 'test.B'>
<class 'test.B'>
<class 'test.B'>
<class 'test.B'>
获取config源码
打印参数,方便输入参数
inspect.getsource1
2
3from inspect import getsource
source = getsource(opt.__class__)
print(source)