{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":893807,"sourceType":"datasetVersion","datasetId":451078},{"sourceId":967725,"sourceType":"datasetVersion","datasetId":514243},{"sourceId":3134515,"sourceType":"datasetVersion","datasetId":1909705},{"sourceId":3870808,"sourceType":"datasetVersion","datasetId":2300826},{"sourceId":9068775,"sourceType":"datasetVersion","datasetId":5469901},{"sourceId":1020426,"sourceType":"datasetVersion","datasetId":532188},{"sourceId":9066671,"sourceType":"datasetVersion","datasetId":5468319}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# **Resnet**","metadata":{}},{"cell_type":"code","source":"import os\nimport random\nfrom PIL import Image\nimport matplotlib.pyplot as plt\n\n# Define the path to the directory\nfake_images_dir = '/kaggle/input/deepfake-and-real-images/Dataset/Train/Fake'\n\n# Get a list of all image files in the directory\nimage_files = [f for f in os.listdir(fake_images_dir) if f.endswith('.jpg')]\n\n# Select a random image file\nrandom_image_file = random.choice(image_files)\n\n# Load and display the image\nimage_path = os.path.join(fake_images_dir, random_image_file)\nimage = Image.open(image_path)\n\nplt.imshow(image)\nplt.axis('off')\nplt.title('Random Fake Image')\nplt.show()\n\nprint(f\"Random image path: {image_path}\")\n","metadata":{"execution":{"iopub.status.busy":"2024-07-31T13:03:34.297911Z","iopub.execute_input":"2024-07-31T13:03:34.298559Z","iopub.status.idle":"2024-07-31T13:03:35.304743Z","shell.execute_reply.started":"2024-07-31T13:03:34.298527Z","shell.execute_reply":"2024-07-31T13:03:35.30376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Training with Augmentation and Regularization**","metadata":{}},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torchvision.transforms as transforms\nfrom torchvision import datasets, models\nfrom torch.utils.data import DataLoader\nimport os\n\n# Paths to the dataset\ntrain_dir = \"/kaggle/input/deepfake-and-real-images/Dataset/Train\"\nvideo_fake_dir = \"/kaggle/input/video-entries\"  # Optional, for including videos if needed\n\n# Image transformations\nimage_transforms = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.RandomHorizontalFlip(),\n    transforms.RandomVerticalFlip(),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\n# Load datasets\ntrain_dataset = datasets.ImageFolder(root=train_dir, transform=image_transforms)\n\n# Create dataloaders\ntrain_loader = DataLoader(train_dataset, batch_size=32, shuffle=True, num_workers=4)\n\n# Load a pre-trained model (e.g., ResNet18) and fine-tune it\nmodel = models.resnet18(pretrained=True)\nnum_features = model.fc.in_features\nmodel.fc = nn.Linear(num_features, 2)  # 2 classes: real and deepfaked\n\n# Move model to GPU if available\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nmodel = model.to(device)\n\n# Define loss function and optimizer\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=0.001)\n\n# Function to train the model\ndef train_model(model, criterion, optimizer, train_loader, num_epochs=10):\n    best_model_wts = model.state_dict()\n    best_acc = 0.0\n\n    for epoch in range(num_epochs):\n        print(f'Epoch {epoch+1}/{num_epochs}')\n        print('-' * 10)\n\n        model.train()\n        running_loss = 0.0\n        corrects = 0\n        total = 0\n\n        for inputs, labels in train_loader:\n            inputs, labels = inputs.to(device), labels.to(device)\n            optimizer.zero_grad()\n\n            outputs = model(inputs)\n            loss = criterion(outputs, labels)\n            loss.backward()\n            optimizer.step()\n\n            running_loss += loss.item() * inputs.size(0)\n            _, preds = torch.max(outputs, 1)\n            corrects += torch.sum(preds == labels.data)\n            total += labels.size(0)\n\n        epoch_loss = running_loss / len(train_loader.dataset)\n        epoch_acc = corrects.double() / total\n\n        print(f'Training Loss: {epoch_loss:.4f} Acc: {epoch_acc:.4f}')\n\n        # Save the best model\n        if epoch_acc > best_acc:\n            best_acc = epoch_acc\n            best_model_wts = model.state_dict()\n\n    print('Training complete')\n    model.load_state_dict(best_model_wts)\n    return model\n\n# Train the model\nmodel = train_model(model, criterion, optimizer, train_loader, num_epochs=10)\n\n# Save the fine-tuned model\ntorch.save(model.state_dict(), '/kaggle/working/fine_tuned_resnet18.pth')\n\n# Function to classify a single image\ndef classify_image(model, image_path):\n    model.eval()\n    transform = transforms.Compose([\n        transforms.Resize((224, 224)),\n        transforms.ToTensor(),\n        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n    ])\n\n    image = Image.open(image_path).convert('RGB')\n    image = transform(image).unsqueeze(0)  # Add batch dimension\n\n    with torch.no_grad():\n        image = image.to(device)\n        output = model(image)\n        _, predicted = torch.max(output, 1)\n\n    return 'Fake' if predicted.item() == 1 else 'Real'\n\n# Example usage for image classification\nimage_path = '/kaggle/input/faceforensics1600-videospreprocess/data/test/fake/1601_0.jpg'\nprint(classify_image(model, image_path))","metadata":{"execution":{"iopub.status.busy":"2024-07-31T13:15:58.602977Z","iopub.execute_input":"2024-07-31T13:15:58.603706Z","iopub.status.idle":"2024-07-31T14:07:23.900344Z","shell.execute_reply.started":"2024-07-31T13:15:58.603674Z","shell.execute_reply":"2024-07-31T14:07:23.899243Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torchvision.transforms as transforms\nfrom PIL import Image\nfrom torchvision import models\nimport torch.nn as nn\n\n# Load the fine-tuned model\nmodel = models.resnet18()\nnum_features = model.fc.in_features\nmodel.fc = nn.Linear(num_features, 2)  # 2 classes: real and deepfaked\n\n# Load the saved model weights\nmodel.load_state_dict(torch.load('/kaggle/working/fine_tuned_resnet18.pth'))\n\n# Move the model to GPU if available\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nmodel = model.to(device)\nmodel.eval()\n\n# Define image transformation\nimage_transforms = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\n# Function to classify an image\ndef classify_image(image_path, model):\n    # Load the image\n    image = Image.open(image_path).convert('RGB')\n    \n    # Apply transformations\n    image = image_transforms(image).unsqueeze(0)  # Add batch dimension\n\n    # Move image to device\n    image = image.to(device)\n    \n    # Get predictions\n    with torch.no_grad():\n        output = model(image)\n        _, predicted = torch.max(output, 1)\n\n    # Map prediction to class\n    classes = ['Deepfaked', 'Real']\n    return classes[predicted.item()]\n\n# Example usage\nimage_path = '/kaggle/input/faceforensics1600-videospreprocess/data/val/fake/1444_0.jpg'\nresult = classify_image(image_path, model)\nprint(f'The image is classified as: {result}')\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-07-31T14:27:55.283048Z","iopub.execute_input":"2024-07-31T14:27:55.283816Z","iopub.status.idle":"2024-07-31T14:27:55.580857Z","shell.execute_reply.started":"2024-07-31T14:27:55.283782Z","shell.execute_reply":"2024-07-31T14:27:55.579878Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Saved Model Eval**","metadata":{}},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torchvision.transforms as transforms\nfrom torchvision import datasets, models\nfrom torch.utils.data import DataLoader\nimport os\n\n# Paths\nval_dir = \"/kaggle/input/deepfake-and-real-images/Dataset/Validation\"\nmodel_path = \"/kaggle/working/fine_tuned_resnet18.pth\"\n\n# Image transformations (ensure consistency with training)\nimage_transforms = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\n# Load validation dataset\nval_dataset = datasets.ImageFolder(root=val_dir, transform=image_transforms)\nval_loader = DataLoader(val_dataset, batch_size=32, shuffle=False, num_workers=4)\n\n# Load the model\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nmodel = models.resnet18(pretrained=False)\nnum_features = model.fc.in_features\nmodel.fc = nn.Linear(num_features, 2)  # Assuming 2 classes: real and fake\n\nmodel.load_state_dict(torch.load(model_path))\nmodel = model.to(device)\nmodel.eval()\n\n# Evaluation function\ndef evaluate_model(model, val_loader):\n    corrects = 0\n    total = 0\n\n    with torch.no_grad():\n        for inputs, labels in val_loader:\n            inputs, labels = inputs.to(device), labels.to(device)\n            outputs = model(inputs)\n            _, preds = torch.max(outputs, 1)\n            corrects += torch.sum(preds == labels.data)\n            total += labels.size(0)\n\n    accuracy = corrects.double() / total\n    print(f'Validation Accuracy: {accuracy:.4f}')\n\n# Run evaluation\nevaluate_model(model, val_loader)\n","metadata":{"execution":{"iopub.status.busy":"2024-07-31T14:32:13.310103Z","iopub.execute_input":"2024-07-31T14:32:13.310496Z","iopub.status.idle":"2024-07-31T14:34:38.864282Z","shell.execute_reply.started":"2024-07-31T14:32:13.310467Z","shell.execute_reply":"2024-07-31T14:34:38.863146Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Image classification**","metadata":{}},{"cell_type":"code","source":"import torch\nimport torchvision.models as models\nimport torch.nn as nn\nimport torchvision.transforms as T\nfrom PIL import Image\n\nclass ResNetWithDropout(nn.Module):\n    def __init__(self, block, layers, num_classes=2):\n        super(ResNetWithDropout, self).__init__()\n        self.resnet = models.resnet18(weights='DEFAULT')\n        self.resnet.fc = nn.Linear(self.resnet.fc.in_features, num_classes)\n        self.dropout = nn.Dropout(p=0.5)  # Adding dropout layer\n\n    def forward(self, x):\n        x = self.resnet(x)\n        x = self.dropout(x)\n        return x\n\n# Load the fine-tuned model\nmodel = ResNetWithDropout(models.resnet.BasicBlock, [2, 2, 2, 2], num_classes=2)\nmodel.load_state_dict(torch.load('/kaggle/working/fine_tuned_resnet18.pth'))\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nmodel = model.to(device)\n\ndef classify_image(image_path, model, device):\n    transform = T.Compose([\n        T.Resize((224, 224)),\n        T.ToTensor(),\n        T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n    ])\n\n    image = Image.open(image_path).convert('RGB')\n    image = transform(image).unsqueeze(0).to(device)\n\n    model.eval()\n    with torch.no_grad():\n        outputs = model(image)\n        _, predicted = torch.max(outputs, 1)\n\n    class_labels = {0: 'fake', 1: 'real'}\n    prediction = class_labels[predicted.item()]\n\n    return prediction\n\n# Example usage\nimage_path = '/kaggle/input/deepfake/DeepFake01/DeepFake01/aassnaulhq.jpg'\nresult = classify_image(image_path, model, device)\nprint(f\"The image is classified as: {result}\")\n","metadata":{"execution":{"iopub.status.busy":"2024-07-31T14:25:58.297555Z","iopub.execute_input":"2024-07-31T14:25:58.297948Z","iopub.status.idle":"2024-07-31T14:25:58.95974Z","shell.execute_reply.started":"2024-07-31T14:25:58.297917Z","shell.execute_reply":"2024-07-31T14:25:58.958386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Finetuning on videos** Optional-suggested","metadata":{}},{"cell_type":"code","source":"import os\nimport cv2\nfrom tqdm import tqdm\n\n# Define the path to the directory containing fake videos\nfake_videos_dir = '/kaggle/input/video-entries'\n# output_frames_dir = '/kaggle/working/fake_frames'\n\n# Create the output directory for extracted frames if it doesn't exist\nos.makedirs(output_frames_dir, exist_ok=True)\n\n# Function to extract frames from a video\ndef extract_frames(video_path, output_dir):\n    video_basename = os.path.basename(video_path)\n    video_name, _ = os.path.splitext(video_basename)\n    video_output_dir = os.path.join(output_dir, video_name)\n    os.makedirs(video_output_dir, exist_ok=True)\n    \n    cap = cv2.VideoCapture(video_path)\n    frame_count = 0\n    while cap.isOpened():\n        ret, frame = cap.read()\n        if not ret:\n            break\n        frame_filename = os.path.join(video_output_dir, f\"frame_{frame_count:04d}.jpg\")\n        cv2.imwrite(frame_filename, frame)\n        frame_count += 1\n    cap.release()\n\n# Extract frames from all fake videos\nfor video_filename in tqdm(os.listdir(fake_videos_dir)):\n    video_path = os.path.join(fake_videos_dir, video_filename)\n    extract_frames(video_path, output_frames_dir)\n","metadata":{"execution":{"iopub.status.busy":"2024-07-30T17:16:26.573289Z","iopub.execute_input":"2024-07-30T17:16:26.573815Z","iopub.status.idle":"2024-07-30T17:16:44.902254Z","shell.execute_reply.started":"2024-07-30T17:16:26.573782Z","shell.execute_reply":"2024-07-30T17:16:44.90132Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nfrom torchvision import transforms as T\nfrom torch.utils.data import Dataset, DataLoader\nfrom PIL import Image\nimport torchvision.models as models\nimport torch.nn as nn\n\n# Define the path to the extracted frames directory\nframes_dir = output_frames_dir\n\n# Define dataset class for extracted frames\nclass FakeFramesDataset(Dataset):\n    def __init__(self, root_dir, transform=None):\n        self.root_dir = root_dir\n        self.transform = transform\n        self.images = []\n        self._load_images()\n\n    def _load_images(self):\n        for video_folder in os.listdir(self.root_dir):\n            video_folder_path = os.path.join(self.root_dir, video_folder)\n            for filename in os.listdir(video_folder_path):\n                if filename.endswith('.jpg'):\n                    self.images.append(os.path.join(video_folder_path, filename))\n\n    def __len__(self):\n        return len(self.images)\n\n    def __getitem__(self, idx):\n        img_path = self.images[idx]\n        image = Image.open(img_path).convert('RGB')\n        label = 0  # All images are from fake videos\n        if self.transform:\n            image = self.transform(image)\n        return image, label\n\n# Define transformations\ntransform = T.Compose([\n    T.Resize((224, 224)),\n    T.RandomHorizontalFlip(),\n    T.RandomRotation(10),\n    T.ToTensor(),\n    T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\n# Create dataset and dataloader\nfake_frames_dataset = FakeFramesDataset(root_dir=frames_dir, transform=transform)\nfake_frames_loader = DataLoader(fake_frames_dataset, batch_size=16, shuffle=True, num_workers=4)\n\n# Load the previously fine-tuned model\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nmodel_resnet = models.resnet18(weights='DEFAULT')\nmodel_resnet.fc = nn.Linear(model_resnet.fc.in_features, 2)  # Binary classification: fake (0) or real (1)\nmodel_resnet.load_state_dict(torch.load('/kaggle/working/fine_tuned_resnet18.pth'))\nmodel_resnet = model_resnet.to(device)\n\n# Define loss function and optimizer\ncriterion = nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model_resnet.parameters(), lr=1e-4)\n\n# Fine-tuning loop\nnum_epochs = 5\nfor epoch in range(num_epochs):\n    model_resnet.train()\n    running_loss = 0.0\n    for inputs, labels in tqdm(fake_frames_loader):\n        inputs, labels = inputs.to(device), labels.to(device)\n        optimizer.zero_grad()\n        outputs = model_resnet(inputs)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n        running_loss += loss.item() * inputs.size(0)\n    epoch_loss = running_loss / len(fake_frames_loader.dataset)\n    print(f\"Epoch {epoch+1}/{num_epochs}, Loss: {epoch_loss:.4f}\")\n\n# Save the further fine-tuned model\ntorch.save(model_resnet.state_dict(), '/kaggle/working/further_fine_tuned_resnet18(test2).pth')\n","metadata":{"execution":{"iopub.status.busy":"2024-07-30T17:32:13.806663Z","iopub.execute_input":"2024-07-30T17:32:13.807096Z","iopub.status.idle":"2024-07-30T17:34:23.753481Z","shell.execute_reply.started":"2024-07-30T17:32:13.807062Z","shell.execute_reply":"2024-07-30T17:34:23.75246Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Checking on Video**","metadata":{}},{"cell_type":"code","source":"import torch\nimport os\nfrom PIL import Image\nfrom torchvision import transforms as T\nimport torchvision.models as models\nimport cv2\nimport numpy as np\n\n# Define transformations\ntransform = T.Compose([\n    T.Resize((224, 224)),\n    T.ToTensor(),\n    T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\n# Load the fine-tuned ResNet model\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nmodel_resnet = models.resnet18(weights='DEFAULT')\nnum_classes = 2  # fake and real\nmodel_resnet.fc = torch.nn.Linear(model_resnet.fc.in_features, num_classes)\nmodel_resnet.load_state_dict(torch.load('/kaggle/working/fine_tuned_resnet18.pth'))\nmodel_resnet = model_resnet.to(device)\nmodel_resnet.eval()\n\ndef classify_video(video_path):\n    cap = cv2.VideoCapture(video_path)\n    frame_predictions = []\n    \n    # Process video frames\n    while True:\n        ret, frame = cap.read()\n        if not ret:\n            break\n        \n        # Convert frame to PIL image and apply transformations\n        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)\n        frame = Image.fromarray(frame)\n        frame = transform(frame).unsqueeze(0).to(device)\n        \n        # Perform inference\n        with torch.no_grad():\n            output = model_resnet(frame)\n            _, predicted = torch.max(output, 1)\n            frame_predictions.append(predicted.item())\n    \n    cap.release()\n    \n    # Aggregate frame predictions\n    if len(frame_predictions) == 0:\n        return \"No frames extracted\"\n\n    # Count predictions\n    prediction_counts = np.bincount(frame_predictions)\n    most_common_prediction = np.argmax(prediction_counts)\n    \n    # Map index to class names\n    class_names = ['real', 'fake']\n    return class_names[most_common_prediction]\n\n# Test with a video file\nvideo_path = '/kaggle/input/video-entries/WhatsApp Video 2024-07-24 at 22.50.08_b9791a84.mp4'  # Replace with your video path\nresult = classify_video(video_path)\nprint(f'The video is classified as: {result}')\n","metadata":{"execution":{"iopub.status.busy":"2024-07-31T14:23:08.432625Z","iopub.execute_input":"2024-07-31T14:23:08.432998Z","iopub.status.idle":"2024-07-31T14:23:25.1099Z","shell.execute_reply.started":"2024-07-31T14:23:08.43297Z","shell.execute_reply":"2024-07-31T14:23:25.108746Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **EfficientNet**","metadata":{}},{"cell_type":"code","source":"import os\nimport torch\nimport torchvision.transforms as T\nfrom torch.utils.data import Dataset, DataLoader\nimport torchvision.models as models\nfrom PIL import Image\nfrom tqdm.notebook import tqdm\n\n# Define paths to dataset\nbase_dir = '/kaggle/input/faceforensics1600-videospreprocess/data'\ntrain_dir = os.path.join(base_dir, 'train')\nval_dir = os.path.join(base_dir, 'val')\ntest_dir = os.path.join(base_dir, 'test')\n\n# Define dataset class\nclass ImageDataset(Dataset):\n    def __init__(self, root_dir, transform=None):\n        self.root_dir = root_dir\n        self.transform = transform\n        self.images = []\n        self.labels = []\n        self._load_images_and_labels()\n\n    def _load_images_and_labels(self):\n        for label in ['fake', 'real']:\n            label_dir = os.path.join(self.root_dir, label)\n            for filename in os.listdir(label_dir):\n                if filename.endswith('.jpg'):\n                    self.images.append(os.path.join(label_dir, filename))\n                    self.labels.append(0 if label == 'fake' else 1)  # 0 for fake, 1 for real\n\n    def __len__(self):\n        return len(self.images)\n\n    def __getitem__(self, idx):\n        img_path = self.images[idx]\n        image = Image.open(img_path).convert('RGB')\n        label = self.labels[idx]\n        if self.transform:\n            image = self.transform(image)\n        return image, label\n\n# Define transformations\ntransform = T.Compose([\n    T.Resize((224, 224)),\n    T.ToTensor(),\n    T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\n# Create datasets and dataloaders\ntrain_dataset = ImageDataset(root_dir=train_dir, transform=transform)\nval_dataset = ImageDataset(root_dir=val_dir, transform=transform)\ntest_dataset = ImageDataset(root_dir=test_dir, transform=transform)\n\ntrain_loader = DataLoader(train_dataset, batch_size=4, shuffle=True, num_workers=2)\nval_loader = DataLoader(val_dataset, batch_size=4, shuffle=False, num_workers=2)\ntest_loader = DataLoader(test_dataset, batch_size=4, shuffle=False, num_workers=2)\n\n# Load pre-trained EfficientNet-B3 model\nmodel = models.efficientnet_b3(weights='DEFAULT')\nnum_classes = 2  # fake and real\nmodel.classifier[1] = torch.nn.Linear(model.classifier[1].in_features, num_classes)\n\n# Move model to GPU if available\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nmodel = model.to(device)\n\n# Define loss function and optimizer\ncriterion = torch.nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=1e-4)\n\n# Training loop\nnum_epochs = 10\nfor epoch in range(num_epochs):\n    model.train()\n    running_loss = 0.0\n    for inputs, labels in tqdm(train_loader):\n        inputs, labels = inputs.to(device), labels.to(device)\n        optimizer.zero_grad()\n        outputs = model(inputs)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n        running_loss += loss.item() * inputs.size(0)\n    epoch_loss = running_loss / len(train_loader.dataset)\n    print(f\"Epoch {epoch+1}/{num_epochs}, Loss: {epoch_loss:.4f}\")\n\n# Save the fine-tuned model\ntorch.save(model.state_dict(), '/kaggle/working/fine_tuned_efficientnet_b3.pth')\n","metadata":{"execution":{"iopub.status.busy":"2024-07-30T16:03:13.303023Z","iopub.execute_input":"2024-07-30T16:03:13.303409Z","iopub.status.idle":"2024-07-30T16:34:18.987661Z","shell.execute_reply.started":"2024-07-30T16:03:13.303378Z","shell.execute_reply":"2024-07-30T16:34:18.986599Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Save the fine-tuned model to the Kaggle output directory\noutput_model_path = '/kaggle/working/fine_tuned_efficientnet_b3.pth'\ntorch.save(model.state_dict(), output_model_path)\n\nprint(f\"Model saved to {output_model_path}\")\n","metadata":{"execution":{"iopub.status.busy":"2024-07-30T16:34:57.105926Z","iopub.execute_input":"2024-07-30T16:34:57.106689Z","iopub.status.idle":"2024-07-30T16:34:57.404941Z","shell.execute_reply.started":"2024-07-30T16:34:57.106656Z","shell.execute_reply":"2024-07-30T16:34:57.403978Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}