当前位置:   article > 正文

Pytorch深度学习之神经网络入门详解_pytorch神经网络高效入门教程

pytorch神经网络高效入门教程

目录

Pytorch 入门

1.将每个图片的label作为txt文件写入另外一个文件夹(txt文件名与图片文件名相同)

2.tensorboard的summary writer

3.torchvision中的transforms

4.DataLoader

5.神经网络-卷积层Conv2d

6.最大池化层

7.非线性激活函数Relu

9.线性层

10.损失函数

11.反向传播和优化器

12.残差网络

13.CIFAR10模型结构


Pytorch 入门

1.将每个图片的label作为txt文件写入另外一个文件夹(txt文件名与图片文件名相同)

  1. root_dir=r"F:\yolo\img"
  2. target_dir="car_img"
  3. print(os.path.join(root_dir,target_dir))
  4. img_path_list=os.listdir(os.path.join(root_dir,target_dir))
  5. print(img_path_list)
  6. out_dir="car_label"
  7. for i in img_path_list:
  8. file_name=i.split(".jpg")[0]
  9. f=open((os.path.join(root_dir,out_dir,file_name)+".txt"),"w")
  10. f.write("car")
  11. f.close()

2.tensorboard的summary writer

  1. import numpy as np
  2. import os
  3. import cv2 as cv
  4. from torch.utils.tensorboard import SummaryWriter
  5. from torchvision import transforms
  6. writer=SummaryWriter("logs1")
  7. cv_img=cv.imread(r"F:\yolo\img\street.jpg")
  8. # for i in range(1,100):
  9. # writer.add_scalar("y=2x",2*i,i)
  10. writer.add_image("test_img",cv_img,1,dataformats='HWC')
  11. tensor_trans=transforms.ToTensor()
  12. test_img1=tensor_trans(cv_img)
  13. writer.add_image("test_img",test_img1,2)
  14. writer.close()

查看可视化结果

控制台 tensorboard --logdir=logs1命令即可

3.torchvision中的transforms

torchvision.transforms是pytorch中的图像预处理包。一般用Compose把多个步骤整合到一起:

  1. transforms.Compose([
  2. transforms.CenterCrop(10),
  3. transforms.ToTensor(),
  4. ])

下面列举两个常用的 transforms中的函数:

class torchvision.transforms.Normalize(mean, std)

给定均值:(R,G,B) 方差:(R,G,B),将会把Tensor正则化。即:Normalized_image=(image-mean)/std

48a0f23a3af44210bf6f260bec3fa3bb.png

实例代码如下:

  1. import cv2 as cv
  2. from torch.utils.tensorboard import SummaryWriter
  3. from torchvision import transforms
  4. writer=SummaryWriter("logs1")
  5. cv_img=cv.imread(r"F:\yolo\img\street.jpg")
  6. tensor_trans=transforms.ToTensor()
  7. test_img1=tensor_trans(cv_img)
  8. writer.add_image("test_img",test_img1,1)
  9. print(test_img1[0][0][0])
  10. trans_norm=transforms.Normalize([0.5,0.5,0.5],[0.5,0.5,0.5])
  11. img_norm=trans_norm(test_img1)
  12. print(img_norm[0][0][0])
  13. writer.add_image("test_img",img_norm,2)
  14. writer.close()

class torchvision.transforms.ToTensor

把一个取值范围是[0,255]PIL.Image或者shape(H,W,C)numpy.ndarray,转换成形状为[C,H,W],取值范围是[0,1.0]torch.FloadTensor

方法总结如下图:

6b67c83d084b40959976fe801b40bc4b.png

4.DataLoader

数据加载器。组合数据集和采样器,并在数据集上提供单进程或多进程迭代器。

参数:

  • dataset (Dataset) – 加载数据的数据集。
  • batch_size (int, optional) – 每个batch加载多少个样本(默认: 1)。
  • shuffle (bool, optional) – 设置为True时会在每个epoch重新打乱数据(默认: False).
  • sampler (Sampler, optional) – 定义从数据集中提取样本的策略。如果指定,则忽略shuffle参数。
  • num_workers (int, optional) – 用多少个子进程加载数据。0表示数据将在主进程中加载(默认: 0)
  • collate_fn (callable, optional) –
  • pin_memory (bool, optional) –
  • drop_last (bool, optional) – 如果数据集大小不能被batch size整除,则设置为True后可删除最后一个不完整的batch。如果设为False并且数据集的大小不能被batch size整除,则最后一个batch将更小。(默认: False)
  1. import cv2 as cv
  2. from torch.utils.tensorboard import SummaryWriter
  3. from torchvision import transforms
  4. from torch.utils.data import DataLoader
  5. import torchvision
  6. train_set=torchvision.datasets.CIFAR10(root="./dataset",train=True,download=True,transform=torchvision.transforms.ToTensor())
  7. # shuffle 为true设置为打乱顺序
  8. train_loader=DataLoader(dataset=train_set,batch_size=64,shuffle=True,num_workers=0,drop_last=False)
  9. writer=SummaryWriter("logs1")
  10. step=0
  11. for data in train_loader:
  12. imgs,targets=data
  13. writer.add_images("imgs",imgs,step)
  14. step=step+1
  15. break
  16. writer.close()

5.神经网络-卷积层Conv2d

class torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)

Parameters:

  • in_channels(int) – 输入信号的通道
  • out_channels(int) – 卷积产生的通道
  • kerner_size(int or tuple) - 卷积核的尺寸
  • stride(int or tupleoptional) - 卷积步长
  • padding(int or tupleoptional) - 输入的每一条边补充0的层数
  • dilation(int or tupleoptional) – 卷积核元素之间的间距
  • groups(intoptional) – 从输入通道到输出通道的阻塞连接数
  • bias(booloptional) - 如果bias=True,添加偏置

 

  1. import cv2 as cv
  2. import torch
  3. from torch.utils.tensorboard import SummaryWriter
  4. from torchvision import transforms
  5. from torch.utils.data import DataLoader
  6. import torchvision
  7. train_set=torchvision.datasets.CIFAR10(root="./dataset",train=True,download=True,transform=torchvision.transforms.ToTensor())
  8. # shuffle 为true设置为打乱顺序
  9. train_loader=DataLoader(dataset=train_set,batch_size=64,shuffle=True,num_workers=0,drop_last=False)
  10. from torch import nn
  11. class test(nn.Module):
  12. def __init__(self):
  13. super(test, self).__init__()
  14. self.conv1 = nn.Conv2d(3, 6, 3, stride=1, padding=0)
  15. def forward(self, x):
  16. x = self.conv1(x)
  17. return x
  18. test=test()
  19. writer=SummaryWriter("logs1")
  20. step=0
  21. for data in train_loader:
  22. imgs,targets=data
  23. writer.add_images("imgs",imgs,step)
  24. step=step+1
  25. output=test(imgs)
  26. # 由于图片只能以三个通道显示,因此要把6个channel改成3个
  27. # torch.size([64,6,30,30])->[???,3,30,30]
  28. # batch_size不知道写多少的时候就写-1,它会自动计算
  29. output=torch.reshape(output,(-1,3,30,30))
  30. writer.add_images("imgs", output, step)
  31. break
  32. writer.close()

6.最大池化层

参数:class torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)

  • kernel_size(int or tuple) - max pooling的窗口大小
  • stride(int or tupleoptional) - max pooling的窗口移动的步长。默认值是kernel_size
  • padding(int or tupleoptional) - 输入的每一条边补充0的层数
  • dilation(int or tupleoptional) – 一个控制窗口中元素步幅的参数
  • return_indices - 如果等于True,会返回输出最大值的序号,对于上采样操作会有帮助
  • ceil_mode - 如果等于True,计算输出信号大小的时候,会使用向上取整,代替默认的向下取整的操作

  1. import cv2 as cv
  2. import torch
  3. from torch.utils.tensorboard import SummaryWriter
  4. from torchvision import transforms
  5. from torch.utils.data import DataLoader
  6. import torchvision
  7. from torch.nn import MaxPool2d
  8. train_set=torchvision.datasets.CIFAR10(root="./dataset",train=True,download=True,transform=torchvision.transforms.ToTensor())
  9. # shuffle 为true设置为打乱顺序
  10. train_loader=DataLoader(dataset=train_set,batch_size=64,shuffle=True,num_workers=0,drop_last=False)
  11. from torch import nn
  12. class test(nn.Module):
  13. def __init__(self):
  14. super(test, self).__init__()
  15. self.maxpool1 = MaxPool2d(kernel_size=3, ceil_mode=True)
  16. def forward(self, input):
  17. output = self.maxpool1(input)
  18. return output
  19. test=test()
  20. writer=SummaryWriter("logs1")
  21. step=0
  22. for data in train_loader:
  23. imgs,targets=data
  24. writer.add_images("imgs1",imgs,step)
  25. step=step+1
  26. output=test(imgs)
  27. writer.add_images("imgs1", output, step)
  28. break
  29. writer.close()

7.非线性激活函数Relu

Relu函数的作用是将将小于0的数据变成为0,实例代码如下:

  1. from torch.nn import ReLU
  2. input=torch.tensor([[1,-0.5],
  3. [-1,3]])
  4. class test(nn.Module):
  5. def __init__(self):
  6. super(test, self).__init__()
  7. #inplace-选择是否进行覆盖运算
  8. self.relu1=ReLU(inplace=False)
  9. def forward(self,input):
  10. output=self.relu1(input)
  11. return output
  12. test=test()
  13. output=test(input)
  14. print(output)

9.线性层

Linear layers

对输入数据做线性变换:y=Ax+b

参数:

  • in_features - 每个输入样本的大小
  • out_features - 每个输出样本的大小
  • bias - 若设置为False,这层不会学习偏置。默认值:True

形状:

  • 输入: (N,in_features)(N,in_features)
  • 输出: (N,out_features)(N,out_features)

变量:

  • weight -形状为(out_features x in_features)的模块中可学习的权值
  • bias -形状为(out_features)的模块中可学习的偏置

如下图:

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81Mjc2NzgzOQ==,size_16,color_FFFFFF,t_70

 代码实例如下:

  1. import torch
  2. import torchvision
  3. from torch import nn
  4. from torch.nn import Linear
  5. from torch.utils.data import DataLoader
  6. dataset=torchvision.datasets.CIFAR10("dataset",train=False,transform=torchvision.transforms.ToTensor(),
  7. download=True)
  8. dataloader=DataLoader(dataset,batch_size=64,drop_last=True)
  9. class test(nn.Module):
  10. def __init__(self):
  11. super(test, self).__init__()
  12. self.linear1=Linear(3072,10)
  13. def forward(self,input):
  14. output=self.linear1(input)
  15. return output
  16. test1=test()
  17. for data in dataloader:
  18. imgs,t=data
  19. print(imgs.shape)
  20. #将图片线性化
  21. output=torch.flatten(imgs)
  22. print(output.shape)
  23. output=test1(output)
  24. print(output.shape)
  25. output:
  26. #torch.Size([64, 3, 32, 32])
  27. #torch.Size([64, 1, 1, 3072])
  28. #torch.Size([64, 1, 1, 10])

10.损失函数

损失函数这里列举几个:

class torch.nn.L1Loss(size_average=True)[source]

创建一个衡量输入x(模型预测输出)和目标y之间差的绝对值的平均值的标准。

                              56c806bb8254453bb4017bd52fe094f1.png

  • x 和 y 可以是任意形状,每个包含n个元素。

  • n个元素对应的差值的绝对值求和,得出来的结果除以n

  • 如果在创建L1Loss实例的时候在构造函数中传入size_average=False,那么求出来的绝对值的和将不会除以n

代码如下实例

  1. import torch
  2. from torch.nn import L1Loss
  3. input=torch.tensor([1,2,3],dtype=torch.float32)
  4. output=torch.tensor([1,2,5],dtype=torch.float32)
  5. loss=L1Loss()
  6. result=loss(input,output)
  7. print(result)

