{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":65471,"databundleVersionId":7211464,"sourceType":"competition"}],"dockerImageVersionId":30626,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-12-23T21:40:20.146913Z","iopub.execute_input":"2023-12-23T21:40:20.147333Z","iopub.status.idle":"2023-12-23T21:40:25.706015Z","shell.execute_reply.started":"2023-12-23T21:40:20.147301Z","shell.execute_reply":"2023-12-23T21:40:25.704614Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport cv2\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport random\nfrom tensorflow.keras.preprocessing.image import load_img, img_to_array\nimport scipy\n\ntrain_dir = '/kaggle/input/arabic-letters-classification/Final_Arabic_Alpha_dataset/Final_Arabic_Alpha_dataset/train'\n\n# Get the list of class directories\nclass_directories = [os.path.join(train_dir, f) for f in os.listdir(train_dir)]\nselected_classes = random.sample(class_directories, 5)\n\n# Visualize a few samples from each class\nnum_samples_per_class = 1\n\nfor class_directory in selected_classes:\n    class_name = os.path.basename(class_directory)\n    \n    # Get a list of image files in the class directory\n    image_files = [os.path.join(class_directory, f) for f in os.listdir(class_directory)][:num_samples_per_class]\n    \n    # Display images\n    for img_path in image_files:\n        img = load_img(img_path)\n        img_array = img_to_array(img)\n        \n        plt.imshow(np.uint8(img_array))\n        plt.title(f'Class: {class_name}')\n        plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-12-23T21:40:25.707938Z","iopub.execute_input":"2023-12-23T21:40:25.708307Z","iopub.status.idle":"2023-12-23T21:40:27.199113Z","shell.execute_reply.started":"2023-12-23T21:40:25.708273Z","shell.execute_reply":"2023-12-23T21:40:27.197779Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from PIL import Image\nimport numpy as np\nimport os\nfrom tqdm import tqdm \n\n#Image Preprocessing:\n\n\ndef load_and_preprocess_image(file_path, target_size=(64, 64)):\n    try:\n        # Load image\n        img = Image.open(file_path)\n\n        # Resize\n        img_resized = img.resize(target_size)\n\n        # Convert to array\n        img_array = np.array(img_resized)\n\n        return img_array \n\n    except Exception as e:\n        print(f\"Error processing image {file_path}: {str(e)}\")\n        return None\n    \n#Directory Preprocessing:\n\n\ndef preprocess_images_in_directory(train_dir, target_size=(64, 64)):\n    # Get the list of class directories\n    class_directories = [os.path.join(train_dir, f) for f in os.listdir(train_dir)]\n\n    # Initialize lists to store preprocessed images and labels\n    preprocessed_images = []\n    labels = []\n\n    # Iterate over each class directory\n    for label_path in tqdm(class_directories):\n        if not os.listdir(label_path):\n            continue  # Skip empty directories\n\n        # Iterate over each image in the class directory\n        for image_name in os.listdir(label_path):\n            image_path = os.path.join(label_path, image_name)\n            img = load_and_preprocess_image(image_path, target_size)\n\n            if img is not None:\n                preprocessed_images.append(img)\n                labels.append(int(os.path.basename(label_path)))\n\n    return preprocessed_images, labels\npreprocessed_images, labels = preprocess_images_in_directory(train_dir)\n\n#if preprocessed_images:\n #   print(\"Number of preprocessed images:\", len(preprocessed_images))\n  #  print(\"Shape of the first preprocessed image:\", preprocessed_images[0].shape)\n#else:\n   # print(\"No preprocessed images.\")","metadata":{"execution":{"iopub.status.busy":"2023-12-23T21:40:27.20067Z","iopub.execute_input":"2023-12-23T21:40:27.201022Z","iopub.status.idle":"2023-12-23T21:41:32.657017Z","shell.execute_reply.started":"2023-12-23T21:40:27.200991Z","shell.execute_reply":"2023-12-23T21:41:32.65541Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torchvision.models as models\nimport torchvision.transforms as transforms\nfrom torch.utils.data import DataLoader, random_split\nfrom torchvision.datasets import ImageFolder\n\n# Define transformation pipeline\ntrain_transform = transforms.Compose([\n    transforms.RandomRotation(degrees=30),\n    transforms.RandomHorizontalFlip(),\n    transforms.RandomVerticalFlip(),\n    transforms.RandomResizedCrop(64),\n    transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.2),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\n# Load the ImageFolder dataset\ntrain_dataset = ImageFolder(train_dir, transform=train_transform) \n\n# Split the dataset into training and validation sets\ndataset_size = len(train_dataset)\nval_size = int(0.2 * dataset_size)\ntrain_size = dataset_size - val_size\ntrain_dataset, val_dataset = random_split(train_dataset, [train_size, val_size])\n\n# Create DataLoader instances\nbatch_size = 32\ntrain_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2023-12-23T21:41:32.660199Z","iopub.execute_input":"2023-12-23T21:41:32.660643Z","iopub.status.idle":"2023-12-23T21:41:35.243266Z","shell.execute_reply.started":"2023-12-23T21:41:32.660606Z","shell.execute_reply":"2023-12-23T21:41:35.242289Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.optim as optim\nfrom torch.optim import lr_scheduler\nimport torchvision.models as models\n\n# Define the number of classes\nnum_classes = 65\n\n# Load pre-trained ResNet model\nresnet = models.resnet18(pretrained=True)\n\n# fully connected layer with Batch Normalization\nresnet.fc = torch.nn.Sequential(\n    torch.nn.Linear(resnet.fc.in_features, num_classes),\n    torch.nn.BatchNorm1d(num_classes),\n)\n\n# num_classes for the final linear layer\nresnet.fc[0] = torch.nn.Linear(resnet.fc[0].in_features, num_classes)\n\n# Move the model to the device (GPU if available)\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nresnet = resnet.to(device)\n\n# Define loss function, optimizer, and scheduler\ncriterion = torch.nn.CrossEntropyLoss()\noptimizer = optim.SGD(resnet.parameters(), lr=0.001, momentum=0.9)\nscheduler = lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1)\n\n# Fine-tuning\nfor param in resnet.parameters():\n    param.requires_grad = False\nfor param in resnet.layer4.parameters():\n    param.requires_grad = True\nfor param in resnet.layer3.parameters():\n    param.requires_grad = True","metadata":{"execution":{"iopub.status.busy":"2023-12-23T21:41:35.244778Z","iopub.execute_input":"2023-12-23T21:41:35.24573Z","iopub.status.idle":"2023-12-23T21:41:35.983971Z","shell.execute_reply.started":"2023-12-23T21:41:35.245693Z","shell.execute_reply":"2023-12-23T21:41:35.982594Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.optim as optim\nfrom torch.optim import lr_scheduler\n\nnum_epochs = 50\nbest_val_accuracy = 0.0\nbest_model = None\n\nfor epoch in range(num_epochs):\n    # Training loop\n    resnet.train()\n    total_loss = 0.0\n    correct_predictions = 0\n    total_samples = 0\n    \n    for batch_idx, (images, labels) in enumerate(train_loader):\n        images, labels = images.to(device), labels.to(device)\n        \n        optimizer.zero_grad()\n        outputs = resnet(images)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n        \n        total_loss += loss.item()\n        _, predicted = outputs.max(1)\n        correct_predictions += predicted.eq(labels).sum().item()\n        total_samples += labels.size(0)\n        \n        if batch_idx % 100 == 0:\n            print(f'Epoch [{epoch + 1}/{num_epochs}], Batch [{batch_idx + 1}/{len(train_loader)}], Loss: {loss.item():.4f}')\n    \n    # learning rate\n    scheduler.step()\n\n    average_loss = total_loss / len(train_loader)\n    accuracy = correct_predictions / total_samples\n    print(f'Epoch [{epoch + 1}/{num_epochs}], Average Loss: {average_loss:.4f}, Accuracy: {accuracy * 100:.2f}')\n\n    # Validation loop\n    resnet.eval()\n    total_correct = 0\n    total_samples = 0\n\n    with torch.no_grad():\n        for images, labels in val_loader:\n            images, labels = images.to(device), labels.to(device)\n            outputs = resnet(images)\n            _, predictions = torch.max(outputs, 1)\n            total_correct += (predictions == labels).sum().item()\n            total_samples += labels.size(0)\n\n    val_accuracy = total_correct / total_samples\n    print(f'Epoch [{epoch + 1}/{num_epochs}], Validation Accuracy: {val_accuracy:.2f}')\n\n    # Save the model if it achieves the best validation accuracy\n    if val_accuracy > best_val_accuracy:\n        best_val_accuracy = val_accuracy\n        best_model = resnet.state_dict()\n        torch.save(best_model, 'best_model.pth')\n\n# Use the best model for inference\nresnet.load_state_dict(best_model)","metadata":{"execution":{"iopub.status.busy":"2023-12-23T21:41:35.986016Z","iopub.execute_input":"2023-12-23T21:41:35.986372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.utils.data import Dataset\nfrom torchvision import transforms\nfrom PIL import Image\n\nclass CustomDataset(Dataset):\n    def __init__(self, root_dir, transform=None):\n        self.root_dir = root_dir\n        self.transform = transform\n\n        # Get a list of all image files in the root directory\n        self.image_files = [f for f in os.listdir(root_dir) if f.endswith(('.png', '.jpg', '.jpeg'))]\n\n    def __len__(self):\n        return len(self.image_files)\n\n    def __getitem__(self, idx):\n        img_name = os.path.join(self.root_dir, self.image_files[idx])\n        image = Image.open(img_name)\n\n        if self.transform:\n            image = self.transform(image).\n        label = int(os.path.splitext(self.image_files[idx])[0])\n\n        return image, label\n\n# Test data directory\ntest_dir = '/kaggle/input/arabic-letters-classification/Final_Arabic_Alpha_dataset/Final_Arabic_Alpha_dataset/test'\n\n# Define transformation pipeline for the test set\ntest_transform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.Grayscale(num_output_channels=3),  # Convert to grayscale with three channels\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])  # Normalize based on ImageNet statistics\n])\n\n# Create a custom dataset for the test set\ncustom_test_dataset = CustomDataset(root_dir=test_dir, transform=test_transform)\n\n# Create DataLoader for the test set\nbatch_size = 32\ntest_loader = DataLoader(custom_test_dataset, batch_size=batch_size, shuffle=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\nimport torch\nfrom torchvision import transforms\n\n# Set the model to evaluation mode\nresnet.eval()\n\n# Initialize lists to store images, true labels, and predicted labels\nsample_images = []\ntrue_labels = []\npredicted_labels = []\n\n# Resize transformation\nresize_transform = transforms.Resize((224, 224), antialias=True)\n\n# Iterate over all batches from the test loader\nfor batch_num, (images, labels) in enumerate(test_loader):\n    images, labels = images.to(device), labels.to(device)\n    \n    # Resize images to a fixed size\n    resized_images = torch.stack([resize_transform(image) for image in images])\n\n    # Forward pass\n    with torch.no_grad():\n        outputs = resnet(resized_images)\n        _, predictions = torch.max(outputs, 1)\n\n    # Convert data to CPU for visualization\n    images_cpu = resized_images.cpu().numpy()\n    labels_cpu = labels.cpu().numpy()\n    predictions_cpu = predictions.cpu().numpy()\n\n    # Append samples for visualization\n    sample_images.extend(images_cpu)\n    true_labels.extend(labels_cpu)\n    predicted_labels.extend(predictions_cpu)\n\n# Convert lists to numpy arrays for easier manipulation\nsample_images = np.array(sample_images)\ntrue_labels = np.array(true_labels)\npredicted_labels = np.array(predicted_labels)\n\n# Visualization\nnum_samples_to_visualize = 10  # Adjust the number of samples to visualize\nfor i in range(num_samples_to_visualize):\n    plt.figure(figsize=(8, 4))\n    \n    # Display the original image\n    plt.subplot(1, 2, 1)\n    plt.imshow(np.transpose(sample_images[i], (1, 2, 0)))\n    plt.title(f'True Label: {true_labels[i]}')\n\n    # Display the predicted label\n    plt.subplot(1, 2, 2)\n    plt.bar(range(outputs.shape[1]), outputs[i].cpu().numpy())\n    plt.title(f'Predicted Label: {predicted_labels[i]}')\n    \n    plt.show()\n\n# Calculate overall accuracy on the test set\ncorrect_predictions = (true_labels == predicted_labels).sum()\ntotal_samples = len(true_labels)\ntest_accuracy = correct_predictions / total_samples\nprint(f'Test Accuracy: {test_accuracy * 100:.2f}%')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\"\"\"import os\nimport cv2\nimport matplotlib.pyplot as plt\nimport random\n\n# Path to your dataset\ndataset_path = '/kaggle/input/arabic-letters-classification/Final_Arabic_Alpha_dataset/Final_Arabic_Alpha_dataset/train'\n\n# Get a list of class directories\nclass_directories = [os.path.join(dataset_path, f) for f in os.listdir(dataset_path)]\n\n# Visualize random samples from each class\nnum_samples_per_class = 3\n\nfor class_directory in class_directories:\n    class_name = os.path.basename(class_directory)\n    \n    # Get a list of image files in the class directory\n    image_files = [os.path.join(class_directory, f) for f in os.listdir(class_directory) if os.path.isfile(os.path.join(class_directory, f))][:num_samples_per_class]\n    \n    # Display images\n    for img_path in image_files:\n        img = cv2.imread(img_path)\n\n        if img is None:\n            print(f\"Error loading image: {img_path}\")\n            continue\n\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        \n        plt.imshow(img)\n        plt.title(f'Class: {class_name}')\n        plt.axis('off')\n        plt.show()\"\"\"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import csv\n\n# Create a CSV file and write the header\ncsv_file_path = 'predictions.csv'\nwith open(csv_file_path, 'w', newline='') as csvfile:\n    fieldnames = ['ID', 'Label']  # Use 'ID' as the column name\n    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)\n    \n    # Write the header\n    writer.writeheader()\n\n    # Iterate over the samples and write predictions to the CSV file\n    for i, (true_label, predicted_label) in enumerate(zip(true_labels, predicted_labels)):\n        writer.writerow({'ID': i, 'Label': predicted_label})\n\nprint(f'Predictions saved to: {csv_file_path}')","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}