Pytorch学习笔记(一)

目录

#Pytorch加载数据

# read_data.py

 # rename_dataset.py

# test_tensorboard.py

# test_transform.py

# dataset_transform.py

# test_dataloader.py


#Pytorch加载数据

读取数据涉及两个类:DatasetDataLoader
Dataset提供一种方式去获取数据及其对应的真实labelDataLoader为网络提供不同的数据形式
Dataset告诉程序数据集存在什么位置、每个数据是什么;Dataloader将数据加载到神经网络中,从Dataset中取数据,怎么取、取多少由DataLoader的参数来控制

# Dataset主要实现什么样的功能?
#①如何获取每一个数据及其label;②告诉我们总共有多少数据
如何使用Dataset
#help(Dataset)
# All datasets that represent a map from keys to data samples should subclass it.
# All subclasses should overwrite :meth:`__getitem__`, supporting fetching a data sample for a given key.

#代码文件概述

# read_data.py(自定义Dataset)\rename_dataset.py(更改dataset文件存储形式)
# test_transform.py(单张图像变换)\test_tensorboard.py(单张图像可视化)

# dataset_transform.py(torchvision dataset与图像变换、可视化的结合)

# test_dataloader.py(DataLoader的使用)

# read_data.py

from torch.utils.data import Dataset
from PIL import Image #Python Image Library
import os

#继承Dataset类
class LoadData(Dataset):
    # 初始化,读取数据集 根据这个类创建一个特例示例的时候会运行的一个类
    #一般会为整个class提供全局变量,为后面的函数提供所需要的量
    def __init__(self,root_dir,label_dir):
        self.root_dir=root_dir #实例化:root_dir=“dataset/train”
        self.label_dir=label_dir #实例化:label是ants或bees label_dir="ants"
        self.path=os.path.join(self.root_dir,self.label_dir) #获取数据所在文件夹地址
        self.img_path_list=os.listdir(self.path) #将文件夹下的数据所在地址形成一个列表

    # 对于指定id,获取该数据并返回
    #在init中创建数据地址列表
    def __getitem__(self, index):
        img_name=self.img_path_list[index]
        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_list)

#实例化
root_dir="dataset/train"
ants_label_dir="ants"
bees_label_dir="bees"
ants_dataset=LoadData(root_dir,ants_label_dir)
bees_dataset=LoadData(root_dir,bees_label_dir)

train_dataset=ants_dataset+bees_dataset

print(ants_dataset[0])

 rename_dataset.py

#常见数据集的形式是将数据与label分开存放
#并且两个文件夹以相同文件名命名 label文件为txt格式

import os
# root_dir="dataset/train"
# target_dir="ants"
# img_path=os.listdir(os.path.join(root_dir,target_dir))
# label=target_dir.split("_")[0]
# out_dir="ants_label"
# for i in img_path:
#     file_name=i.split('.jpg')[0]
#     with open(os.path.join(root_dir,out_dir,"{}.txt".format(file_name)),'w') as f:
#         f.write(label)



root_dir="dataset/train"
target_dir="bees"
img_path=os.listdir(os.path.join(root_dir,target_dir))
label=target_dir.split("_")[0]
out_dir="bees_label"
for i in img_path:
    file_name=i.split('.jpg')[0]
    with open(os.path.join(root_dir,out_dir,"{}.txt".format(file_name)),'w') as f:
        f.write(label)

test_tensorboard.py

from torch.utils.tensorboard import SummaryWriter
import numpy as np
from PIL import Image

writer=SummaryWriter("logs")
#运行后产生文件在logs中
#打开logs文件:在Terminal命令台输入 tensorboard --logdir=事件文件所在文件夹名 --port=指定端口 避免和其他人一样

# 两个重要方法
# ①writer.add_image()
# ②writer.add_scalar() #标量、数

# def add_image(self,
#               tag: str, 显示title
#               img_tensor: Any, 图像类型:torch.Tensor, numpy.ndarray, or string/blobname
#               global_step: int = None, 纵轴
#               walltime: float = None,
#               dataformats: str = "CHW") -> None 指定shape中每一维度的含义 e.g. dataformats='HWC'(高度、宽度、通道)


#图片格式及打开方式
# ①PIL Image.open()
# ②tensor transforms.ToTensor()
# ③narrays cv2.imread()

