application_vnd.jupyter.stderr_output_1.png
from PIL import Image

from sklearn.model_selection import train_test_split

from torch.utils.data import Dataset

from torch.utils.data import Dataset, DataLoader

import os

import pandas as pd

import timm

import timm

import torch

import torch.nn as nn

import torch.optim as optim

import torchvision.transforms as transforms

torch.manual_seed(123)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

image_dir = '/kaggle/input/plant-pathology-2020-fgvc7/images'
image_files = os.listdir(image_dir)
image_paths = [os.path.join(image_dir, filename) for filename in image_files]

import pandas as pd
test_labels = pd.read_csv('/kaggle/input/plant-pathology-2020-fgvc7/test.csv')
test_image_ids = test_labels['image_id'].values

train_labels = pd.read_csv('/kaggle/input/plant-pathology-2020-fgvc7/train.csv')
train_labels = train_labels[['healthy', 'multiple_diseases', 'rust', 'scab']]
train_labels = train_labels.values

from sklearn.model_selection import train_test_split
train_image_paths = [path for path in image_paths if 'Train' in path]
test_image_paths = [path for path in image_paths if 'Test' in path]
train_image_paths, valid_image_paths, train_labels, valid_labels = train_test_split(train_image_paths, train_labels, test_size=0.2, random_state=123)

from torch.utils.data import Dataset
class CustomDataset(Dataset):
    def __init__(self, image_paths, labels=None, transform=None):
        self.image_paths = image_paths
        self.labels = labels
        self.transform = transform
    def __len__(self):
        return len(self.image_paths)
    def __getitem__(self, index):
        image_path = self.image_paths[index]
        image = Image.open(image_path).convert('RGB')
        if self.transform:
            image = self.transform(image)
        if self.labels is not None:
            label = self.labels[index]
            return (image, label)
        else:
            return image
transform = transforms.Compose([transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])
train_dataset = CustomDataset(train_image_paths, train_labels, transform=transform)
valid_dataset = CustomDataset(valid_image_paths, valid_labels, transform=transform)
test_dataset = CustomDataset([os.path.join(image_dir, f'{image_id}.jpg') for image_id in test_image_ids], transform=transform)

batch_size = 16
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=4)
valid_loader = DataLoader(valid_dataset, batch_size=batch_size, shuffle=False, num_workers=4)

import timm
model = timm.create_model('vit_base_patch16_224', pretrained=True)
num_classes = 4
model.head = nn.Linear(model.head.in_features, num_classes)
model = model.to(device)

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, patience=5)

num_epochs = 50
for epoch in range(num_epochs):
    model.train()
    total_train_loss = 0.0
    total_train_correct = 0
    total_train_samples = 0
    for images, labels in train_loader:
        images = images.to(device)
        labels = labels.to(device)
        optimizer.zero_grad()
        outputs = model(images)
        _, predicted = torch.max(outputs, 1)
        total_train_correct += (predicted == labels.argmax(dim=1)).sum().item()
        total_train_samples += labels.size(0)
        labels_float = labels.float()
        loss = criterion(outputs, labels_float)
        loss.backward()
        nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
        optimizer.step()
        total_train_loss += loss.item()
    train_accuracy = total_train_correct / total_train_samples
    train_loss = total_train_loss / len(train_loader)
    model.eval()
    total_valid_loss = 0.0
    total_valid_correct = 0
    total_valid_samples = 0
    with torch.no_grad():
        for images, labels in valid_loader:
            images = images.to(device)
            labels = labels.to(device)
            outputs = model(images)
            _, predicted = torch.max(outputs, 1)
            total_valid_correct += (predicted == labels.argmax(dim=1)).sum().item()
            total_valid_samples += labels.size(0)
            labels_float = labels.float()
            loss = criterion(outputs, labels_float)
            total_valid_loss += loss.item()
    valid_accuracy = total_valid_correct / total_valid_samples
    valid_loss = total_valid_loss / len(valid_loader)
    scheduler.step(valid_loss)
    print(f'Epoch [{epoch + 1}/{num_epochs}], Train Loss: {train_loss:.4f}, Train Accuracy: {train_accuracy:.4f}')
    print(f'Epoch [{epoch + 1}/{num_epochs}], Valid Loss: {valid_loss:.4f}, Valid Accuracy: {valid_accuracy:.4f}')