import torch
import torch.nn as nn
import torch.optim as optim
import torchvision.models as models
import torchvision.transforms as transforms
from torch.utils.data import DataLoader, Dataset
from torchvision.datasets import ImageFolder
import pandas as pd
from sklearn.model_selection import train_test_split
from PIL import Image
# Defining the dataset class
# train_dataset = SkinLesionDataset(train_data_dir, train_df, transform=transform)
class SkinLesionDataset(Dataset):
def __init__(self, data_dir, df, transform=None):
self.data_dir = data_dir
self.df = df
self.transform = transform
def __getitem__(self, index):
image_id = self.df.iloc[index]["image_id"]
image_path = f"{self.data_dir}/{image_id}.jpg"
image = Image.open(image_path).convert("RGB")
if self.transform is not None:
image = self.transform(image)
label_str = self.df.iloc[index]["label"]
label = 1 if label_str == "malignant" else 0
return image, label
def __len__(self):
return len(self.df)
class SkinLesionDatasetForTest(Dataset):
def __init__(self, data_dir, df, transform=None):
self.data_dir = data_dir
self.df = df
self.transform = transform
def __getitem__(self, index):
image_id = self.df.iloc[index]["image_id"]
image_path = f"{self.data_dir}/{image_id}.jpg"
image = Image.open(image_path).convert("RGB")
if self.transform is not None:
image = self.transform(image)
label_str = self.df.iloc[index]["label"]
label = 1 if label_str == 1.0 else 0
return image, label
def __len__(self):
return len(self.df)
# Read the CSV files
train_csv_file = "ISBI2016_ISIC_Training_GroundTruth.csv"
val_csv_file = "ISBI2016_ISIC_Validation_GroundTruth.csv"
test_csv_file = "ISBI2016_ISIC_Test_GroundTruth.csv"
train_df = pd.read_csv(train_csv_file, delimiter=",", header=None, names=["image_id", "label"])
val_df = pd.read_csv(val_csv_file, delimiter=",", header=None, names=["image_id", "label"])
test_df = pd.read_csv(test_csv_file, delimiter=",", header=None, names=["image_id", "label"])
# Split the dataset into training, validation, and test sets
train_data_dir = "ISBI2016_ISIC_Training_Data"
val_data_dir = "ISBI2016_ISIC_Validation_Data"
test_data_dir = "ISBI2016_ISIC_Test_Data"
# Define the transformations
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])
])
# Create the dataset objects
train_dataset = SkinLesionDataset(train_data_dir, train_df, transform=transform)
val_dataset = SkinLesionDataset(val_data_dir, val_df, transform=transform)
test_dataset = SkinLesionDatasetForTest(test_data_dir, test_df, transform=transform)
# Create the data loaders
batch_size = 32
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
# Load the pretrained ResNet50 model
model = models.resnet50(pretrained=True)
# Replace the last fully connected layer
num_features = model.fc.in_features
model.fc = nn.Linear(num_features, 2) # 2 classes: benign and malignant
# Move the model to the device
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)
# Define the loss function and optimizer
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# Training and evaluation loop
num_epochs = 10
for epoch in range(num_epochs):
# Training
model.train()
train_loss = 0.0
train_correct = 0
for images, labels in train_loader:
images = images.to(device)
labels = labels.to(device)
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
_, preds = torch.max(outputs, 1)
train_correct += torch.sum(preds == labels.data)
loss.backward()
optimizer.step()
train_loss += loss.item() * images.size(0)
train_loss = train_loss / len(train_dataset)
train_acc = train_correct.double() / len(train_dataset)
# Validation
model.eval()
val_loss = 0.0
val_correct = 0
with torch.no_grad():
for images, labels in val_loader:
images = images.to(device)
labels = labels.to(device)
outputs = model(images)
loss = criterion(outputs, labels)
_, preds = torch.max(outputs, 1)
val_correct += torch.sum(preds == labels.data)
val_loss += loss.item() * images.size(0)
val_loss = val_loss / len(val_dataset)
val_acc = val_correct.double() / len(val_dataset)
print(f"Epoch {epoch+1}/{num_epochs}:"
f" Train Loss: {train_loss:.4f}, Train Acc: {train_acc:.4f},"
f" Val Loss: {val_loss:.4f}, Val Acc: {val_acc:.4f}")
# Evaluation on the test set
test_correct = 0
model.eval()
with torch.no_grad():
for images, labels in test_loader:
images = images.to(device)
labels = labels.to(device)
outputs = model(images)
_, preds = torch.max(outputs, 1)
test_correct += torch.sum(preds == labels.data)
test_acc = test_correct.double() / len(test_dataset)
print(f"Test Accuracy: {test_acc:.4f}")C:\Users\fklas\AppData\Local\Programs\Python\Python311\Lib\site-packages\torchvision\models\_utils.py:208: UserWarning: The parameter 'pretrained' is deprecated since 0.13 and may be removed in the future, please use 'weights' instead.
warnings.warn(
C:\Users\fklas\AppData\Local\Programs\Python\Python311\Lib\site-packages\torchvision\models\_utils.py:223: UserWarning: Arguments other than a weight enum or `None` for 'weights' are deprecated since 0.13 and may be removed in the future. The current behavior is equivalent to passing `weights=ResNet50_Weights.IMAGENET1K_V1`. You can also use `weights=ResNet50_Weights.DEFAULT` to get the most up-to-date weights.
warnings.warn(msg)
Epoch 1/10: Train Loss: 0.5386, Train Acc: 0.7901, Val Loss: 13.0946, Val Acc: 0.8667
Epoch 2/10: Train Loss: 0.4343, Train Acc: 0.8111, Val Loss: 0.8220, Val Acc: 0.6111
Epoch 3/10: Train Loss: 0.4542, Train Acc: 0.7914, Val Loss: 0.4609, Val Acc: 0.8667
Epoch 4/10: Train Loss: 0.4548, Train Acc: 0.8037, Val Loss: 0.4562, Val Acc: 0.8333
Epoch 5/10: Train Loss: 0.4845, Train Acc: 0.8012, Val Loss: 5.2942, Val Acc: 0.8667
Epoch 6/10: Train Loss: 0.4583, Train Acc: 0.8086, Val Loss: 0.6526, Val Acc: 0.7333
Epoch 7/10: Train Loss: 0.4698, Train Acc: 0.8037, Val Loss: 0.3620, Val Acc: 0.8778
Epoch 8/10: Train Loss: 0.4457, Train Acc: 0.8025, Val Loss: 0.4424, Val Acc: 0.8778
Epoch 9/10: Train Loss: 0.4188, Train Acc: 0.8173, Val Loss: 0.5997, Val Acc: 0.9000
Epoch 10/10: Train Loss: 0.4061, Train Acc: 0.8210, Val Loss: 0.6453, Val Acc: 0.8778
Test Accuracy: 0.8206













