pytorch实战学习入门(理解篇)

第一节、自定义数据类

class Mydata():
    def __init__(self,name,path):
        self.name=name
        self.path=path	#定义实类的时候可以直接将函数值赋予
    def hello(self,sex):
       	print(self.path+sex)
    def __len__(self):
        print(len(self.name))

一个讲解自定义数据集很好的一个blog(按住crtl+点击这里)

#自定义数据类,必须重载__getitem__()函数和__len__()函数
class MyData(torch.utils.data.Dataset):
	#自定义实体类时,回直接调用__init__()函数,可以同时为内部所需要赋值的类变量赋予变量
    def __init__(self, root_dir, image_dir, label_dir, transform):
        #self.的对象及是类的变量
        self.root_dir = root_dir
        self.image_dir = image_dir
        self.label_dir = label_dir
        self.label_path = os.path.join(self.root_dir, self.label_dir)
        self.image_path = os.path.join(self.root_dir, self.image_dir)
        self.image_list = os.listdir(self.image_path)
        self.label_list = os.listdir(self.label_path)
        self.transform = transform
        # 因为label 和 Image文件名相同,进行一样的排序,可以保证取出的数据和label是一一对应的
        self.image_list.sort()
        self.label_list.sort()
	#	__getitem__(self, idx)必须要重载此函数,此函数可以对数据进行索引
    def __getitem__(self, idx):
        img_name = self.image_list[idx]
        label_name = self.label_list[idx]
        img_item_path = os.path.join(self.root_dir, self.image_dir, img_name)
        label_item_path = os.path.join(self.root_dir, self.label_dir, label_name)
        img = Image.open(img_item_path)

        with open(label_item_path, 'r') as f:
            label = f.readline()

        # img = np.array(img)
        img = self.transform(img)
        sample = {'img': img, 'label': label}
        return sample
	# 必须重载此函数,此函数可以获得数据集的长度
    def __len__(self):
        assert len(self.image_list) == len(self.label_list)
        return len(self.image_list)

第二节、tensorboard

from torch.utils.tensorboard import SummaryWriter #导入tensorboard数据包

write=SummaryWriter('logs')	#创建write

write.add_image('title',img,index,dataformat='HWC')	
#添加图表,所需数据类型为numpy,需要指定数据高	宽通道	一个顺序

write.add_scalar('标题',x,y)	#添加图表的标题

tensorboard --logdir=logs	#tensorboard的显示

tensorboard --logdir=logs --port=6007	#改变端口

write.close()	#关掉

第三节、transform

import torchvision.transforms as transforms
#transform的作用是将原始数据继续裁剪,归一化,totensor等等操作

#totensor

#resize

#alt+enter快速引入库

tensor_trans=transform.toTensor()	#获得转换的一个函数,相当于类的实体化,主要利用transform的各种函数

tensor_img=tensor_trans(img)	#可以将img转化为tensor数据类型

transform.compose([
    transform.centercrop(),
    transform.totensor()
]) 							#将多个进行合成

trans_norms=transoform.normalize([],[])	#归一化transform内部有很多内置函数,可以在transform中进行查看

img_norms=trans_norm(img_tensor)	#totensor之后的图像可以转化为归一化,进行tansform之前要把数据类型转化为tensor数据类型

trans_resize=transform.resize(high,length)

img_resize=trans_resize(img)

img_resize=trans_totensor(img_resize)	#可以在forward中查看所学的数据类型

trans_reszie_s=transform.reszie(512)

trans_compose=transform.compose([trans_reszie_2,
                                trans_totensor])	# transpose构建之后和其余的函数一致,只是单纯生成了函数

img_resize_2=trans_compose(img)

#__call__方法可以直接调用,函数需要.调用

#ctrl+p提醒参数数据类型

#关注输入和输出,官方文档print(type(img_resize))查看数据类型

第四节、数据集的使用

train_set=torchvision.datasets.CIFAR10(root='./dataset',
                                       train=true,
                                       download=true)
#将数据集进行下载并且作为训练集,可以利用这种方法使用官方提供的数据集

第五节、DataLoader

#大多数参数都有默认值,需要从中找到没有默认值的参数
#其中dataset为指定数据集,batch_size为每次得到的数据大小,shuffle是是否随机排序,num_workers多进程,在windows下可能有一些问题,drop_last,batch_size中的数据不够整除,是否丢掉
#其中返回的test_loader是img,label的数据,共有batch_size个,从dataset中获取
test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=True)

第六节、网络:nn.module

1、初步了解module
import torch.nn as nn
import torch.nn.functional as F

