Pytorch 及Python 常用技巧(持续更新)

PYTHON 安装包移植

#下载包
pip freeze > requestments.txt # 编辑此文件对需要的包进行删减
pip download  -r requirements.txt  -d  /tmp/paks/ #下载requirements.txt中包至 /tmp/paks/下
# 导入新环境
pip install   --no-index   --find-links=/packs/   pandas 或      
pip install   --no-index   --find-links=/packs/   -r   requirements.txt (也可能是 --find-link)
# 在线安装
pip install -r requirements.txt

pip 安装源

pip install pythonModuleName (==version) -i https://mirrors.aliyun.com/pypi/simple

---------------
或将下面代码放入:C:\Users\Administrator\AppData\Local\pip, 新建文件pip.ini中。

[global]
timeout = 6000
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
trusted-host = pypi.tuna.tsinghua.edu.cn

pip删除安装缓存

Linux and Unix

~/.cache/pip

OS X

~/Library/Caches/pip

Windows

%LocalAppData%\pip\Cache

windows 的git安装与应用

先从git 官网下载git.exe, 并安装,后配置环境变量如下:
;C:\Program Files\Git\bin\git.exe;C:\Program Files\Git\cmd
重启cmd。

torch 的安装 、CUDA的安装、cudnn的安装

进入pytorch的官网,选择要安装的版本并匹配好。
根据CUDA的版本选择cudnn,
windows:

  1. 把cuda\bin\cudnn64_7.dll复制到 C:\Program Files
    \NVIDIA GPU Computing Toolkit\CUDA\v9.0\bin 目录下.
  2. 把\cuda\ include\cudnn.h复制到 C:\Program Files
    \NVIDIA GPU Computing Toolkit\CUDA\v9.0\include 目录下.
  3. 把\cuda\lib\x64\cudnn.lib复制到C:\Program Files
    \NVIDIA GPU Computing Toolkit\CUDA\v9.0\lib\x64 目录下.

ubuntu:
查看cuda版本: nvcc -V
查看cudnn版本:cat /usr/local/cuda/include/cudnn_version.h | grep CUDNN_MAJOR -A 2

torch <–> numpy 转换

torch.from_numpy()
arry. numpy()

import numpy as np
import torch
np_arr = np.array([1,2,3,4])
tor_arr=torch.from_numpy(np_arr)
tor2numpy=tor_arr.numpy()
print('\nnumpy\n',np_arr,'\ntorch\n',tor_arr,'\nnumpy\n',tor2numpy)

CUDA: 进入cuda_toolkit官网,找到你要下载的cuda.

torch.utils.data.Dataloader 的注意与使用事项

collate_fn:如何取样本的,我们可以定义自己的函数来准确地实现想要的功能。default_collate会将labels分割合并转换成tensor。因此,如果是ndarray会将batchsize 内的array cat到一起。如果是list,会分割,可能不会得到想要的矩阵。因此,如果labels的shape固定,可以在此之前做成array的形式,不会导致错误。

from torch.utils.data import DataLoader
import numpy as np
import os
import torch
import cv2
from glob import glob


class MyDataset(DataLoader):
    """

    """
    def __init__(self, img_folder, lab_folder, transform=None):
        self.transform = transform
        ll = glob(img_folder)
        # read labels first, if there is no labels.
        lab_names = os.listdir(lab_folder)
        self.imgs = []
        for id, lab_name in enumerate(lab_names):
            file_first_name = str(lab_name).split('.')[0]
            lab_abspath= os.path.join(lab_folder, lab_name)
            bbs = self._read_line(lab_abspath)
            if bbs is []:
                continue
            img_abspath = os.path.join(img_folder, file_first_name+'.png')
            self.imgs.append((img_abspath, bbs))

    def __getitem__(self, index):
        fn, label = self.imgs[index]

        img = cv2.imread(fn)
        img = cv2.resize(img,(400, 400))
        if self.transform is not None:
            img = self.transform(img)
        return img, label

    def __len__(self):
        return len(self.imgs)


    def _read_line(self, path, pass_obj=['Others', ]):
        """
        Parse the labels from file.

        :param pass_obj: pass the labels in the list.
                        e.g. pass_obj=['Others','Pedestrian']
        :param path: the path of file that need to parse.
        :return:lists of the classes and the key points.
        """
        file_open = open(path, 'r')
        bbs = []
        for line in file_open.readlines():
            tmps = line.strip().split(' ')
            if tmps[0] in pass_obj:
                continue
            box_x1 = float(tmps[4])
            box_y1 = float(tmps[5])
            box_x2 = float(tmps[6])
            box_y2 = float(tmps[7])
            bbs.append([tmps[0], box_x1, box_y1, box_x2, box_y2])
        return bbs


def collect_fn(batches):
    imgs = []
    labs = []
    for i, batch in enumerate(batches):
        m = batch[0]
        imgs.append(m)
        labs.append(batch[1])
    images = torch.from_numpy(np.asarray(imgs))
    return images, labs
    
# 使用zip的技巧使代码简单。
def collate_fn_2(batch):
    imgs, labels = zip(*batch)
    return torch.from_numpy(np.asarray(imgs)), list(labels)

mydata=MyDataset('../../datasets/kitti/training/image_2/',
                 '../../datasets/kitti/training/label_2/')

traindata = DataLoader(dataset=mydata, batch_size=10,collate_fn=collect_fn, shuffle=False)

data = iter(traindata)
i, l = next(data)  # 其中default_collate会将labels分割合并转换成tensor。collate_fn:如何取样本的,我们可以定义自己的函数来准确地实现想要的功能
# or use the next code.
# for i, data in enumerate(traindata):
#     print(data[0].size, data[1].shape)

上面代码就不会导致labels做成tensor时失败。

zip 的使用技巧

zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。

如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。

a = [1,2,3]
b = [4,5,6]
c = [4,5,6,7,8]
zip(a,b)     # 打包为元组的列表
#[(1, 4), (2, 5), (3, 6)]
zip(a,c)              # 元素个数与最短的列表一致
#[(1, 4), (2, 5), (3, 6)]
zip(*zipped)          # 与 zip 相反,*zipped 可理解为解压,返回二维矩阵式
#[(1, 2, 3), (4, 5, 6)]

l = ['a', 'b', 'c', 'd', 'e','f']
print l

#打印列表
print zip(l[:-1],l[1:])

输出结果:

