赞
踩
PyTorch是利用深度学习进行科学研究的重要工具,学术界常用的深度学习框架,简洁、高效、扩展性好。
conda create -n pytorch python=3.8
conda info --envs
conda activate pytorch
但之后用jutpter notebook时出现了以下问题:
解决方法:参考了安装PyTorch后jupyter notebook中仍出现“No module named torch“,
Anaconda虚拟环境安装PyTorch并使用Spyder
,操作之后即可成功运行
conda activate pytorch
conda deactivate
conda install package_name
conda remove package_name
conda list
import torch
x = torch.rand(4,3) #随机初始化矩阵
y = torch.zeros(4,3,dtype = torch.long) #全0矩阵的构建,并且通过dtype设置数据类型为 long
z = torch.zero_(x) #将现有矩阵转换为全0矩阵,torch.zeros_like()也是此用法
x = torch.tensor([5,6]) #直接使用数据构造张量
print(x)
#基于已经存在的tensor,创建一个tensor
x = x.new_ones(4, 3, dtype=torch.double) #创建一个新的全1矩阵tensor,返回的tensor默认具有相同的torch.dtype和torch.device
print(x)
x = torch.randn_like(x, dtype=torch.float) # 重置数据类型
print(x)
常见的构造Tensor方法:
函数 | 功能 |
---|---|
Tensor(sizes) | 基础构造函数 |
tensor(data) | 类似于np.array |
ones(size) | 全1 |
zeros(size) | 全0 |
eye(sizes) | 对角为1,其余为0 |
arange(s,e,step) | 从s到e,步长为step |
linspace(s,e,steps) | 从s到e,均匀分成step份 |
rand/randn(sizes) | rand是[0,1)均匀分布;randn是服从N(0,1)的正态分布 |
normal(mean,std) | 正态分布(均值为mean,标准差是std) |
randperm(m) | 随机排列 |
print(x+y) #方式一
print(torch.add(x,y)) #方式二
y.add_(x) #方式三
索引操作(类似于numpy)
需要注意的是:索引出来的结果与原数据共享内存,修改一个,另一个会跟着修改。如果不想修改,可以考虑使用copy()等方法
维度变换
x = torch.randn(4, 4)
y = x.view(16)
z = x.view(-1, 8) # -1是指这一维的维数由其他维度决定
print(x.size(), y.size(), z.size())
torch.view() 返回的新tensor与源tensor共享内存(其实是同一个tensor),更改其中的一个,另外一个也会跟着改变。
为了使创建的张量和原始张量不共享内存,我们先用 clone() 创造一个张量副本然后再使用 torch.view()进行函数维度变换 。
当对两个形状不同的 Tensor 按元素运算时,可能会触发广播(broadcasting)机制:先适当复制元素使这两个 Tensor 形状相同后再按元素运算。
from __future__ import print_function
import torch
x = torch.randn(3,3,requires_grad=True) ##创建一个张量并设置requires_grad=True用来追踪其计算历史
print(x.grad_fn) #每个张量都有一个.grad_fn属性,该属性引用了创建 Tensor 自身的Function,如果张量是用户手动创建的,这个张量的grad_fn是 None
#如果需要计算导数,可以在 Tensor 上调用 .backward()。如果 Tensor 是一个标量(即它包含一个元素的数据),则不需要为 backward() 指定任何参数,但是如果它有更多的元素,则需要指定一个gradient参数,该参数是形状匹配的张量
y == x**2 #y是计算的结果,所以它有grad_fn属性
y.backward(gradient=torch.randn(3,3))
z = y * y * 3
out = z.mean()
out.backward() #反向传播,因为 out 是一个标量,因此out.backward()和 out.backward(torch.tensor(1.)) 等价
print(x.grad) #输出导数 d(out)/dx
#再来反向传播一次
out2 = x.sum()
out2.backward()
print(x.grad)
out3 = x.sum()
x.grad.data.zero_() #grad在反向传播过程中是累加的(accumulated),这意味着每一次运行反向传播,梯度都会累加之前的梯度,所以一般在反向传播之前需把梯度清零。
out3.backward()
print(x.grad)
#防止跟踪
with torch.no_grad():
print((x**2).requires_grad)
##希望修改tensor的数值,但又不希望autograd记录(即不会影响反向传播),可以对 tensor.data 进行操作
x = torch.ones(1,requires_grad=True)
print(x.data) # 还是一个tensor
print(x.data.requires_grad) # 但是已经是独立于计算图之外
y = 2 * x
x.data *= 100 # 只改变了值,不会记录在计算图,所以不会影响梯度传播
y.backward()
print(x.data) # 更改data的值也会影响tensor的值
print(x.grad)
#方法一
import os
os.environ["CUDA_VISIBLE_DEVICE"] = "2" # 设置默认的显卡
#方法二
CUDA_VISBLE_DEVICE=0,1 python train.py # 使用0,1两块GPU
深度学习中训练和验证过程最大的特点在于读入数据是按批的,每次读入一个批次的数据,放入GPU中训练,然后将损失函数反向传播回网络最前面的层,同时使用优化器调整网络参数。这里会涉及到各个模块配合的问题。训练/验证后还需要根据设定好的指标计算模型表现。
batch_size = 16 # 批次的大小
lr = 1e-4 # 优化器的学习率
max_epochs = 100 #训练次数
GPU的设置有两种常见的方式:
# 方案一:使用os.environ,这种情况如果使用GPU不需要设置
os.environ['CUDA_VISIBLE_DEVICES'] = '0,1'
# 方案二:使用“device”,后续对要使用GPU的变量用.to(device)即可
device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu")
PyTorch数据读入是通过Dataset(定义好数据的格式和数据变换形式)+DataLoader(用iterative的方式不断读入批次数据)的方式完成的
主要包含三个函数:
_init_: 用于向类中传入外部参数,同时定义样本集
_getitem_: 用于逐个读取样本集合中的元素,可以进行一定的变换,并将返回训练/验证所需的数据
_len_: 用于返回数据集的样本数
import torch
from torchvision import datasets
train_data = datasets.ImageFolder(train_path, transform=data_transform) #PyTorch自带的ImageFolder类的用于读取按一定结构存储的图片数据(path对应图片存放的目录,目录下包含若干子目录,每个子目录对应属于同一个类的图片)
val_data = datasets.ImageFolder(val_path, transform=data_transform) #data_transform”可以对图像进行一定的变换,如翻转、裁剪等操作,可自己定义
需要自己来定义Dataset类:
class MyDataset(Dataset): def __init__(self, data_dir, info_csv, image_list, transform=None): """ Args: data_dir: path to image directory. info_csv: path to the csv file containing image indexes with corresponding labels. image_list: path to the txt file contains image names to training/validation set transform: optional transform to be applied on a sample. """ label_info = pd.read_csv(info_csv) image_file = open(image_list).readlines() self.data_dir = data_dir self.image_file = image_file self.label_info = label_info self.transform = transform def __getitem__(self, index): """ Args: index: the index of item Returns: image and its labels """ image_name = self.image_file[index].strip('\n') raw_label = self.label_info.loc[self.label_info['Image_index'] == image_name] label = raw_label.iloc[:,0] image_name = os.path.join(self.data_dir, image_name) image = Image.open(image_name).convert('RGB') if self.transform is not None: image = self.transform(image) return image, label def __len__(self): return len(self.image_file)
构建好Dataset后,就可以使用DataLoader来按批次读入数据了:
from torch.utils.data import DataLoader
train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, num_workers=4, shuffle=True, drop_last=True)
val_loader = torch.utils.data.DataLoader(val_data, batch_size=batch_size, num_workers=4, shuffle=False)
#样本是按“批”读入的,batch_size就是每次读入的样本数
#num_workers:有多少个进程用于读取数据
#shuffle:是否将读入的数据打乱
#drop_last:对于样本最后一部分没有达到批次数的样本,使其不再参与训练
PyTorch中的DataLoader的读取可以使用next和iter来完成:
import matplotlib.pyplot as plt
images, labels = next(iter(val_loader))
print(images.shape)
plt.imshow(images[0].transpose(1,2,0))
plt.show()
构造多层感知机:
import torch from torch import nn #Module 类是 nn 模块里提供的一个模型构造类,是所有神经网络模块的基类,我们可以继承它来定义我们想要的模型 class MLP(nn.Module): # 声明带有模型参数的层,这里声明了两个全连接层 def __init__(self, **kwargs): #用于创建模型参数 # 调用MLP父类Block的构造函数来进行必要的初始化。这样在构造实例时还可以指定其他函数 super(MLP, self).__init__(**kwargs) self.hidden = nn.Linear(784, 256) self.act = nn.ReLU() self.output = nn.Linear(256,10) # 定义模型的前向计算,即如何根据输入x计算返回所需要的模型输出 def forward(self, x): o = self.act(self.hidden(x)) return self.output(o)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。