运行结果如下图,如果不需要求平均可以这样设置

loss=L1Loss(reduction="sum")

 610c0ecb800c44518cfda484be1bffde.png

class torch.nn.MSELoss(size_average=True)[source]

创建一个衡量输入x(模型预测输出)和目标y之间均方误差标准。

5187ec816a7741ba888415b47c1f3d0d.png
  • x 和 y 可以是任意形状,每个包含n个元素。

  • n个元素对应的差值的绝对值求和,得出来的结果除以n

  • 如果在创建MSELoss实例的时候在构造函数中传入size_average=False,那么求出来的平方和将不会除以n

class torch.nn.CrossEntropyLoss(weight=None, size_average=True)

9c79c2cac78340249d468cd671b8388d.png

 当训练一个多类分类器的时候,这个方法是十分有用的。exp是以e为底的指数函数,在一个猫狗二分类问题中,一个图片经过神经网络模型输出为x[0.5,0.7],其中这张图片的target为0,0代表为猫,1代表为狗,损失函数的计算为-x[0(target)]+ln(exp(x[0])+exp(x[1])。

代码如下

  1. import torch
  2. from torch.nn import CrossEntropyLoss
  3. x=torch.tensor([0.1,0.2,0.3])
  4. y=torch.tensor([1])
  5. x=torch.reshape(x,(1,3))
  6. loss=CrossEntropyLoss()
  7. result=loss(x,y)
  8. print(result)

11.反向传播和优化器

反向传播 loss.backward()

优化器一般是使用梯度下降的方法进行优化:在梯度法中,函数的取值从当前位置沿着梯度方向前进一定距离,然后在新的地方重新求梯度,再沿着新梯度方向前进,如此反复,不断地沿梯度方向前进。像这样,通过不断地沿梯度方向前进,逐渐减小函数值的过程就是梯度法(gradient method)。梯度法是解决机器学习中最优化问题的常用方法,特别是在神经网络的学习中经常被使用。根据目的是寻找最小值还是最大值,梯度法的叫法有所不同。严格地讲,寻找最小值的梯度法称为梯度下降法(gradient descent method),寻找最大值的梯度法称为梯度上升法(gradient ascent method)。但是通过反转损失函数的符号,求最小值的问题和求最大值的问题会变成相同的问题,因此“下降”还是“上升”的差异本质上并不重要。一般来说,神经网络(深度学习)中,梯度法主要是指梯度下降法。

反向传播和优化器代码实例如下:

  1. test1=test()
  2. #lossFunction模型
  3. loss=nn.CrossEntropyLoss()
  4. #优化器模型
  5. optim=torch.optim.SGD(test1.parameters(),0.01)
  6. #进行20次优化
  7. for epcho in range (20):
  8. running_loss=0.0
  9. for data in dataloader:
  10. imgs,t=data
  11. output=test1(imgs)
  12. loss=loss(output,t)
  13. #将每个梯度清为0(初始化)
  14. optim.zero_grad()
  15. #反向传播,得到每个可调节参数对应的梯度(grad不再是none)
  16. loss.backward()
  17. #对每个参数进行改变,weight-data被改变
  18. optim.step()
  19. #计算每轮优化中每个变量的loss和
  20. running_loss=running_loss+result_loss
  21. print(running_loss)
  22. output:
  23. #总loss在逐渐变小
  24. # tensor(18712.0938, grad_fn= < AddBackward0 >)
  25. # tensor(16126.7949, grad_fn= < AddBackward0 >)
  26. # tensor(15382.0703, grad_fn= < AddBackward0 >)

12.残差网络

传统的神经网络,由于网络层数增加,会导致梯度越来越小,这样会导致后面无法有效的训练模型,这样的问题成为梯度消弭。为了解决这样的问题,引入残差神经网络(Residual Networks),残差神经网络的核心是”跳跃”+“残差块”。通过引入RN网络,可以有效缓解梯度消失的问题,可以训练更深的网络。

下图是一个基本残差块。它的操作是把某层输入跳跃连接到下一层乃至更深层的激活层之前,同本层输出一起经过激活函数输出。

24353e89d9c84a17babbbf4ebe90630b.png

定义残差模型,根据最基本的残差块,残差中间需要经过卷积->激活->卷积这样的操作,为了保证输入输出大小一致,故中间两个卷积层的输入输出大小都和模型最初输入大小保持一致。

  1. class ResidualBlock(nn.Module):
  2. def __init__(self, channels):
  3. super(ResidualBlock, self).__init__()
  4. self.channels = channels
  5. self.conv1 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)
  6. self.conv2 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)
  7. def forward(self, x):
  8. y = F.relu(self.conv1(x))
  9. y = self.conv2(y)
  10. return F.relu(x + y)

