官网:torch — PyTorch 2.6 documentation
Pycharm
解释器
一般搞深度学习都用虚拟情况的解释器,为了满足不同的项目所必要的不同的包的版本。
1. system interpreter表示当地的解释器
也就是你电脑系统里安装的解释器
2. Virtual Environment—Python的虚拟情况
anaconda可以帮我们创建虚拟情况
a. 创建虚拟情况
- conda create -n name python = 3.8
复制代码 b. 检察系统中已经存在的情况, * 在哪就是当前在哪个情况。
c. 激活情况
d. 退出情况
3. conda Enviroment
Anaconda内里附带安装的Python解释器
PyTorch下载命令
- 建议挑选conda的而不是wheel的命令,conda支持虚拟情况而且能自动办理依靠标题。
常见标题
- 高版本的解释器在anaconda3虚拟路径文件夹envs下边。
- 不表现In[2],打开终端,↓
- jupyter默认只安装在base情况当中,如果base情况没有安装pytorch,那么jupyter是没有办法使用pytorch的。
方案1:在base情况里安装pytorch
方案2:在pytorch情况里安装jupyter
- 装库时报错Caused by SSLError(SSLZeroReturnError(6, 'TLS/SSL connection has been closed (EOF)
把代理关了。
- module = self._system_import(name, *args, **kwargs)
- ImportError: DLL load failed while importing _imaging: 找不到指定的模块。
复制代码 办理方法:卸载了pywin32包
- LooseVersion = distutils.version.LooseVersion AttributeError: module 'distutils' has no attribute 'version'
复制代码 办理方法:注释掉控制台init方法的4-7和第10行。
修改固态盘的页面巨细,最小值是内存的1.5倍,最大值是内存的3倍。
低沉tensorboard版本
- pip install tensorboard==2.12.0
复制代码- image = image.resize((scaled_width, scaled_height), Image.ANTIALIAS)
- AttributeError: module 'PIL.Image' has no attribute 'ANTIALIAS'
复制代码 新版本pillow(10.0.0之后)Image.ANTIALIAS 被移除了,取而代之的是Image.LANCZOS or Image.Resampling.LANCZOS,干系描述可以可以在pillow的releasenotes中查到。点进去报错的文件,ANTIALIAS改成LANCZOS就可以了。
在 Jupyter Notebook 中切换/使用 conda 虚拟情况
服务器上配置有多个 conda 虚拟情况,在使用jupyter notebook时必要使用其中的一个情况,但是其默认还是使用 base 情况。Jupyter 在一个名为 kernel 的单独进程中运行用户的代码。kernel 可以是不同的 Python 安装在不同的 conda 情况或虚拟情况。
方法1:使用 nb_conda_kernels 添加所有情况(推荐)
- conda activate my-conda-env # this is the environment for your project and code
- conda install ipykernel
- conda deactivate
- conda activate base # could be also some other environment
- conda install nb_conda_kernels
- jupyter notebook
复制代码 注意:这里的 conda install nb_conda_kernels 是在 base 情况下操作的。
安装好后,打开 jupyter notebook 就会表现所有的 conda 情况啦,点击随意切换。
方法2:为 conda 情况创建特别内核
- conda create -n my-conda-env # creates new virtual env
- conda activate my-conda-env # activate environment in terminal
- conda install ipykernel # install Python kernel in new conda env
- ipython kernel install --user --name=my-conda-env-kernel # configure Jupyter to use Python kernel
- jupyter notebook # run jupyter from system
复制代码 只有 Python 内核会在 conda 情况中运行,系统中的 Jupyter 或不同的 conda 情况将被使用——它没有安装在 conda 情况中。通过调用ipython kernel install将 jupyter 配置为使用 conda 情况作为内核.
windows/mac/linux jupyter notebook 切换默认情况
方法3:在 conda 情况中运行 Jupyter 服务器和内核
- conda create -n my-conda-env # creates new virtual env
- conda activate my-conda-env # activate environment in terminal
- conda install jupyter # install jupyter + notebook
- jupyter notebook # start server + kernel
复制代码 这种方法就是为每一个 conda 情况 都安装 jupyter。
Jupyter 将完全安装在 conda 情况中。不同版本的 Jupyter 可用于不同的 conda 情况,但此选项可能有点矫枉过正。
在情况中包含内核就充足了,内核是运行代码的封装 Python 的组件。Jupyter notebook 的别的部门可以被视为编辑器或检察器,并且没有须要为每个情况单独安装它并将其包含在每个 env.yml 文件中。
常用函数
- help(torch.cuda.is_available()) / 还有一种方式获取官方文档信息:xxxx ??
复制代码 跳到句首
数据加载
DataSet抽象类
提供一种方式去获取数据及其label。
DataLoader类
torch.utils.data.DataLoader是一个迭代器,方便我们去多线程地读取数据,并且可以实现batchsize以及
shuffle 的读取等。为后边的网络提供不同的数据情势。
- 如何获取每一个数据及其label
- 告诉我们统共有多少数据
神经网络经常必要对一个数据迭代多次,只有知道当前有多少个数据,进行练习时才知道要练习多少次,才气把整个数据集迭代完。
- from torch.utils.data import Dataset
- import os
- #读取图片
- from PIL import Image
- class MyDataset(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"
- label_dir = "ants"
- ants_dataset = MyDataset(root_dir,label_dir)
- bees_dataset = MyDataset(root_dir,label_dir)
- ants_dataset[0]
复制代码 TensorBoard(PyTorch1.1之后)
demo
- from torch.utils.tensorboard import SummaryWriter
- #日志的所在地址
- writer = SummaryWriter("D:\PythonProject\Introduction\logs")
- #第一个参数相当于表头,绘图
- for i in range(100):
- writer.add_scalar('y=x',3 * i, i)
- writer.close()
复制代码 检察logs
在控制台输入
- tensorboard --logdir=logs
复制代码 指定端口,防止当别人也在访问时跟别人冲突
- tensorboard --logdir=logs --port=6007
复制代码 注意:如果出现拟合,那么可以删掉logs下边的文件,重新运行。
添加图像
通过打印发现,此范例不得当当作tensorboard的添加图片的输入范例。
- PyDev console: using IPython 8.12.2
- Python 3.8.20 (default, Oct 3 2024, 15:19:54) [MSC v.1929 64 bit (AMD64)] on win32
- img_path = "dataset/train/ants/0013035.jpg"
- from PIL import Image
- img = Image.open(img_path)
- print(type(img))
- <class 'PIL.JpegImagePlugin.JpegImageFile'>
复制代码 so,使用Opencv读取图片,得到numpy范例图片数据
使用numpy.array(),对PIL图片进行转换。
Transforms单张图片
输入图像到transforms.py,它像一个工具箱,把一些数据范例转化为tensor(神经网络 的专用数据范例,包装了很多神经网络必要的参数),或者resize.
- from torch.utils.tensorboard import SummaryWriter
- from torchvision import transforms
- from PIL import Image
- #通过transform.Totensor解决俩问题
- #1. transform应该如何使用
- #2. 为什么需要一个Tensor的数据类型
- img_path = "dataset/train/ants/0013035.jpg"
- img = Image.open(img_path)
- writer = SummaryWriter('logs')
- tensor_trans = transforms.ToTensor()
- tensor_img = tensor_trans(img)
- # print(tensor_img)
- # print(img)
- writer.add_image("Tensor_img", tensor_img, 3)
- writer.close()
复制代码 图片不表现的把logs下其他的文件删掉,关掉终端打开再重新运行。
归一化----加速收敛
正则化是防止过拟合
让不同的特征在数值上保持一致,制止某些特征对模型的影响过大,从而更好地学习到数据当中的模式和关系。归一化之后,均值为0,标准差为1.
__call__介绍,把对象当函数用。
- class Person:
- def __call__(self, name):
- print("__call__"+"Hello"+name)
- def hello(self,name):
- print("hello"+name)
- #__xxx__这种都是内置函数,可以对其进行重写
- person = Person()
- #__call__可以直接使用对象里加参数,而不用.的方式。
- person("zhangsan")
- person.hello("lisi")
复制代码 忽略巨细写匹配:
settings ----> 搜索case------>Generral下的Code Completion------->取勾Match case
Compose()的用法
Compose()中的参数必要是一个列表,Python中,列表的情势为[xx,xx,xx,xx,...]
在Compose()中,数据必要是transforms范例,以是,Compose(transsforms参数1,transsforms参数2,...)
用于将多个数据预处置惩罚操作组合成一个整体的变换,具体而言,按列表次序进行转换。巨细,裁剪,翻转,归一化等。
- from torch.utils.tensorboard import SummaryWriter
- from torchvision import transforms
- from PIL import Image
- #通过transform.Totensor解决俩问题
- #1. transform应该如何使用
- #2. 为什么需要一个Tensor的数据类型
- img_path = "dataset/train/ants/0013035.jpg"
- img = Image.open(img_path)
- writer = SummaryWriter('logs')
- tensor_trans = transforms.ToTensor()
- tensor_img = tensor_trans(img)
- # print(tensor_img)
- # print(img)
- #writer.add_image("Tensor_img", tensor_img, 3)
- print(tensor_img[0][0][0])
- #Normalize,归一化,提供三个均值,三个标准差
- tensor_norm = transforms.Normalize([0.5,0.5,0.5], [0.5,0.5,0.5])
- #把图片归一化
- img_norm = tensor_norm(tensor_img)
- print(img_norm[0][0][0])
- writer.add_image("Normalize", img_norm,2)
- #Resize
- print(img.size)
- tran_resize = transforms.Resize((512,512))
- #img PIL -> resize -> img_resize PIL
- #这个方法需要传入PIL类型的img
- img_resize = tran_resize(img)
- # img_resize PIL -> toTensor ->img_resize tensor
- img_resize = tensor_trans(img_resize)
- writer.add_image("Resize", img_resize,0)
- print(img_resize)
- #Compose
- trans_resize_2 = transforms.Resize(512)
- trans_compose = transforms.Compose([trans_resize_2 , tensor_trans])
- trans_resize_2 = trans_compose(img)
- writer.add_image("Resize2", trans_resize_2,1)
- #RandomCrop,随机裁剪
- trans_random = transforms.RandomCrop((512,512))
- trans_compose_2 = transforms.Compose([trans_random , tensor_trans])
- #循环的目的是为了展示随机效果
- for i in range(10):
- img_crop = trans_compose_2(img)
- writer.add_image("RandomCrop", img_crop,i)
- writer.close()
复制代码 torchvision中的数据集的使用
单纯加载数据集CIFAR10 torchvision.datasets — Torchvision master documentation
- import torchvision
- train_set = torchvision.datasets.CIFAR10(root='./data', train=True, download=True)
- test_set = torchvision.datasets.CIFAR10(root='./data', train=False, download=True)
- #打印的是target,就是标签
- print(test_set[0])
- print(test_set.classes)
- img , target = test_set[0]
- print(img)
- print(target)
- print(test_set.classes[target])
- #对于PIL数据集直接调用这个方法就可以展示图片了
- img.show()
复制代码 对数据集变换
- import torchvision
- from torch.utils.tensorboard import SummaryWriter
- dataset_transform = torchvision.transforms.Compose([
- torchvision.transforms.ToTensor(),
- #因为图片太小了就只进行这一个变换
- ])
- train_set = torchvision.datasets.CIFAR10(root='./data', train=True,transform=dataset_transform, download=True)
- test_set = torchvision.datasets.CIFAR10(root='./data', train=False,transform=dataset_transform, download=True)
- print(test_set[0])
- #输出的是tensor数据类型,那么就可以用tensorboard进行一个显示
- writer = SummaryWriter(log_dir='p10')
- for i in range(10):
- img, target = test_set[i]
- #ctrl+p
- #此时img是tensor类型的
- writer.add_image("test_set", img, i)
- writer.close()
复制代码 在终端输入命令
- tensorboard --logdir="p10"
复制代码 如果下载太慢的话,可以打开数据集函数进去复制连接本身下载,然后放在对应的文件夹下。
DataLoader的使用
加载器,可以批量加载
参数:
num_workers : 使用多少进程去加载,但是可能只能linux用,win可能报错BrokenPipeErrror,默认值为0,代表使用主进程进行加载。
drop_last : 末了的余数图片要不要加载,false就是不舍弃的意思
shuffle : 遍历完一遍以后才会打乱,而且是在每轮练习当中打乱,一个epoch打乱一次
target不是标签,是标签存放的位置,标签列表是classes,真正的标签是classes[target]
batchsize打印:
- import torch
- import torchvision
- from torch.utils.data import DataLoader
- #准备的测试数据集
- test_data = torchvision.datasets.CIFAR10(root='./data', train=False, download=False,transform=torchvision.transforms.ToTensor())
- test_loader = DataLoader(test_data, batch_size=4, shuffle=True,num_workers=0,drop_last=False)
- #测试数据集中第一张图片
- img ,target = test_data[0]
- print(img.shape)
- print(target)
- #data是test_loader里的每一个对象,test_loader是可迭代对象
- for data in test_loader:
- imgs , targets = data
- print(imgs.shape)
- print(targets)
- #输出的tensor是把每个图片的target融合在一起了。
复制代码
验证shuffle
- #验证shuffle
- for epoch in range(2):
- step = 0
- for data in test_loader:
- imgs, targets = data
- writer.add_images("Epoch:{}".format(epoch), imgs, step)
- step += 1
复制代码 总代码:
- import torchimport torchvisionfrom torch.utils.data import DataLoaderfrom torch.utils.tensorboard import SummaryWriter#预备的测试数据集test_data = torchvision.datasets.CIFAR10(root='./data', train=False, download=False,transform=torchvision.transforms.ToTensor())test_loader = DataLoader(test_data, batch_size=4, shuffle=True,num_workers=0,drop_last=False)#测试数据集中第一张图片img ,target = test_data[0]print(img.shape)print(target)#data是test_loader里的每一个对象,test_loader是可迭代对象 # print(imgs.shape) # print(targets)#输出的tensor是把每个图片的target融合在一起了。writer = SummaryWriter(log_dir='./dataloader')step = 0for data in test_loader: imgs , targets = data writer.add_images("test_data", imgs, step) step += 1#验证shuffle
- for epoch in range(2):
- step = 0
- for data in test_loader:
- imgs, targets = data
- writer.add_images("Epoch:{}".format(epoch), imgs, step)
- step += 1writer.close()
复制代码 mini-batch
随机梯度降落
nn.Module
关于神经网络的工具,一般在torch.nn里边。神经网络的根本骨架,一般是被继承的父类
conv2常用参数
padding ----- 添补,更好的使用边缘信息,如许可以均匀使用数据,默认是不进行添补的。
bias ------ 偏置参数
padding_mode ------- 添补模式,一般默认是0
dilation -------- 空洞卷积
卷积demo,因为nn.Module函数当中内置了call函数,以是把参数放进对象里,会自动调用forward函数。是在call函数里调用的。
- import torch
- from torch import nn
- class MyNet(nn.Module):
- def __init__(self):
- super().__init__()
- def forward(self, input):
- output = input + 1
- return output
- my_net = MyNet()
- x =torch.tensor(1.0)
- y = my_net(x)
- print(y)
复制代码 为什么要调解形状,因为我们一开始打印出来发现只有高和宽,不满足conv2d的api要求输入的形状。
- import torch
- input = torch.tensor([[1,2,0,3,1],
- [0,1,2,3,1],
- [1,2,1,0,0],
- [5,2,3,1,1],
- [2,1,0,1,1]])
- kernel = torch.tensor([[1,2,1],
- [0,1,0],
- [2,1,0]])
- #这个尺寸只有高和宽
- print(input.shape)
- #torch.Size([5, 5])
- print(kernel.shape)
- #torch.Size([3, 3])
复制代码
pytorch给我们提供了尺寸变换
- input = torch.reshape(input,(1,1,5,5))
- kernel = torch.reshape(kernel,(1,1,3,3))
复制代码 变换以后就可以使用卷积进行输入
- output = F.conv2d(input,kernel,stride=1)
- output2 = F.conv2d(input,kernel,stride=2)
- print(output)
- print(output2)
复制代码- import torch
- import torchvision
- from torch import nn
- from torch.utils.data import DataLoader
- from torch.utils.tensorboard import SummaryWriter
- dataset = torchvision.datasets.CIFAR10(root='./data', train=False,
- transform=torchvision.transforms.ToTensor(),
- download=False)
- dataloader = DataLoader(dataset, batch_size=64)
- class MyNet(nn.Module):
- def __init__(self):
- super(MyNet, self).__init__()
- self.conv1 = nn.Conv2d(3, 6, 3)
- def forward(self, x):
- x = self.conv1(x)
- return x
- my_net = MyNet()
- writer = SummaryWriter("./logs")
- #可以打印网络结构
- #print(my_net)
- step = 0
- for data in dataloader:
- imgs, targets = data
- output = my_net(imgs)
- print(output.shape)
- print(imgs.shape)
- #torch.Size([64, 3, 32, 32])
- writer.add_images("input", imgs, step)
- #torch.Size([64, 6, 30, 30])
- #-1是占位符,会被自动计算那个地方的值是多少
- output = torch.reshape(output, (-1,3,30,30))
- writer.add_images("output", output, step)
- step += 1
复制代码 参数:dilation:空洞卷积,卷积核是隔一个的。
- import torchimport torch.nn.functional as Finput = torch.tensor([ [1,2,0,3,1], [0,1,2,3,1], [1,2,1,0,0], [5,2,3,1,1], [2,1,0,1,1]])kernel = torch.tensor([[1,2,1], [0,1,0], [2,1,0]])print(input.shape)print(kernel.shape)#ctrl+p,提示参数#(卷积核数量,通道数,,)#一个卷积核天生一个通道input = torch.reshape(input,(1,1,5,5))
- kernel = torch.reshape(kernel,(1,1,3,3))print(input.shape)print(kernel.shape)output = F.conv2d(input,kernel,stride=1)output2 = F.conv2d(input,kernel,stride=2)output3 = F.conv2d(input,kernel,stride=1,padding=1)print(output)print(output2)print(output3)
复制代码 池化层
https://github.com/vdumoulin/conv_arithmetic
空洞卷积表示图↑
ceil_mode ------- 当卷积核卷出去以后,true,保存,false,不保存
卷积:提取特征
池化:降维
demo
- import torch
- import torchvision
- from torch import nn
- from torch.utils.data import DataLoader
- from torch.utils.tensorboard import SummaryWriter
- dataset = torchvision.datasets.CIFAR10(root='./data', train=False, download=False,
- transform=torchvision.transforms.ToTensor())
- dataloader = DataLoader(dataset, batch_size=4)
- input = torch.tensor([
- [1,2,0,3,1],
- [0,1,2,3,1],
- [1,2,1,0,0],
- [5,2,3,1,1],
- [2,1,0,1,1]
- ], dtype=torch.float32)
- input = torch.reshape(input,(-1,1,5,5))
- print(input.shape)
- class MyNet(nn.Module):
- def __init__(self):
- super(MyNet, self).__init__()
- self.maxpool1 = nn.MaxPool2d(kernel_size=3, ceil_mode=True)
- def forward(self, x):
- output = self.maxpool1(x)
- return output
- mynet = MyNet()
- #print(mynet(input))
- writer = SummaryWriter('./logs_maxpool')
- steps = 0
- for data in dataloader:
- imgs,targets = data
- writer.add_images("input", imgs, steps)
- output = mynet(imgs)
- writer.add_images("output", output, steps)
- steps += 1
- writer.close()
复制代码 非线性激活
- import torch
- import torchvision
- from torch.utils.data import DataLoader
- from torch.utils.tensorboard import SummaryWriter
- input = torch.tensor([[1,-0.5],
- [-1,3]])
- output = torch.reshape(input,(-1,1,2,2))
- print(output)
- dataset = (torchvision.datasets.CIFAR10(root='./data', train=False, download=False,
- transform=torchvision.transforms.ToTensor()))
- dataloader = DataLoader(dataset, batch_size=64)
- class MyNet(torch.nn.Module):
- def __init__(self):
- super(MyNet, self).__init__()
- self.relu1 = torch.nn.ReLU()
- self.sigmoid = torch.nn.Sigmoid()
- def forward(self, x):
- output = self.sigmoid(x)
- return output
- mynet = MyNet()
- writer = SummaryWriter('./logs_relu')
- step = 0
- for data in dataloader:
- imgs,targets = data
- writer.add_images("input",imgs,step)
- output = mynet(imgs)
- writer.add_images("output",imgs,step)
- step += 1
- writer.close()
- output = mynet(input)
- print(output)
复制代码
Sequential
让代码看起来更简洁。
demo:对cifar10进行简单分类的神经网络,好像是颠末一次最大池化,尺寸就减半。

已知输入尺寸和输出尺寸,联立两个公式,可以反解出padding。dilation接纳默认的1,就是不进行膨胀。

倒数第二个和倒数第三个,倒数第一个和倒数第二个之间还分别各自有一个线性层。
- import torch
- from torch import nn
- from torch.nn import MaxPool2d, Flatten, Conv2d, Linear
- from torch.utils.tensorboard import SummaryWriter
- class MyNet(nn.Module):
- def __init__(self):
- super(MyNet, self).__init__()
- # self.conv1 = nn.Conv2d(3, 32, kernel_size=5,
- # padding=2)
- # self.maxpool1 = nn.MaxPool2d(2)
- # self.conv2 = nn.Conv2d(32, 32,5, padding=2)
- # self.maxpool2 = nn.MaxPool2d(2)
- # self.conv3 = nn.Conv2d(32, 64,5, padding=2)
- # self.maxpool3 = MaxPool2d(2)
- # self.flatten = Flatten()
- # #从图片里看出来的,64*4*4
- # self.linear1 = nn.Linear(1024,64)
- # self.linear2 = nn.Linear(64,10)
- self.model1 = nn.Sequential(
- Conv2d(3, 32, kernel_size=5, padding=2),
- MaxPool2d(2),
- Conv2d(32, 32, kernel_size=5, padding=2),
- MaxPool2d(2),
- Conv2d(32, 64, kernel_size=5, padding=2),
- MaxPool2d(2),
- Flatten(),
- Linear(1024, 64),
- Linear(64,10)
- )
- def forward(self, x):
- x = self.model1(x)
- # x = self.conv1(x)
- # x = self.maxpool1(x)
- # x = self.conv2(x)
- # x = self.maxpool2(x)
- # x = self.conv3(x)
- # x = self.maxpool3(x)
- # x = self.flatten(x)
- # x = self.linear1(x)
- # x = self.linear2(x)
- return x
- my_net = MyNet()
- print(my_net)
- input = torch.ones((64, 3, 32, 32))
- output = my_net(input)
- print(output.shape)
- writer = SummaryWriter("./logs_seq")
- writer.add_graph(my_net, input)
- writer.close()
复制代码 损失函数
L1Loss
- import torch
- from torch.nn import L1Loss
- inputs = torch.tensor([1,2,3],dtype=torch.float32)
- targets = torch.tensor([1,2,5],dtype=torch.float32)
- inputs = torch.reshape(inputs,(1,1,1,3))
- targets = torch.reshape(targets,(1,1,1,3))
- loss = L1Loss(reduction='sum')
- result = loss(inputs,targets)
- print(result)
- #2.
复制代码 MSELoss
- loss_mse = nn.MSELoss()
- result_mse = loss_mse(result,targets)
- print(result_mse)
- #1.3333
复制代码 交织熵
- x = torch.tensor([0.1,0.2,0.3])
- y = torch.tensor([1])
- x = torch.reshape(x,(1,3))
- loss_cross = nn.CrossEntropyLoss()
- result_cross = loss_cross(x,y)
- print(result_cross)
- #tensor(1.1019)
复制代码 用之前的网络来对数据集进行分类,不外此时的分类是没有意义的,因为还没有颠末练习。
- import torch
- import torchvision
- from torch import nn
- from torch.nn import MaxPool2d, Flatten, Conv2d, Linear
- from torch.utils.data import DataLoader
- from torch.utils.tensorboard import SummaryWriter
- dataset = torchvision.datasets.CIFAR10(root='./data', train=False, download=False,
- transform=torchvision.transforms.ToTensor())
- dataloader = DataLoader(dataset,batch_size=1)
- class MyNet(nn.Module):
- def __init__(self):
- super(MyNet, self).__init__()
- self.model1 = nn.Sequential(
- Conv2d(3, 32, kernel_size=5, padding=2),
- MaxPool2d(2),
- Conv2d(32, 32, kernel_size=5, padding=2),
- MaxPool2d(2),
- Conv2d(32, 64, kernel_size=5, padding=2),
- MaxPool2d(2),
- Flatten(),
- Linear(1024, 64),
- Linear(64,10)
- )
- def forward(self, x):
- x = self.model1(x)
- return x
- my_net = MyNet()
- loss = nn.CrossEntropyLoss()
- for data in dataloader:
- imgs,targets = data
- outputs = my_net(imgs)
- result_loss = loss(outputs, targets)
- print(result_loss)
- #tensor(2.2306, grad_fn=<NllLossBackward>)
- #tensor(2.2557, grad_fn=<NllLossBackward>)
- #tensor(2.3920, grad_fn=<NllLossBackward>)
- #......
- # print(outputs)
- # print(targets)
复制代码 反向传播
- 计算现实输出和目标之间的差距
- 为我们更新输出提供肯定的依据,方向传播,grad。
一开始是没有梯度的,后来运行完37行,
就出现梯度了,有利于反向传播。
优化器
eg:lr是学习速率
- optimizer = optim.SGD(model.named_parameters(), lr=0.01, momentum=0.9)
- optimizer = optim.Adam([('layer0', var1), ('layer1', var2)], lr=0.0001)
复制代码 demo
- import torch
- import torchvision
- from torch import nn
- from torch.nn import MaxPool2d, Flatten, Conv2d, Linear
- from torch.utils.data import DataLoader
- from torch.utils.tensorboard import SummaryWriter
- dataset = torchvision.datasets.CIFAR10(root='./data', train=False, download=False,
- transform=torchvision.transforms.ToTensor())
- dataloader = DataLoader(dataset,batch_size=1)
- class MyNet(nn.Module):
- def __init__(self):
- super(MyNet, self).__init__()
- self.model1 = nn.Sequential(
- Conv2d(3, 32, kernel_size=5, padding=2),
- MaxPool2d(2),
- Conv2d(32, 32, kernel_size=5, padding=2),
- MaxPool2d(2),
- Conv2d(32, 64, kernel_size=5, padding=2),
- MaxPool2d(2),
- Flatten(),
- Linear(1024, 64),
- Linear(64,10)
- )
- def forward(self, x):
- x = self.model1(x)
- return x
- my_net = MyNet()
- optim = torch.optim.SGD(my_net.parameters(), lr=0.01)
- loss = nn.CrossEntropyLoss()
- for epoch in range(20):
- running_loss = 0.0
- for data in dataloader:
- imgs,targets = data
- outputs = my_net(imgs)
- result_loss = loss(outputs, targets)
- #梯度清零
- optim.zero_grad()
- #优化器需要每个参数的梯度
- result_loss.backward()
- #给每个参数进行调优
- optim.step()
- running_loss += result_loss
- print(running_loss)
- #print(result_loss)
复制代码 现有网络模型的使用以及修改
- import torchvision.datasets
- from torch import nn
- from torchvision import transforms
- #train_data = torchvision.datasets.ImageNet("./data_image_net",split='train',
- # download=True,transform=transforms.ToTensor())
- vgg16_false = torchvision.models.vgg16(pretrained=False)
- #打印的是已经预训练好的网络架构,参数都是在训练之后的
- vgg16_true = torchvision.models.vgg16(pretrained=True)
- print(vgg16_true)
- train_data = torchvision.datasets.CIFAR10(root='./data', train=True, download=False
- ,transform=torchvision.transforms.ToTensor())
- #把vgg16当一个前置的网络结构
- vgg16_true.classifier.add_module('add_linear',nn.Linear(1000, 10))
- print(vgg16_true)
- vgg16_false.classifier[6]=nn.Linear(4096, 10)
复制代码 网络模型保存
方式1
模型结构+模型参数
- import torch
- import torchvision
- vgg16 = torchvision.models.vgg16(pretrained=False)
- #保存方式1
- torch.save(vgg16,"vgg16_method1.pth")
复制代码 加载模型
- #保存方式1,加载模型
- model = torch.load("vgg16_method1.pth")
- print(model)
复制代码 如果是用方式1并且是自定义模型的话,肯定要让访问的代码能够访问到模型定义的地方。
方式2---字范例例
模型参数(官方推荐,好像是如许比较小)
- #保存方式2
- torch.save(vgg16.state_dict(),"vgg16_state_dict.pth")
复制代码 加载模型,字典情势打印出来就看不见网络结构了,也可以再恢复成网络结构的。
- #方式2加载方式
- #如果你想恢复成网络模型结构
- vgg16 = torchvision.models.vgg16(pretrained=False)
- model = torch.load("vgg16_state_dict.pth")
- print(model)
- print(vgg16)
复制代码 模型练习
item和本身的区别:
train.py
- import torch
- import torchvision
- from model import *
- train_data = torchvision.datasets.CIFAR10(root='./data', train=True, download=True,transform=torchvision.transforms.ToTensor())
- test_data = torchvision.datasets.CIFAR10(root='./data', train=False, download=True,transform=torchvision.transforms.ToTensor())
- train_data_size = len(train_data)
- test_data_size = len(test_data)
- print("训练数据集的长度是:{}".format(train_data_size))
- print("测试数据集的长度为:{}".format(test_data_size))
- #加载数据集
- train_dataloader = torch.utils.data.DataLoader(train_data,
- batch_size=64,
- )
- #ctrl+d复制本行到下一行
- test_dataloader = torch.utils.data.DataLoader(test_data, batch_size=64,)
- #创建网络模型
- mynet = MyNet()
- #损失函数,交叉熵
- loss_function = torch.nn.CrossEntropyLoss()
- #优化器
- optimizer = torch.optim.SGD(mynet.parameters(), lr=0.001, momentum=0.9)
- #设置训练网络的一些参数
- #记录训练的次数
- total_train_step = 0
- total_test_step = 0
- epoch = 10
- for i in range(epoch):
- print("第{}轮训练开始".format(i+1))
- for data in train_dataloader:
- imgs,targets = data
- outputs = mynet(imgs)
- loss = loss_function(outputs, targets)
- optimizer.zero_grad()
- loss.backward()
- optimizer.step()
- total_train_step += 1
- print("训练次数:{},Loss{}".format(total_train_step,loss.item()))
复制代码 model.py
- import torch
- from torch import nn
- from torch.nn import Conv2d, MaxPool2d, Flatten, Linear
- #搭建神经网络
- class MyNet(nn.Module):
- def __init__(self):
- super(MyNet, self).__init__()
- self.model1 = nn.Sequential(
- Conv2d(3, 32, kernel_size=5, padding=2),
- MaxPool2d(2),
- Conv2d(32, 32, kernel_size=5, padding=2),
- MaxPool2d(2),
- Conv2d(32, 64, kernel_size=5, padding=2),
- MaxPool2d(2),
- Flatten(),
- Linear(1024, 64),
- Linear(64,10)
- )
- def forward(self, x):
- x = self.model1(x)
- return x
- if __name__ == '__main__':
- mynet = MyNet()
- #64张图片
- input = torch.ones((64,3,32,32))
- output = mynet(input)
- print(output.shape)
复制代码 test
- import torch
- import torchvision
- from torch.utils.tensorboard import SummaryWriter
- from model import *
- train_data = torchvision.datasets.CIFAR10(root='./data', train=True, download=True,transform=torchvision.transforms.ToTensor())
- test_data = torchvision.datasets.CIFAR10(root='./data', train=False, download=True,transform=torchvision.transforms.ToTensor())
- train_data_size = len(train_data)
- test_data_size = len(test_data)
- print("训练数据集的长度是:{}".format(train_data_size))
- print("测试数据集的长度为:{}".format(test_data_size))
- #加载数据集
- train_dataloader = torch.utils.data.DataLoader(train_data,
- batch_size=64,
- )
- #ctrl+d复制本行到下一行
- test_dataloader = torch.utils.data.DataLoader(test_data, batch_size=64,)
- #创建网络模型
- mynet = MyNet()
- #损失函数,交叉熵
- loss_function = torch.nn.CrossEntropyLoss()
- #优化器
- optimizer = torch.optim.SGD(mynet.parameters(), lr=0.001, momentum=0.9)
- #设置训练网络的一些参数
- #记录训练的次数
- total_train_step = 0
- total_test_step = 0
- epoch = 10
- writer = SummaryWriter('./logs_train')
- for i in range(epoch):
- print("第{}轮训练开始".format(i+1))
- for data in train_dataloader:
- imgs,targets = data
- outputs = mynet(imgs)
- loss = loss_function(outputs, targets)
- optimizer.zero_grad()
- loss.backward()
- optimizer.step()
- total_train_step += 1
- if total_train_step % 100 == 0:
- print("训练次数:{},Loss{}".format(total_train_step,loss.item()))
- writer.add_scalar('train_loss', loss.item(), total_train_step)
- #测试步骤开始
- total_test_loss = 0
- total_accuracy = 0
- with torch.no_grad():
- for data in test_dataloader:
- imgs , targets = data
- outputs = mynet(imgs)
- loss = loss_function(outputs, targets)
- total_test_loss += loss.item() == targets
- accurancy = outputs.argmax(1)
- total_accuracy+=accurancy
- print("整体测试集上的loss:{}".format(total_test_loss))
- print("整体测试集上的正确率{}".format(total_accuracy))
- writer.add_scalar("test_loss",total_test_loss, total_test_step)
- writer.add_scalar("test_accuracy",total_accuracy, total_test_step)
- total_test_step+=1
- torch.save(mynet,"mynet_{}.pth".format(i))
- print("模型已保存")
- writer.close()
复制代码 规范tips
当网络中有dropout层等东西的时间,可以调用他们
练习之前
测试之前
使用GPU练习
思路:在如下几处加入干系代码
- 网络模型
- 数据(输入,标注)
- 损失函数
- .cuda
方法1
- if torch.cuda.is_available():
- loss_function = loss_function.cuda()
- if torch.cuda.is_available():
- imgs = imgs.cuda()
- targets = targets.cuda()
复制代码 方法2
- .to(device)
- Device = torch.device("cpu")
- Device = torch.device("gpu")
- #定义训练的设备
- device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
- #电脑上如果有多张显卡,这样来指定显卡
- Torch.device("cuda:0")
- Torch.device("cuda:1")
- imgs, targets = imgs.to(device), targets.to(device)
复制代码- import torch
- import torch.nn as nn
- import torchvision
- import time
- from torch.nn import Conv2d, MaxPool2d, Flatten, Linear
- from torch.utils.tensorboard import SummaryWriter
- #定义训练的设备
- device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
- class MyNet(nn.Module):
- def __init__(self):
- super(MyNet, self).__init__()
- self.model1 = nn.Sequential(
- Conv2d(3, 32, kernel_size=5, padding=2),
- MaxPool2d(2),
- Conv2d(32, 32, kernel_size=5, padding=2),
- MaxPool2d(2),
- Conv2d(32, 64, kernel_size=5, padding=2),
- MaxPool2d(2),
- Flatten(),
- Linear(1024, 64),
- Linear(64,10)
- )
- def forward(self, x):
- x = self.model1(x)
- return x
- train_data = torchvision.datasets.CIFAR10(root='./data', train=True, download=True,transform=torchvision.transforms.ToTensor())
- test_data = torchvision.datasets.CIFAR10(root='./data', train=False, download=True,transform=torchvision.transforms.ToTensor())
- train_data_size = len(train_data)
- test_data_size = len(test_data)
- print("训练数据集的长度是:{}".format(train_data_size))
- print("测试数据集的长度为:{}".format(test_data_size))
- #加载数据集
- train_dataloader = torch.utils.data.DataLoader(train_data,
- batch_size=64,
- )
- #ctrl+d复制本行到下一行
- test_dataloader = torch.utils.data.DataLoader(test_data, batch_size=64,)
- #创建网络模型
- mynet = MyNet()
- mynet.to(device)
- #损失函数,交叉熵
- loss_function = torch.nn.CrossEntropyLoss()
- loss_function.to(device)
- # if torch.cuda.is_available():
- # loss_function = loss_function.cuda()
- #优化器
- optimizer = torch.optim.SGD(mynet.parameters(), lr=0.001, momentum=0.9)
- #设置训练网络的一些参数
- #记录训练的次数
- total_train_step = 0
- total_test_step = 0
- epoch = 10
- writer = SummaryWriter('./logs_train')
- start_time = time.time()
- for i in range(epoch):
- print("第{}轮训练开始".format(i+1))
- for data in train_dataloader:
- imgs,targets = data
- imgs, targets = imgs.to(device), targets.to(device)
- # if torch.cuda.is_available():
- # imgs = imgs.cuda()
- # targets = targets.cuda()
- outputs = mynet(imgs)
- loss = loss_function(outputs, targets)
- optimizer.zero_grad()
- loss.backward()
- optimizer.step()
- total_train_step += 1
- if total_train_step % 100 == 0:
- end_time = time.time()
- print(end_time - start_time)
- print("训练次数:{},Loss{}".format(total_train_step,loss.item()))
- writer.add_scalar('train_loss', loss.item(), total_train_step)
- #测试步骤开始
- total_test_loss = 0
- total_accuracy = 0
- with torch.no_grad():
- for data in test_dataloader:
- imgs , targets = data
- imgs, targets = imgs.to(device), targets.to(device)
- # if torch.cuda.is_available():
- # imgs = imgs.cuda()
- # targets = targets.cuda()
- outputs = mynet(imgs)
- loss = loss_function(outputs, targets)
- total_test_loss += loss.item()
- accurancy = (outputs.argmax(1) == targets).sum()
- total_accuracy+=accurancy.item()
- print("整体测试集上的loss:{}".format(total_test_loss))
- print("整体测试集上的正确率{}".format(total_accuracy))
- writer.add_scalar("test_loss",total_test_loss, total_test_step)
- writer.add_scalar("test_accuracy",total_accuracy, total_test_step)
- total_test_step+=1
- torch.save(mynet,"mynet_{}.pth".format(i))
- print("模型已保存")
- writer.close()
复制代码 模型验证
使用已经练习好的模型,给它提供输入。
tips:
png图像是4通道,除了rgb以外ia,还有一个透明通道。
- image = image.convert('RGB')
复制代码 demo
- import torch
- import torchvision
- from PIL import Image
- from torch import nn
- from torch.nn import Conv2d, MaxPool2d, Flatten, Linear
- class MyNet(nn.Module):
- def __init__(self):
- super(MyNet, self).__init__()
- self.model1 = nn.Sequential(
- Conv2d(3, 32, kernel_size=5, padding=2),
- MaxPool2d(2),
- Conv2d(32, 32, kernel_size=5, padding=2),
- MaxPool2d(2),
- Conv2d(32, 64, kernel_size=5, padding=2),
- MaxPool2d(2),
- Flatten(),
- Linear(1024, 64),
- Linear(64,10)
- )
- def forward(self, x):
- x = self.model1(x)
- return x
- image_path = "./images/dog.png"
- image = Image.open(image_path)
- print(image)
- transform = torchvision.transforms.Compose([
- torchvision.transforms.Resize((32,32)),
- torchvision.transforms.ToTensor()])
- image = transform(image)
- print(image.shape)
- model = torch.load("mynet_9.pth",map_location=torch.device('cpu'))
- print(model)
- image = torch.reshape(image, (1,3,32,32))
- model.eval()
- with torch.no_grad():
- output = model(image)
- print(output)
- print(output.argmax(1))
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |