当前位置:   article > 正文

「深度学习一遍过」必修3:使用Pytorch进行数据读取_from createdataloader import loaddata

from createdataloader import loaddata

本专栏用于记录关于深度学习的笔记,不光方便自己复习与查阅,同时也希望能给您解决一些关于深度学习的相关问题,并提供一些微不足道的人工神经网络模型设计思路。
专栏地址:「深度学习一遍过」必修篇

目录

1 CreateDataset——生成训练集和测试集 

1.1 思路

1.2 代码

1.3 结果

2 CreateDataloader——数据加载

2.1 思路

2.2 代码

2.3 结果

2.4 补充

3 加载自己的数据——使用DataLoader读取Dataset

3.1 思路

3.2 代码

3.3 结果


1 CreateDataset——生成训练集和测试集 

生成训练集和测试集,保存在 txt 文件中。

相当于模型的输入。后面做数据加载器 dataload 的时候从里面读它的数据。

1.1 思路

导入库

  1. import os # 导入系统库
  2. import random # 随机数生成器(打乱数据用的)

百分之 60 用来当训练集
百分制 40 用来当测试集

  1. train_ratio = 0.6
  2. test_ratio = 1 - train_ratio

数据的根目录,保存到这个根目录下的 data 文件夹

rootdata = r"data" 

产生 train.txt 和 test.txt

前一部分:图片所在目录/位置;
后一部分:图片对应标签       具体如下图所示

 打乱训练数据集次序

random.shuffle(train_list)

 写入 train.txt 和 test.txt

1.2 代码

  1. import os
  2. import random
  3. train_ratio = 0.6
  4. test_ratio = 1 - train_ratio
  5. rootdata = r"data"
  6. train_list, test_list = [], []
  7. data_list = []
  8. class_flag = -1
  9. for a, b, c in os.walk(rootdata):
  10. print(a)
  11. for i in range(len(c)):
  12. data_list.append(os.path.join(a, c[i]))
  13. for i in range(0, int(len(c) * train_ratio)):
  14. train_data = os.path.join(a, c[i]) + '\t' + str(class_flag) + '\n' # os.path.join 拼接起来,给一个从0开始逐一编号的标签
  15. train_list.append(train_data)
  16. for i in range(int(len(c) * train_ratio), len(c)):
  17. test_data = os.path.join(a, c[i]) + '\t' + str(class_flag) + '\n'
  18. test_list.append(test_data)
  19. class_flag += 1
  20. print(train_list)
  21. random.shuffle(train_list)
  22. random.shuffle(test_list)
  23. with open('train.txt', 'w', encoding='UTF-8') as f:
  24. for train_img in train_list:
  25. f.write(str(train_img))
  26. with open('test.txt', 'w', encoding='UTF-8') as f:
  27. for test_img in test_list:
  28. f.write(test_img)

1.3 结果

2 CreateDataloader——数据加载

把数据传入模型中进行训练。 

2.1 思路

图片标准化

  1. transform_BZ= transforms.Normalize(
  2. mean=[0.5, 0.5, 0.5],# 取决于数据集
  3. std=[0.5, 0.5, 0.5]
  4. )

加载得到图片信息

  1. def get_images(self, txt_path):
  2. with open(txt_path, 'r', encoding='utf-8') as f:
  3. imgs_info = f.readlines()
  4. imgs_info = list(map(lambda x:x.strip().split('\t'), imgs_info))
  5. return imgs_info

训练与测试数据的归一化与标准化

  1. self.train_tf = transforms.Compose([
  2. transforms.Resize(224), # 将图片压缩成224*224的大小
  3. transforms.RandomHorizontalFlip(), # 对图片进行随机的水平翻转
  4. transforms.RandomVerticalFlip(), # 随机的垂直翻转
  5. transforms.ToTensor(), # 把图片改为Tensor格式
  6. transform_BZ # 图片标准化的步骤
  7. ])
  8. self.val_tf = transforms.Compose([ # 简单把图片压缩了变成Tensor模式
  9. transforms.Resize(224),
  10. transforms.ToTensor(),
  11. transform_BZ # 标准化操作
  12. ])

填充黑色操作,如果尺寸太小可以扩充,填充黑色使得图片成为 224*224。

  1. def padding_black(self, img):
  2. w, h = img.size
  3. scale = 224. / max(w, h)
  4. img_fg = img.resize([int(x) for x in [w * scale, h * scale]])
  5. size_fg = img_fg.size
  6. size_bg = 224
  7. img_bg = Image.new("RGB", (size_bg, size_bg))
  8. img_bg.paste(img_fg, ((size_bg - size_fg[0]) // 2,
  9. (size_bg - size_fg[1]) // 2))
  10. img = img_bg
  11. return img

 True 为将 "train.txt" 文件数据看做训练集对待

 train_dataset = LoadData("train.txt", True)    

2.2 代码

  1. import torch
  2. from PIL import Image
  3. import torchvision.transforms as transforms
  4. from PIL import ImageFile
  5. ImageFile.LOAD_TRUNCATED_IMAGES = True
  6. from torch.utils.data import Dataset
  7. transform_BZ= transforms.Normalize(
  8. mean=[0.5, 0.5, 0.5],
  9. std=[0.5, 0.5, 0.5]
  10. )
  11. class LoadData(Dataset):
  12. def __init__(self, txt_path, train_flag=True):
  13. self.imgs_info = self.get_images(txt_path)
  14. self.train_flag = train_flag
  15. self.train_tf = transforms.Compose([
  16. transforms.Resize(224),
  17. transforms.RandomHorizontalFlip(),
  18. transforms.RandomVerticalFlip(),
  19. transforms.ToTensor(),
  20. transform_BZ
  21. ])
  22. self.val_tf = transforms.Compose([
  23. transforms.Resize(224),
  24. transforms.ToTensor(),
  25. transform_BZ
  26. ])
  27. def get_images(self, txt_path):
  28. with open(txt_path, 'r', encoding='utf-8') as f:
  29. imgs_info = f.readlines()
  30. imgs_info = list(map(lambda x:x.strip().split('\t'), imgs_info))
  31. return imgs_info
  32. def padding_black(self, img):
  33. w, h = img.size
  34. scale = 224. / max(w, h)
  35. img_fg = img.resize([int(x) for x in [w * scale, h * scale]])
  36. size_fg = img_fg.size
  37. size_bg = 224
  38. img_bg = Image.new("RGB", (size_bg, size_bg))
  39. img_bg.paste(img_fg, ((size_bg - size_fg[0]) // 2,
  40. (size_bg - size_fg[1]) // 2))
  41. img = img_bg
  42. return img
  43. def __getitem__(self, index): # 返回真正想返回的东西
  44. img_path, label = self.imgs_info[index]
  45. img = Image.open(img_path)
  46. img = img.convert('RGB')
  47. img = self.padding_black(img)
  48. if self.train_flag:
  49. img = self.train_tf(img)
  50. else:
  51. img = self.val_tf(img)
  52. label = int(label)
  53. return img, label
  54. def __len__(self):
  55. return len(self.imgs_info)
  56. if __name__ == "__main__":
  57. train_dataset = LoadData("train.txt", True)
  58. print("数据个数:", len(train_dataset))
  59. train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
  60. batch_size=10,
  61. shuffle=True)
  62. for image, label in train_loader:
  63. print(image.shape)
  64. print(image)
  65. print(label)

2.3 结果

2.4 补充

  1. import torchvision
  2. # 准备的测试数据集
  3. from torch.utils.data import DataLoader
  4. from torch.utils.tensorboard import SummaryWriter
  5. test_data = torchvision.datasets.CIFAR10('./dataset', train=False, download=True, transform=torchvision.transforms.ToTensor())
  6. test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=True)
  7. # 测试数据集中第一张图片及target
  8. img, target = test_data[0]
  9. print(img.shape)
  10. print(target)
  11. writer = SummaryWriter('dataloader')
  12. step = 0
  13. for data in test_loader:
  14. imgs, targets = data
  15. writer.add_images('test_data', imgs, step)
  16. step = step + 1
  17. writer.close()

3 加载自己的数据——使用DataLoader读取Dataset

3.1 思路

定义网络模型

  1. class NeuralNetwork(nn.Module):
  2. def __init__(self):
  3. super(NeuralNetwork, self).__init__()
  4. # 碾平,将数据碾平为一维
  5. self.flatten = nn.Flatten()
  6. # 定义linear_relu_stack,由以下众多层构成
  7. self.linear_relu_stack = nn.Sequential(
  8. # 全连接层
  9. nn.Linear(3*224*224, 512),
  10. # ReLU激活函数
  11. nn.ReLU(),
  12. # 全连接层
  13. nn.Linear(512, 512),
  14. nn.ReLU(),
  15. nn.Linear(512, 5), # 5个类别按照分类数来
  16. nn.ReLU()
  17. )
  18. # x为传入数据
  19. def forward(self, x):
  20. # x先经过碾平变为1维
  21. x = self.flatten(x)
  22. # 随后x经过linear_relu_stack
  23. logits = self.linear_relu_stack(x)
  24. # 输出logits
  25. return logits

 定义训练函数

  1. def train(dataloader, model, loss_fn, optimizer):
  2. size = len(dataloader.dataset)
  3. # 从数据加载器中读取batch(一次读取多少张,即批次数),X(图片数据),y(图片真实标签)。
  4. for batch, (X, y) in enumerate(dataloader):
  5. # 将数据存到显卡
  6. X, y = X.cuda(), y.cuda()
  7. # 得到预测的结果pred
  8. pred = model(X)
  9. # 计算预测的误差
  10. # print(pred,y)
  11. loss = loss_fn(pred, y)
  12. # 反向传播,更新模型参数
  13. optimizer.zero_grad()
  14. loss.backward()
  15. optimizer.step()
  16. # 每训练100次,输出一次当前信息
  17. if batch % 100 == 0:
  18. loss, current = loss.item(), batch * len(X)
  19. print(f"loss: {loss:>7f} [{current:>5d}/{size:>5d}]")

定义测试函数 

  1. def test(dataloader, model):
  2. size = len(dataloader.dataset)
  3. print("size = ",size)
  4. # 将模型转为验证模式
  5. model.eval()
  6. # 初始化test_loss 和 correct, 用来统计每次的误差
  7. test_loss, correct = 0, 0
  8. # 测试时模型参数不用更新,所以no_gard()
  9. # 非训练, 推理期用到
  10. with torch.no_grad():
  11. # 加载数据加载器,得到里面的X(图片数据)和y(真实标签)
  12. for X, y in dataloader:
  13. # 将数据转到GPU
  14. X, y = X.cuda(), y.cuda()
  15. # 将图片传入到模型当中就,得到预测的值pred
  16. pred = model(X)
  17. # 计算预测值pred和真实值y的差距
  18. test_loss += loss_fn(pred, y).item()
  19. # 统计预测正确的个数
  20. correct += (pred.argmax(1) == y).type(torch.float).sum().item()
  21. test_loss /= size
  22. correct /= size
  23. print("correct = ",correct)
  24. print(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")

 给训练集和测试集分别创建一个数据集加载器

  1. train_data = LoadData("train.txt", True)
  2. valid_data = LoadData("test.txt", False)

num_workers :CPU开多线程读取数据(数字越大读取速度越快,适合多少要看 CPU 多线程能力有多强);
pin_memory = True :原本先放到内存在放到显卡,现在避免放到电脑虚拟内存中,这样写使得读取速度变快;
batch_size = batch_size :一次读多少数据;
shuffle = True :每次读取数据进行打乱。

而测试数据集不需打乱数据。

  1. train_dataloader = DataLoader(dataset=train_data, num_workers=4, pin_memory=True, batch_size=batch_size, shuffle=True)
  2. test_dataloader = DataLoader(dataset=valid_data, num_workers=4, pin_memory=True, batch_size=batch_size)

如果显卡可用,则用显卡进行训练

device = "cuda" if torch.cuda.is_available() else "cpu"

调用刚定义的模型,将模型转到GPU(如果可用)

model = NeuralNetwork().to(device)

定义损失函数,计算相差多少,交叉熵,

loss_fn = nn.CrossEntropyLoss()

定义优化器,用来训练时候优化模型参数,随机梯度下降法

optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)  # lr:初始学习率

读取训练好的模型,加载训练好的参数

  1. model = NeuralNetwork()
  2. model.load_state_dict(torch.load("model.pth")) 

3.2 代码

  1. import torch
  2. from torch import nn
  3. from torch.utils.data import DataLoader
  4. from transfer_learning.CreateDataloader import LoadData
  5. # 定义网络模型
  6. class NeuralNetwork(nn.Module):
  7. def __init__(self):
  8. super(NeuralNetwork, self).__init__()
  9. self.flatten = nn.Flatten()
  10. self.linear_relu_stack = nn.Sequential(
  11. nn.Linear(3*224*224, 512),
  12. nn.ReLU(),
  13. nn.Linear(512, 512),
  14. nn.ReLU(),
  15. nn.Linear(512, 5),
  16. nn.ReLU()
  17. )
  18. def forward(self, x):
  19. x = self.flatten(x)
  20. logits = self.linear_relu_stack(x)
  21. return logits
  22. # 定义训练函数
  23. def train(dataloader, model, loss_fn, optimizer):
  24. size = len(dataloader.dataset)
  25. for batch, (X, y) in enumerate(dataloader):
  26. X, y = X.cuda(), y.cuda()
  27. pred = model(X)
  28. loss = loss_fn(pred, y)
  29. optimizer.zero_grad()
  30. loss.backward()
  31. optimizer.step()
  32. if batch % 100 == 0:
  33. loss, current = loss.item(), batch * len(X)
  34. print(f"loss: {loss:>7f} [{current:>5d}/{size:>5d}]")
  35. # 定义测试函数
  36. def test(dataloader, model):
  37. size = len(dataloader.dataset)
  38. print("size = ",size)
  39. model.eval()
  40. test_loss, correct = 0, 0
  41. with torch.no_grad():
  42. for X, y in dataloader:
  43. X, y = X.cuda(), y.cuda()
  44. pred = model(X)
  45. test_loss += loss_fn(pred, y).item()
  46. correct += (pred.argmax(1) == y).type(torch.float).sum().item()
  47. test_loss /= size
  48. correct /= size
  49. print("correct = ",correct)
  50. print(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")
  51. if __name__=='__main__':
  52. batch_size = 16
  53. train_data = LoadData("train.txt", True)
  54. valid_data = LoadData("test.txt", False)
  55. train_dataloader = DataLoader(dataset=train_data, num_workers=4, pin_memory=True, batch_size=batch_size, shuffle=True)
  56. test_dataloader = DataLoader(dataset=valid_data, num_workers=4, pin_memory=True, batch_size=batch_size)
  57. for X, y in test_dataloader:
  58. print("Shape of X [N, C, H, W]: ", X.shape)
  59. print("Shape of y: ", y.shape, y.dtype)
  60. break
  61. device = "cuda" if torch.cuda.is_available() else "cpu"
  62. print("Using {} device".format(device))
  63. model = NeuralNetwork().to(device)
  64. print(model)
  65. loss_fn = nn.CrossEntropyLoss()
  66. optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)
  67. epochs = 5
  68. for t in range(epochs):
  69. print(f"Epoch {t+1}\n-------------------------------")
  70. train(train_dataloader, model, loss_fn, optimizer)
  71. test(test_dataloader, model)
  72. print("Done!")
  73. model = NeuralNetwork()
  74. model.load_state_dict(torch.load("model.pth"))

3.3 结果

欢迎大家交流评论,一起学习

希望本文能帮助您解决您在这方面遇到的问题

感谢阅读
END

  1. 版权声明:本文为CSDN博主「荣仔!最靓的仔!」的原创文章,遵循 CC 4.0 BY-SA 版权协议。
  2. 转载请在醒目位置附上原文出处链接及本声明。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/123879
推荐阅读
相关标签
  

闽ICP备14008679号