13.CIFAR10模型结构

下面是利用CIFAR10模型结构进行图像分类数据的训练和预测。

c702f32874c54bb998261fa356c9a38f.png

  1. import torch
  2. import torchvision
  3. from torch import nn
  4. from torch.utils.data import DataLoader
  5. from torch.utils.tensorboard import SummaryWriter
  6. #import自己写的models
  7. from p27_1model import *
  8. train_data=torchvision.datasets.CIFAR10("../datasets",train=True,transform=torchvision.transforms.ToTensor(),
  9. download=True)
  10. test_data=torchvision.datasets.CIFAR10("../datasets",train=False,transform=torchvision.transforms.ToTensor(),
  11. download=True)
  12. #查看数据集长度
  13. train_size=len(train_data)
  14. test_size=len(test_data)
  15. print("size of train,test is:{},{}".format(train_size,test_size))
  16. #利用dataloader加载
  17. train_dataloader=DataLoader(train_data,64)
  18. test_dataloader=DataLoader(test_data,64)
  19. #创建网络模型
  20. test1=test()
  21. #损失函数
  22. loss_f=nn.CrossEntropyLoss()
  23. #优化器
  24. #1e-2=0.01
  25. learning_rate=1e-2
  26. opt=torch.optim.SGD(test1.parameters(),lr=learning_rate,)
  27. #设置训练网络的参数
  28. #记录训练次数
  29. train_step=0
  30. #测试次数
  31. test_step=0
  32. #训练轮数
  33. epoch=10
  34. #添加tensoeboard
  35. writer=SummaryWriter("train_log")
  36. for i in range(epoch):
  37. print("第{}轮训练开始".format(i+1))
  38. #训练步骤开始
  39. #有时不必要:test1.train()
  40. for data in train_dataloader:
  41. imgs,t=data
  42. output=test1(imgs)
  43. loss=loss_f(output,t)
  44. #优化器优化模型
  45. opt.zero_grad()
  46. loss.backward()
  47. opt.step()
  48. train_step=train_step+1
  49. #loss.item更加规范(.item不会打印数据类型,例如tensor(5))
  50. if train_step%100==0:
  51. print("训练次数{},loss值为{}".format(train_step,loss.item()))
  52. writer.add_scalar("train_loss",loss.item(),train_step)
  53. loss_total=0
  54. #测试步骤开始
  55. #有时不必要:test1.eval()
  56. total_correct=0
  57. with torch.no_grad():
  58. for data in test_dataloader:
  59. imgs,t=data
  60. output=test1(imgs)
  61. loss=loss_f(output,t)
  62. loss_total=loss_total+loss.item()
  63. test_step=test_step+1
  64. #argmax参数:1为横向比较,2为纵向比较,output为64,10的矩阵
  65. #output.argmax(1)==t是为了得到[Ture,False,True....]这种形式
  66. #.sum:T为1,F为0
  67. corect=(output.argmax(1)==t).sum()
  68. total_correct=total_correct+corect
  69. accuracy=total_correct/test_size
  70. print("测试集总loss{}".format(loss_total))
  71. writer.add_scalar("test_loss",loss_total,test_step)
  72. writer.add_scalar("accuracy",accuracy,test_step)
  73. torch.save(test1,"test1{}.pth".format(i))
  74. print("模型已保存")

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/51951
推荐阅读
相关标签
  

闽ICP备14008679号