#继承与父类
class Model(nn.Module):
    #自定初始化函数
    def __init__(self):
        #初始化父类,必须要写的
        #所写的函数只是定义,并不是所执行
        super().__init__()
        self.conv1 = nn.Conv2d(1, 20, 5)
        self.conv2 = nn.Conv2d(20, 20, 5)
    #前向传播,input->forward->output
    #该函数是自动执行的,不需要调用即可。实体类在进行调用之后便会自己执行forward函数
    #该函数中是经过依次卷积,经过relu激活函数
    #再进行一次卷积,在经过依次非线性激活relu
    def forward(self, x):
        x = F.relu(self.conv1(x))
        return F.relu(self.conv2(x))
2、torch.nn
#可以从官网文档查看函数中每个参数的意义
torch.reshape(input,(,,,))
F.conv2d(data,kernal)
3、卷积层
#conv2d主要应用在图像中 
#in_channels输入图片的通道数
#out_channels输出图片的通道数
#kernal_size卷积核的大小
#stride步长
#padding卷积方式
torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros', device=None, dtype=None)

#数据集的导入常用技巧
dataset = torchvision.datasets.CIFAR10("../data", train=False, transform=torchvision.transforms.ToTensor(),
                                       download=True)
dataloader = DataLoader(dataset, batch_size=64)

卷积进行输入时的维度是[batch_size,channal,high,宽]

4、池化层

卷积层,池化层中输入都是[batch_size,channal,high,wide]四个参数组成

#这个是torch.nn中的
torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
#这个是torch.nn.functional中的
torch.nn.functional.max_pool2d(input, kernel_size, stride=None, padding=0, dilation=1, ceil_mode=False, return_indices=False)
5、非线性激活
#在functional中的和torch.nn中一般是functional要进行输入,而torch.nn是调用出来
#这个是torch.nn.functional中的
torch.nn.functional.relu(input, inplace=False) → Tensor
#这个是torch.nn中的
#inplace一般设为false,若为true,则原始数据也被替换
torch.nn.ReLU(inplace=False)
6、正则化层
#正则化层
#dropout
7、线形层
# in_feature=输入的特征维度
# out_feature=输出的特征维度
# bias偏置
torch.nn.Linear(in_features, out_features, bias=True, device=None, dtype=None)
torch.flatten(img)	#将数据展平
8、sequential
# 使用sequential后可以按照顺序继续宁执行
model = nn.Sequential(
          nn.Conv2d(1,20,5),
          nn.ReLU(),
          nn.Conv2d(20,64,5),
          nn.ReLU()
        )
        
# 自定义一个网络类,并且继承nn.module
class Net(nn.Module):
    def __init__(self):
    	# 对父类进行初始化
        super(Net, self).__init__()
        # 利用sequential建立网络
        self.model1 = Sequential(
        	# 输入的维度,输出的维度,卷积核大小,padding方式
            Conv2d(3, 32, 5, padding=2),
            # 池化方式
            MaxPool2d(2),
            # 输入的卷积维度,输出的卷积维度,卷积核大小
            Conv2d(32, 32, 5, padding=2),
            # 池化的方式
            MaxPool2d(2),
            # 输入的卷积维度,输出的卷积维度,padding的方式
            Conv2d(32, 64, 5, padding=2),
            # 池化的方式
            MaxPool2d(2),
            # 平铺
            Flatten(),
            # 线性输入的维度,线性输出的维度
            Linear(1024, 64),
            # 线性输入的维度,线性输出的维度
            Linear(64, 10)
        )
	# 在前向调用中直接调用model1,也就是sequential所定义的网络结构
    def forward(self, x):
        x = self.model1(x)
        return x

所使用的网络模型如下所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pA5dUZJI-1655220591425)(D:\研一\课程\深度学习\DeepLearning\pytorch学习笔记图片\1655100535458.png)]

# 倘若无法计算线形层的结构是多少,可以查看数据的大小,然后继续线性操作
Conv2d(3, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 32, 5, padding=2),
            MaxPool2d(2),
            Conv2d(32, 64, 5, padding=2),
            MaxPool2d(2),
            Flatten()
net=Net()
input = torch.ones((64, 3, 32, 32))
output = net(input)
print(output.shape)
# 可以通过自定义一个torch对象,查看所输出的数据类型

两种定义网络的方式,一种是定义sequential,另一种是初始化里面里面变量,在forward中调用

writer = SummaryWriter("../logs_seq")
writer.add_graph(net, input)
writer.close()

# 可以通过这种方式将所搭建的网络直接通过tensorboard继续输出查看
9、Loss function
# 交叉熵损失
torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=- 100, reduce=None, reduction='mean', label_smoothing=0.0)

