文章目录
pytorch介绍
PyTorch是一个处理张量的库。张量:Tensor,可以是一个标量、一维、二维、或任何n维数组
Tensor是一个类,包含data(参数值,是一个Tensor)和grad(损失对参数的偏导,也是一个Tensor)
Tensor直接参与运算【张量与张量运算,张量与标量运算】,是在构建计算图
基本张量操作
from torchvision import transforms
Tensor.item()#当Tensor中数据为标量时,返回python的标量:只适用于保存了标量的Tensor
# 一般张量参与运算时,即构建计算图。但张量.data参与运算时,此时不参与构建计算图
Tensor.data#x.data返回和x的相同数据 tensor, 将参数从网络中隔离开,不会加入到x的计算历史里,不参与更新
x = torch.Tensor(2,3) #构造一个2x3的张量,没初始化但仍然会有值
x = torch.Tensor([1.0]) #构造一个张量
# 从numpy创建张量
array_numpy = numpy.array([1, 2, 3])
t = torch.from_numpy(array_numpy)# 注意该法创建的tensor于原ndarray共享内存,当修改其中一个数据,另一个也将会被改动
#根据size创建未初始化的张量,有随机数据u
#torch.empty(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False, pin_memory=False)
torch.empty(2, 3)
torch.ones(2,3)# 根据size创建全0张量
# 创建同input_tensor形状的全0张量
input = torch.empty(2, 3)
torch.ones_like(input)
torch.zeros(2,3)# 根据size创建全1张量
# 创建同input_tensor形状的全1张量
torch.zeros_like(input)
# 修改张量的维度
tensor.view()#其中出现-1时,表示该位置自动计算
tensor=torch.randn(4,4) #4*4
tensor.view(16)#torch.Size([16])
tensor.view(2,-1)#torch.Size([2, 8])
tensor.view(-1,8)#torch.Size([2, 8])
tensor.view(2,2,-1)#torch.size([2,2,4])
tensor.view(-1,2,2)#torch.size([4,2,2])
torch.exp(input_tensor)#返回一个新张量,包含输入input张量每个元素的指数
'''
神经网络希望输入的数据比较小,最好[-1,1],最好属于正态分布,对训练有帮助
Compose中[]里都是类,将数据按照[]中的顺序对PIL.Image进行依次处理
transforms.ToTensor():
opencv读取图片为np.array:高*宽*通道数(彩色是高*宽*3,黑白是高*宽),像素值为0~255,bgr需转为rgb使用
pillow(pytorch的tv.dataset读取图片时使用)读取图片为:Image对象(宽*高),像素值为0~255,rgb,可直接使用ToTensor,或者先转为np.array此时变为那个
transforms.ToTensor()将其变成:通道数*高*宽(彩色是3*高*宽,黑白是1*高*宽),像素值进行归一化:先转为float后除以255.为0~1,方便高效处理数据
transforms.Normalize((0.1307,), (0.3081,)):
n为通道数
(mean,std)=((均值1,均值2,..均值n,(标准差1. 标准差2,..标准差n))
统计了数据的均值和标准差之后的数值
标准化:(数值-mean)/std,使其服从分布N(0,1) 均值为0,标准差为1,不一定是正太分布
'''
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
使用gpu
# 检测是否有gpu
status=torch.cuda.is_available()
# gpu个数
num=torch.cuda.device_count()
#如果有gpu,使用gpu
device=torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model.to(device)
#使用gpu计算,把数据转为gpu专用
x_data,y_data=x_data.to(device),y_data.to(device)
保存模型
gpu和cpu
训练结束后保存
如何选取最优的?
- 在训练时,放入测试,最后选择测试集上效果最好的
- 保存训练过程中最小损失的模型
保存模型:数据量大,加载时慢
保存格式
.pth
代码
- 保存模型:存训练过程中最小损失的模型
import torch
import copy
min_loss=100#给一个大值
min_epoch=3#更改min_loss的epoch
best_model=None
def train(x):
global min_loss
global min_epoch
global best_model
if loss<min_loss and epoch>=min_epoch:
min_loss=loss
best_model=copy.deepcopy(model)
path="D:/"
now = datetime.datetime.now()
now_time=now.strftime("%Y-%m-%d-%H%M%S")
torch.save(model.state_dict(),path+'/' + str(now_time)+' loss=' + str("%.4f" % min_loss) + '.pth')
- 保存模型:在训练时,放入测试,最后选择测试集上效果最好的
import torch
import copy
min_loss=100#给一个大值
min_epoch=3#更改min_loss的epoch
best_model=None
best_acc=0 #给一个小值
def train(x):
global min_loss
global min_epoch
global best_model
#训练结束
acc=test()
if acc>best_acc and epoch>=min_epoch:
min_loss=loss
best_acc=acc
best_model=copy.deepcopy(model)
path="D:/"
now = datetime.datetime.now()
now_time=now.strftime("%Y-%m-%d-%H%M%S")
torch.save(model.state_dict(),path+'/' + str(now_time)+' loss=' + str("%.4f" % min_loss) + ' acc=' + str("%.4f" % best_acc)+'.pth')
- 加载模型
class Net(torch.nn.Module):
pass
path="D:/nn/2021-07-31-165415 loss=12.9383.pth"
model = torch.load(path)
保存模型参数
保存格式
.pth.state
代码
- 保存模型:存训练过程中最小损失的模型
import torch
import copy
min_loss=100#给一个大值
min_epoch=3#更改min_loss的epoch
best_model_state_dict=None
def train(x):
global min_loss
global min_epoch
global best_model_state_dict
if loss<min_loss and epoch>=min_epoch:
min_loss=loss
best_model_state_dict=model.state_dict()
path="D:/"
now = datetime.datetime.now()
now_time=now.strftime("%Y-%m-%d-%H%M%S")
#torch.save(net.state_dict(),PATH)
torch.save(best_model_state_dict,path+'/' + str(now_time)+' loss=' + str("%.4f" % min_loss) + '.pth.state')
- 保存模型:在训练时,放入测试,最后选择测试集上效果最好的
import torch
import copy
min_loss=100#给一个大值
min_epoch=3#更改min_loss的epoch
best_model_state_dict=None
best_acc=0 #给一个小值
def train(x):
global min_loss
global min_epoch
global best_model_state_dict
#训练结束
acc=test()
if acc>best_acc and epoch>=min_epoch:
min_loss=loss
best_acc=acc
best_model_state_dict=model.state_dict()
path="D:/"
now = datetime.datetime.now()
now_time=now.strftime("%Y-%m-%d-%H%M%S")
#torch.save(net.state_dict(),PATH)
torch.save(best_model_state_dict,path+'/' + str(now_time)+' loss=' + str("%.4f" % min_loss) + ' acc=' + str("%.4f" % best_acc)+'.pth.state')
- 加载模型
class Net(torch.nn.Module):
pass
path="D:/nn/2021-07-31-165415 loss=12.9383.pth.state"
model = Net(*args, **kwargs)
model.load_state_dict(torch.load(path))
训练中不得已结束(如:停电断网)时保存 checkpoint 断点续传,以便加载后继续训练
保存格式
.pth.checkpoint
代码
- 保存
checkpoint_dict={
'epoch': epoch,
'model_state_dict': model.state_dict(),
'optimizer_state_dict': optimizer.state_dict(),
'loss': loss,
}
path="D:/"
now = datetime.datetime.now()
now_time=now.strftime("%Y-%m-%d-%H%M%S")
#torch.save(checkpoing_dict, PATH)
torch.save(checkpoing_dict,path+'/' + str(now_time)+'.pth.checkpoint')
- 加载
'''
运行推理之前,务必调用 model.eval() 去设置 dropout 和 batch normalization 为评估。
如果不这样做,有可能得到不一致的推断结果。 如果你想要恢复训练,请调用 model.train() 以
确保这些层处于训练模式。
'''
class Net(torch.nn.Module):
pass
model = Net(*args, **kwargs)
optimizer = TheOptimizerClass(*args, **kwargs)
path="D:/nn/2021-07-31-165415.pth.checkpoint"
checkpoint_dict = torch.load(path)
model.load_state_dict(checkpoint_dict['model_state_dict'])
optimizer.load_state_dict(checkpoint_dict['optimizer_state_dict'])
start_epoch = checkpoint['epoch']+1
loss = checkpoint['loss']
pytorch自带数据集
import torchvision as tv
#torchvision.datasets为数据集
'''
minist:手写数字图片,用于分类器的检测
training set:6000
test set:1000
classes:10
'''
#tv.dataset中图片是用PILLOW(PIL)加载的,数据为0~255,把他们转成张量时,数据会压缩成[0,1]或[-1,1]
train_set = tv.datasets.MNIST(root='', train=True,transform=tv.transforms.toTensor(),download=True)
test_set = tv.datasets.MNIST(root='', train=False,transform=tv.transforms.toTensor(),download=True)
'''
CIFAR-10:动物、交通工具图片,用于分类器的检测
training set:5000
test set:1000
classes:10
'''
train_set2 = tv.datasets.CIFAR10(root='', train=True,transform=tv.transforms.toTensor(),download=True)
test_set2 = tv.datasets.CIFAR10()(root='', train=False,transform=tv.transforms.toTensor(),download=True)
pytorch从数据集制作mini-batch
#Dataset抽象类,不能实例化,只能被子类继承,使用时需构造自己的类
from torch.utils.data import Dataset
#DataLoader加载数据于pytorch
from torch.utils.data import DataLoader
'''
Dataset是抽象类,不能实例化,继承Dataset时,需要重写__init__,__getitem__和__len__
1. 数据量不大,如结构性的:直接在__init__加载所有数据进内存,如下
2.数据量大,如图片,语音:
x:在__init__中把文件名放到列表里,__getitem__用时再加载进内存,并返回
y是:
简单的数值,__init__直接加载进内存
复杂的张量,在__init__中把文件名放到列表里,__getitem__用时再加载进内存,并返回
'''
class DataDataset(Dataset):
def __init__(self,filepath):
#因为一般的显卡只支持32位浮点数,所以不用double64位
data = np.loadtxt(filepath,delimiter=',',dtype=np.float32)
self.len=data.shape[0]#shape (行数,列数)
self.x_data=torch.from_numpy(data[:, :-1])
self.y_data=torch.from_numpy(data[:, [-1]])
def __getitem__(self, index):
return self.x_data[index], self.y_data[index]
def __len__(self):
return self.len
dataset=DataDataset('D:\BaiduNetdiskDownload\PyTorch深度学习实践\diabetes.csv.gz')
'''
batch_size:mini-batch的样本数
shuffle:分组前先打乱顺序
num_workers:读取进内存时,是否多线程,windows下,要求须在__name__=='__main__'下调用
'''
train_loader=DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=2)
'''
train_loader先把数据打乱(shuffle),再分组,把每个组跑一遍,enumerate(,start_index)
x_data_mini_batch,y_data_mini_batch:Tensor
'''
for i,(x_data_mini_batch,y_data_mini_batch) in enumerate(train_loader,0):
训练集和测试集
从pytorch自带的数据集
#DataLoader加载数据于pytorch
from torch.utils.data import DataLoader
import torchvision as tv
#tv.dataset中图片是用PILLOW(PIL)加载的,数据为0~255,把他们转成张量时,数据会压缩成[0,1]或[-1,1]
train_set = tv.datasets.MNIST(root='', train=True,transform=tv.transforms.toTensor(),download=True)
test_set = tv.datasets.MNIST(root='', train=False,transform=tv.transforms.toTensor(),download=True)
train_loader=DataLoader(dataset=train_set,batch_size=32,shuffle=True)
#不需打乱
test_loader=DataLoader(dataset=test_set,batch_size=32,shuffle=False)
for batch_idx, (x_data_mini_batch,y_data_mini_batch) in enumerate(train_loader):
本地数据
# 读取原始数据,并划分训练集和测试集
raw_data = np.loadtxt('diabetes.csv', delimiter=',', dtype=np.float32)
X = raw_data[:, :-1]
y = raw_data[:, [-1]]
Xtrain, Xtest, Ytrain, Ytest = train_test_split(X,y,test_size=0.3)
Xtest = torch.from_numpy(Xtest)
Ytest = torch.from_numpy(Ytest)
# 将训练数据集进行批量处理
# prepare dataset
class DiabetesDataset(Dataset):
def __init__(self, data,label):
self.len = data.shape[0] # shape(多少行,多少列)
self.x_data = torch.from_numpy(data)
self.y_data = torch.from_numpy(label)
def __getitem__(self, index):
return self.x_data[index], self.y_data[index]
def __len__(self):
return self.len
train_dataset = DiabetesDataset(Xtrain,Ytrain)
train_loader = DataLoader(dataset=train_dataset, batch_size=32, shuffle=True, num_workers=1) #num_workers 多线程
pytorch实现线性回归
# -*- coding: utf-8 -*-
"""
Created on Thu Jul 15 16:12:43 2021
@author: Administrator
"""
import torch
import matplotlib.pyplot as plt
epoch_list=[]
loss_list=[]
#torch.nn.Module是所有网络的父类
#torch.nn.Module是callable的。可以采用对象(参数)的方式
class LinearModel(torch.nn.Module):
#构造函数
def __init__(self):
super(LinearModel,self).__init__()
#(in_feature:每个样本的特征,out_feature,bias=True 要b)
#获取w张量:self.linear.weight
#获取b张量: self.linear.bias
self.linear=torch.nn.Linear(1,1,bias=True)
#重载nn.Module中的forward函数,定义y_pred=wx+b
def forward(self,x_data):
y_pred=self.linear(x_data)
return y_pred
#不用写backward函数,nn.Module会自动生成
x_data=torch.Tensor([[1.0],[2.0],[3.0]])#3*1
y_data=torch.Tensor([[2.0],[4.0],[6.0]])#3*1
model