当前位置:   article > 正文

初入Kaggle之数据集的使用及预测结果生成_kaggle数据集

kaggle数据集

目录

划分数据集

读取数据集

使用数据集

预测结果生成

单次预测

结果生成


使用resnet网络预测植物幼苗分类。

kaggle链接:weiliutao | Novice | Kaggle

给的数据分为三部门,第一个是test文件夹,存放所有要预测的图片。第二个是train文件夹,里面是各个已经分好类别的植物幼苗图片文件夹,用来进行训练模型。还有一个提交样例的csv文件。

划分数据集

由于我们在训练网络时要关注模型在每一轮的正确率,因此需要将train(在实现时防止混淆我将这个名称改为train1)下的数据划分为训练集和验证集,即将train1文件夹划分为train和val文件夹,一般以0.9:0.1进行划分。train和val文件夹下仍然是各个种类幼苗的文件夹,使用一个划分脚本来实现。

代码源自:同济子豪兄的个人空间_哔哩哔哩_bilibili

  1. import os
  2. from shutil import copy, rmtree
  3. import random
  4. def mk_file(file_path: str):
  5. if os.path.exists(file_path):
  6. # 如果文件夹存在,则先删除原文件夹在重新创建
  7. rmtree(file_path)
  8. os.makedirs(file_path)
  9. def main():
  10. # 保证随机可复现
  11. random.seed(0)
  12. # 将数据集中10%的数据划分到验证集中
  13. split_rate = 0.1
  14. # 指向你解压后的flower_photos文件夹
  15. #这里的os.getcwd方法是获取当前代码所在路径
  16. #我的数据集在上上一级目录下的data_set的plant下的train_1中
  17. cwd = os.getcwd()
  18. data_root = os.path.join(cwd, "../data_set/plant")
  19. origin_flower_path = os.path.join(data_root, "train_1")
  20. assert os.path.exists(origin_flower_path), "path '{}' does not exist.".format(origin_flower_path)
  21. flower_class = [cla for cla in os.listdir(origin_flower_path)
  22. if os.path.isdir(os.path.join(origin_flower_path, cla))]
  23. # 建立保存训练集的文件夹,生成在data_root目录下
  24. train_root = os.path.join(data_root, "train")
  25. mk_file(train_root)
  26. for cla in flower_class:
  27. # 建立每个类别对应的文件夹
  28. mk_file(os.path.join(train_root, cla))
  29. # 建立保存验证集的文件夹
  30. val_root = os.path.join(data_root, "val")
  31. mk_file(val_root)
  32. for cla in flower_class:
  33. # 建立每个类别对应的文件夹
  34. mk_file(os.path.join(val_root, cla))
  35. for cla in flower_class:
  36. cla_path = os.path.join(origin_flower_path, cla)
  37. images = os.listdir(cla_path)
  38. num = len(images)
  39. # 随机采样验证集的索引
  40. eval_index = random.sample(images, k=int(num*split_rate))
  41. for index, image in enumerate(images):
  42. if image in eval_index:
  43. # 将分配至验证集中的文件复制到相应目录
  44. image_path = os.path.join(cla_path, image)
  45. new_path = os.path.join(val_root, cla)
  46. copy(image_path, new_path)
  47. else:
  48. # 将分配至训练集中的文件复制到相应目录
  49. image_path = os.path.join(cla_path, image)
  50. new_path = os.path.join(train_root, cla)
  51. copy(image_path, new_path)
  52. print("\r[{}] processing [{}/{}]".format(cla, index+1, num), end="") # processing bar
  53. print()
  54. print("processing done!")
  55. if __name__ == '__main__':
  56. main()

读取数据集

在train模块中使用这个数据集时: 首先将路径指定到存放train和val的文件夹下,也就是plant,这里我存储的位置是上上级目录的data_set文件夹下的plant。

  1. data_root = os.path.abspath(os.path.join(os.getcwd(), "../..")) # get data root path
  2. image_path = os.path.join(data_root, "data_set", "plant") # flower data set path
  3. assert os.path.exists(image_path), "{} path does not exist.".format(image_path)
  4. train_dataset = datasets.ImageFolder(root=os.path.join(image_path, "train"),
  5. transform=data_transform["train"])

找到文件夹后使用torchvision下的datasets包的ImageFolder方法读取‘train’文件中的训练图片 ,这里的transform是对图片做出的处理,先不管。

  1. train_loader = torch.utils.data.DataLoader(train_dataset,
  2. batch_size=batch_size, shuffle=True,
  3. num_workers=nw)
  4. validate_dataset = datasets.ImageFolder(root=os.path.join(image_path, "val"),
  5. transform=data_transform["val"])
  6. val_num = len(validate_dataset)
  7. validate_loader = torch.utils.data.DataLoader(validate_dataset,
  8. batch_size=batch_size, shuffle=False,
  9. num_workers=nw)

train_loader是使用DataLoader方法处理刚刚读取的train_dataset,batch_size是将图片按照给定的batch_size分组,shuffle是否打乱顺序,num_workers是使用cpu或GPU的个数。

有了数据集,便能使用神经网络进行训练。在训练时如何使用这些图片。

使用数据集

tqdm是为了记录时间。

