• Pytorch:一些常用代码


    1、PIL读取图像转成tensor

    1. pil_img = Image.open(img_path)
    2. array = np.asarray(pil_img)
    3. data = t.from_numpy(array)

    2、读取路径,得到文件名

    1)遍历文件夹,得到想要的文件名 

    1. img_path = self.imgs[index]
    2. # dog->1, cat->0
    3. label = 1 if 'dog' in img_path.split('/')[-1] else 0
    4. imgs = os.listdir(root)
    5. # 所有图片的绝对路径
    6. # 这里不实际加载图片,只是指定路径,当调用__getitem__时才会真正读图片
    7. self.imgs = [os.path.join(root, img) for img in imgs]
    1. def __init__(self, root, transforms=None, train=True, test=False):
    2. """
    3. 主要目标: 获取所有图片的地址,并根据训练,验证,测试划分数据
    4. """
    5. self.test = test
    6. imgs = [os.path.join(root, img) for img in os.listdir(root)]
    7. # test1: data/test1/8973.jpg
    8. # train: data/train/cat.10004.jpg
    9. # imgs:['data/test1/8973.jpg', 'data/test1/8974.jpg', 'data/test1/8975.jpg', 'data/test1/8976.jpg']
    10. if self.test:
    11. imgs = sorted(imgs, key=lambda x: int(x.split('.')[-2].split('/')[-1]))
    12. else:
    13. imgs = sorted(imgs, key=lambda x: int(x.split('.')[-2]))
    14. imgs_num = len(imgs)

    2)另外一个例子:遍历所有文件的名字,随机划分训练集合验证集

    读取换行的文件名,记得去除空格:

    Python strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。

    1. def main():
    2. random.seed(0) # 设置随机种子,保证随机结果可复现
    3. #所有图片名字格式: 2007_00000027.jpg
    4. files_path = "./VOCdevkit/VOC2012/Annotations"
    5. assert os.path.exists(files_path), "path: '{}' does not exist.".format(files_path)
    6. val_rate = 0.5
    7. files_name = sorted([file.split(".")[0] for file in os.listdir(files_path)])
    8. files_num = len(files_name)
    9. val_index = random.sample(range(0, files_num), k=int(files_num*val_rate))
    10. train_files = []
    11. val_files = []
    12. for index, file_name in enumerate(files_name):
    13. if index in val_index:
    14. val_files.append(file_name)
    15. else:
    16. train_files.append(file_name)
    17. try:
    18. train_f = open("train.txt", "x")
    19. eval_f = open("val.txt", "x")
    20. train_f.write("\n".join(train_files))
    21. eval_f.write("\n".join(val_files))
    22. except FileExistsError as e:
    23. print(e)
    24. exit(1)

    3、PyTorch提供了torchvision。

    它是一个视觉工具包,提供了很多视觉图像处理的工具,其中transforms模块提供了对PIL Image对象和Tensor对象的常用操作。

    对PIL Image的操作包括:

    • Scale:调整图片尺寸,长宽比保持不变
    • CenterCropRandomCropRandomResizedCrop: 裁剪图片
    • Pad:填充
    • ToTensor:将PIL Image对象转成Tensor,会自动将[0, 255]归一化至[0, 1]

    对Tensor的操作包括

    • Normalize:标准化,即减均值,除以标准差
    • ToPILImage:将Tensor转为PIL Image对象

    Compose函数拼接多个操作,如下:

    1. from PIL import Image
    2. import numpy as np
    3. from torchvision import transforms as T
    4. transform = T.Compose([
    5. T.Resize(224), # 缩放图片(Image),保持长宽比不变,最短边为224像素
    6. T.CenterCrop(224), # 从图片中间切出224*224的图片
    7. T.ToTensor(), # 将图片(Image)转成Tensor,归一化至[0, 1]
    8. T.Normalize(mean=[.5, .5, .5], std=[.5, .5, .5]) # 标准化至[-1, 1],规定均值和标准差
    9. ])

    4、torchvision.io :read_image

    this function allows to read an image and directly load it as a tensor.允许读取图像并将其作为张量直接加载。

    1. from pathlib import Path
    2. import matplotlib.pyplot as plt
    3. import numpy as np
    4. import torch
    5. import torchvision.transforms as T
    6. from torchvision.io import read_image
    7. plt.rcParams["savefig.bbox"] = 'tight'
    8. torch.manual_seed(1)
    9. def show(imgs):
    10. fix, axs = plt.subplots(ncols=len(imgs), squeeze=False)
    11. for i, img in enumerate(imgs):
    12. img = T.ToPILImage()(img.to('cpu'))
    13. axs[0, i].imshow(np.asarray(img))
    14. axs[0, i].set(xticklabels=[], yticklabels=[], xticks=[], yticks=[])
    15. dog1 = read_image(str(Path('assets') / 'dog1.jpg'))
    16. dog2 = read_image(str(Path('assets') / 'dog2.jpg'))
    17. show([dog1, dog2])

    5、torchvision.transforms中的图像预处理代码

    1. from torchvision import models, transforms
    2. # 迁移学习,预训练模型
    3. net = models.resnet18(pretrained=True)
    4. # 标准化
    5. normalize = transforms.Normalize(
    6. mean=[0.485, 0.456, 0.406],
    7. std=[0.229, 0.224, 0.225]
    8. )
    9. # 数据转换
    10. image_transform = transforms.Compose([
    11. # 将输入图片resize成统一尺寸
    12. transforms.Resize([224, 224]),
    13. # 随机裁剪(随机大小,随机宽高比)并调整至指定大小
    14. T.RandomReSizedCrop(224),
    15. # 随机水平翻转
    16. T.RandomHorizontalFlip(),
    17. # 将PIL Image或numpy.ndarray转换为tensor,并除255归一化到[0,1]之间
    18. transforms.ToTensor(),
    19. # 标准化处理-->转换为标准正太分布,使模型更容易收敛
    20. normalize
    21. ])

    6、zip压缩函数使用:

    将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
    enumerate() 枚举函数:用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。

    1. # training and plot
    2. for epoch in range(Epoch):
    3. for step, (b_x, b_y) in enumerate(loader):
    4. for net,opt,l_his in zip(nets,optimizers,losses_his):
    5. output = net(b_x)
    6. loss=criterion(output,b_y)
    7. opt.zero_grad()
    8. loss.backward()
    9. opt.step()
    10. l_his.append(loss.data.numpy())
    11. if step%25 == 1 and epoch%7==0:
    12. labels = ['SGD', 'Momentum', 'RMSprop', 'Adam','Adagrad']
    13. for i, l_his in enumerate(losses_his):
    14. plt.plot(l_his, label=labels[i])
    15. plt.legend(loc='best')
    16. plt.xlabel('Steps')
    17. plt.ylabel('Loss')
    18. plt.ylim((0, 0.2))
    19. plt.xlim((0, 200))
    20. print('epoch: {}/{},steps:{}/{}'.format(epoch+1,Epoch,step*Batch_size,len(loader.dataset)))
    21. plt.show()

    7、指定范围,随机填充tensor

    torch.empty(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False, pin_memory=False)
    根据给定形状和类型,返回一个包含未经初始化数据的张量.

    random_(from=0, to=None, *, generator=None) → Tensor
    用一个离散均匀分布[from, to - 1]来填充当前自身张量.

    1. import torch
    2. loss = nn.CrossEntropyLoss()
    3. input = torch.randn(3, 5, requires_grad=True)
    4. input
    5. Out[12]:
    6. tensor([[-0.1153, -1.0817, 2.5642, 0.5169, -0.3778],
    7. [-1.3685, 1.6164, 1.3879, -0.1657, 0.4537],
    8. [ 0.6512, 0.2624, 0.5835, 0.1809, 0.8777]], requires_grad=True)
    9. target = torch.empty(3, dtype=torch.long).random_(5)# 指定范围
    10. target
    11. Out[14]: tensor([1, 3, 0])
    12. output = loss(input, target)
    13. output.backward()
    14. output
    15. Out[17]: tensor(2.6730, grad_fn=<NllLossBackward0>)

    torch.linspace(start, end, steps=100, out=None) → Tensor

    返回一个1维张量,包含在区间start和end上均匀间隔的step个点。

    输出张量的长度由steps决定。这个有时会用到取plot横坐标。
     

    1. torch.linspace(3, 10, steps=5)
    2. 3.0000
    3. 4.7500
    4. 6.5000
    5. 8.2500
    6. 10.0000
    7. [torch.FloatTensor of size 5]

    8、批量更改文件名、修改图片大小

         由于参考代码训练的是32X32图片,而且图片名字也是标签名+序号,所以我们想要直接用的话,就必须做修改工作。

    分为:rename、resize两个步骤。

    1. #coding=utf-8
    2. from PIL import Image
    3. import os
    4. import os.path
    5. import glob
    6. def rename(rename_path,outer_path,folderlist):
    7. #列举文件夹
    8. for folder in folderlist:
    9. if os.path.basename(folder)=='bus':
    10. foldnum = 0
    11. elif os.path.basename(folder)=='taxi':
    12. foldnum = 1
    13. elif os.path.basename(folder)=='truck':
    14. foldnum = 2
    15. elif os.path.basename(folder)=='family sedan':
    16. foldnum = 3
    17. elif os.path.basename(folder)=='minibus':
    18. foldnum = 4
    19. elif os.path.basename(folder)=='jeep':
    20. foldnum = 5
    21. elif os.path.basename(folder)=='SUV':
    22. foldnum = 6
    23. elif os.path.basename(folder)=='heavy truck':
    24. foldnum = 7
    25. elif os.path.basename(folder)=='racing car':
    26. foldnum = 8
    27. elif os.path.basename(folder)=='fire engine':
    28. foldnum = 9
    29. inner_path = os.path.join(outer_path, folder)
    30. total_num_folder = len(folderlist) #文件夹的总数
    31. # print 'total have %d folders' % (total_num_folder) #打印文件夹的总数
    32. filelist = os.listdir(inner_path) #列举图片
    33. i = 0
    34. for item in filelist:
    35. total_num_file = len(filelist) #单个文件夹内图片的总数
    36. if item.endswith('.jpg'):
    37. src = os.path.join(os.path.abspath(inner_path), item) #原图的地址
    38. dst = os.path.join(os.path.abspath(rename_path), str(foldnum) + '_' + str(i) + '.jpg') #新图的地址(这里可以把str(folder) + '_' + str(i) + '.jpg'改成你想改的名称)
    39. try:
    40. os.rename(src, dst)
    41. # print 'converting %s to %s ...' % (src, dst)
    42. i += 1
    43. except:
    44. continue
    45. #训练集
    46. rename_path1 = 'E:/Tensorflow-CNN-VehicleIdentification/renametrain'
    47. outer_path1 = 'E:/Tensorflow-CNN-VehicleIdentification/train'
    48. folderlist1 = os.listdir(r"E:/Tensorflow-CNN-VehicleIdentification/train")
    49. rename(rename_path1,outer_path1,folderlist1)
    50. print("train totally rename ! ! !")
    51. #测试集
    52. rename_path2 = 'E:/Tensorflow-CNN-VehicleIdentification/renametest'
    53. outer_path2 = 'E:/Tensorflow-CNN-VehicleIdentification/val'
    54. folderlist2 = os.listdir(r"E:/Tensorflow-CNN-VehicleIdentification/val")
    55. rename(rename_path2,outer_path2,folderlist2)
    56. print("test totally rename ! ! !")
    57. #修改图片尺寸
    58. def convertjpg(jpgfile,outdir,width=32,height=32):
    59. img=Image.open(jpgfile)
    60. img=img.convert('RGB')
    61. img.save(os.path.join(outdir,os.path.basename(jpgfile)))
    62. new_img=img.resize((width,height),Image.BILINEAR)
    63. new_img.save(os.path.join(outdir,os.path.basename(jpgfile)))
    64. #训练集
    65. for jpgfile in glob.glob("E:/Tensorflow-CNN-VehicleIdentification/renametrain/*.jpg"):
    66. convertjpg(jpgfile,"E:/Tensorflow-CNN-VehicleIdentification/data")
    67. print("train totally resize ! ! !")
    68. #测试集
    69. for jpgfile in glob.glob("E:/Tensorflow-CNN-VehicleIdentification/renametest/*.jpg"):
    70. convertjpg(jpgfile,"E:/Tensorflow-CNN-VehicleIdentification/test")
    71. print("test totally resize ! ! !")

    9、查看python包的版本

    1.方法一 通过命令行
    pip listconda list中有相应的包名和版本号
    pip show 包名
    pip show numpy
    2.方法二
    通过程序

    1. import numpy
    2. print(numpy.__version__)


    3. 查看python版本
    命令行中输入python
    命令行 python --version
    (配置好环境变量的前提下)

    10、在python的List中使用for循环语句的技巧汇编

    参考文章:《在python的List中使用for循环语句的技巧汇编_-派神-的博客-CSDN博客_list for

    1) 简单替换for循环

    它的主要语法结构如下:

    my_list=[ 表达式 for 循环项 in 循环体 (if 条件) ]

    这里表达式可以为循环项,也可以为循环项的函数或者方法,下面我们看给例子:

    1. name = "Donald Trump"
    2.  
    3. #list内的for循环语法,只使用一句代码
    4. my_list = [c for c in name]
    5.  
    6. print(name)
    7. print(my_list)

    2)在list内的循环中使用if 条件

    1. names_list = ["Washington", "Trump", "Obama", "bush", "Clinton", "Reagan"]
    2. l1 = [name for name in names_list if name.startswith('W')]
    3. l2 = [name for name in names_list if name.startswith('W') or len(name) < 5]
    4. l3 = [name for name in names_list if len(name) < 5 and name.islower()]
    5. print(l1, l2, l3)

    3) 使用更加复杂的表达式

    1. names_list = ["washington", "trump", "obama", "bush", "clinton", "reagan"]
    2. #将人名首字母大写
    3. new_names = [name.capitalize() for name in names_list]
    4. print(new_names)

    这里我们list内的表达式使用了循环项name的方法capitalize(), 我们再看一个例子:

    my_list=[ 表达式(if...else 条件) for 循环项 in 循环体 ] 

    1. names_list = ["Washington", "Trump", "Obama", "bush", "Clinton", "Reagan"]
    2. #在表达式中使用if条件
    3. new_names = [name if name.startswith('T') else 'Not President' for name in names_list]
    4. print(new_names)

    之前我们是在for循环的尾部添加if 条件,不过我们也可以在表达式中使用if条件语句。这里需要指出的是表达式内的if条件语句中必须要同时使用else语句,这和之前在for循环尾部添加if条件有所不同,这是因为在表达式内的if语句必须遵循给变量赋值的python语法.

    4)尽量使用生成器(Generator)变量来减少内存开销 

    在python中定义一个list变量时,一般会给这个list变量立即分配内存,这种在定义变量时立即分配内存的方式会增加系统的内存开销,而一种高效的方法是只在定义变量时并不立即分配实际内存,只在真正使用变量时才会分配内存,这就是我们的Generator变量,在定义Generator变量时只要将原来list的方括号替换成圆括号即可:

    1. #list变量,立即分配实际内存
    2. L1 = [x for x in range(1_000_000)]
    3. #Generator变量,不分配实际内存
    4. L2 = (x for x in range(1_000_000))
    5. print(L1.__sizeof__())
    6. print(L2.__sizeof__())

     

    1. #list变量
    2. L1 = [ w for w in range(10)]
    3. for i in L1:
    4. print(i)
    5. #替换为生成器变量
    6. L2 = (w for w in range(10))
    7. for i in L2:
    8. print(i)

    11、Python中文件的open,close,read,write等操作

    1)字文本值,可以这样操作。f.readlines()返回的是列表,可以直接用for循环解析 。

    1. f = open('test.txt', 'r')
    2. content = f.readlines() #读取文件中的全部行,按行划分存储到列表中,类型字符串
    3. print(type(content)) #打印读取结果的值类型,用list列表存储
    4. i=1 #遍历列表,将读取的内容显示出来,按照原来文件的行划分。
    5. for temp in content:
    6. print("%d:%s"%(i, temp))
    7. i+=1
    8. f.close()

    参考网址:Python中文件的open,close,read,write等操作_涤生大数据的博客-CSDN博客

    读取换行的文件名,记得去除空格:

    Python strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。

    1. with open(txt_path) as read:
    2. xml_list = [os.path.join(self.annotations_root, line.strip() + ".xml")
    3. for line in read.readlines() if len(line.strip()) > 0]

    2)Python如何读取二进制文件,并解析。

    1. def xshow(filename, nx, nz):
    2. # 我们需要给定二进制数据的行数列数(nx和ny)来确定图像的形状
    3. f = open(filename, "rb")
    4. pic = np.zeros((nx, nz))
    5. for i in range(nx):
    6. for j in range(nz):
    7. data = f.read(4)
    8. # 使用 struct 模块中的 unpack() 函数将二进制转化为十进制的float32型
    9. elem, = struct.unpack("f", data)
    10. pic[i][j] = elem
    11. f.close()
    12. return pic


    参考文章:

    1、使用Python读取二进制文件的实例讲解 - 杰米工坊 更新日期:2022/11/20

    2、python怎么读二进制文件 - 知乎 

    3、Python读取二进制文件代码方法解析_程序猿中的BUG的博客-CSDN博客

    12、python中字符串的join()函数的用法

    分隔符,后面可以接- 列表元组字符串字典集合,它将可迭代的每个元素(如列表,字符串和元组)连接到字符串,并返回连接后的字符串。

    1. str="abcd"
    2. print("_".join(str))

    运行结果: 

    13、指定数据类型申请list和tupe

    这是 Python 3.5 中引入的 Type Annotation,是一种注解,用来提示变量的类型。其中

    • var 为要定义的变量;
    • type 为该变量期待的类型;
    • value 为赋给该变量的值。
    1. a: int = 10
    2. def func(arg: int)
    1. # 第一种
    2. original_image_sizes = torch.jit.annotate(list[tuple[int, int]], [])
    3. a = [1,2]
    4. b = [3,4]
    5. original_image_sizes.append((a,b))
    6. # 第二种
    7. original:list[tuple[int, int]] = []
    8. original.append((a,b))

    14、Pycharm的Python Console终端清除命令

    Pycharm的Python Console 清除单个变量命令:

    del 变量名称

    Pycharm的Python Console 清除所有变量命令:

    reset -f

    Pycharm的Python Console 清屏:

    右击鼠标,选择clear。

    15、torch.as_tensor()、torch.Tensor() 、 torch.tensor() 、transforms.ToTensor()的区别

    详细情况参考我这篇文章《torch.as_tensor()、torch.Tensor() 、 torch.tensor() 、transforms.ToTensor()的区别_三世的博客-CSDN博客》

    1)torch.as_tensor(data, dtype=None,device=None)->Tensor : 为data生成tensor,浅拷贝

    如果data已经是tensor或ndarray,且dtype和device与参数相同,则生成的tensor会和data共享内存(浅拷贝)。

    1. #1)数据类型和device相同,浅拷贝,共享内存
    2. import numpy
    3. a = numpy.array([1, 2, 3])
    4. t = torch.as_tensor(a)
    5. t[0] = -1

    2) torch.tensor() 是一个通过深拷贝数据,构造一个新张量的函数

    torch.tensor(data*dtype=Nonedevice=Nonerequires_grad=Falsepin_memory=False) →Tensor

    重点是data的数据类型can be a list, tuple, NumPy ndarray, scalar, and other types,就没waring。
    但data是tensor类型,使用torch.tensor(data)就会报waring

    1. #没警告:data can be a list, tuple, NumPy ndarray, scalar, and other types
    2. import torch
    3. import numpy
    4. a = numpy.array([1, 2, 3])
    5. t = torch.tensor(a)
    6. b = [1,2,3]
    7. t= torch.tensor(b)
    8. c = (1,2,3)
    9. t= torch.tensor(c)

    #data是tensor类型,有警告 

    1. #data是tensor类型,有警告
    2. import torch
    3. import numpy
    4. d = torch.tensor([[1,2,3],[1,2,3]])
    5. t= torch.tensor(d) #能深拷贝,但会报warning,建议用t = a.clone().detach()
    6. # detach是内存共享的,而clone()是不内存共享的。
    7. print(d.shape,d.dtype,t.shape,t.dtype)
    8. # torch.Size([2, 3]) torch.int64 torch.Size([2, 3]) torch.int64

     3)torch.Tensor() 是默认张量类型 (torch.FloatTensor()) 的别名。也就是说,torch.Tensor() 的作用实际上跟 torch.FloatTensor() 一样。

    4)transforms.ToTensor()

    ToTensor()将shape为(H, W, C)的nump.ndarray或img转为shape为(C, H, W)的tensor,其将每一个数值归一化到[0,1],其归一化方法比较简单。
    在transforms.Compose([transforms.ToTensor()])中加入transforms.Normalize(),如上面代码所示:则其作用就是先将输入归一化到(0,1),再使用公式"(x-mean)/std",将每个元素分布到(-1,1)。

    16、Python 列表list详解(超详细)

    参考这篇文章《Python 列表list详解(超详细)_LeoATLiang的博客-CSDN博客_python的list

    17、python学习--DataFrame,可以分组统计 groupby

    参考这篇文章《python学习--DataFrame_悠闲的小鱼Liu的博客-CSDN博客_python dataframe

    18、 Python 更新字典的三种形式(update())

    1. >>> d = {
    2. ... 'title': 'Python Web Site',
    3. ... 'url': 'http://www.python.org'
    4. ... }
    5. >>> x = [('title', 'Python Language Website')]
    6. >>> d.update(x)
    7. >>> d
    8. {'url': 'http://www.python.org', 'title': 'Python Language Website'}

    参考这篇文章《Python 更新字典的三种形式_梦因you而美的博客-CSDN博客_python 字典 更新

    19、Python中Tuple(元组的单引号)

    Python 规定,单元素 tuple 要多加一个逗号“,”,这样就避免了歧义。比如t=(1),被误解为申请了一个int型变量t =1:

    1. >>> t = (1,)
    2. >>> print t
    3. (1,)

    参考这篇文章《Python中Tuple(元组)_码上寒山石径斜的博客-CSDN博客_python tuple

    20、Python中的isinstance()函数:

     1)判断一个函数是否是一个已知的类型,多个类型的话,第二个参数用一个元组代替。

    1. a = 2
    2. isinstance(a,int) # 结果返回 True
    3. isinstance(a,str) # 结果返回 False
    4. isinstance(a,(str,int,list)) # 是元组中的一个类型 int,结果返回 True

    2)与type()函数的区别是:

    • isinstance() 会认为子类是一种父类类型,考虑继承关系。
    • type() 不会认为子类是一种父类类型,不考虑继承关系。
    1. class A:
    2. pass
    3. class B(A):
    4. pass
    5. isinstance(A(), A) # returns True
    6. type(A()) == A # returns True
    7. isinstance(B(), A) # returns True
    8. type(B()) == A # returns False

     参考这篇文章《Python中的isinstance()函数_DaYinYi的博客-CSDN博客_python isinstance

    21、python中如何使用None增加数据维度 

    1. import torch
    2. x = torch.randint(4,(1, 4)) # torch.Size([1, 4])
    3. print(x)
    4. # 增加第一维度
    5. a = x[None, :, :] # torch.Size([1, 1, 4])
    6. # 也是增加了第一维度
    7. b = x[None] # torch.Size([1, 1, 4])
    8. # 增加第三维度
    9. c = x[:,:,None] # torch.Size([1, 4, 1])

    参考文章:

    Pytorch中用None增加Tensor维度_打呼噜的星.的博客-CSDN博客_pytorch 添加维度

    python中如何使用None增加数据维度_月下花弄影的博客-CSDN博客

    再举个例子《Fast R-CNN》里的代码:

    1. def normalize(self, image):
    2. """标准化处理"""
    3. dtype, device = image.dtype, image.device
    4. mean = torch.as_tensor(self.image_mean, dtype=dtype, device=device)
    5. std = torch.as_tensor(self.image_std, dtype=dtype, device=device)
    6. # [:, None, None]: shape [3] -> [3, 1, 1]
    7. return (image - mean[:, None, None]) / std[:, None, None]

    写个case验证一下。 

    1. import torch
    2. image = torch.rand((10,3,2))
    3. mean =[0.1]*10
    4. std = [0.5]*10
    5. mean = torch.as_tensor(mean)
    6. std = torch.as_tensor(std)
    7. m = (image-mean[:,None,None]) /std[:,None,None] #image的shape是C*H*W,mean和std只是一个维度,所以要增加两个维度,才能计算。

     22、pytorch之torch.unbind()函数

    移除指定维后,返回一个元组,包含了沿着指定维切片后的各个切片。

    1. import torch
    2. t = torch.rand(3,3) #随机生成一个tensor
    3. print(t)
    4. print(t.shape)
    5. r = torch.unbind(t,dim=0)#dim = 0指定拆除的维度
    6. print(r)
    7. s = torch.unbind(t,dim=1)#dim = 1指定拆除的维度
    8. print(s)

    结果: 

     参考文章《pytorch之torch.unbind - 飞猪流 - 博客园

    23、torch.stack()函数

    stack 将tensor进行按照指定维度进行堆叠,函数返回的结果会新增一个维度。

    dim = 0时,将tensor1和tensor2进行堆叠;
    dim = 1时,将tensor1[0]和tensor2[0]进行堆叠;
    dim = 2时,将tensor1[0][0]和tensor2[0][0]进行堆叠;

    1. import torch
    2. w = torch.arange(12).reshape(3, 4)
    3. h = -torch.arange(12).reshape(3, 4)
    4. c = torch.stack((w, h), dim=0)
    5. >>>
    6. tensor([[[ 0, 1, 2, 3],
    7. [ 4, 5, 6, 7],
    8. [ 8, 9, 10, 11]],
    9. [[ 0, -1, -2, -3],
    10. [ -4, -5, -6, -7],
    11. [ -8, -9, -10, -11]]])
    12. >>> c.shape
    13. >torch.Size([2, 3, 4])
    14. -----------------------------------------------
    15. b = torch.stack((w, h), dim=1)
    16. >>>
    17. tensor([[[ 0, 1, 2, 3],
    18. [ 0, -1, -2, -3]],
    19. [[ 4, 5, 6, 7],
    20. [ -4, -5, -6, -7]],
    21. [[ 8, 9, 10, 11],
    22. [ -8, -9, -10, -11]]])
    23. >>>b.shape
    24. >torch.Size([3, 2, 4])
    25. -----------------------------------------------
    26. d = torch.stack((w, h), dim=2)
    27. print(d)
    28. print(d.shape)
    29. >>>
    30. tensor([[[ 0, 0],
    31. [ 1, -1],
    32. [ 2, -2],
    33. [ 3, -3]],
    34. [[ 4, -4],
    35. [ 5, -5],
    36. [ 6, -6],
    37. [ 7, -7]],
    38. [[ 8, -8],
    39. [ 9, -9],
    40. [ 10, -10],
    41. [ 11, -11]]])
    42. torch.Size([3, 4, 2])

    参考文章:

    torch.stack()函数_小娜美要努力努力的博客-CSDN博客_torch.stack() 》

    torch.stack()用法_打呼噜的星.的博客-CSDN博客_torch.stack()

    24、【torch.Tensor.new_full】详解

    用新值,填充新建tensor和原先tensor形状一样

    1. import torch
    2. ten = torch.ones((2,), dtype=torch.float64)
    3. new_ten=ten.new_full((3, 4), 3.141592)
    4. print(new_ten.dtype,new_ten.device,new_ten.requires_grad)
    5. print(new_ten)

    参考文章《【torch.Tensor.new_full】详解_panbaoran913的博客-CSDN博客_new_full

     25、zip()可以用for循环并行迭代

    1)zip()返回的是zip对象,可以通过list()转换成list查看,也可以通过dict()转换成字典查看

    1. a = ["a","c","e","g"]
    2. b = ["b","d","f","h"]
    3. print("这是一个列表\n",list(zip(a,b))) #转换成列表
    4. print("这是一个字典\n",dict(zip(a,b))) #转换成字典

    2)每个迭代器的元素个数不一致,则返回的列表长度与最短的一致。

    3)zip()可以用for循环并行迭代

    1. a = [1,2,3,4,5]
    2. b = [5,4,3,2,6]
    3. c = zip(a,b)
    4. for a, b in c:
    5. print(a,"*",b,"=",a*b)

    结果:

    4)与 zip 相反,zip(*) 可理解为解压,返回二维矩阵式 

    1. a = [1,2,3,4,5]
    2. b = ["d","b","e","r"]
    3. c = zip(*(zip(a,b)))
    4. print(list(c))

    结果:

     参考文章:《Python内置函数zip()的用法 - 小白白学Python - 博客园

    26、torch.copy_()函数进行tensor的复制。

     Tensor.copy_(srcnon_blocking=False) → Tensor

    定义:Copies the elements from src into self tensor and returns self.

    1)若采用直接赋值的方式,原来权重的存储指针会指向新得到的权重张量的存储区域;而使用 .copy_() 的话,仅仅是改变原来权重的值,存储区域则不发生改变。copy_()有利于降低运算。

    1. import torch
    2. x = torch.tensor([[1,2], [3,4], [5,6]])
    3. y = torch.rand((3,2)) # [0,1)之间均匀分布
    4. print(y,id(y))
    5. y = x #赋值操作,导致y的地址指向变了
    6. print(y,id(y))
    1. import torch
    2. x = torch.tensor([[1,2], [3,4], [5,6]])
    3. y = torch.rand((3,2)) # [0,1)之间均匀分布
    4. print(y,id(y))
    5. y.copy_(x) # copy_()操作,y的地址指向没变,只是重新赋值。
    6. print(y,id(y))

    2)指定区域拷贝

    1. import torch
    2. x = torch.tensor([[1,2], [3,4], [5,6]])
    3. z = torch.rand((4,2))
    4. z[:x.shape[0],:x.shape[1]].copy_(x) #只拷贝x的大小区域
    5. print(z[:x.shape[0],:x.shape[1]].copy_(x))
    6. print(z)

     参考文章

    【Pytorch 模型训练 Issue】tensor.copy_() 与 直接赋值(=) 对训练耗时的影响 - 知乎

    torch.copy_()函数介绍_三世的博客-CSDN博客

    27、Python官方的copy操作: 直接赋值、浅拷贝和深度拷贝解析 

    • 直接赋值:其实就是对象的引用(别名)。

    • 浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象。

    • 深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象。

    • 列表切片等价于深复制  比如:list1 = [1,2,[3,4]]  list2 = list1[:]

    参考文章:

    python 模块 copy 复制详解_ghostwritten的博客-CSDN博客_python copy

    Python 直接赋值、浅拷贝和深度拷贝解析 | 菜鸟教程

    28、torch.nn.init常用函数总结

    1. torch.nn.init.uniform_(tensor, a=0.0, b=1.0):按均匀分布U ( a , b ) U(a,b)U(a,b)对tensor随机赋值。
    2. torch.nn.init.normal_(tensor, mean=0.0, std=1.0) :按正态分布N ( μ 或 mean , σ 或 std ) N(\mu或mean,\sigma或std)N(μ或mean,σ或std)对tensor随机赋值。
    3. torch.nn.init.constant_(tensor, val):使用常数valtensor赋值。
      # 使用nn.init.constant_对参数赋值
      nn.init.constant_(self.linear.weight, 0.2)
    4. torch.nn.init.ones_(tensor) :使用常数1tensor赋值。
    5. torch.nn.init.zeros_(tensor):使用常数0tensor赋值。
    6. torch.nn.init.eye_(tensor) :使用常数1tensor的主对角线进行赋值,其余位置为常数0
    7. torch.nn.init.sparse_(tensor, sparsity, std=0.01) :生成稀疏矩阵。

      sparsity :每列中需要被设置成零的元素比例,std :用于生成的正态分布的标准差。

    参考文章《torch.nn.init常用函数总结_不牌不改的博客-CSDN博客_torch.nn.init.normal_

    29、pytorch中stack()函数和cat()函数的区别

    pytorch框架其中stack()函数和cat()函数都是将两个输入组合成一个batch.

    1)stack函数
    二者的区别在于,stack()函数是将两个输入堆叠起来,维度会增加1。

    1. import torch
    2. x = torch.rand((2,3))
    3. y = torch.rand((2,3))
    4. z = torch.stack((x,y),dim=0)

    这样两个堆叠起来的 z 的维度是(2,2,3),相当于在dim=0将二者堆叠起来,第一个数字2就是增加的维度。输出结果:

     2)cat函数
    而cat()函数是将两个输入在现有维度上叠加起来,不改变维度数量。

    1. import torch
    2. x1 = torch.rand((2,3))
    3. y1 = torch.rand((2,3))
    4. z1 = torch.cat((x1,y1),dim=0)

    这样两个叠加起来的 z1 的维度是(2,3),相当于在dim=0将二者叠加起来,不改变输入的维度。结果输出:

    30、Pytorch的tensor基本操作

    1)tensor的创建

    2)tensor的索引与切片

    3)tensor维度的变换

    参考文章《Pytorch的tensor基本操作_Swayzzu的博客-CSDN博客_pytorch tensor

    30、torch.split()用法

    torch.split(tensorsplit_size_or_sectionsdim=0)

     torch.split()作用将tensor分成块结构。

    1)split_size_or_sections为int型时

    1. import torch
    2. x = torch.rand(4,8,6)
    3. y = torch.split(x,2,dim=0) #按照4这个维度去分,每大块包含2个小块
    4. for i in y :
    5. print(i.size())
    6. output:
    7. torch.Size([2, 8, 6])
    8. torch.Size([2, 8, 6])

      2)split_size_or_sections为list型时。

    1. import torch
    2. x = torch.rand(4,8,6)
    3. y = torch.split(x,[2,3,3],dim=1)
    4. for i in y:
    5. print(i.size())
    6. output:
    7. torch.Size([4, 2, 6])
    8. torch.Size([4, 3, 6])
    9. torch.Size([4, 3, 6])

    参考文章:《torch.split()_skycrygg的博客-CSDN博客_torch.split

  • 相关阅读:
    Linux MQTT智能家居(MQTT框架)
    数据交换的常见格式,如JSON格式和XML格式
    Spring Data JPA系列3:JPA项目中核心场景与进阶用法介绍
    基于nodejs+vue酒店综合服务[程序+论文+开题]-计算机毕业设计
    MySQL 索引
    VsCode密钥链接远程服务器
    Qt开发经验小技巧241-245
    在线问诊 Python、FastAPI、Neo4j — 创建 检查节点
    客户端和服务器之间的通信
    java/golang/csharp/c++/python生成pb文件的方法
  • 原文地址:https://blog.csdn.net/qimo601/article/details/123575648