image.png
    image.png
    image.png
    image.png
    完整代码:

    1. import os
    2. from PIL import Image
    3. import torch
    4. import torchvision
    5. import sys
    6. from efficientnet_pytorch import EfficientNet
    7. device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    8. from PIL import Image
    9. from torch import optim
    10. from torch import nn
    11. os.environ['CUDA_VISIBLE_DEVICES'] = '0,1'
    12. import d2lzh_pytorch as d2l
    13. from time import time
    14. import time
    15. import csv
    16. class MyDataset(torch.utils.data.Dataset): # 创建自己的类:MyDataset,这个类是继承的torch.utils.data.Dataset
    17. def __init__(self, is_train,root): # 初始化一些需要传入的参数
    18. super(MyDataset, self).__init__()
    19. fh = open(root, 'r', encoding="utf-8") # 按照传入的路径和txt文本参数,打开这个文本,并读取内容
    20. imgs = [] # 创建一个名为img的空列表,一会儿用来装东西
    21. for line in fh: # 按行循环txt文本中的内容
    22. line = line.rstrip() # 删除 本行string 字符串末尾的指定字符,这个方法的详细介绍自己查询python
    23. words = line.split() # 通过指定分隔符对字符串进行切片,默认为所有的空字符,包括空格、换行、制表符等
    24. imgs.append((words[0], int(words[1]))) # 把txt里的内容读入imgs列表保存,具体是words几要看txt内容而定
    25. self.imgs = imgs
    26. self.is_train = is_train
    27. if self.is_train:
    28. self.train_tsf = torchvision.transforms.Compose([
    29. torchvision.transforms.RandomResizedCrop(524, scale=(0.1, 1), ratio=(0.5, 2)),
    30. torchvision.transforms.ToTensor()
    31. ])
    32. else:
    33. self.test_tsf = torchvision.transforms.Compose([
    34. torchvision.transforms.Resize(size=524),
    35. torchvision.transforms.CenterCrop(size=500),
    36. torchvision.transforms.ToTensor()])
    37. def __getitem__(self, index): # 这个方法是必须要有的,用于按照索引读取每个元素的具体内容
    38. feature, label = self.imgs[index] # fn是图片path #fn和label分别获得imgs[index]也即是刚才每行中word[0]和word[1]的信息
    39. feature = Image.open(feature).convert('RGB') # 按照path读入图片from PIL import Image # 按照路径读取图片
    40. if self.is_train:
    41. feature = self.train_tsf(feature)
    42. else:
    43. feature = self.test_tsf(feature)
    44. return feature, label
    45. def __len__(self): # 这个函数也必须要写,它返回的是数据集的长度,也就是多少张图片,要和loader的长度作区分
    46. return len(self.imgs)
    47. def get_k_fold_data(k, k1, image_dir):
    48. # 返回第i折交叉验证时所需要的训练和验证数据
    49. assert k > 1
    50. # if k1==0:#第一次需要打开文件
    51. file = open(image_dir, 'r', encoding='utf-8')
    52. reader=csv.reader(file )
    53. imgs_ls = []
    54. for line in file.readlines():
    55. # if len(line):
    56. imgs_ls.append(line)
    57. file.close()
    58. #print(len(imgs_ls))
    59. avg = len(imgs_ls) // k
    60. #print(avg)
    61. f1 = open('/ddhome/bird20_K/train_k.txt', 'w')
    62. f2 = open('/ddhome/bird20_K/test_k.txt', 'w')
    63. writer1 = csv.writer(f1)
    64. writer2 = csv.writer(f2)
    65. for i, row in enumerate(imgs_ls):
    66. if (i // avg) == k1:
    67. writer2.writerow(row)
    68. else:
    69. writer1.writerow(row)
    70. f1.close()
    71. f2.close()
    72. def k_fold(k,image_dir,num_epochs,device,batch_size,optimizer,loss,net):
    73. train_k = '/root/Datasets/bird/train_k.txt'
    74. test_k = '/root/Datasets/bird/test_k.txt'
    75. #loss_acc_sum,train_acc_sum, test_acc_sum = 0,0,0
    76. Ktrain_min_l = []
    77. Ktrain_acc_max_l = []
    78. Ktest_acc_max_l = []
    79. for i in range(k):
    80. get_k_fold_data(k, i,image_dir)
    81. #修改train函数,使其返回每一批次的准确率,tarin_ls用列表表示
    82. train_data = MyDataset(is_train=True, root=train_k)
    83. test_data = MyDataset(is_train=False, root=test_k)
    84. train_loader = torch.utils.data.DataLoader(dataset=train_data, batch_size=10, shuffle=True, num_workers=5)
    85. test_loader = torch.utils.data.DataLoader(dataset=test_data, batch_size=10, shuffle=True, num_workers=5)
    86. loss_min,train_acc_max,test_acc_max=train(i,train_loader,test_loader, net, loss, optimizer, device, num_epochs)
    87. Ktrain_min_l.append(loss_min)
    88. Ktrain_acc_max_l.append(train_acc_max)
    89. Ktest_acc_max_l.append(test_acc_max)
    90. #train_acc_sum += train_acc# train函数epoches(即第k个数据集被测试后)结束后,累加
    91. #test_acc_sum += test_acc#
    92. #loss_acc_sum+=loss_acc
    93. #print('fold %d, lose_rmse_max %.4f, train_rmse_max %.4f, test_rmse_max %.4f ' %(i+1, loss_acc,train_acc, test_acc_max_l[i]))
    94. return sum(Ktrain_min_l)/len(Ktrain_min_l),sum(Ktrain_acc_max_l)/len(Ktrain_acc_max_l),sum(Ktest_acc_max_l)/len(Ktest_acc_max_l)
    95. def train(i,train_iter, test_iter, net, loss, optimizer, device, num_epochs):
    96. net = net.to(device)
    97. print("training on ", device)
    98. start = time.time()
    99. test_acc_max_l = []
    100. train_acc_max_l = []
    101. train_l_min_l=[]
    102. for epoch in range(num_epochs): #迭代100次
    103. batch_count = 0
    104. train_l_sum, train_acc_sum, test_acc_sum, n = 0.0, 0.0, 0.0, 0
    105. for X, y in train_iter:
    106. X = X.to(device)
    107. y = y.to(device)
    108. y_hat = net(X)
    109. l = loss(y_hat, y)
    110. optimizer.zero_grad()
    111. l.backward()
    112. optimizer.step()
    113. train_l_sum += l.cpu().item()
    114. train_acc_sum += (y_hat.argmax(dim=1) == y).sum().cpu().item()
    115. n += y.shape[0]
    116. batch_count += 1
    117. #至此,一个epoches完成
    118. test_acc_sum= d2l.evaluate_accuracy(test_iter, net)
    119. train_l_min_l.append(train_l_sum/batch_count)
    120. train_acc_max_l.append(train_acc_sum/n)
    121. test_acc_max_l.append(test_acc_sum)
    122. print('fold %d epoch %d, loss %.4f, train acc %.3f, test acc %.3f'
    123. % (i+1,epoch + 1, train_l_sum / batch_count, train_acc_sum / n, test_acc_sum))
    124. #train_l_min_l.sort()
    125. #¥train_acc_max_l.sort()
    126. index_max=test_acc_max_l.index(max(test_acc_max_l))
    127. f = open("/root/pythoncodes/results.txt", "a")
    128. if i==0:
    129. f.write("%d fold"+" "+"train_loss"+" "+"train_acc"+" "+"test_acc")
    130. f.write('\n' +"fold"+str(i+1)+":"+str(train_l_min_l[index_max]) + " ;" + str(train_acc_max_l[index_max]) + " ;" + str(test_acc_max_l[index_max]))
    131. f.close()
    132. print('fold %d, train_loss_min %.4f, train acc max%.4f, test acc max %.4f, time %.1f sec'
    133. % (i + 1, train_l_min_l[index_max], train_acc_max_l[index_max], test_acc_max_l[index_max], time.time() - start))
    134. return train_l_min_l[index_max],train_acc_max_l[index_max],test_acc_max_l[index_max]
    135. batch_size=10
    136. k=5
    137. image_dir='/root/Datasets/bird/shuffle_datas.txt'
    138. num_epochs=100
    139. net = EfficientNet.from_pretrained('efficientnet-b0')
    140. net._fc = nn.Linear(1280, 6)
    141. output_params = list(map(id, net._fc.parameters()))
    142. feature_params = filter(lambda p: id(p) not in output_params, net.parameters())
    143. lr = 0.01
    144. optimizer = optim.SGD([{'params': feature_params},
    145. {'params': net._fc.parameters(), 'lr': lr * 10}],
    146. lr=lr, weight_decay=0.001)
    147. net=net.cuda()
    148. net = torch.nn.DataParallel(net)
    149. loss = torch.nn.CrossEntropyLoss()
    150. loss_k,train_k, valid_k=k_fold(k,image_dir,num_epochs,device,batch_size,optimizer,loss,net)
    151. f=open("/root/pythoncodes/results.txt","a")
    152. f.write('\n'+"avg in k fold:"+"\n"+str(loss_k)+" ;"+str(train_k)+" ;"+str(valid_k))
    153. f.close()
    154. print('%d-fold validation: min loss rmse %.5f, max train rmse %.5f,max test rmse %.5f' % (k,loss_k,train_k, valid_k))
    155. print("Congratulations!!! hou bin")
    156. torch.save(net.module.state_dict(), "./bird_model_k.pt")