['a', 'b', 'c', 'd', 'e', 'f']
[('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'e'), ('e', 'f')]

nums = ['flower','flow','flight']
for i in zip(*nums):
print(i)

输出结果:

('f', 'f', 'f')
('l', 'l', 'l')
('o', 'o', 'i')
('w', 'w', 'g')

使用zip的技巧使代码简单,如上上个代码。

zip list np.array 数据转换

关于Python 的知识可参考:W3C school

a = [1, 2, 3]
a is a list
list->ndarray
b=np.asarray(a)
zip = (1, 2, 3)
c = list(zip)

tuple也是一个class,是不可变的list类型,不可以增删改。
创建:
tup1 = (‘physics’, ‘chemistry’, 1997, 2000);
tup2 = (1, 2, 3, 4, 5 );
tup3 = “a”, “b”, “c”, “d”;
访问:(与list一样)tup1[1:5];
修改:不可以修改,只能增加新的部分;
tup3 = tup1 + tup2;
print tup3;

easydict的使用

easydict的作用:可以使得以属性的方式去访问字典的值!

>>> from easydict import EasyDict as edict
>>> d = edict({'foo':3, 'bar':{'x':1, 'y':2}})
>>> d.foo
3
>>> d.bar.x
1
 
>>> d = edict(foo=3)
>>> d.foo
3
解析json目录时很有用

    >>> from easydict import EasyDict as edict
    >>> from simplejson import loads
    >>> j = """{
    "Buffer": 12,
    "List1": [
        {"type" : "point", "coordinates" : [100.1,54.9] },
        {"type" : "point", "coordinates" : [109.4,65.1] },
        {"type" : "point", "coordinates" : [115.2,80.2] },
        {"type" : "point", "coordinates" : [150.9,97.8] }
    ]
    }"""
    >>> d = edict(loads(j))
    >>> d.Buffer
    12
    >>> d.List1[0].coordinates[1]
    54.9

也可以这样用

    >>> d = EasyDict()
    >>> d.foo = 3
    >>> d.foo
    3

    >>> d = EasyDict(log=False)
    >>> d.debug = True
    >>> d.items()
    [('debug', True), ('log', False)]


    >>> class Flower(EasyDict):
    ...     power = 1
    ...
    >>> f = Flower({'height': 12})
    >>> f.power
    1
    >>> f['power']
    1

参考:https://pypi.org/project/easydict/1.2/

Tqdm 是 Python 进度条库

Tqdm 是 Python 进度条库,可以在 Python 长循环中添加一个进度提示信息用法:tqdm(iterator)

# 方法1:
import time
from tqdm import tqdm  

for i in tqdm(range(100)):  
    time.sleep(0.01)

方法2:
import time
from tqdm import trange

for i in trange(100):
    time.sleep(0.01) 

结果:
 0%|          | 0/100 [00:00<?, ?it/s]
 11%|█         | 11/100 [00:00<00:00, 100.00it/s]
 22%|██▏       | 22/100 [00:00<00:00, 100.00it/s]
 32%|███▏      | 32/100 [00:00<00:00, 100.00it/s]
 43%|████▎     | 43/100 [00:00<00:00, 100.00it/s]
 54%|█████▍    | 54/100 [00:00<00:00, 100.00it/s]
 64%|██████▍   | 64/100 [00:00<00:00, 99.11it/s] 
 74%|███████▍  | 74/100 [00:00<00:00, 99.37it/s]
 85%|████████▌ | 85/100 [00:00<00:00, 99.56it/s]
 95%|█████████▌| 95/100 [00:00<00:00, 99.69it/s]
100%|██████████| 100/100 [00:01<00:00, 99.70it/s]

可以为进度条设置描述:
import time
from tqdm import tqdm

pbar = tqdm(["a", "b", "c", "d"])  
for char in pbar:  
    # 设置描述
    pbar.set_description("Processing %s" % char)
    time.sleep(1)

结果:
0%|          | 0/4 [00:00<?, ?it/s]
Processing a:  25%|██▌       | 1/4 [00:01<00:03,  1.00it/s]
Processing b:  50%|█████     | 2/4 [00:02<00:02,  1.00it/s]
Processing c:  75%|███████▌  | 3/4 [00:03<00:01,  1.00it/s]
Processing d: 100%|██████████| 4/4 [00:04<00:00,  1.00it/s]

手动控制进度:
import time
from tqdm import tqdm

# 一共200个,每次更新10,一共更新20次

with tqdm(total=200) as pbar:
  for i in range(20):
    pbar.update(10) 
    time.sleep(0.1)

#方法2:
pbar = tqdm(total=200)  
for i in range(20):  
    pbar.update(10)
    time.sleep(0.1)
close() 不要也没出问题?
pbar.close()

结果:
  0%|          | 0/200 [00:00<?, ?it/s]
 15%|█▌        | 30/200 [00:00<00:01, 150.00it/s]
 25%|██▌       | 50/200 [00:00<00:01, 130.43it/s]
 30%|███       | 60/200 [00:00<00:01, 119.52it/s]
 40%|████      | 80/200 [00:00<00:01, 112.91it/s]
 50%|█████     | 100/200 [00:00<00:00, 108.70it/s]
 55%|█████▌    | 110/200 [00:01<00:00, 105.93it/s]
 65%|██████▌   | 130/200 [00:01<00:00, 104.08it/s]
 75%|███████▌  | 150/200 [00:01<00:00, 102.82it/s]
 80%|████████  | 160/200 [00:01<00:00, 101.96it/s]
 85%|████████▌ | 170/200 [00:01<00:00, 96.38it/s] 
 90%|█████████ | 180/200 [00:01<00:00, 97.44it/s]
100%|██████████| 200/200 [00:01<00:00, 98.19it/s]

扩展阅读:https://blog.csdn.net/langb2014/article/details/54798823?locationnum=8&fps=1

文件 path 的应用

OS.path的应用

os.path.abspath(path) 	返回绝对路径 
os.path.basename(path) 	返回path最后的文件名
os.path.commonprefix(list) 	返回list(多个路径)中,所有path共有的最长的路径
os.path.dirname(path) 	返回文件路径
os.path.exists(path) 	如果路径 path 存在,返回 True;如果路径 path 不存在,返回 False。
os.path.lexists 	路径存在则返回True,路径损坏也返回True
os.path.expanduser(path) 	把path中包含的"~""~user"转换成用户目录
os.path.expandvars(path) 	根据环境变量的值替换path中包含的"$name""${name}"
os.path.getatime(path) 	返回最近访问时间(浮点型秒数)
os.path.getmtime(path) 	返回最近文件修改时间
os.path.getctime(path) 	返回文件 path 创建时间
os.path.getsize(path) 	返回文件大小,如果文件不存在就返回错误
os.path.isabs(path) 	判断是否为绝对路径
os.path.isfile(path) 	判断路径是否为文件
os.path.isdir(path) 	判断路径是否为目录
os.path.islink(path) 	判断路径是否为链接
os.path.ismount(path) 	判断路径是否为挂载点
os.path.join(path1[, path2[, ...]]) 	把目录和文件名合成一个路径
os.path.normcase(path) 	转换path的大小写和斜杠
os.path.normpath(path) 	规范path字符串形式
os.path.realpath(path) 	返回path的真实路径
os.path.relpath(path[, start]) 	从start开始计算相对路径
os.path.samefile(path1, path2) 	判断目录或文件是否相同
os.path.sameopenfile(fp1, fp2) 	判断fp1和fp2是否指向同一文件
os.path.samestat(stat1, stat2) 	判断stat tuple stat1和stat2是否指向同一个文件
os.path.split(path) 	把路径分割成 dirname 和 basename,返回一个元组
os.path.splitdrive(path) 	一般用在 windows 下,返回驱动器名和路径组成的元组
os.path.splitext(path) 	分割路径,返回路径名和文件扩展名的元组
os.path.splitunc(path) 	把路径分割为加载点与文件
os.path.walk(path, visit, arg) 	遍历path,进入每个目录都调用visit函数,visit函数必须有3个参数(arg, dirname, names),dirname表示当前目录的目录名,names代表当前目录下的所有文件名,args则为walk的第三个参数
os.path.supports_unicode_filenames 	设置是否支持unicode路径名

深度学习训练中指定GPU使用设置

类似tensorflow指定GPU的方式,使用CUDA_VISIBLE_DEVICES。

1、直接终端中设定:
CUDA_VISIBLE_DEVICES=1 python main.py
2、python代码中设定:
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "2"
3、使用函数 set_device
import torch
torch.cuda.set_device(id)

参考:http://www.cnblogs.com/darkknightzh/p/6591923.html

python 小数取有效位数的方法

方法一:round()函数
以下展示了使用 round() 方法的实例:

#!/usr/bin/python
print "round(80.23456, 2) : ", round(80.23456, 2)
print "round(100.000056, 3) : ", round(100.000056, 3)
print "round(-100.000056, 3) : ", round(-100.000056, 3)
以上实例运行后输出结果为:
round(80.23456, 2) :  80.23
round(100.000056, 3) :  100.0
round(-100.000056, 3) :  -100.0

方法二:’%.2f’ %f 方法

f = 1.23456

print('%.4f' % f)
print('%.3f' % f)
print('%.2f' % f)

list of different size tensor concatenate to one tensor

a = torch.Tensor([1,2,3,4,5,6,7,7,8])
b =  torch.Tensor([1,2])
c = [a, b]
out = torch.cat(c,dim=0)

结果:
out:torch.Tensor([1,2,3,4,5,6,7,7,8, 	1, 2 ])

numpy 数组拼接

Python中numpy数组的合并有很多方法,如

np.append() 
np.concatenate((a,b),axis=1) 
np.stack() 
np.hstack((a,b)) 
np.vstack((a,b)) 
np.dstack() 

python 获得时间格式的字符串

 time.strftime('%Y_%m_%d_%r',time.localtime(time.time()))
%y 两位数的年份表示(00-99%Y 四位数的年份表示(000-9999%m 月份(01-12%d 月内中的一天(0-31%H 24小时制小时数(0-23%I 12小时制小时数(01-12%M 分钟数(00=59%S 秒(00-59

torch 计算参数量summary()

from torchsummary import summary

summary(model, input_size=(3,224,224), batch_size=-1, device='cuda')

yield()

简单地讲,yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator,调用 fab(5) 不会执行 fab 函数,而是返回一个 iterable 对象!在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。

def batch_iter(x, y, batch_size=64):
    """生成批次数据"""
    data_len = len(x)
    num_batch = int((data_len - 1) / batch_size) + 1

    indices = np.random.permutation(np.arange(data_len))
    x_shuffle = x[indices]
    y_shuffle = y[indices]

    for i in range(num_batch):
        start_id = i * batch_size
        end_id = min((i + 1) * batch_size, data_len)
        yield x_shuffle[start_id:end_id], y_shuffle[start_id:end_id]

One-hot function in PyTorch

Method1: use scatter_ function
labels = [0, 1, 4, 7, 3, 2]
one_hot = torch.zeros(6, 8).scatter_(dim = 1, index = labels, value = 1)

Method2: use index_select() funtion
labels = [0, 1, 4, 7, 3, 2]
index = torch.eye(8)
one_hot = torch.index_select(index, dim = 0, index = labels)

Method3: use Embedding module
emb = nn.Embedding(8, 8)
emb.weight.data = torch.eye(8)

then we can get

emb(Variable(torch.LongTensor([1, 2], [3, 4])))
Variable containing:
(0,.,.) = 
0 1 0 0 0 0 0 0 
0 0 1 0 0 0 0 0
(1 ,.,.) =
0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0

Method4: create a module
class One_Hot(nn.Module):
    def __init__(self, depth):
        super(One_Hot,self).__init__()
        self.depth = depth
        self.ones = torch.sparse.torch.eye(depth)
    def forward(self, X_in):
        X_in = X_in.long()
        return Variable(self.ones.index_select(0,X_in.data))
    def __repr__(self):
        return self.__class__.__name__ + "({})".format(self.depth)

Github 速度慢的解决方法

获取Github相关网站的ip
访问https://www.ipaddress.com,拉下来,找到页面中下方的“IP Address Tools – Quick Links”
分别输入github.global.ssl.fastly.net和github.com& codeload.github.com,查询ip地址
修改本地hosts文件C:\Windows\System32\drivers\etc
参考如下,增加github.global.ssl.fastly.net和github.com的映射。

# Github
199.232.5.194 github.global.ssl.fastly.net
192.30.253.112 github.com
140.82.114.10 codeload.github.com

更新DNS缓存(貌似不更新也可以,会自动更新)
命令行输入:ipconfig /flushdns

不同类名的批量调用 getattr(self,‘layer’+str(l))

如题 : getattr(self,‘layer’+str(l))

torch.mul() 和 torch.mm() 的区别

torch.mul(a, b)是矩阵a和b对应位相乘,a和b的维度必须相等,比如a的维度是(1, 2),b的维度是(1, 2),返回的仍是(1, 2)的矩阵,

torch.mm(a, b)是矩阵a和b矩阵相乘,比如a的维度是(1, 2),b的维度是(2, 3),返回的就是(1, 3)的矩阵

torchvision.utils

torchvision.utils.make_grid(tensor, nrow=8, padding=2, normalize=False, range=None, scale_each=False, pad_value=0)
制作图像网格。

参数说明:

tensor (Tensor or list)4D小批量形状Tensor张量(B x C x H x W)或所有大小相同的图像列表。
nrows (int, optional) – 网格中的行数。最终的网格大小(B / nrow,nrow)。默认值是8。
normalize (bool, optional) – 如果TRUE,将图像移到范围(0, 1)中,减去最小值并除以最大像素值。
range (tuple, optional) – 元组(min,max),其中min和max是数字,然后使用这些数字对图像进行标准化。默认情况下,min和max是从张量计算的。
scale_each (bool, optional) – 如果TRUE,则在批处理图像中分别缩放每个图像,而不是在所有图像上(最小、最大)缩放图像。
pad_value (float, optional) – 填充像素的值。
查看下面的例子:

torchvision.utils.save_image(tensor, filename, nrow=8, padding=2, normalize=False, range=None, scale_each=False, pad_value=0)
将给定的Tensor张量保存到图像文件中。 参数说明:

Tensor (张量或者列表) – 要保存的图像。如果小批量的Tensor张量,调用make_grid把Tensor张量存储为网格图像。
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值