创建新项目的时候选择的编译器要选择Conda环境,如果手选Conda环境,要在Anaconda3的envs这个文件里选pytorch里面的python.exe就可以了。
两个重要函数 pytorch是一个package工具箱
dir()
:打开,看见里面有什么东西。当使用dir()得到的参数是双下划线的时候,说明这些标识符是函数。
help()
:说明书,还有一种形式例如Dataset??
例如查看is_available()
函数,我们就运行help(torch.cuda.is_available)
,括号里只需要输入标识符即可
加载数据 如何读取数据涉及到两个类
Dataset:提供一种方式去获取数据及其label。
Dataset是一个抽象类,所有数据集都要继承它,所有子类都要实现getitem
方法,选择性重写len
方法。
如何获取每一个数据及其label?实现getitem
方法。
告诉我们总共有多少的数据?重写len
方法
Dataloader:对我们要送进网络的数据进行打包,为网络提供不同的数据形式
import os :
os.path.join(str1,str2...)
函数的参数可以放字符串,得到的字符串结果是把多个字符串用\\
连接,因为单独的\会被当成转义字符,/并不是转义字符,例如:
root_dir="dataset/train" label_dir="ants" path=os.path.join(root_dir,label_dir) >>>path={str }'dataset/train\\ants'
os.listdir(path)
函数可以将路径path中的文件转化成列表形式,例如:
img_path_list=os.listdir(path) >>>img_path_list={list :124 }[...]
from PIL import Image :
Image.open(img_path)
此函数用于创建图片,返回{JpegImageFile}
变量
img.show()
函数用于显示图片
对目前所学的一个例子:
from torch.utils.data import Datasetfrom 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.path,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) bees_label_dir = "bees" bees_dataset = MyData(root_dir, bees_label_dir) print (ants_dataset[0 ])img,label = ants_dataset[0 ] img.show()//显示图片 img,label = bees_dataset[1 ] img.show() len (ants_dataset)len (bees_dataset)train_dataset = ants_dataset+bees_dataset len (train_dataset)img,label=train_dataset[123 ] img,label=train_dataset[124 ]
作出数据集的另一种存储方式:
import osroot_dir = '练手数据集/train' target_dir = 'ants_image' 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)
TensorBoard的使用 TensorBoard:演示transform的结果,在运行完方法后展示图像。例如loss图、训练结果output。
首先要from torch.utils.tensorboard import SummaryWriter
。
SummaryWriter类使用 CTRL
+鼠标移至类可以查看类的用法。
主要用到两个方法:
writer.add_scalar(tag(string),scalar_value(float or string/blobname),global_step(int))
参数tag(string)
设置图表的title
参数scalar_value(float or string/blobname)
设置图表y轴
参数global_step(int)
对应x轴
打开事件文件,在pycharm的命令行,输入tensorboard --logdir=事件文件所在文件夹名
。如果端口被占用了,可以自行添加端口,输入tensorboard --logdir=事件文件所在文件夹名 --port=端口值
如果打开的tensorboard出现了重复在一张图上的情况,需要进行删除原来的事件文件,或者重新SummaryWriter一个log_dir
文件
writer.add_image(tag(string),img_tensor(torch.Tensor, numpy.array, or string/blobname),global_step(int))
参数tag(string)
,设置图像的title
参数img_tensor(torch.Tensor, numpy.array, or string/blobname)
,设置图像
参数global_step(int)
,设置训练步骤
可以利用Opencv读取图片,获得numpy型图片数据。
如果是用PIL数据转化成numpy数据,需要在add_image()中指定shape中每一个数字/维表示的含义。主要是通道数。
step可以理解为多张图片可以放在同一个title里面,通过滑块可以看到每一步的图片,如果想让多张图片单独显示,需要把title重新命名
上面的代码综合运用:
from torch.utils.tensorboard import SummaryWriterfrom PIL import Imageimport numpy as npwriter = SummaryWriter("logs" ) for i in range (100 ): writer.add_scalar("y=3x" ,3 *i,i) img_path = "data/train/ants_image/0013035.jpg" img = Image.open (img_path) img_array = np.array(img) print (type (img_array))print (img_array.shape) writer.add_image("train" ,img_array,1 ,dataformats='HWC' ) writer.close()
Transforms主要是用于对图片进行一些变换。将特定格式的图片经过工具之后输出我们想要的图片结果。
Transforms.py工具箱具有的工具:
Totensor类,Totensor就是把PIL Image或者numpy.ndarray类型转化为tensor类型的
resize类,裁剪
…
tensor数据类型 通过transforms.Totensor去解决两个问题:
上述示例代码:
from torch.utils.tensorboard import SummaryWriterfrom torchvision import transformsfrom PIL import Imageimport cv2img_path = "data/train/ants_image/0013035.jpg" img = Image.open (img_path) print (img) tensor_trans = transforms.ToTensor() tensor_img = tensor_trans(img) print (tensor_img)cv_img = cv2.imread(img_path) tensor_cv_img = tensor_trans(cv_img) print (tensor_cv_img)writer = SummaryWriter("logs" ) writer.add_image("Tensor_img" ,tensor_img) writer.close()
python中call函数的作用:call函数可以直接使用对象名(参数)
这种方式去调用,这种方式就像Java重写的toString一样
Compose类:把不同的transform结合在一起
ToTensor类:把PIL Image或者numpy.ndarray类型转化为tensor类型
ToPILImage类:把tensor类型或者ndarray类型转化为PIL Image类型
Normalize类:用平均值和标准差对tensor image(图像张量)进行归一化,归一到[-1,1]
Resize类:把图像缩放成指定的大小,如果给了元组序列,图像就会按元组序列的大小来重新调整,如果只是给了一个int型,图像就会以这个int型进行等比缩放,最短边的长度等于int值。输入为PIL Image,返回值还是PIL Image
RandomCrop类:随即裁剪,和Resize用法差不多,输入都是 PIL Image
使用方法总结:1. 关注输入和输出类型,输出可以直接print()看,也可以断点看 2.多看官方文档 3.关注方法需要的参数,没有设置默认值就是要输入的参数,找到它然后查看它的类型
上述代码实例:
from PIL import Imagefrom torch.utils.tensorboard import SummaryWriterfrom torchvision import transformsimg = Image.open ("data/train/ants_image/0013035.jpg" ) print (img)writer = SummaryWriter("logs" ) trans_totensor = transforms.ToTensor() img_tenser = trans_totensor(img) writer.add_image("ToTenser" , img_tenser) print (img_tenser[0 ][0 ][0 ])trans_norm = transforms.Normalize([0.5 ,0.5 ,0.5 ],[0.5 ,0.5 ,0.5 ]) img_norm = trans_norm(img_tenser) print (img_norm[0 ][0 ][0 ])writer.add_image("Normalize" ,img_norm) print (img.size) trans_resize = transforms.Resize((512 ,512 )) img_resize = trans_resize(img) print (img_resize) img_resize = trans_totensor(img_resize) writer.add_image("Resize" ,img_resize,0 ) trans_resize_2 = transforms.Resize(512 ) trans_compose = transforms.Compose([trans_resize_2,trans_totensor]) img_resize_2 = trans_compose(img) writer.add_image("Resize" ,img_resize_2,1 ) trans_random = transforms.RandomCrop(512 ) trans_compose_2 = transforms.Compose([trans_random,trans_totensor]) for i in range (10 ): img_crop = trans_compose_2(img) writer.add_image("RandomCrop" ,img_crop,i) writer.close()
dataset告诉我们数据集在什么样的位置和多少数据,给索引+数据
具体实例:
import torchvisionfrom PIL import Imagefrom torch.utils.tensorboard import SummaryWriterdataset_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 ])print (test_set.classes)img, target = test_set[0 ] print (img)print (target)print (test_set.classes[target])img.show() print (test_set[0 ])writer = SummaryWriter("logs" ) for i in range (10 ): img,target = test_set[i] writer.add_image("test_set" ,img,i) writer.close()
dataloader dataloader就是从dataset中取数据,参数控制取多少怎么取
batch_size这个参数是指每次取多少数据
suffle这个参数是打乱顺序
num_workers多线程,加载数据的时候采用单个线程还是多个线程,默认情况为0,采用主线程
drop_last是否舍去最后的余数
代码实例:
import torchvisionfrom torch.utils.data import DataLoaderfrom torch.utils.tensorboard import SummaryWritertest_data = torchvision.datasets.CIFAR10("./dataset" ,train=False ,transform=torchvision.transforms.ToTensor()) test_loader = DataLoader(dataset=test_data,batch_size=64 ,shuffle=False ,num_workers=0 ,drop_last=False ) img,target = test_data[0 ] print (img.shape)print (target)writer = SummaryWriter("logs" ) for epoch in range (2 ): step = 0 for data in test_loader: imgs, targets = data writer.add_images("Epoch:{}" .format (epoch),imgs,step) step = step+1 writer.close()
网络基本骨架的搭建 关于神经网络的工具一般都在torch.nn里面
Containers—>神经网络的骨架、结构,常用Module模块,为所有神经网络提供一个基本的骨架,所搭建的神经网络必须从torch.nn.Module类继承而来。其中有个forward函数,它是call方法的实现,在所有继承了torch.nn.Module类的子类中都要重写,是前向传播,比较重要,类似于call方法直接调用类作为方法,它的作用是输入通过forward变为输出
Module的使用代码:
import torchfrom torch import nnclass Model (nn.Module): def __init__ (self ) -> None : super ().__init__() def forward (self,input ): output = input +1 return output model = Model() x = torch.tensor(1.0 ) output = model(x) print (output)
Sequential的目的可以让神经网络代码压缩在一段代码中,过程连续。
sequential实例代码:
import torchfrom torch import nnfrom torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequentialfrom torch.utils.tensorboard import SummaryWriterclass CNN (nn.Module): def __init__ (self ): super (CNN, self).__init__() self.module1 = Sequential( 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(), Linear(1024 , 64 ), Linear(64 , 10 ) ) def forward (self,x ): x = self.module1(x) return x cnn = CNN() print (cnn)input = torch.ones((64 ,3 ,32 ,32 ))output = cnn(input ) print (output.shape)writer = SummaryWriter("logs" ) writer.add_graph(cnn,input ) writer.close()
Covolution Layers—>卷积层 卷积核随机初始化,网络训练的就是卷积核
卷积操作内部具体实现<实践用不到>:
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 ]]) 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 ) print (output)output2 = F.conv2d(input ,kernel,stride=2 ) print (output2)output3 = F.conv2d(input ,kernel,stride=1 ,padding=1 ) print (output3)
代码示例:
import torchvisionimport torchimport torch.nnfrom torch import nnfrom torch.nn import Conv2dfrom torch.utils.data import DataLoaderfrom torch.utils.tensorboard import SummaryWriterdataset = torchvision.datasets.CIFAR10("./dataset" ,train=False ,transform=torchvision.transforms.ToTensor(),download=True ) dataloader = DataLoader(dataset,batch_size=64 ) class NN (nn.Module): def __init__ (self ): super (NN, self).__init__() self.conv1 = Conv2d(in_channels=3 ,out_channels=6 ,kernel_size=3 ,stride=1 ,padding=0 ) def forward (self,x ): x = self.conv1(x) return x nn = NN() print (nn)writer = SummaryWriter("logs" ) step = 0 for data in dataloader: imgs,targets = data output = nn(imgs) print (imgs.shape) print (output.shape) writer.add_images("input" ,imgs,step) output = torch.reshape(output,(-1 ,3 ,30 ,30 )) writer.add_images("output" ,output,step) step = step + 1
Pooling Layers—>池化层 最大池化目的:保留输入的特征,同时把参数量减少
代码示例:
import torchimport torchvision.datasetsfrom torch import nnfrom torch.nn import MaxPool2dfrom torch.utils.data import DataLoaderfrom torch.utils.tensorboard import SummaryWriterdataset = torchvision.datasets.CIFAR10("./dataset" ,train=False ,download=True ,transform=torchvision.transforms.ToTensor()) dataloader = DataLoader(dataset, batch_size=64 ) 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 maxpool (nn.Module): def __init__ (self ): super (maxpool, self).__init__() self.maxpool1 = MaxPool2d(kernel_size=3 ,ceil_mode=True ) def forward (self,input ): output = self.maxpool1(input ) return output mp = maxpool() writer = SummaryWriter("logs" ) step = 0 for data in dataloader: imgs,targets = data writer.add_images("input" ,imgs,step) output = mp(imgs) writer.add_images("output" ,output,step) step=step+1 writer.close()
非线性激活 RELU,当input>0时,赋值为input原来值,当input<0时,赋值为0,输入只有N—>batch_size;Sigmoid,也只是输入N。
ReLU的实例代码:
import torchfrom torch import nnfrom torch.nn import ReLUinput = torch.tensor([[1 ,-0.5 ], [-1 ,3 ]]) input = torch.reshape(input ,(-1 ,1 ,2 ,2 ))print (input .shape)class RELU (nn.Module): def __init__ (self ): super (RELU, self).__init__() self.relu = ReLU() def forward (self,input ): output = self.relu(input ) return output relu = RELU() output = relu(input ) print (output)
Sigmoid的实例代码:
import torchimport torchvision.datasetsfrom torch import nnfrom torch.nn import ReLU, Sigmoidfrom torch.utils.data import DataLoaderfrom torch.utils.tensorboard import SummaryWriterclass SigMoid (nn.Module): def __init__ (self ): super (SigMoid, self).__init__() self.sigmoid = Sigmoid() def forward (self,input ): output = self.sigmoid(input ) return output sigmoid = SigMoid() dataset = torchvision.datasets.CIFAR10("./dataset" ,train=False ,download=True ,transform=torchvision.transforms.ToTensor()) dataloader = DataLoader(dataset,batch_size = 64 ) writer = SummaryWriter("logs" ) step = 0 for data in dataloader: imgs,targets = data writer.add_images("input" ,imgs,step) output=sigmoid(imgs) writer.add_images("output" ,output,step) step=step+1 writer.close()
Padding Layers—>填充层,用的不多,在卷积里能达到同样的效果
Normalization Layers—>标准化层,用的不多
Linear Layers—>全连接层 Linear代码示例:
import torchimport torchvisionfrom torch import nnfrom torch.nn import Linearfrom torch.utils.data import DataLoaderdataset =torchvision.datasets.CIFAR10("./dataset" ,train=False ,transform=torchvision.transforms.ToTensor()) dataloader= DataLoader(dataset,batch_size=64 ) class LINEAR (nn.Module): def __init__ (self ): super (LINEAR, self).__init__() self.linear = Linear(196608 ,10 ) def forward (self,input ): output = self.linear(input ) return output linear = LINEAR() for data in dataloader: imgs,target = data print (imgs.shape) output = torch.flatten(imgs) print (output.shape) output = linear(output) print (output.shape)
Loss Function:loss就是输出值与实际的误差值,越小越好,是神经网络训练的依据。可以计算实际输出和目标之间的差距,为我们更新输出提供一定的依据(反向传播)。
CrossEntropyLoss,交叉熵,分类问题中有C个类别。
各种loss函数的使用
import torchfrom torch import nnfrom torch.nn import L1Loss, MSELossinputs = 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() result = loss(inputs,targets) print (result)loss_mse = MSELoss() result_mse = loss_mse(inputs,targets) print (result_mse)x = torch.tensor([0.1 ,0.2 ,0.3 ]) print (x.shape)y = torch.tensor([1 ]) x = torch.reshape(x,(1 ,3 )) print (x.shape)loss_cross = nn.CrossEntropyLoss() result_cross = loss_cross(x,y) print (result_cross)
import torchimport torchvisionfrom torch import nnfrom torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequentialfrom torch.utils.data import DataLoaderdataset = torchvision.datasets.CIFAR10("./dataset" ,train = False ,transform=torchvision.transforms.ToTensor(),download=True ) dataloader = DataLoader(dataset,batch_size=1 ) class CNN (nn.Module): def __init__ (self ): super (CNN, self).__init__() self.module1 = Sequential( 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(), Linear(1024 , 64 ), Linear(64 , 10 ) ) def forward (self,x ): x = self.module1(x) return x loss = nn.CrossEntropyLoss() cnn = CNN() for data in dataloader: imgs,targets = data output = cnn(imgs) result_loss = loss(output,targets) result_loss.backward()
加上参数调优之后的整个网络:
import torchimport torchvisionfrom torch import nnfrom torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequentialfrom torch.utils.data import DataLoaderdataset = torchvision.datasets.CIFAR10("./dataset" ,train = False ,transform=torchvision.transforms.ToTensor(),download=True ) dataloader = DataLoader(dataset,batch_size=1 ) class CNN (nn.Module): def __init__ (self ): super (CNN, self).__init__() self.module1 = Sequential( 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(), Linear(1024 , 64 ), Linear(64 , 10 ) ) def forward (self,x ): x = self.module1(x) return x loss = nn.CrossEntropyLoss() cnn = CNN() optim = torch.optim.SGD(cnn.parameters(),lr= 0.01 ) for epoch in range (20 ): running_loss = 0.0 for data in dataloader: imgs,targets = data output = cnn(imgs) result_loss = loss(output,targets) optim.zero_grad() result_loss.backward() optim.step() running_loss = running_loss + result_loss print (running_loss)
使用网络模型调参 import torchvisionfrom torch import nnvgg16_false = torchvision.models.vgg16(pretrained=False ) vgg16_true = torchvision.models.vgg16(pretrained=True ) train_data = torchvision.datasets.CIFAR10("./dataset" ,train=True ,transform=torchvision.transforms.ToTensor(),download=True ) vgg16_true.add_module('add_linear' ,nn.Linear(1000 ,10 )) vgg16_true.classifier.add_module('add_linear' ,nn.Linear(1000 ,10 )) vgg16_false.classifier[6 ] =nn.Linear(4096 ,10 ) print (vgg16_false)
网络模型的保存与读取 import torchimport torchvisionfrom torch import nnvgg16 = torchvision.models.vgg16(pretrained=False ) torch.save(vgg16,"vgg16_method1.pth" ) class cnn (nn.Module): def __init__ (self ): super (cnn, self).__init__() self.conv1 = nn.Conv2d(3 ,64 ,kernel_size=3 ) def forward (self,x ): x = self.conv1(x) return x Cnn = cnn() torch.save(cnn,"Cnn_method1.pth" ) model = torch.load("Cnn_method1.pth" ) torch.save(vgg16.state_dict(),"vgg16_method2.pth" ) vgg16 = torchvision.models.vgg16(pretrained=False ) vgg16.load_state_dict(torch.load("vgg16_method2.pth" ))
完整的模型训练套路 import torchvisionfrom torch.utils.data import DataLoaderfrom torch.utils.tensorboard import SummaryWriterfrom model import *train_data = torchvision.datasets.CIFAR10("./dataset" ,train=True ,transform=torchvision.transforms.ToTensor(),download=True ) test_data = torchvision.datasets.CIFAR10("./dataset" ,train=False ,transform=torchvision.transforms.ToTensor(),download=True ) train_data_size = len (train_data) test_data_size = len (test_data) print ("训练数据集的长度为:{}" .format (train_data_size))print ("测试数据集的长度为:{}" .format (test_data_size))train_dataloader = DataLoader(train_data,batch_size=64 ) test_dataloader = DataLoader(test_data,batch_size=64 ) cnn = CNN() loss_fn = nn.CrossEntropyLoss() learning_rate = 1e-2 optimizer = torch.optim.SGD(cnn.parameters(),lr=learning_rate) total_train_step = 0 total_test_step = 0 epoch = 10 writer = SummaryWriter("logs" ) for i in range (epoch): print ("---------第{}轮训练开始---------" .format (i+1 )) cnn.train() for data in train_dataloader: imgs,targets = data outputs = cnn(imgs) loss = loss_fn(outputs,targets) optimizer.zero_grad() loss.backward() optimizer.step() total_train_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) cnn.eval () total_test_loss = 0 total_accuracy = 0 with torch.no_grad(): for data in test_dataloader: imgs,targets = data outputs = cnn(imgs) loss = loss_fn(outputs,targets) total_test_loss = total_test_loss+loss accuracy = (outputs.argmax(1 ) == targets).sum () total_accuracy = total_accuracy + accuracy print ("整体测试集上的Loss:{}" .format (total_test_loss)) print ("整体测试集上的正确率:{}" .format (total_accuracy/test_data_size)) writer.add_scalar("test_accuracy" ,total_accuracy/test_data_size,total_test_step) writer.add_scalar("test_loss" ,total_test_loss,total_test_step) total_test_step = total_test_step+1 writer.close()
上述的准确率计算的说明:
import torchoutputs = torch.tensor([[0.1 ,0.2 ], [0.3 ,0.4 ]]) print (outputs.argmax(1 ))preds = outputs.argmax(1 ) targets = torch.tensor([0 ,1 ]) print ((preds == targets).sum ())
代码的CNN模型<未调参>:
import torchfrom torch import nnclass CNN (nn.Module): def __init__ (self ): super (CNN, self).__init__() self.model=nn.Sequential( nn.Conv2d(3 ,32 ,5 ,1 ,2 ), nn.MaxPool2d(2 ), nn.Conv2d(32 ,32 ,5 ,1 ,2 ), nn.MaxPool2d(2 ), nn.Conv2d(32 ,64 ,5 ,1 ,2 ), nn.MaxPool2d(2 ), nn.Flatten(), nn.Linear(1024 ,64 ), nn.Linear(64 ,10 ) ) def forward (self,x ): x = self.model(x) return x
如何使用GPU来训练 第一种方式:需要网络模型、数据(输入,输出)、损失函数,调用.cuda()
返回即可
import torchimport torchvisionfrom torch import nnfrom torch.utils.data import DataLoaderfrom torch.utils.tensorboard import SummaryWriterimport timetrain_data = torchvision.datasets.CIFAR10("./dataset" ,train=True ,transform=torchvision.transforms.ToTensor(),download=True ) test_data = torchvision.datasets.CIFAR10("./dataset" ,train=False ,transform=torchvision.transforms.ToTensor(),download=True ) train_data_size = len (train_data) test_data_size = len (test_data) print ("训练数据集的长度为:{}" .format (train_data_size))print ("训练数据集的长度为:{}" .format (test_data_size))train_dataloader = DataLoader(train_data,batch_size=64 ) test_dataloader = DataLoader(test_data,batch_size=64 ) class CNN (nn.Module): def __init__ (self ): super (CNN, self).__init__() self.model=nn.Sequential( nn.Conv2d(3 ,32 ,5 ,1 ,2 ), nn.MaxPool2d(2 ), nn.Conv2d(32 ,32 ,5 ,1 ,2 ), nn.MaxPool2d(2 ), nn.Conv2d(32 ,64 ,5 ,1 ,2 ), nn.MaxPool2d(2 ), nn.Flatten(), nn.Linear(1024 ,64 ), nn.Linear(64 ,10 ) ) def forward (self,x ): x = self.model(x) return x cnn = CNN() if torch.cuda.is_available(): cnn = cnn.cuda() loss_fn = nn.CrossEntropyLoss() if torch.cuda.is_available(): loss_fn = loss_fn.cuda() learning_rate = 1e-2 optimizer = torch.optim.SGD(cnn.parameters(),lr=learning_rate) total_train_step = 0 total_test_step = 0 epoch = 10 writer = SummaryWriter("logs" ) start_time = time.time() for i in range (epoch): print ("---------第{}轮训练开始---------" .format (i+1 )) cnn.train() for data in train_dataloader: imgs,targets = data if torch.cuda.is_available(): imgs = imgs.cuda() targets = targets.cuda() outputs = cnn(imgs) loss = loss_fn(outputs,targets) optimizer.zero_grad() loss.backward() optimizer.step() total_train_step = total_train_step+1 if total_train_step % 100 == 0 : end_time = time.time() print ("耗时:{}" .format (end_time-start_time)) print ("训练次数:{},Loss:{}" .format (total_train_step,loss.item())) writer.add_scalar("train_loss" ,loss.item(),total_train_step) cnn.eval () total_test_loss = 0 total_accuracy = 0 with torch.no_grad(): for data in test_dataloader: imgs,targets = data if torch.cuda.is_available(): imgs = imgs.cuda() targets = targets.cuda() outputs = cnn(imgs) loss = loss_fn(outputs,targets) total_test_loss = total_test_loss+loss accuracy = (outputs.argmax(1 ) == targets).sum () total_accuracy = total_accuracy + accuracy print ("整体测试集上的Loss:{}" .format (total_test_loss)) print ("整体测试集上的正确率:{}" .format (total_accuracy/test_data_size)) writer.add_scalar("test_accuracy" ,total_accuracy/test_data_size,total_test_step) writer.add_scalar("test_loss" ,total_test_loss,total_test_step) total_test_step = total_test_step+1 writer.close()
第二种GPU训练方式:需要网络模型、数据(输入,输出)、损失函数,调用.to(device)
,这个divcie = torch.device("cpu")
也可以是device = torch.device("cuda")
,电脑有多个显卡的话,可以指定device = torch.device("cuda:n")
import torchimport torchvisionfrom torch import nnfrom torch.utils.data import DataLoaderfrom torch.utils.tensorboard import SummaryWriterimport timedevice = torch.device("cuda" if torch.cuda.is_avaliable() else "cpu" ) train_data = torchvision.datasets.CIFAR10("./dataset" ,train=True ,transform=torchvision.transforms.ToTensor(),download=True ) test_data = torchvision.datasets.CIFAR10("./dataset" ,train=False ,transform=torchvision.transforms.ToTensor(),download=True ) train_data_size = len (train_data) test_data_size = len (test_data) print ("训练数据集的长度为:{}" .format (train_data_size))print ("训练数据集的长度为:{}" .format (test_data_size))train_dataloader = DataLoader(train_data,batch_size=64 ) test_dataloader = DataLoader(test_data,batch_size=64 ) class CNN (nn.Module): def __init__ (self ): super (CNN, self).__init__() self.model=nn.Sequential( nn.Conv2d(3 ,32 ,5 ,1 ,2 ), nn.MaxPool2d(2 ), nn.Conv2d(32 ,32 ,5 ,1 ,2 ), nn.MaxPool2d(2 ), nn.Conv2d(32 ,64 ,5 ,1 ,2 ), nn.MaxPool2d(2 ), nn.Flatten(), nn.Linear(1024 ,64 ), nn.Linear(64 ,10 ) ) def forward (self,x ): x = self.model(x) return x cnn = CNN() cnn = cnn.cuda() cnn = cnn.to(device) loss_fn = nn.CrossEntropyLoss() loss_fn = loss_fn.cuda() loss_fn = loss_fn.to(device) learning_rate = 1e-2 optimizer = torch.optim.SGD(cnn.parameters(),lr=learning_rate) total_train_step = 0 total_test_step = 0 epoch = 10 writer = SummaryWriter("logs" ) start_time = time.time() for i in range (epoch): print ("---------第{}轮训练开始---------" .format (i+1 )) cnn.train() for data in train_dataloader: imgs,targets = data imgs = imgs.to(device) targets = targets.to(device) outputs = cnn(imgs) loss = loss_fn(outputs,targets) optimizer.zero_grad() loss.backward() optimizer.step() total_train_step = total_train_step+1 if total_train_step % 100 == 0 : end_time = time.time() print ("耗时:{}" .format (end_time-start_time)) print ("训练次数:{},Loss:{}" .format (total_train_step,loss.item())) writer.add_scalar("train_loss" ,loss.item(),total_train_step) cnn.eval () total_test_loss = 0 total_accuracy = 0 with torch.no_grad(): for data in test_dataloader: imgs,targets = data imgs = imgs.to(device) targets = targets.to(device) outputs = cnn(imgs) loss = loss_fn(outputs,targets) total_test_loss = total_test_loss+loss accuracy = (outputs.argmax(1 ) == targets).sum () total_accuracy = total_accuracy + accuracy print ("整体测试集上的Loss:{}" .format (total_test_loss)) print ("整体测试集上的正确率:{}" .format (total_accuracy/test_data_size)) writer.add_scalar("test_accuracy" ,total_accuracy/test_data_size,total_test_step) writer.add_scalar("test_loss" ,total_test_loss,total_test_step) total_test_step = total_test_step+1 writer.close()
完整的模型验证(测试,demo)套路 核心是利用已经训练好的模型,然后给它提供输入。
例如:
import torchimport torchvisionfrom PIL import Imagefrom torch import nnimage_path = "./img/dog.jpg" image = Image.open (image_path) image = image.convert('RGB' ) transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32 ,32 )), torchvision.transforms.ToTensor()]) image = transform(image) print (image.shape)class CNN (nn.Module): def __init__ (self ): super (CNN, self).__init__() self.model=nn.Sequential( nn.Conv2d(3 ,32 ,5 ,1 ,2 ), nn.MaxPool2d(2 ), nn.Conv2d(32 ,32 ,5 ,1 ,2 ), nn.MaxPool2d(2 ), nn.Conv2d(32 ,64 ,5 ,1 ,2 ), nn.MaxPool2d(2 ), nn.Flatten(), nn.Linear(1024 ,64 ), nn.Linear(64 ,10 ) ) def forward (self,x ): x = self.model(x) return x model = torch.load("cnn_9.pth" ,map_location=torch.device('cpu' )) torch.reshape(image,(1 ,3 ,32 ,32 )) model.eval () with torch.no_grad(): output = model(image) print (output.argmax(1 ))