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):
= self.df.iloc[index]["image_id"]
image_id = f"{self.data_dir}/{image_id}.jpg"
image_path = Image.open(image_path).convert("RGB")
image
if self.transform is not None:
= self.transform(image)
image
= self.df.iloc[index]["label"]
label_str = 1 if label_str == "malignant" else 0
label
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):
= self.df.iloc[index]["image_id"]
image_id = f"{self.data_dir}/{image_id}.jpg"
image_path = Image.open(image_path).convert("RGB")
image
if self.transform is not None:
= self.transform(image)
image
= self.df.iloc[index]["label"]
label_str = 1 if label_str == 1.0 else 0
label
return image, label
def __len__(self):
return len(self.df)
# Read the CSV files
= "ISBI2016_ISIC_Training_GroundTruth.csv"
train_csv_file = "ISBI2016_ISIC_Validation_GroundTruth.csv"
val_csv_file = "ISBI2016_ISIC_Test_GroundTruth.csv"
test_csv_file
= pd.read_csv(train_csv_file, delimiter=",", header=None, names=["image_id", "label"])
train_df = pd.read_csv(val_csv_file, delimiter=",", header=None, names=["image_id", "label"])
val_df = pd.read_csv(test_csv_file, delimiter=",", header=None, names=["image_id", "label"])
test_df
# Split the dataset into training, validation, and test sets
= "ISBI2016_ISIC_Training_Data"
train_data_dir = "ISBI2016_ISIC_Validation_Data"
val_data_dir = "ISBI2016_ISIC_Test_Data"
test_data_dir
# Define the transformations
= transforms.Compose([
transform 224, 224)),
transforms.Resize((
transforms.ToTensor(),=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
transforms.Normalize(mean
])
# Create the dataset objects
= SkinLesionDataset(train_data_dir, train_df, transform=transform)
train_dataset = SkinLesionDataset(val_data_dir, val_df, transform=transform)
val_dataset = SkinLesionDatasetForTest(test_data_dir, test_df, transform=transform)
test_dataset
# Create the data loaders
= 32
batch_size = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
train_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False)
val_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
test_loader
# Load the pretrained ResNet50 model
= models.resnet50(pretrained=True)
model
# Replace the last fully connected layer
= model.fc.in_features
num_features = nn.Linear(num_features, 2) # 2 classes: benign and malignant
model.fc
# Move the model to the device
= torch.device("cuda" if torch.cuda.is_available() else "cpu")
device = model.to(device)
model
# Define the loss function and optimizer
= nn.CrossEntropyLoss()
criterion = optim.Adam(model.parameters(), lr=0.001)
optimizer
# Training and evaluation loop
= 10
num_epochs
for epoch in range(num_epochs):
# Training
model.train()= 0.0
train_loss = 0
train_correct
for images, labels in train_loader:
= images.to(device)
images = labels.to(device)
labels
optimizer.zero_grad()
= model(images)
outputs = criterion(outputs, labels)
loss
= torch.max(outputs, 1)
_, preds += torch.sum(preds == labels.data)
train_correct
loss.backward()
optimizer.step()
+= loss.item() * images.size(0)
train_loss
= train_loss / len(train_dataset)
train_loss = train_correct.double() / len(train_dataset)
train_acc
# Validation
eval()
model.= 0.0
val_loss = 0
val_correct
with torch.no_grad():
for images, labels in val_loader:
= images.to(device)
images = labels.to(device)
labels
= model(images)
outputs = criterion(outputs, labels)
loss
= torch.max(outputs, 1)
_, preds += torch.sum(preds == labels.data)
val_correct
+= loss.item() * images.size(0)
val_loss
= val_loss / len(val_dataset)
val_loss = val_correct.double() / len(val_dataset)
val_acc
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
= 0
test_correct
eval()
model.with torch.no_grad():
for images, labels in test_loader:
= images.to(device)
images = labels.to(device)
labels
= model(images)
outputs
= torch.max(outputs, 1)
_, preds += torch.sum(preds == labels.data)
test_correct
= test_correct.double() / len(test_dataset)
test_acc 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