#img_tensor参数 图片类型的处理:
# ①如何由常见的图片类型PIL转换为torch.Tensor类型:利用numpy.array()对PIL图片进行转换;
# ②利用OpenCV读取图片,获得numpy型图片数据(narrays)  # pip install opencv-python

# ①PIL->torc.Tensor
image_path="dataset/train/ants/0013035.jpg"
img_PIL=Image.open(image_path)
img_array=np.array(img_PIL)
print(type(img_array))
print(img_array.shape)
writer.add_image("test",img_array,1,dataformats='HWC')#Note:从PIL到numpy需要在add_image()中指定shape中每一个数字/维表示的含义

#②Opencv读取图片->numpy
import cv2
img_cv=cv2.imread(image_path)
writer.add_image("train",img_cv,1,dataformats='HWC')

# def add_scalar(self,
#                tag: str, 显示图像的title
#                scalar_value: Any, 横轴
#                global_step: int = None, 纵轴
#                walltime: float = None,
#                new_style: bool = False,
#                double_precision: bool = False) -> None

#y=2x
for i in range(100):
    writer.add_scalar("y=2x",2*i,i)

writer.close()

# test_transform.py


from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms

# transforms结构及用法
#transforms.py相当于工具箱 里面不同的class相当于工具  例如:totensor、resize等等
#transforms的使用:特定格式的图片根据工具箱创建具体的工具(初始化/实例化)后,使用工具(调用方法),输出我们想要图片的结果(预期图片变换)

#transforms在python中的用法 其中比较重要的一个概念是Tensor数据类型
#通过transform.ToTensor解决两个问题:
# ①transforms该如何使用(python)
# ②为什么我们需要Tensor数据类型

#summary
#多看官方文档;关注每个方法class的输入输出参数类型;关注方法需要什么参数;可以通过print/debug查看输出数据类型print()/print(type())

#绝对路径 D:\PycharmProjects\pythonProject\dataset\train\ants\5650366_e22b7e1065.jpg
#相对路径 dataset/train/ants/5650366_e22b7e1065.jpg
img_path="dataset/train/ants/5650366_e22b7e1065.jpg"
img=Image.open(img_path)
writer=SummaryWriter("logs")

# # # ToTensor使用
# Convert a ``PIL Image`` or ``numpy.ndarray`` to tensor.
#方法①
tensor_trans=transforms.ToTensor()
img_tensor=tensor_trans(img)
print(img_tensor)
#方法②
# img_tensor=transforms.ToTensor().__call__(img)
# print(img_tensor)
# 方法③
# img_tensor=transforms.ToTensor()(img)
# print(img_tensor)
writer.add_image("img_ToTensor",img_tensor)
#在test_tensorboard中使用了利用numpy将PIL图片转换为torch.Tensor类型方法;
# 在这里直接调用transforms.ToTensor()中的call方法实现


# # # Normalize使用
#Normalize a tensor image with mean and standard deviation
# output[channel] = (input[channel] - mean[channel]) / std[channel]=2*input-1
#将input限定为[0,1] ,则output会限定在[-1,1]

print(img_tensor[0][0][0])
trans_norm=transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])#3 channes mean and standard deviation 可以随意设定
img_norm=trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("img_Normalize",img_norm,0)

trans_norm=transforms.Normalize([1,3,5],[2,1,1])#3 channes mean and standard deviation 可以随意设定
img_norm=trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("img_Normalize",img_norm,1)

trans_norm=transforms.Normalize([6,2,5],[3,4,1])#3 channes mean and standard deviation 可以随意设定
img_norm=trans_norm(img_tensor)
print(img_norm[0][0][0])
writer.add_image("img_Normalize",img_norm,2)

# # # Resize使用
print(img.size)
#img_PIL -> resize -> img_resize PIL
trans_resize=transforms.Resize((512,512))
img_resize=trans_resize(img)
print(img_resize) #PIL类型
#img_resize ->totensor ->img_resize tensor
img_resize=tensor_trans(img_resize)
print(img_resize)#tensor类型
writer.add_image("img_Resize",img_resize,0)
print(img_resize)

# # #Compose()使用
#Composes several transforms together.
#Compose()中的参数需要是一个列表,python中列表的表示形式为[数据1,数据2...];Compose中数据需要是transforms类型
#因此Compose([transforms参数1,transforms参数2,...])
#Note:Compose中transforms参数的输入输出匹配原则:后一个变换所需的输入类型要与前一个变换的输出类型匹配

