不写网络,你也可以拿满分100,暴力满分:cnn_finetune

Sanqi 2019-06-02 16:47
关注文章

面值识别,第一眼看到这个赛题,感觉很简单,就因为特征太明显了,但是为了不辜负师妹送我的“掉包侠”的称号,我就直接上模型了,哪个复杂上那个,搞个baseline再说。

label查看

csv_data = pd.read_csv('train_face_value_label.csv')
print(csv_data.shape)
csv_data.head(3)

description

扫一眼图片(其实没必要)

def show_landmarks(image, label='0'):
    plt.imshow(image)
    plt.pause(0.001)  # pause a bit so that plots are updated

plt.figure()
show_landmarks(io.imread("train_data/"+train_data[1000][0]))
plt.show()

description

定义数据读取

class RMB_Dataset(Dataset):
    def __init__(self, root_dir, csv_data=train_data, transform=None):
        
        self.csv_data = csv_data
        self.root_dir = root_dir
        self.transform = transform
        
    def __len__(self):
        return len(self.csv_data)
    
    def __getitem__(self, idx):
        image = io.imread(self.root_dir + self.csv_data[idx][0])
        sample = {'image': image, 'label': self.csv_data[idx][1]}
        
        if self.transform:
            sample = self.transform(sample)
            
        return sample

测试下

train_rmb_dataset = RMB_Dataset(root_dir="train_data/")
fig = plt.figure()

for i in range(len(train_rmb_dataset)):
    sample = train_rmb_dataset[i]
    ax = plt.subplot(4, 1, i + 1)
    plt.tight_layout()
    ax.set_title('Sample_' + str(sample['label']))
    ax.axis('off')
    show_landmarks(sample['image'], sample['image'])
    if i == 3:
        plt.show()
        break

transform搞一下

class Rescale(object):
    def __init__(self, output_size):
        assert isinstance(output_size, (int, tuple))
        self.output_size = output_size
        
    def __call__(self, sample):
        image, label = sample['image'], sample['label']
        h, w = image.shape[:2]
        if isinstance(self.output_size, int):
            if h > w:
                new_h, new_w = self.output_size * h / w, self.output_size
            else:
                new_h, new_w = self.output_size, self.output_size * w / h
        else:
            new_h, new_w = self.output_size

        new_h, new_w = int(new_h), int(new_w)

        img = transform.resize(image, (new_h, new_w))
        return {'image': img, 'label': label}

class ToTensor(object):
    """Convert ndarrays in sample to Tensors."""

    def __call__(self, sample):
        image, label = sample['image'], sample['label']
        label = class_list.index(label)

        # swap color axis because
        # numpy image: H x W x C
        # torch image: C X H X W
        image = image.transpose((2, 0, 1))
        return {'image': torch.from_numpy(image).float(),
                'label': torch.from_numpy(np.array(float(label))).float()}

模型

from cnn_finetune import make_model
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model = make_model('resnext101_64x4d', num_classes=num_class, pretrained=True).to(device)

train and test

train_dataloader = DataLoader(train_rmb_dataset, batch_size=16, shuffle=True, num_workers=0)
test_dataloader = DataLoader(test_rmb_dataset, batch_size=16, shuffle=True, num_workers=0)

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.0001)

def train(epoch):
    total_loss = 0
    total_size = 0
    model.train()
    for batch_idx, sample_batched in enumerate(train_dataloader):
        data, target = sample_batched['image'].to(device), sample_batched['label'].to(device)
        
        optimizer.zero_grad()
        output = model(data)
        loss = criterion(output, target.long())
        total_loss += loss.item()
        total_size += data.size(0)
        loss.backward()
        optimizer.step()
        
        if batch_idx % 100 == 0:
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tAverage loss: {:.6f}'.format(
                epoch, batch_idx * len(data), len(train_dataloader.dataset),
                100. * batch_idx / len(train_dataloader), total_loss / total_size))
    
def test():
    model.eval()
    correct = 0
    with torch.no_grad():
        for batch_idx, sample_batched in enumerate(test_dataloader):
            data, target = sample_batched['image'].to(device), sample_batched['label'].to(device)
            output = model(data)
            pred = output.data.max(1, keepdim=True)[1]
            correct += pred.eq(target.long().data.view_as(pred)).long().cpu().sum().item()
            
    #test_loss /= len(test_dataloader.dataset)
    print('\nTest set: Accuracy: {}/{} ({:.6f}%)\n'.format(
        correct, len(test_dataloader.dataset),
        100. * correct / len(test_dataloader.dataset)))
    return correct / len(test_dataloader.dataset)

结果

Train Epoch: 1 [0/18000 (0%)]	Average loss: 0.139738
Train Epoch: 1 [1600/18000 (9%)]	Average loss: 0.133583
Train Epoch: 1 [3200/18000 (18%)]	Average loss: 0.126630
Train Epoch: 1 [4800/18000 (27%)]	Average loss: 0.120235
Train Epoch: 1 [6400/18000 (36%)]	Average loss: 0.114122
Train Epoch: 1 [8000/18000 (44%)]	Average loss: 0.108484
Train Epoch: 1 [9600/18000 (53%)]	Average loss: 0.103001
Train Epoch: 1 [11200/18000 (62%)]	Average loss: 0.097861
Train Epoch: 1 [12800/18000 (71%)]	Average loss: 0.093004
Train Epoch: 1 [14400/18000 (80%)]	Average loss: 0.088457
Train Epoch: 1 [16000/18000 (89%)]	Average loss: 0.084247
Train Epoch: 1 [17600/18000 (98%)]	Average loss: 0.080312
test()
Test set: Accuracy: 21613/21620 (99.967623%)

数据简单说一下,我从每类中随机抽出2000个作为训练集:2000*9=18000.所以最后验证集会有39620-18000=21620个,数据对半开一个epoch能有这个精度,还磨蹭什么,直接提交吧

文章被以下专辑收录
{{panelTitle}}
支持Markdown和数学公式,公式格式:\\(...\\)或\\[...\\]

还没有内容

关注微信公众号