text_plain_output_1.png
from sklearn.model_selection import train_test_split

from torch.utils.data import TensorDataset, DataLoader, Dataset

import cv2

import matplotlib.pyplot as plt

import numpy as np

import os

import pandas as pd

import torch

import torch.nn as nn

labels = pd.read_csv('../input/train.csv')
sub = pd.read_csv('../input/sample_submission.csv')
train_path = '../input/train/train/'
test_path = '../input/test/test/'

dtrain, dval = train_test_split(labels, stratify=labels.has_cactus, test_size=0.1)
(dtrain.shape, dval.shape)

class MyDataset(Dataset):
    def __init__(self, df_data, data_dir='./', transform=None):
        super().__init__()
        self.df = df_data.values
        self.data_dir = data_dir
        self.transform = transform
    def __len__(self):
        return len(self.df)
    def __getitem__(self, index):
        img_name, label = self.df[index]
        img_path = os.path.join(self.data_dir, img_name)
        image = cv2.imread(img_path)
        if self.transform is not None:
            image = self.transform(image)
        return (image, label)

class VGG(nn.Module):
    def __init__(self, cfg):
        super(VGG, self).__init__()
        self.features = self._make_layers(cfg)
        self.classifier = nn.Linear(4608, 2)
    def forward(self, x):
        out = self.features(x)
        out = out.view(out.size(0), -1)
        out = self.classifier(out)
        return out
    def _make_layers(self, cfg):
        """
        cfg: a list define layers this layer contains
            'M': MaxPool, number: Conv2d(out_channels=number) -> BN -> ReLU
        """
        layers = []
        in_channels = 3
        for x in cfg:
            if x == 'M':
                layers += [nn.MaxPool2d(kernel_size=2, stride=2)]
            else:
                layers += [nn.Conv2d(in_channels, x, kernel_size=3, padding=1), nn.BatchNorm2d(x), nn.ReLU(inplace=True)]
                in_channels = x
        layers += [nn.AvgPool2d(kernel_size=1, stride=1)]
        return nn.Sequential(*layers)

vgg_cfg = {'VGG11': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 'VGG13': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 'VGG16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'], 'VGG19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M']}

def train(model, train_loader, loss_func, optimizer, device):
    total_loss = 0
    for i, (images, labels) in enumerate(train_loader):
        images = images.to(device)
        labels = labels.to(device)
        outputs = model(images)
        loss = loss_func(outputs, labels)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        total_loss += loss.item()
    return total_loss / len(train_loader)

def save_model(model, save_path):
    torch.save(model.state_dict(), save_path)

def evaluate(model, val_loader, device):
    model.eval()
    with torch.no_grad():
        correct = 0
        total = 0
        for i, (images, labels) in enumerate(val_loader):
            images = images.to(device)
            labels = labels.to(device)
            outputs = model(images)
            _, predicted = torch.max(outputs.data, dim=1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
        accuracy = correct / total
        return accuracy

def show_curve(ys, title):
    """
    plot curlve for Loss and Accuacy
    Args:
        ys: loss or acc list
        title: loss or accuracy
    """
    x = np.array(range(len(ys)))
    y = np.array(ys)
    plt.axis()

def fit(model, num_epochs, optimizer, device):
    loss_func = nn.CrossEntropyLoss()
    model.to(device)
    loss_func.to(device)
    losses = []
    accs = []
    for epoch in range(num_epochs):
        loss = train(model, loader_train, loss_func, optimizer, device)
        losses.append(loss)
        accuracy = evaluate(model, loader_valid, device)
        accs.append(accuracy)

num_epochs = 30
num_classes = 2
batch_size = 128
learning_rate = 0.001
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')

model = VGG(vgg_cfg['VGG16'])
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
fit(model, num_epochs, optimizer, device)