# Example of target with class indices
将损失函数首先定义,然后调用即可
loss = nn.CrossEntropyLoss()
input = torch.randn(3, 5, requires_grad=True)
target = torch.empty(3, dtype=torch.long).random_(5)
output = loss(input, target)
output.backward()

# Example of target with class probabilities
input = torch.randn(3, 5, requires_grad=True)
target = torch.randn(3, 5).softmax(dim=1)
output = loss(input, target)
output.backward()


# pytorch中标签转为one-hot形式
def one_hot(data, dim):
    data = torch.tensor(data)
    index = data.unsqueeze(1).to(dtype=int)
    train_target = torch.zeros(len(data), dim).scatter_(1, index, 1)
    return train_target
10、优化器
# 两种常用的优化器 
# lr 学习速率
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
optimizer = optim.Adam([var1, var2], lr=0.0001)


# 每一次训练要zero_grad(),否则会出现问题
for input, target in dataset:
    optimizer.zero_grad()
    output = model(input)
    loss = loss_fn(output, target)
    loss.backward()
    optimizer.step()
11、GPU训练
# 方法一
# 利用GPU训练可以选择网络模型,损失函数,数据
if torch.cuda.is_available()
	net.cuda()
	loss.cuda()
	data.cuda()	#数据中包含数据和标签,data & label

# 方法二
device = torch.device('cpu')
device = torch.device('cuda:0')
cnnNet.to(device)
loss.to(device)
12、网络模型的修改
# 在torchvision 中的模型可以导入已经训练好的模型,设置为true则使用官方训练好的额,为false则为未经过训练的原始数据
vgg16_false = torchvision.models.vgg16(pretrained=False)
vgg16_true = torchvision.models.vgg16(pretrained=True)
# 查看网络架构
print(vgg16,true)
# 利用现成的网络模型预测自己的数据
train_data = torchvision.datasets.CIFAR10('../data', train=True, transform=torchvision.transforms.ToTensor(),
                                          download=True)

# 利用VGG16作为前缀网络,添加一个线性层
vgg16_true.add_module('add_linear', nn.Linear(1000, 10))
vgg16_true.classifier.add_module('add_linear', nn.Linear(1000, 10))

# 若是对VGG16做修改
vgg16_false.classifier[6] = nn.Linear(4096, 10)
13、模型的保存和读取
# 模型保存方式1
# vgg16是模型的名称
# 第二个参数是保存的名称
# 保存的是模型的机构和参数
torch.save(vgg16, "vgg16_method1.pth")
# 进行模型的读取
model = torch.load('vgg16_method1.pth')
print(modefl)

# 模型的保存方式二
# 只是保存网络的参数,第一个是网络要保存的参数
# 第二个参数是保存的网络参数的路径名称
torch.save(vgg16.state_dict(), "vgg16_method2.pth")
# 模型的读取
model = torch.load('vgg16_method2.pth')
print(model)
# 因为读取的不是网络,需要把读取到的网络参数放到网络中,因此需要先导入网络架构
vgg16 = torchvision.models.vgg16(pretrained=False)
vgg16.load_state_dic(model)

# 若是自定义的网络
# 需要Net()网络类可以被访问到
cnnNet = Net()
torch.save(cnnNet,'cnnNet_method1.pth')
model = torch.load('cnnNet_method1.pth')
14、模型的训练套路
# 准备数据集,建立数据集类
train_data = torchvision.datasets.CIFAR10(root="../data", train=True, transform=torchvision.transforms.ToTensor(),
                                          download=True)
# 建立测试集
test_data = torchvision.datasets.CIFAR10(root="../data", train=False, transform=torchvision.transforms.ToTensor(),
                                         download=True)
# 利用Dataloader进行导入 ,同时指定batch_size的大小
train_dataloader = DataLoader(train_data, batch_size=64)
# 网络类实体化
# 网络模型可以定义在一个文件中
cnnNet = Net()
# 损失函数定义
loss_fn = nn.CrossEntropyLoss()
# 优化器定义
optim = torch.optim.SGD(tudui.parameters(), lr=learning_rate)
# 指定训练的轮数
epoch = 10
# 添加tensorboard
writer = SummaryWriter("logs")

#开始进行训练步骤
for i in range(epoch):
	# 获得损失
	data = data
	label = label
	output = cnnNet(data)
	loss = loss_fn(output,label)
	
	# 利用优化器对损失进行处理
	optim.zeros_grad()
	loss.backward()
	optim.step()
	
# 开始进行测试步骤
with torch.no_grad():
	for data in testData:
		output = cnnNet(data)
		loss = loss_fn(output,label)
		total_loss = total_loss+loss.item()
		
  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值