一、数据加载
1.使用PyTorch现有数据集
# 准备数据集
datasets_train = torchvision.datasets.CIFAR10(root="train", train=True, transform=torchvision.transforms.ToTensor(),
download=True)
datasets_test = torchvision.datasets.CIFAR10(root="train", train=False, transform=torchvision.transforms.ToTensor(),
download=True)
# 加载器
dataloader_train = DataLoader(dataset=datasets_train, batch_size=64)
dataloader_test = DataLoader(dataset=datasets_test, batch_size=64)
2.自定义数据集加载
自定义数据集需要继承DataSets类,并实现__getItem__ 和 __len__方法
class MyDataset(Dataset):#需要继承torch.utils.data.Dataset类
def __init__(self):
# 初始化文件路径或文件名列表。
# 初始化该类的一些基本参数。
pass
def __getitem__(self, index):
# 1、从文件中读取一个数据(例如,plt.imread)。
# 2、预处理数据(例如torchvision.Transform)。
# 3、返回数据对(例如图像和标签)。
# 这里需要注意的是,第一步:read one data,是一个data
pass
def __len__(self):
# 返回数据集的总大小。
# 具体实例如下
class AnimalDataSet(Dataset):
def __init__(self, root_dir, transform=None):
self.root_dir = root_dir #文件目录
self.transform = transform #变换
self.images = os.listdir(self.root_dir)#目录里的所有文件
def __len__(self):
return len(self.images)
def __getitem__(self,index):#根据索引index返回dataset[index]
image_index = self.images[index]#根据索引index获取该图片
img_path = os.path.join(self.root_dir, image_index)#获取索引为index的图片的路径名
img = io.imread(img_path)# 读取该图片
label = img_path.split('\\')[-1].split('.')[0]# 根据该图片的路径名获取该图片的label,具体根据路径名进行分割。我这里是"E:\\Python Project\\Pytorch\\dogs-vs-cats\\train\\cat.0.jpg",所以先用"\\"分割,选取最后一个为['cat.0.jpg'],然后使用"."分割,选取[cat]作为该图片的标签
sample = {'image':img,'label':label}#根据图片和标签创建字典
if self.transform:
sample = self.transform(sample)#对样本进行变换
return sample #返回该样本
二、模型搭建
网络继承nn.Module类,并实现__init__ 和 __forward__方法
# 实例如下:
class First(nn.Module):
def __init__(self):
super(First, self).__init__()
self.model = nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2),
nn.MaxPool2d(kernel_size=2),
nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, padding=2),
nn.MaxPool2d(kernel_size=2),
nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2),
nn.MaxPool2d(kernel_size=2),
nn.Flatten(),
nn.Linear(in_features=1024, out_features=64),
nn.Linear(in_features=64, out_features=10)
)
def forward(self, x):
x = self.model(x)
return x
三、模型训练和测试
epoch = 10 # 定义epoch,表示模型训练的轮次数
for i in range(epoch):
print("第{}轮训练:".format(i + 1))
# 表示模型训练阶段,此时需要对模型中的权重梯度进行改变
first.train()
for data in dataloader_train:
img, target = data
output = first(img)
loss = loss_fn(output, target)
# 放入优化器中优化:梯度清零,反向传播得到每个参数节点的梯度,优化参数
optim.zero_grad() # 将上一轮的梯度清零
loss.backward() # 反向传播计算梯度
optim.step() # 梯度更新
total_train_step += 1 # 记录训练的次数
if total_train_step % 100 == 0: # 每训练一百次输出loss
writer.add_scalar("train_loss", loss.item(), global_step=total_train_step)
print("训练次数为{}时,loss为:{}".format(total_train_step, loss.item()))
# 测试步骤:此时不要对模型中的梯度进行改变
first.eval()
total_test_loss = 0
total_accuracy = 0
# 测试的时候不需要梯度进行调整
with torch.no_grad():
for data in dataloader_test:
img, target = data
output = first(img)
loss = loss_fn(output, target)
# 这里吧loss进行相加是为了后期比较不同的轮次上,整体数据集的loss,如第一个epoch上,整体数据集的loss为12,第二个epoch上,loss为9,固也可以得知模型训练的效果
total_test_loss = total_test_loss + loss.item()
accuracy = (output.argmax(1) == target).sum()
total_accuracy = total_accuracy + accuracy
print("整体测试集上的loss为:{}".format(total_test_loss))
print("整体测试集上的准确率为:{}".format(total_accuracy / len(datasets_test)))
writer.add_scalar("test_accuracy", total_accuracy / len(datasets_test), total_test_step)
writer.add_scalar("test_loss", total_test_loss, global_step=total_test_step)
total_test_loss += 1
# 每一轮训练后,保存模型
torch.save(first, "first_{}.pth".format(i))
上述模型的训练和测试步骤可以归纳为:
epoch = N # 定义epoch,表示模型训练的轮次数
for i in range(epoch):
# 表示模型训练阶段,此时需要对模型中的权重梯度进行改变
first.train()
for data in dataloader_train:
img, target = data
output = first(img)
loss = loss_fn(output, target)
# 放入优化器中优化:梯度清零,反向传播得到每个参数节点的梯度,优化参数
optim.zero_grad() # 将上一轮的梯度清零
loss.backward() # 反向传播计算梯度
optim.step() # 梯度更新
# 输出当前loss值
# 测试步骤:此时不要对模型中的梯度进行改变
first.eval()
total_test_loss = 0
total_accuracy = 0
# 测试的时候不需要梯度进行调整
with torch.no_grad():
for data in dataloader_test:
img, target = data
output = first(img)
loss = loss_fn(output, target)
total_test_loss = total_test_loss + loss.item()
accuracy = (output.argmax(1) == target).sum()
total_accuracy = total_accuracy + accuracy
# 输出loss和accuracy值
# 每一轮训练后,保存模型
torch.save(first, "first_{}.pth".format(i))
# 上面的几行代码几乎是固定的,然后对模型训练中的指标进行输出
“”“
主要是对两个指标进行输出
1.loss.item():模型训练中的loss值的变化,因为模型的训练主要目的就是为了对loss函数进行优化,使其达到尽可能小,故定时输出loss观察模型的训练效果是很有必要的。语句为print("训练次数为{}时,模型的损失函数值为{}".format(total_train, loss.item()))
2.accuracy:accuracy等于训练一个批次(即一个内层循环中)中,output与target相等的数量与该批次的总数相比,表示模型训时的精确度
语句为:
accuracy = (output.argmax(1) == target).sum() # 一个批次中的一个数据的比较结果,如果output所得结果与target相同,就累加
total_accuracy = total_accuracy + accuracy # 将一个批次的训练准确的次数都加起来
print(total_accuracy / len(dataloader_train))
# 这里的精确度,可以放在一个epoch迭代完成后输出,只输出一个轮次的精确度。
”“”