# # # Compose-resize-2
# #利用Compose将Resize与ToTensor变换一起实现
# Resize只有一个参数时 transforms.Resize(x)其表示将短边缩放至x,长宽比保持不变
trans_resize_2=transforms.Resize(512)
#PIL(trans_resize_2输入) -> PIL(trans_resize_2输出、tensor_trans输入) -> tensor(tensor_trans输出)
trans_compose=transforms.Compose([trans_resize_2,tensor_trans])
img_resize_2=trans_compose(img)
writer.add_image("img_Resize",img_resize_2,1)

# # #RandomCrop使用
trans_random=transforms.RandomCrop(100)
trans_compose_2=transforms.Compose([trans_random,tensor_trans])
for i in range(10):
    img_crop=trans_compose_2(img)
    writer.add_image("img_RandomCrop",img_crop,i)
writer.close()

dataset_transform.py

#可以在pytorch官网查看torchvision的官方文档
#左侧栏改为v0.9.0可看到与土堆相同的界面
#查看官方文档中数据集所需要的参数及含义
#在pytorch中引用下载即可
#以torchvision中的CIFAR10数据集为例
import torchvision
from torch.utils.tensorboard import SummaryWriter

# # #①dataset应用transforms前

# train_set=torchvision.datasets.CIFAR10(root="./dataset",train=True,download=True)
# test_set=torchvision.datasets.CIFAR10(root="./dataset",train=False,download=True)
# print(train_set[0]) #数据集应用transforms前,此处打印出的信息为img_PIL
# print(test_set.classes) #数据集类别列表
#
# img,target=test_set[0]#数据集中的数据组成为img和target两部分
# print(img)
# print(target)  #target是类别对应的数字/索引
# print(test_set.classes[target]) #根据索引打印出特定数据对应类别
# img.show()

# # #②dataset应用transforms后

#将transforms应用到数据集中的每一张图片
dataset_transform=torchvision.transforms.Compose([torchvision.transforms.ToTensor()])
train_set=torchvision.datasets.CIFAR10(root="./dataset",train=True,transform=dataset_transform,download=True)
test_set=torchvision.datasets.CIFAR10(root="./dataset",train=False,transform=dataset_transform,download=True)
print(test_set[0])#将transforms应用到数据集后,此处打印出的信息为img_tensor

#③结合tensorboard使用
writer=SummaryWriter("logs")
for i in range(10):
    img,target=test_set[i]
    writer.add_image("test_set",img,i)
writer.close()

# test_dataloader.py

#DataLoder 参数含义
# dataset (Dataset) – dataset from which to load the data.
# batch_size (int, optional) – how many samples per batch to load (default: 1).
# shuffle (bool, optional) – set to True to have the data reshuffled at every epoch (default: False).是否打乱顺序
# num_workers (int, optional) 数据加载子进程数目 取0时表示只有一个主进程
# drop_last (bool, optional) 是否舍去没有整除剩下的数据

import torchvision
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

# 从torchvision中获取数据集并利用transforms将其中的img_PIL转换为img_tensor
test_data=torchvision.datasets.CIFAR10("./dataset",train=True,transform=torchvision.transforms.ToTensor())
# 每batch_size个样本进行打包,并在一个epoch后打乱顺序
test_loader=DataLoader(dataset=test_data,batch_size=64,shuffle=True,num_workers=0,drop_last=False)
# 测试数据集中第一个样本信息img及target(单个数据)
img,target=test_data[0]
print(img.shape)
print(target)

writer=SummaryWriter("logs")
# 可以在外层加上对epoch变量的for循环,观察多轮抓取数据时数据顺序是否一致
# 这由dataloader中的shuffle参数控制
for epoch in range(2):
    step=0
    #一个for循环便是抓取完一轮数据,也就是一个epoch
    # 每次将多个数据进行打包抓取(每batch_size个数据打包)
    for data in test_loader:
        imgs,targets=data
        # print(imgs.shape)
        # print(targets)
        writer.add_images("Epoch:{}".format(epoch),imgs,step)#Note:add_images!!!  #format是输出格式,{}里输出内容为format括号里的内容
        step=step+1
writer.close()

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值