小土堆PyTorch入门教程
Python的内置函数dir()
dir()函数,打开工具箱。用于列出一个对象的所有属性和方法。它返回一个包含对象所有属性和方法名称的列表。如果不传入参数,则返回当前作用域中所有可用的名称
#示例 查看pytorch
dir(torch)
dir(torch.cuda) # 可以更加具体详细的查看
dir(torch.cuda.is_available) #注意torch.cuda.is_available后没有括号
返回的结果是一个函数对象的属性列表
python 里 前后各有双下划线__函数名__是什么?
在 Python 中,魔术属性(Magic Attributes)也称为特殊属性(Special Attributes)也称为魔法方法、双下划线方法(Double Underscore Methods),是以双下划线 __ 开头和结尾的特殊命名方式,用于实现对象的特殊行为和操作,不允许被修改
Python的内置函数help(),查看官方解释文档
help()函数,查看说明书。用于获取对象、模块、函数、关键字等的帮助信息。当传入对象时,它会显示该对象的帮助文档。如果没有传入任何参数,则会进入交互式帮助模式。
help(torch.cuda.is_available)
Pytorch读取数据的两个类 Dataset和DataLoader
from torch.utils.data import Dataset
help(Dataset)
Dataset??
Dataset将数据和label进行组织编号0 1 2 3……,使得可以根据编号读取数据;需获取每一个数据及其label以及数据总数,要实现 len() 方法和 getitem() 方法。 len() 方法返回数据集的样本数量; getitem() 方法根据给定的索引返回对应的数据样本;
DataLoader对数据进行打包将数据集划分为小批量,按batchsize送入网络模型;可以接收一个 Dataset 对象作为输入,并根据指定的批量大小、是否打乱数据、是否使用多线程等参数,来构建一个用于数据加载的迭代器
Dataset类代码实战
通过继承Dataset类class MyData(Dataset),实现__len__和__getitem__方法,可以自定义自己的数据集类以适应不同的数据,蚂蚁蜜蜂/练手数据集:链接 密码: 5suq
from torch.utils.data import Dataset
from PIL import Image
import os
class MyData(Dataset):
def __init__(self, root_dir, label_dir):
self.root_dir = root_dir
self.label_dir = label_dir
self.path = os.path.join(self.root_dir, self.label_dir)
self.img_path = os.listdir(self.path)
def __getitem__(self, idx):
img_name = self.img_path[idx]
img_item_path = os.path.join(self.root_dir, self.label_dir,img_name)
img = Image.open(img_item_path)
label = self.label_dir
return img,label
def __len__(self):
return len(self.img_path)
root_dir = "蚂蚁蜜蜂数据集\\dataset\\train"
ants_label_dir = "ants"
ants_dataset = MyData(root_dir, ants_label_dir)
print(ants_dataset)
print(ants_dataset[0] ) # 根据重写的getitem返回 img与 label
img, label = ants_dataset[0]
img.show()
bees_label_dir = "bees"
bees_dataset = MyData(root_dir, bees_label_dir)
img, label = bees_dataset[0]
img.show()
train_dataset =ants_dataset + bees_dataset #两个数据集的拼接 未改变顺序,ants在前 bees在后
print(len(ants_dataset))
print(len(bees_dataset))
print(len(train_dataset))
# <__main__.MyData object at 0x000001A7F75D7980>
# (<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=768x512 at 0x1A7F8DEBDA0>, 'ants')
# 124
# 121
# 245
利用numpy.array()对PIL的图像进行转换
from PIL import Image
import numpy as np
img_path = r"images\7bf18e636a5dfe815fd7a53b5ad6ab94.png"
img = Image.open(img_path)
print(type(img))
img_array = np.array(img)
print(type(img_array))
# <class 'PIL.PngImagePlugin.PngImageFile'>
# <class 'numpy.ndarray'>
Pytorch中的Transforms
用于对图像进行预处理和数据增强操作,如调整图像大小、中心裁剪、随机裁剪、随机水平翻转、归一化、将 PIL 图像转换为 Tensor 等等
使用transforms的ToTensor()进行图片类型的转化
from torchvision import transforms
from PIL import Image
img_path = r"images\7bf18e636a5dfe815fd7a53b5ad6ab94.png"
img = Image.open(img_path)
print(type(img))
tensor_trans = transforms.ToTensor() # transforms.ToTensor() 这一步相当于实例化 返回totensor的对象
tensor_img = tensor_trans(img)
print(type(tensor_img))
# <class 'PIL.PngImagePlugin.PngImageFile'>
# <class 'torch.Tensor'>
Python的__call__ 方法
在 Python 中,_call_ 是一个特殊方法(也称为魔术方法或双下划线方法),用于使对象可以像函数一样被调用。当你在一个对象上调用 obj() 时,Python 解释器会查找该对象的__call__ 方法并调用它
class MyClass:
def __init__(self, value):
self.value = value
def __call__(self, x):
return self.value + x
obj = MyClass(10)
result = obj(5) # 调用了 __call__ 方法
print(result) # 输出: 15
在 Python 中,_call_ 是一个特殊方法(也称为魔术方法或双下划线方法),用于使对象可以像函数一样被调用。当你在一个对象上调用 obj() 时,Python 解释器会查找该对象的 _call_ 方法并调用它。
__call__方法的灵活性使得对象可以像函数一样被使用,这在某些情况下非常有用,例如实现可调用的对象或者定制对象的行为.
查看transforms的源代码,发现其实现了__call__方法
所以tensor_trans = transforms.ToTensor() ,tensor_img = tensor_trans(img)直接传入img调用了其中的__call__
tensor数据类型
神经网络专用的数据类型,包含了许多神经网络需要的参数,使用Python Console查看tensor_img的参数
opencv 使用cv2.imread()
读取的图像数据类型是numpy.ndarray
常见的transforms
使用Normalize对图像进行归一化,对每个通道进行归一化:(输入值–均值)/ 标准差
from torchvision import transforms
help(transforms.Normalize)
# Help on class Normalize in module torchvision.transforms.transforms:
# class Normalize(torch.nn.modules.module.Module)
# | Normalize(mean, std, inplace=False)
# |
# | Normalize a tensor image with mean and standard deviation.
# | This transform does not support PIL Image.
# | Given mean: ``(mean[1],...,mean[n])`` and std: ``(std[1],..,std[n])`` for ``n``
# | channels, this transform will normalize each channel of the input
# | ``torch.*Tensor`` i.e.,
# | ``output[channel] = (input[channel] - mean[channel]) / std[channel]``
# |
# | .. note::
# | This transform acts out of place, i.e., it does not mutate the input tensor.
# |
# | Args:
# | mean (sequence): Sequence of means for each channel.
# | std (sequence): Sequence of standard deviations for each channel.
# | inplace(bool,optional): Bool to make this operation in-place.
# |
# | Method resolution order:
# | Normalize
# | torch.nn.modules.module.Module
# | builtins.object
# |
# ...
# | call_super_init = False
# |
# | dump_patches = False
# Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...
假设三个通道的均值和标准差都为0.5
from torch.utils.tensorboard import SummaryWriter
from PIL import Image
from torchvision import transforms
writer = SummaryWriter("logs") # 日志文件存储位置
img_path = "C:\\Users\\Sen\\Desktop\\pytorch\\Pytorch教程\\data\\train\\bees_image\\16838648_415acd9e3f.jpg"
img = Image.open(img_path)
tensor_trans = transforms.ToTensor()
tensor_img = tensor_trans(img)
trans_norm = transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
img_norm = trans_norm(tensor_img)
print(tensor_img[0][0][0])
print(img_norm[0][0][0])
writer.add_image("Normalize",img_norm)
writer.close()
transform.Resize()的使用
注意图片数据类型,通过Image.open读取的是PIL类型的
transform.Resize() 可以处理 PIL 图像对象,也可以处理张量类型的数据
from PIL import Image
from torchvision import transforms
img_path = r"images\7bf18e636a5dfe815fd7a53b5ad6ab94.png"
img = Image.open(img_path)
print("图片原始大小,读取为PIL类型",img.size)
trans_resize = transforms.Resize((512,512))
img_resize = trans_resize(img)
print("对PIL类型进行Resize",img_resize)
tensor_trans = transforms.ToTensor()
img_resize = tensor_trans(img_resize)
print("将PIL Reszie的图片转换为Tensor",img_resize)
trans_resize2 = transforms.Resize((256,256))
img_resize = trans_resize(img_resize)
print("对tensor类型的数据进行Resize",img_resize)
利用Compose进行resize
Compose用于组合多个图像转换(transform)操作。通过 Compose,可以创建一个转换流程,这个流程可以按顺序执行多个图像处理操作,这些操作可以包括缩放、裁剪、归一化等,其需要的参数是一个列表,其元素类型是transforms类型。
格式Compose([transforms参数1,transforms参数2,…])
from PIL import Image
from torchvision import transforms
img_path = r"images\7bf18e636a5dfe815fd7a53b5ad6ab94.png"
img = Image.open(img_path)
print(img)
trans_resize2 = transforms.Resize(512)
trans_totensor = transforms.ToTensor()
trans_compose = transforms.Compose([trans_resize2,trans_totensor])
img_resize_2 = trans_compose(img)
print(img_resize_2)
随机裁剪RandomCrop
RandomCrop 是 PyTorch 中用于图像数据增强(data augmentation)的函数之一,它可以在图像或张量的随机位置裁剪出指定大小的区域
transforms.RandomCrop((128, 128))会随机在输入图像中裁剪出大小为 128x128 的区域,并返回裁剪后的图像对象
from PIL import Image
from torchvision import transforms
help(transforms.RandomCrop)