requirement.txt

  1. sklearn
  2. pandas
  3. efficientnet_pytorch

数据分析

  1. import os
  2. import cv2
  3. img_path = "./dataset/train/images/"
  4. img_list = [img_path+ i for i in os.listdir(img_path)]
  5. shape = []
  6. for img in img_list:
  7. arr = cv2.imread(img)
  8. shape.append(arr.shape)

训练

主要修改模型的结构 class VisitNet(nn.Module)

  1. # -*- coding: utf-8 -*-
  2. import os, sys, glob, argparse
  3. import pandas as pd
  4. import numpy as np
  5. from tqdm import tqdm
  6. import time, datetime
  7. import pdb, traceback
  8. import cv2
  9. # import imagehash
  10. from PIL import Image
  11. from sklearn.model_selection import train_test_split, StratifiedKFold, KFold
  12. from efficientnet_pytorch import EfficientNet
  13. # model = EfficientNet.from_pretrained('efficientnet-b4')
  14. import torch
  15. torch.manual_seed(0)
  16. torch.backends.cudnn.deterministic = False
  17. torch.backends.cudnn.benchmark = True
  18. import torchvision.models as models
  19. import torchvision.transforms as transforms
  20. import torchvision.datasets as datasets
  21. import torch.nn as nn
  22. import torch.nn.functional as F
  23. import torch.optim as optim
  24. from torch.autograd import Variable
  25. from torch.utils.data.dataset import Dataset
  26. # input dataset
  27. """
  28. train_set 目录结构
  29. ├── 0
  30. | ├── xx.jpg
  31. │ ├── xx.jpg
  32. ├── 1
  33. | ├── xx.jpg
  34. │ ├── xx.jpg
  35. ├── 2
  36. | ├── xx.jpg
  37. │ ├── xx.jpg
  38. ├── 3
  39. | ├── xx.jpg
  40. │ ├── xx.jpg
  41. """
  42. train_jpg = glob.glob('./train_dataset/*/*')
  43. train_jpg = np.array(train_jpg)
  44. print(train_jpg)
  45. if os.path.exists("log.txt"):
  46. os.remove("log.txt")
  47. class QRDataset(Dataset):
  48. def __init__(self, img_path, transform=None):
  49. self.img_path = img_path
  50. if transform is not None:
  51. self.transform = transform
  52. else:
  53. self.transform = None
  54. def __getitem__(self, index):
  55. start_time = time.time()
  56. img = Image.open(self.img_path[index]).convert('RGB')
  57. if self.transform is not None:
  58. img = self.transform(img)
  59. return img,torch.from_numpy(np.array(int(self.img_path[index].split("/")[-2])))
  60. def __len__(self):
  61. return len(self.img_path)
  62. def accuracy(output, target, topk=(1,)):
  63. """Computes the accuracy over the k top predictions for the specified values of k"""
  64. with torch.no_grad():
  65. maxk = max(topk)
  66. batch_size = target.size(0)
  67. _, pred = output.topk(maxk, 1, True, True)
  68. pred = pred.t()
  69. correct = pred.eq(target.view(1, -1).expand_as(pred))
  70. res = []
  71. for k in topk:
  72. correct_k = correct[:k].view(-1).float().sum(0, keepdim=True)
  73. res.append(correct_k.mul_(100.0 / batch_size))
  74. return res
  75. class AverageMeter(object):
  76. """Computes and stores the average and current value"""
  77. def __init__(self, name, fmt=':f'):
  78. self.name = name
  79. self.fmt = fmt
  80. self.reset()
  81. def reset(self):
  82. self.val = 0
  83. self.avg = 0
  84. self.sum = 0
  85. self.count = 0
  86. def update(self, val, n=1):
  87. self.val = val
  88. self.sum += val * n
  89. self.count += n
  90. self.avg = self.sum / self.count
  91. def __str__(self):
  92. fmtstr = '{name} {val' + self.fmt + '} ({avg' + self.fmt + '})'
  93. return fmtstr.format(**self.__dict__)
  94. class ProgressMeter(object):
  95. def __init__(self, num_batches, *meters):
  96. self.batch_fmtstr = self._get_batch_fmtstr(num_batches)
  97. self.meters = meters
  98. self.prefix = ""
  99. def pr2int(self, batch):
  100. entries = [self.prefix + self.batch_fmtstr.format(batch)]
  101. entries += [str(meter) for meter in self.meters]
  102. print('\t'.join(entries))
  103. with open("log.txt", "a+") as f:
  104. f.write('\t'.join(entries)+"\n")
  105. def _get_batch_fmtstr(self, num_batches):
  106. num_digits = len(str(num_batches // 1))
  107. fmt = '{:' + str(num_digits) + 'd}'
  108. return '[' + fmt + '/' + fmt.format(num_batches) + ']'
  109. class VisitNet(nn.Module):
  110. def __init__(self):
  111. super(VisitNet, self).__init__()
  112. model = models.resnet18(True)
  113. model.avgpool = nn.AdaptiveAvgPool2d(1)
  114. model.fc = nn.Linear(512, 4)
  115. self.resnet = model
  116. # model = EfficientNet.from_pretrained('efficientnet-b4')
  117. # model._fc = nn.Linear(1792, 4)
  118. # self.resnet = model
  119. def forward(self, img):
  120. out = self.resnet(img)
  121. return out
  122. def validate(val_loader, model, criterion):
  123. batch_time = AverageMeter('Time', ':6.3f')
  124. losses = AverageMeter('Loss', ':.4e')
  125. top1 = AverageMeter('Acc@1', ':6.2f')
  126. top5 = AverageMeter('Acc@2', ':6.2f')
  127. progress = ProgressMeter(len(val_loader), batch_time, losses, top1, top5)
  128. # switch to evaluate mode
  129. model.eval()
  130. with torch.no_grad():
  131. end = time.time()
  132. for i, (input, target) in enumerate(val_loader):
  133. input = input.cuda()
  134. target = target.cuda()
  135. # compute output
  136. output = model(input)
  137. loss = criterion(output, target)
  138. # measure accuracy and record loss
  139. acc1, acc5 = accuracy(output, target, topk=(1, 2))
  140. losses.update(loss.item(), input.size(0))
  141. top1.update(acc1[0], input.size(0))
  142. top5.update(acc5[0], input.size(0))
  143. # measure elapsed time
  144. batch_time.update(time.time() - end)
  145. end = time.time()
  146. # TODO: this should also be done with the ProgressMeter
  147. print(' * Acc@1 {top1.avg:.3f} Acc@5 {top5.avg:.3f}'
  148. .format(top1=top1, top5=top5))
  149. with open("log.txt", "a+") as f:
  150. f.write(' * Acc@1 {top1.avg:.3f} Acc@5 {top5.avg:.3f}'
  151. .format(top1=top1, top5=top5)+"\n")
  152. return top1
  153. def predict(test_loader, model, tta=10):
  154. # switch to evaluate mode
  155. model.eval()
  156. test_pred_tta = None
  157. for _ in range(tta):
  158. test_pred = []
  159. with torch.no_grad():
  160. end = time.time()
  161. for i, (input, target) in enumerate(test_loader):
  162. input = input.cuda()
  163. target = target.cuda()
  164. # compute output
  165. output = model(input, path)
  166. output = output.data.cpu().numpy()
  167. test_pred.append(output)
  168. test_pred = np.vstack(test_pred)
  169. if test_pred_tta is None:
  170. test_pred_tta = test_pred
  171. else:
  172. test_pred_tta += test_pred
  173. return test_pred_tta
  174. def train(train_loader, model, criterion, optimizer, epoch):
  175. batch_time = AverageMeter('Time', ':6.3f')
  176. # data_time = AverageMeter('Data', ':6.3f')
  177. losses = AverageMeter('Loss', ':.4e')
  178. top1 = AverageMeter('Acc@1', ':6.2f')
  179. # top5 = AverageMeter('Acc@5', ':6.2f')
  180. progress = ProgressMeter(len(train_loader), batch_time, losses, top1)
  181. # switch to train mode
  182. model.train()
  183. end = time.time()
  184. for i, (input, target) in enumerate(train_loader):
  185. input = input.cuda(non_blocking=True)
  186. target = target.cuda(non_blocking=True)
  187. # compute output
  188. output = model(input)
  189. loss = criterion(output, target)
  190. # measure accuracy and record loss
  191. acc1, acc5 = accuracy(output, target, topk=(1, 2))
  192. losses.update(loss.item(), input.size(0))
  193. top1.update(acc1[0], input.size(0))
  194. # top5.update(acc5[0], input.size(0))
  195. # compute gradient and do SGD step
  196. optimizer.zero_grad()
  197. loss.backward()
  198. optimizer.step()
  199. # measure elapsed time
  200. batch_time.update(time.time() - end)
  201. end = time.time()
  202. if i % 100 == 0:
  203. progress.pr2int(i)
  204. skf = KFold(n_splits=2, random_state=233, shuffle=True)
  205. for flod_idx, (train_idx, val_idx) in enumerate(skf.split(train_jpg, train_jpg)):
  206. print(flod_idx, train_idx, val_idx)
  207. train_loader = torch.utils.data.DataLoader(
  208. QRDataset(train_jpg[train_idx],
  209. transforms.Compose([
  210. # transforms.RandomGrayscale(),
  211. transforms.Resize((512, 512)),
  212. transforms.RandomAffine(10),
  213. transforms.ColorJitter(hue=.05, saturation=.05),
  214. transforms.RandomCrop((224, 224)),
  215. transforms.RandomHorizontalFlip(),
  216. transforms.RandomVerticalFlip(),
  217. transforms.ToTensor(),
  218. transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
  219. ])
  220. ), batch_size=2, shuffle=True, num_workers=8, pin_memory=True
  221. )
  222. val_loader = torch.utils.data.DataLoader(
  223. QRDataset(train_jpg[val_idx],
  224. transforms.Compose([
  225. transforms.Resize((512, 512)),
  226. # transforms.Resize((124, 124)),
  227. # transforms.RandomCrop((88, 88)),
  228. transforms.ToTensor(),
  229. transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
  230. ])
  231. ), batch_size=1, shuffle=False, num_workers=8, pin_memory=True
  232. )
  233. model = VisitNet().cuda()
  234. # model = nn.DataParallel(model).cuda()
  235. criterion = nn.CrossEntropyLoss().cuda()
  236. optimizer = torch.optim.Adam(model.parameters())
  237. scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=25, gamma=0.85)
  238. best_acc = 0.0
  239. for epoch in range(120):
  240. scheduler.step()
  241. print('Epoch: ', epoch)
  242. with open("log.txt", "a+") as f:
  243. f.write('Epoch: '+str(epoch)+"\n")
  244. train(train_loader, model, criterion, optimizer, epoch)
  245. val_acc = validate(val_loader, model, criterion)
  246. if val_acc.avg.item() > best_acc:
  247. best_acc = val_acc.avg.item()
  248. torch.save(model.state_dict(), './efficientnet{0}.pt'.format(flod_idx))

预测

# -*- coding: utf-8 -*-
import os, sys, glob, argparse
import pandas as pd
import numpy as np
from tqdm import tqdm

import time, datetime
import pdb, traceback

import cv2
# import imagehash
from PIL import Image

from sklearn.model_selection import train_test_split, StratifiedKFold, KFold

from efficientnet_pytorch import EfficientNet
# model = EfficientNet.from_pretrained('efficientnet-b4') 

import torch
torch.manual_seed(0)
torch.backends.cudnn.deterministic = False
torch.backends.cudnn.benchmark = True

import torchvision.models as models
import torchvision.transforms as transforms
import torchvision.datasets as datasets
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.autograd import Variable
from torch.utils.data.dataset import Dataset

class QRDataset(Dataset):
    def __init__(self, img_path, transform=None):
        self.img_path = img_path
        if transform is not None:
            self.transform = transform
        else:
            self.transform = None

    def __getitem__(self, index):
        start_time = time.time()
        img = Image.open(self.img_path[index]).convert('RGB')

        if self.transform is not None:
            img = self.transform(img)
        return img, torch.from_numpy(np.array([1]))#,torch.from_numpy(np.array(int(self.img_path[index].split("/")[-2])))

    def __len__(self):
        return len(self.img_path)

class VisitNet(nn.Module):
    def __init__(self):
        super(VisitNet, self).__init__()

#         model = models.resnet18(True)
#         model.avgpool = nn.AdaptiveAvgPool2d(1)
#         model.fc = nn.Linear(512, 4)
#         self.resnet = model

        model = EfficientNet.from_pretrained('efficientnet-b4') 
        model._fc = nn.Linear(1792, 4)
        self.resnet = model

    def forward(self, img):        
        out = self.resnet(img)
        return out

def predict(test_loader, model, tta=10):
    # switch to evaluate mode
    model.eval()

    test_pred_tta = None
    for _ in range(tta):
        test_pred = []
        with torch.no_grad():
            end = time.time()
            for i, (input, target) in enumerate(test_loader):
                input = input.cuda()
                target = target.cuda()

                # compute output
                output = model(input)
                output = output.data.cpu().numpy()

                test_pred.append(output)
        test_pred = np.vstack(test_pred)

        if test_pred_tta is None:
            test_pred_tta = test_pred
        else:
            test_pred_tta += test_pred

    return test_pred_tta

upload_csv_file = "./dataset/test/upload.csv"
result = pd.read_csv(upload_csv_file) 
test_jpg = list(result.iloc[:, 0].values)
test_jpg = list(map(lambda x:"./dataset/test/"+x, test_jpg))
test_jpg = np.array(test_jpg)


test_pred = None
for model_path in ["efficientnet0.pt", "efficientnet1.pt"]:#['resnet18_fold{}.pt'.format(i) for i in [0,2,3,4,6]]:
    print(model_path)
    test_loader = torch.utils.data.DataLoader(
        QRDataset(test_jpg,
                transforms.Compose([
                            transforms.Resize((224, 224)),
#                             transforms.RandomHorizontalFlip(),
#                             transforms.RandomVerticalFlip(),
                            transforms.ToTensor(),
                            transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
            ])
        ), batch_size=64, shuffle=False, num_workers=16, pin_memory=True
    )


    model = VisitNet().cuda()
    model.load_state_dict(torch.load(model_path))
    # model = nn.DataParallel(model).cuda()
    if test_pred is None:
        test_pred = predict(test_loader, model, 5)
    else:
        test_pred += predict(test_loader, model, 5)


test_csv = pd.DataFrame()
test_csv[0] = list(result.iloc[:, 0].values)
test_csv[1] = np.argmax(test_pred, 1)
test_csv.to_csv('tmp.csv', index=None, header=None)