通过enumerate遍历训练集(此时的训练集分为若干个batch_size大小的集合),每次step都会得到一个batch_size大小的集合,分别为images集合和labels集合,将images送到模型得到结果。再将结果与真实标签label作损失函数处理,再反向传播。

  1. for epoch in range(epochs):
  2. # train
  3. net.train()
  4. running_loss = 0.0
  5. train_bar = tqdm(train_loader, file=sys.stdout)
  6. for step, data in enumerate(train_bar):
  7. images, labels = data
  8. optimizer.zero_grad()
  9. logits = net(images.to(device))
  10. loss = loss_function(logits, labels.to(device))
  11. loss.backward()
  12. optimizer.step()
  13. # print statistics
  14. running_loss += loss.item()
  15. train_bar.desc = "train epoch[{}/{}] loss:{:.3f}".format(epoch + 1,
  16. epochs,
  17. loss)
  18. # validate
  19. net.eval()
  20. acc = 0.0 # accumulate accurate number / epoch
  21. with torch.no_grad():
  22. val_bar = tqdm(validate_loader, file=sys.stdout)
  23. for val_data in val_bar:
  24. val_images, val_labels = val_data
  25. outputs = net(val_images.to(device))
  26. # loss = loss_function(outputs, test_labels)
  27. predict_y = torch.max(outputs, dim=1)[1]
  28. acc += torch.eq(predict_y, val_labels.to(device)).sum().item()
  29. val_bar.desc = "valid epoch[{}/{}]".format(epoch + 1,
  30. epochs)
  31. val_accurate = acc / val_num
  32. print('[epoch %d] train_loss: %.3f val_accuracy: %.3f' %
  33. (epoch + 1, running_loss / train_steps, val_accurate))
  34. if val_accurate > best_acc:
  35. best_acc = val_accurate
  36. torch.save(net.state_dict(), save_path)
  37. print('Finished Training')

预测结果生成

因为不会将一个列表写入到一个csv文件中,所以搜了一下写了个测试代码:

  1. import pandas as pd
  2. import numpy as np
  3. # predict_kind = np.array([np.arange(794) , np.arange(2)] , dtype=str)
  4. # predict_kind[0][0]='12323'
  5. # print(predict_kind)
  6. # import numpy as np
  7. # m = np.array([np.arange(2), np.arange(5)], dtype=str) # 创建一个二维数组
  8. # m[0][1] = "love"
  9. # print(m)
  10. # print(m[0][1])
  11. # a = np.array(794*2,dtype=object)
  12. # a[1] = "12sdsds"
  13. # print(a)
  14. a = [[] for i in range(5)]
  15. a[0].append("asdasda")
  16. a[0].append("ppppp")
  17. a[1].append(("dddd"))
  18. print(a)
  19. data1 = pd.DataFrame(a)
  20. data1.to_csv('d.csv')

测试了很多发现最后没有注释的可以实现,因为我想要两列数据,一列是图片名称,一列是预测值,在此处定义一个二维列表,每个一维维度都代表一行数据,也就是一行中的两个数据,将列表转换为DataFrame格式才能写入csv文件中。

单次预测

这里我稍微改了预测方法为带参方法,传入的是图片的路径,进行预处理后(和训练时方式一样)将这张图片拿给模型,模型给出概率最大的结果。

Image是PIL包中的类,可以通过给定图片路径拿到图片

data_transform是对图片做出的处理,这时候的图片是一个三维[C,H,W],在最前面加上一个维度。

  1. def result(image_name):
  2. device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
  3. data_transform = transforms.Compose(
  4. [transforms.Resize(256),
  5. transforms.CenterCrop(224),
  6. transforms.ToTensor(),
  7. transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])
  8. # load image
  9. img_path = image_name
  10. assert os.path.exists(img_path), "file: '{}' dose not exist.".format(img_path)
  11. img = Image.open(img_path)
  12. #plt.imshow(img)
  13. # [N, C, H, W]
  14. img = data_transform(img)
  15. # expand batch dimension
  16. img = torch.unsqueeze(img, dim=0)
  17. # read class_indict
  18. json_path = './class_indices.json'
  19. assert os.path.exists(json_path), "file: '{}' dose not exist.".format(json_path)
  20. with open(json_path, "r") as f:
  21. class_indict = json.load(f)
  22. # create model
  23. model = resnet101(num_classes=12).to(device)
  24. # load model weights
  25. weights_path = "./resNet101.pth"
  26. assert os.path.exists(weights_path), "file: '{}' dose not exist.".format(weights_path)
  27. model.load_state_dict(torch.load(weights_path, map_location=device))
  28. # prediction
  29. model.eval()
  30. with torch.no_grad():
  31. # predict class
  32. output = torch.squeeze(model(img.to(device))).cpu()
  33. predict = torch.softmax(output, dim=0)
  34. predict_cla = torch.argmax(predict).numpy()
  35. return class_indict[str(predict_cla)]

model(img)将图片给到模型,再压缩batch方向维度。通过softmax处理得到概率分布。通过argmax找到最大值所对应的索引。在class_indict找到索引对应的类别。

结果生成

通过os.listdir可以遍历文件夹下的所有文件名称,先将名称加入进去,将路径加上图片名称传给result,将每个预测结果存放到名称后面,最后转换为DataFrame存储到CSV文件中。

  1. data_root = os.path.abspath(os.path.join(os.getcwd(), "../..")) # get data root path
  2. image_path = os.path.join(data_root, "data_set", "plant","test") # flower data set path
  3. predict_kind = [[] for i in range(794)]
  4. i=0
  5. for filename in os.listdir(image_path):
  6. #image_name.append(filename)
  7. predict_kind[i].append(filename)
  8. path_image = os.path.join(image_path, filename)
  9. predict_kind[i].append(result(path_image))
  10. #print(path_image)
  11. #predict_kind.append(result(path_image))
  12. i+=1
  13. print(i)
  14. #print(predict_kind)
  15. data1 = pd.DataFrame(predict_kind)
  16. data1.to_csv('predict_2.csv')

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号