{"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":"none","dataSources":[{"sourceId":7327,"databundleVersionId":861871,"sourceType":"competition"}],"dockerImageVersionId":30648,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nimport matplotlib.pyplot as plt\nimport torch\nfrom torchvision import datasets, transforms, models\nfrom torch import nn, optim\nfrom torch.autograd import Variable\nfrom torch.utils.data.sampler import SubsetRandomSampler\nfrom torch.utils.data import Dataset, DataLoader\nfrom PIL import Image\nfrom skimage import io, transform\nimport torch.utils.data as data_utils\nimport torchvision.models as models\nfrom tabulate import tabulate\nfrom sklearn.model_selection import StratifiedKFold\nfrom torch.utils.data import Subset\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-02-10T14:23:10.913959Z","iopub.execute_input":"2024-02-10T14:23:10.914396Z","iopub.status.idle":"2024-02-10T14:23:10.922902Z","shell.execute_reply.started":"2024-02-10T14:23:10.914368Z","shell.execute_reply":"2024-02-10T14:23:10.921782Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class DogBreedsDataset(Dataset):\n    \n    def __init__(self, csv_file, root_dir, transform=None):\n        self.labels_frame = pd.read_csv(csv_file)\n        self.class_to_idx = {breed: idx for idx, breed in enumerate(self.labels_frame['breed'].unique())}\n        self.idx_to_class = {idx: breed for breed, idx in self.class_to_idx.items()}\n        self.map = dict(zip(self.labels_frame['breed'].unique(), range(0, len(self.labels_frame['breed'].unique()))))\n        self.labels_frame['breed'] = self.labels_frame['breed'].map(self.map)\n        self.root_dir = root_dir\n        self.transform = transform\n        \n    def getmap(self):\n        return self.class_to_idx\n        \n    def __getclasses__(self):\n        return self.labels_frame['breed'].unique().tolist()\n\n    def __len__(self):\n        return len(self.labels_frame)\n\n    def __getitem__(self, idx):\n        img_name = os.path.join(self.root_dir, self.labels_frame.iloc[idx, 0] + '.jpg')\n        image = io.imread(img_name)\n        PIL_image = Image.fromarray(image)\n        label = self.labels_frame.iloc[idx, 1]\n        label = np.array(label)\n        label = torch.from_numpy(label).long()\n        if self.transform:\n            image = self.transform(PIL_image)\n        return image, label\n    \ncsv='/kaggle/input/dog-breed-identification/labels.csv'\nroot='/kaggle/input/dog-breed-identification/train'\n\ntransformer =  transforms.Compose([\n        transforms.RandomResizedCrop(size=256, scale=(0.95, 1.0)),\n        transforms.RandomRotation(degrees=15),\n        transforms.ColorJitter(),\n        transforms.RandomHorizontalFlip(),\n        transforms.CenterCrop(size=224),\n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n    ])\n\nalldata = DogBreedsDataset(csv_file=csv, root_dir=root, transform=transformer)\nprint(\"Dispositif utilisé:\", device)\nprint('**'*40)\nprint(\"Nombre d'éléments dans le dataset :\", len(alldata))\nprint(\"Classes uniques :\", len(alldata.__getclasses__()))\nprint('**'*40)\nclass_map = alldata.getmap()\nclass_table = [(key, value) for key, value in class_map.items()]\nprint(\"Correspondance des classes :\")\nprint(tabulate(class_table, headers=['Classe', 'Index']))\nprint('**'*40)\n\nbatch_size = 100\ndata_loader = DataLoader(alldata, batch_size=batch_size, shuffle=True)\n\ndef show_images_with_labels(images, labels, class_map):\n    class_names = list(class_map.keys())\n    num_images = len(images)\n    num_cols = 8 \n    num_rows = (num_images - 1) // num_cols + 1\n    plt.figure(figsize=(15, 3*num_rows))\n    for i, (image, label) in enumerate(zip(images, labels)):\n        plt.subplot(num_rows, num_cols, i + 1)\n        plt.imshow(image.permute(1, 2, 0))\n        plt.title(class_names[label.item()])\n        plt.axis('off')\n    plt.show()\n\nfor batch in data_loader:\n    images, labels = batch\n    show_images_with_labels(images[:], labels[:], class_map)\n    break","metadata":{"execution":{"iopub.status.busy":"2024-02-10T14:23:10.925552Z","iopub.execute_input":"2024-02-10T14:23:10.925896Z","iopub.status.idle":"2024-02-10T14:23:20.673635Z","shell.execute_reply.started":"2024-02-10T14:23:10.925867Z","shell.execute_reply":"2024-02-10T14:23:20.670093Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CustomVGG16MultiClass(nn.Module):\n    def __init__(self, num_classes):\n        super(CustomVGG16MultiClass, self).__init__()\n        \n        vgg16 = models.vgg16(pretrained=True)\n        self.features = vgg16.features.to(device)\n        num_features = self._calculate_num_features(vgg16.features)\n        \n        for params in self.features.parameters():\n            params.requires_grad = False\n\n        # Update the input size of the linear layer to match the actual feature size\n        self.classifier = nn.Linear(num_features, num_classes)\n        \n    def _calculate_num_features(self, features):\n        x = torch.randn(1, 3, 224, 224).to(device)\n        x = features(x)\n        return x.view(x.size(0), -1).size(1)\n\n    def forward(self, x):\n        x = self.features(x)\n        x = x.view(x.size(0), -1)\n        x = self.classifier(x)\n        return x\n\nnum_classes = 120\nmodel = CustomVGG16MultiClass(num_classes).to(device)\n","metadata":{"execution":{"iopub.status.busy":"2024-02-10T14:23:20.675616Z","iopub.execute_input":"2024-02-10T14:23:20.676943Z","iopub.status.idle":"2024-02-10T14:23:22.685529Z","shell.execute_reply.started":"2024-02-10T14:23:20.676894Z","shell.execute_reply":"2024-02-10T14:23:22.684298Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def accuracy(output, target):\n    _, predicted = torch.max(output, 1)\n    correct = (predicted == target).sum().item()\n    total = target.size(0)\n    acc = correct / total * 100  # Modification pour obtenir le pourcentage\n    return acc\n\nprint('bien')","metadata":{"execution":{"iopub.status.busy":"2024-02-10T14:23:22.687025Z","iopub.execute_input":"2024-02-10T14:23:22.687389Z","iopub.status.idle":"2024-02-10T14:23:22.694737Z","shell.execute_reply.started":"2024-02-10T14:23:22.687359Z","shell.execute_reply":"2024-02-10T14:23:22.693531Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_model(model, train_loader, criterion, optimizer):\n    model.train()\n    train_loss = 0.0\n    train_accuracy = 0.0\n    \n    for batch_i, (data, target) in enumerate(train_loader):\n        # Déplace les données sur le GPU\n        data, target = data.to(device), target.to(device)\n        \n        optimizer.zero_grad()\n        output = model(data)\n        loss = criterion(output, target)\n        loss.backward()\n        optimizer.step()\n        train_loss += loss.item()\n        train_accuracy += accuracy(output, target)\n        \n#         if batch_i % 20 == 19:\n        print('Batch %d loss: %.16f | accuracy: %.4f' % (batch_i + 1, train_loss / 20, train_accuracy / 20))\n        train_loss = 0.0\n        train_accuracy = 0.0","metadata":{"execution":{"iopub.status.busy":"2024-02-10T14:23:22.698677Z","iopub.execute_input":"2024-02-10T14:23:22.699218Z","iopub.status.idle":"2024-02-10T14:23:22.710575Z","shell.execute_reply.started":"2024-02-10T14:23:22.699177Z","shell.execute_reply":"2024-02-10T14:23:22.709343Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def evaluate_model(model, data_loader, criterion, train_on_gpu):\n    model.eval()\n    total_loss = 0.0\n    total_accuracy = 0.0\n    num_batches = len(data_loader)\n\n    for batch_i, (data, target) in enumerate(data_loader):\n        if train_on_gpu:\n            data, target = data.cuda(), target.cuda()\n\n        with torch.no_grad():\n            output = model(data)\n            loss = criterion(output, target)\n            total_loss += loss.item()\n            total_accuracy += accuracy(output, target)\n\n#         if (batch_i + 1) % 20 == 0 or (batch_i + 1) == num_batches:\n        avg_loss = total_loss / (batch_i + 1)\n        avg_accuracy = total_accuracy / (batch_i + 1)\n        print(f'Batch {batch_i + 1}/{num_batches} | '\n                  f'Average Loss: {avg_loss:.4f} | '\n                  f'Average Accuracy: {avg_accuracy:.2f}%')\n\n    return total_loss / len(data_loader)\nprint('bien')","metadata":{"execution":{"iopub.status.busy":"2024-02-10T14:23:22.712388Z","iopub.execute_input":"2024-02-10T14:23:22.713196Z","iopub.status.idle":"2024-02-10T14:23:22.725443Z","shell.execute_reply.started":"2024-02-10T14:23:22.713155Z","shell.execute_reply":"2024-02-10T14:23:22.724335Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_classes = len(alldata.__getclasses__())\ncriterion = nn.CrossEntropyLoss()\noptimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\nnum_folds = 5\ncv = StratifiedKFold(n_splits=num_folds, shuffle=True, random_state=0)\ntrain_on_gpu = torch.cuda.is_available()\n\n# Move model to GPU if available\nif train_on_gpu:\n    model.cuda()\n\nfor fold, (train_idx, val_idx) in enumerate(cv.split(X=alldata.labels_frame, y=alldata.labels_frame['breed'])):\n    print(f'****************  FOLD {fold}  *********************')\n\n    # Create training and validation datasets for the current fold\n    train_dataset = Subset(alldata, train_idx)\n    val_dataset = Subset(alldata, val_idx)\n\n    # Use the subsets in DataLoader for training and validation\n    train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\n    val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False)\n\n    # Train the model\n    for epoch in range(2):\n        model.train()  # set the model to training mode\n        train_loss = 0.0\n        train_accuracy = 0.0\n        for batch_i, (data, target) in enumerate(train_loader):\n            # move tensors to GPU if CUDA is available\n            if train_on_gpu:\n                data, target = data.cuda(), target.cuda()\n\n            # clear the gradients of all optimized variables\n            optimizer.zero_grad()\n\n            # forward pass: compute predicted outputs by passing inputs to the model\n            output = model(data)\n\n            # calculate the batch loss\n            loss = criterion(output, target)\n\n            # backward pass: compute gradient of the loss with respect to model parameters\n            loss.backward()\n\n            # perform a single optimization step (parameter update)\n            optimizer.step()\n\n            # update training loss \n            train_loss += loss.item()\n            train_accuracy += accuracy(output, target)\n\n            if batch_i % 20 == 19:    # print training loss every specified number of mini-batches\n                print(f'Batch {batch_i + 1} loss: {train_loss / 20:.4f} | accuracy: {train_accuracy / 20:.2f}%')\n                train_loss = 0.0\n                train_accuracy = 0.0\n\n    # Evaluate the model on the validation dataset\n    validation_loss = evaluate_model(model, val_loader, criterion, train_on_gpu)\n    print(f'Fold {fold + 1}, Validation Loss: {validation_loss}')\n","metadata":{"execution":{"iopub.status.busy":"2024-02-10T14:23:22.726697Z","iopub.execute_input":"2024-02-10T14:23:22.727103Z","iopub.status.idle":"2024-02-10T14:45:51.721374Z","shell.execute_reply.started":"2024-02-10T14:23:22.727042Z","shell.execute_reply":"2024-02-10T14:45:51.720140Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"criterion = nn.CrossEntropyLoss()\noptimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\nnum_epochs = 10\n\nfor epoch in range(num_epochs):\n    train_model(model, train_loader, criterion, optimizer)\n    evaluate_model(model, val_loader, criterion, train_on_gpu)","metadata":{"execution":{"iopub.status.busy":"2024-02-10T14:45:51.723179Z","iopub.execute_input":"2024-02-10T14:45:51.724142Z","iopub.status.idle":"2024-02-10T15:11:30.143134Z","shell.execute_reply.started":"2024-02-10T14:45:51.724100Z","shell.execute_reply":"2024-02-10T15:11:30.141849Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def predict(model, sample_sub, test_path, transform, dataset):\n    sub = pd.DataFrame(columns=sample_sub.columns)\n    for index, rows in sample_sub.iterrows():\n        image_id = rows[\"id\"]\n        image = Image.open(test_path + f\"/{image_id}.jpg\")\n        image_processed = transform(image).unsqueeze(dim=0).to(device)\n        \n        y_logits = model(image_processed).squeeze()\n        y_probs = torch.softmax(y_logits, dim=0)\n        \n        sub_classes = {dataset.idx_to_class[index]: [prob.item()] for index, prob in enumerate(y_probs)}\n        sub_classes[\"id\"] = image_id\n        \n        sub = pd.concat([sub, pd.DataFrame(sub_classes)])\n    return sub","metadata":{"execution":{"iopub.status.busy":"2024-02-10T15:11:30.144882Z","iopub.execute_input":"2024-02-10T15:11:30.145860Z","iopub.status.idle":"2024-02-10T15:11:30.155411Z","shell.execute_reply.started":"2024-02-10T15:11:30.145816Z","shell.execute_reply":"2024-02-10T15:11:30.154209Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_sub = pd.read_csv('/kaggle/input/dog-breed-identification/sample_submission.csv')\nDATA_TEST_PATH = '/kaggle/input/dog-breed-identification/test'\ntrain_transform = transforms.Compose([\n   transforms.RandomResizedCrop(size=256, scale=(0.95, 1.0)),\n        transforms.RandomRotation(degrees=15),\n        transforms.RandomHorizontalFlip(),\n        transforms.CenterCrop(size=224),\n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n])\ntrain_data = alldata  # Assuming train_data contains classes_to_idx attribute\nmy_sub = predict(model, sample_sub, DATA_TEST_PATH, train_transform, train_data)\n\nmy_sub = my_sub.reset_index(drop=True)\nmy_sub.to_csv(\"sub_1.csv\", index=False)\nsample_sub","metadata":{"execution":{"iopub.status.busy":"2024-02-10T15:11:30.156832Z","iopub.execute_input":"2024-02-10T15:11:30.157215Z","iopub.status.idle":"2024-02-10T15:17:46.751168Z","shell.execute_reply.started":"2024-02-10T15:11:30.157184Z","shell.execute_reply":"2024-02-10T15:17:46.749913Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"my_sub","metadata":{"execution":{"iopub.status.busy":"2024-02-10T15:17:46.752962Z","iopub.execute_input":"2024-02-10T15:17:46.753469Z","iopub.status.idle":"2024-02-10T15:17:46.804496Z","shell.execute_reply.started":"2024-02-10T15:17:46.753425Z","shell.execute_reply":"2024-02-10T15:17:46.803151Z"},"trusted":true},"execution_count":null,"outputs":[]}]}