文章目录
- os.name
- os.path.expanduser(path)
- cv.setNumThreads(0)
- seed 设置随机的种子
- for m in self.modules()
- model.load_state_dict()
- 学习率调整 && 优化器
- multiprocessing.set_start_method('spawn',force=True)
- torch.backends.cudnn.benchmark=True
- clamp()
- torchvision 计算机视觉工具包
- skvideo.io.vread()
- PIL.Image与numpy.array(np.array)
- cv2.imread() && cv2.imwrite() && PIL.Image.open() && matplotlib.image.imread() && imageio.imread() && imageio.imwrite && skimage.io.imread
- from collections import OrderedDict
- from collections import Counter
- torch.nn与 torch.nn.functional
- transforms.ToTensor()与torch.from_numpy()
- split("/")[-1] 和 split("/",-1)的区别
- torch.bmm()
os.name
指代当前使用的操作系统(包括:‘posix’, ‘nt’, ‘mac’, ‘os2’, ‘ce’, ‘java’)
遇到:net_path=Path(network_dir)
返回的结果为:
可以看到其结果是一样的,但是变成了PosixPath
os.path.expanduser(path)
把path中包含的"~" 和 "~user"转换成用户目录
cv.setNumThreads(0)
设定OpenCV使用的线程数,这里把线程数设置为0
代码中的解释为:This is needed to avoid strange crashes related to opencv
seed 设置随机的种子
np.random.seed(args.seed)
torch.manual_seed(args.seed)
torch.cuda.manual_seed_all(args.seed)
torch.backends.cudnn.deterministic=True
torch.backends.cudnn.benchmark=True #让程序在开始时花费一点额外时间,为整个网络的每个卷积层搜索最适合它的卷积实现算法,进而实现网络的加速。
torch.backends.cudnn.benchmark=True 参考
for m in self.modules()
得到所用的模型,然后整个遍历,从而进行初始化,记录一种初始化方式
另外一种常见的初始化方式为:
使用nn.init.kaiming_normal(m.weight.data,mode=‘fan_in’)
model.load_state_dict()
模型加载参数
model.load_state_dict(model_zoo.load_url(model_urls['resnet18'])#加载模型以及参数
params=model.state_dict() #获得模型的原始状态以及参数。
for k,v in params.items():
print(k) #只打印key值,不打印具体参数。
上面加载的有模型也有参数,打印需要选择key值还是value,如果只加载参数呢,也就是value,用net.parameters()
学习率调整 && 优化器
torch.optim.lr_scheduler.StepLR(optimizer,step_size=15,gamma=0.2)这个是等间隔调整学习率
我觉得这个博客写的很详细
从上面可以看到学习率调整输入的参数第一个就是优化器,所以两者是不可分的。
optimizer=torch.optim.Adam(actor.net.bb_regressor.parameters(),lr=1e-3)
可以看到优化器参数之一是原来的网络参数,请接着往下看
loss ,stats =self.actor(data) #forward pass
if loader.training:
self.optimizer.zero_grad()
loss.backward()
self.optimizer.step()
这是在一个mini-batch中,首先进行前向传播,然后将梯度置0,反向传播梯度(在调用backward之前需要让结果变成标量才能求出导数),然后进行优化器的更新,(对之前的参数进行更新)所以优化器的更新在mini-batch中哦
那学习率的调整在哪一块呢?在epoch 中,
看到 self.lr_scheduler.step() , 这便是学习率的更新
参考博客
multiprocessing.set_start_method(‘spawn’,force=True)
multiprocessing 模块提供了多进程编程的能力
它的API非常类似于threading 模块,但是也提供了一些thr eading模块不具有的能力,
相比于线程,它通过派生子进程来绕过GIL的限制,从而可以充分利用多核处理器的能力
它提供了进程间的同步
multiprocessing 模块支持三种派生子进程的模式:
1.spawn模式: 父进程重新开启了一个全新的python解释器进程,然后子进程的代码运行在这个新的解释器进程中
子进程只继承了必要的资源来完成任务。父进程打开的文件描述符和一些句柄不会被子进程继承
该模式在三种模式中速度最慢
2.fork模式;父进程使用os.fork()来派生一个python解释器进程。子进程的代码运行在这个新的解释器进程中
子进程几乎与父进程完全相同;子进程继承了父进程的所有资源
3.forkserver模式,在这种模式下,父进程派生了一个server进程。当任何时候,父进程需要创建子进程时,由父进程通知server 进程来派生一个子进程。
torch.backends.cudnn.benchmark=True
可以让内置的 cuDNN 的 auto-tuner 自动寻找最适合当前配置的高效算法,来达到优化运行效率的问题
我看的一篇博客
clamp()
该函数的功能是:clamp(x,low,high )若X在[low,high]范围内,则等于X;如果X小于low,则返回low;如果X大于high,则返回high。返回结果到一个新的Tensor。
这样,我们就可以使用 x.clamp(min=0) 来代替 relu函数
torchvision 计算机视觉工具包
有四大类:
torchvision.datasets
用来进行数据加载(如:MNIST,ImageNet-12)
torchvision.models
提供已经训练好的模型,我们可以直接加载使用(如:resnet,vgg,alexnet)
torchvision.transforms
提供了图像转化的操作类(如ToTensor【将(H x W x C转换成C x H x W),实质上ji将PILImage或者numpy的ndarray转化成Tensor,range[0, 255]变为range[0, 1]】,ToPILImage,RandomCrop,Normalize,Compose【将多个transform组合起来使用】)
torchvision.utils
经常使用make_grid (把图片排列成网格形状) ,save_img(用于把指定的Tensor保存成图片文件)
skvideo.io.vread()
读取视频,输出的是 <class ‘tuple’>: (6831, 180, 320, 3),第一个代表帧数,第二个呢第三个呢?当然是图片的长宽,最后是图片的channel
PIL.Image与numpy.array(np.array)
image -> array
img=numpy.array(im)
array ->image
img=Image.fromarray(xxx)
可以看一下区别,第一个是array,看最前面,它写着ndarray, 它独有的是shape,而第二个呢?它独有的img信息?
cv2.imread() && cv2.imwrite() && PIL.Image.open() && matplotlib.image.imread() && imageio.imread() && imageio.imwrite && skimage.io.imread
总结这个的起因是以下报错(这个报错的意思是,从格式为float32转为uint8 会有精度损耗,建议先下手为强,直接转为uint8以避免这个警告),和从来没有注意过float32和uint8等各种形式,
opencv读进来的图片已经是一个numpy矩阵了,彩色图片维度是(高度,宽度,通道数)。数据类型是uint8,数值范围是0~255之间,opencv对于读进来的图片的通道排列是BGR,而不是主流的RGB!谨记!需要使用cv2.cvtColor(im,cv2.COLOR_BGR2RGB)来转换
但是我们在深度做卷积的时候用的是(channel,height,width),需要转化一下,img=img.transpose(2,0,1)
#如何解决“读到的图片不存在的问题”? #加入判断语句,如果为空,做异常处理
img=cv2.imread('xxx.jpg')
if img ==None:
print('fail to load image!')
PIL(python imaging library,也就是我们所说的pillow)读进来的图像是一个对象,而不是我们所熟知的numpy 矩阵,可以使用np.array()转化为numpy
plt.imread(import matplotlib.pyplot as plt)读入的就是一个矩阵,跟opencv一样,但彩图读进的是RGB,与opencv有区别
imageio模块进行图片的读写,读进来的是一个numpy矩阵,格式为uint8
总结:图片或视频读取的方式很多,掌握其读取后的形式和结构,要不最后都是bug
参考资料 写的很详细
from collections import OrderedDict
Python中的字典(dict)对象可以使用‘键、值’对的形式存取值,但默认的内置类型字典中的元素是无序的。Collections模块下的OrderedDict类实现了对字典的排序,OrderedDict是dict的一个子类,实现了对字典排序的功能。参考
from collections import Counter
from collections import Counter
words=["cat","bt","hat","tree"]
chars="atach"
print(Counter(words))
print(Counter(chars))
输出结果为:
Counter({'cat': 1, 'bt': 1, 'hat': 1, 'tree': 1})
Counter({'a': 2, 't': 1, 'c': 1, 'h': 1})
torch.nn与 torch.nn.functional
在这里插入代码片
torch.nn.X是类,例如,torch.nn.Conv2d,它的forward()函数实现是用F.conv2d()实现的,结构中包含所需要初始化的参数,进而backward(用于需要学习的weights,bias等variable)而torch.nn.functional.X是函数,需要在函数外定义并初始化相应参数,并作为参数传入,(用于不需要学习的参数,如torch.nn.ReLU等)
参考博客
transforms.ToTensor()与torch.from_numpy()
这两个的功能都是用于 将numpy转化为Tensor,但是到底是一样还是不一样呢?
transforms.ToTensor()
将numpy的ndarray或PIL.Image读到的图片转化成形状为(C,H,W)的Tensor,dtpye是torch.float32,并且/255归一化到[0,1.0]之间(如果是cv.imread读到的图片需要由BGR转为RGB)
而torch.from_numpy()
只是将将numpy的ndarray或PIL.Image读到的图片转化成形状为,(H,W,C)的Tensor, 并且dtpye是torch.uint8,并没有进行归一化操作。 所以如果想转为形状为(C,H,W)的Tensor,需要用transport()或者permute()函数进行转化,如果想变为float32类型还需要强制转化或者.float,如果想要归一化还得重新归一化。
torch.from_numpy(a).float().permute(2,0,1).unsqueeze(0)
tansforms.ToTensor()(a)
#第一种方法没有归一化,剩下的这两种方法都一样
split("/")[-1] 和 split("/",-1)的区别
通过指定分隔符对字符串进行切片,split("/")[-1]是分割后取最后一个,[1]取第一个,以此类推;而split("/",0),如果参数 num 有指定值,则分隔 num+1 个子字符串,得到一个字符串,全部;1,切一下,得到两个字符串;但是-1的话表示全部切开。split("/",-1)和split("/")效果一样
torch.bmm()
计算两个Tensor的矩阵乘法,torch.bmm(a,b),tensor a的size为(b,h,w),tensor b的size为(b,w,h)注意两个tensor的维度必须为3.
参考示例