{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":34426,"databundleVersionId":3218632,"sourceType":"competition"}],"dockerImageVersionId":30787,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Import thư viện","metadata":{}},{"cell_type":"code","source":"import os\nimport random\nfrom tqdm import tqdm\nimport torch\nimport torch.nn as nn\nfrom torchvision import transforms\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision.models import resnet34\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import train_test_split","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-20T08:12:04.045638Z","iopub.execute_input":"2024-11-20T08:12:04.045978Z","iopub.status.idle":"2024-11-20T08:12:08.582402Z","shell.execute_reply.started":"2024-11-20T08:12:04.045945Z","shell.execute_reply":"2024-11-20T08:12:08.581445Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Kiểm tra và sử dụng GPU nếu có\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(\"Using device:\", device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-20T08:12:08.584178Z","iopub.execute_input":"2024-11-20T08:12:08.584755Z","iopub.status.idle":"2024-11-20T08:12:08.650074Z","shell.execute_reply.started":"2024-11-20T08:12:08.584713Z","shell.execute_reply":"2024-11-20T08:12:08.649028Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Khám phá dữ liệu (EDA)","metadata":{}},{"cell_type":"code","source":"# Đường dẫn dữ liệu\ntrain_dir = '/kaggle/input/dog-vs-cat-classification/train/train'\ntest_dir = '/kaggle/input/dog-vs-cat-classification/test/test'\n\n# Kiểm tra số lượng ảnh\nprint(\"Số lượng ảnh trong train/cats:\", len(os.listdir(os.path.join(train_dir, 'cats'))))\nprint(\"Số lượng ảnh trong train/dogs:\", len(os.listdir(os.path.join(train_dir, 'dogs'))))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-20T08:12:08.651339Z","iopub.execute_input":"2024-11-20T08:12:08.651681Z","iopub.status.idle":"2024-11-20T08:12:08.818180Z","shell.execute_reply.started":"2024-11-20T08:12:08.651644Z","shell.execute_reply":"2024-11-20T08:12:08.817338Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Tạo danh sách file ảnh\ncat_files = [os.path.join(train_dir, 'cats', img) for img in os.listdir(os.path.join(train_dir, 'cats'))]\ndog_files = [os.path.join(train_dir, 'dogs', img) for img in os.listdir(os.path.join(train_dir, 'dogs'))]\nall_files = cat_files + dog_files\n\nprint('Số lượng ảnh tập train:', len(all_files))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-20T08:12:08.820458Z","iopub.execute_input":"2024-11-20T08:12:08.820826Z","iopub.status.idle":"2024-11-20T08:12:08.942585Z","shell.execute_reply.started":"2024-11-20T08:12:08.820789Z","shell.execute_reply":"2024-11-20T08:12:08.941650Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"labels = [0] * len(cat_files) + [1] * len(dog_files)  # 0: mèo, 1: chó\n\n# Shuffle và chia tập train/validation\ntrain_files, val_files, train_labels, val_labels = train_test_split(\n    all_files, labels, test_size=0.2, random_state=42, stratify=labels\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-20T08:12:08.943572Z","iopub.execute_input":"2024-11-20T08:12:08.943813Z","iopub.status.idle":"2024-11-20T08:12:08.967029Z","shell.execute_reply.started":"2024-11-20T08:12:08.943789Z","shell.execute_reply":"2024-11-20T08:12:08.966225Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from PIL import Image\n\ndef display_sample_images(folder_path, label, num_images=5):\n    images = os.listdir(folder_path)[:num_images]\n    plt.figure(figsize=(10, 5))\n    for i, img_name in enumerate(images):\n        img_path = os.path.join(folder_path, img_name)\n        img = Image.open(img_path)\n        plt.subplot(1, num_images, i + 1)\n        plt.imshow(img)\n        plt.title(label)\n        plt.axis('off')\n    plt.show()\n\n# Hiển thị hình ảnh mẫu\ndisplay_sample_images(os.path.join(train_dir, 'cats'), 'Cat', 5)\ndisplay_sample_images(os.path.join(train_dir, 'dogs'), 'Dog', 5)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-20T08:12:08.968075Z","iopub.execute_input":"2024-11-20T08:12:08.968357Z","iopub.status.idle":"2024-11-20T08:12:09.930417Z","shell.execute_reply.started":"2024-11-20T08:12:08.968331Z","shell.execute_reply":"2024-11-20T08:12:09.929556Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Chuẩn bị dữ liệu huấn luyện","metadata":{}},{"cell_type":"code","source":"# Tham số huấn luyện\nimage_dim = 224\nbatch_size = 128\nepochs = 10\nlearning_rate = 0.001\nvalidation_split = 0.2  # 20% validation","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-20T08:12:09.931640Z","iopub.execute_input":"2024-11-20T08:12:09.931952Z","iopub.status.idle":"2024-11-20T08:12:09.936543Z","shell.execute_reply.started":"2024-11-20T08:12:09.931919Z","shell.execute_reply":"2024-11-20T08:12:09.935725Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Transform dữ liệu\ndata_preprocessing = transforms.Compose([\n    transforms.Resize((image_dim, image_dim)),\n    transforms.ToTensor(),\n    transforms.Normalize(0.5,0.5)\n])\n\n# Dataset tùy chỉnh\nclass AnimalDataset(Dataset):\n    def __init__(self, file_paths, labels, transform=None):\n        self.file_paths = file_paths\n        self.labels = labels\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.file_paths)\n\n    def __getitem__(self, index):\n        img_path = self.file_paths[index]\n        image = Image.open(img_path).convert(\"RGB\")\n        label = self.labels[index]\n        if self.transform:\n            image = self.transform(image)\n        return image, label","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-20T08:12:09.937626Z","iopub.execute_input":"2024-11-20T08:12:09.937909Z","iopub.status.idle":"2024-11-20T08:12:09.946167Z","shell.execute_reply.started":"2024-11-20T08:12:09.937883Z","shell.execute_reply":"2024-11-20T08:12:09.945389Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Xây dụng mô hình và huấn luyện","metadata":{}},{"cell_type":"code","source":"# Dataset và DataLoader\ntrain_dataset = AnimalDataset(train_files, train_labels, data_preprocessing)\nval_dataset = AnimalDataset(val_files, val_labels, data_preprocessing)\n\ntrain_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=2)\nval_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False, num_workers=2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-20T08:12:09.947089Z","iopub.execute_input":"2024-11-20T08:12:09.947347Z","iopub.status.idle":"2024-11-20T08:12:09.956006Z","shell.execute_reply.started":"2024-11-20T08:12:09.947322Z","shell.execute_reply":"2024-11-20T08:12:09.955168Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Mô hình ResNet34 tùy chỉnh\nclass CustomResNet34(nn.Module):\n    def __init__(self, output_classes):\n        super(CustomResNet34, self).__init__()\n        self.base_model = resnet34(weights='DEFAULT')\n        in_features = self.base_model.fc.in_features\n        self.base_model.fc = nn.Linear(in_features, output_classes)\n\n    def forward(self, x):\n        return self.base_model(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-20T08:12:09.959040Z","iopub.execute_input":"2024-11-20T08:12:09.959349Z","iopub.status.idle":"2024-11-20T08:12:09.964962Z","shell.execute_reply.started":"2024-11-20T08:12:09.959315Z","shell.execute_reply":"2024-11-20T08:12:09.964182Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Khởi tạo mô hình\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nmodel = CustomResNet34(output_classes=2).to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-20T08:12:09.965874Z","iopub.execute_input":"2024-11-20T08:12:09.966155Z","iopub.status.idle":"2024-11-20T08:12:11.438425Z","shell.execute_reply.started":"2024-11-20T08:12:09.966130Z","shell.execute_reply":"2024-11-20T08:12:11.437681Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)\nloss_fn = nn.CrossEntropyLoss()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-20T08:12:11.439535Z","iopub.execute_input":"2024-11-20T08:12:11.439871Z","iopub.status.idle":"2024-11-20T08:12:11.444675Z","shell.execute_reply.started":"2024-11-20T08:12:11.439837Z","shell.execute_reply":"2024-11-20T08:12:11.443855Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Hhuấn luyện và đánh giá mô hình\nfor ep in range(epochs):\n    print(f\"Epoch {ep+1}/{epochs}\")\n    train_loss, train_accuracy = 0.0, 0.0\n    val_loss, val_accuracy = 0.0, 0.0\n\n    # Huấn luyện\n    model.train()\n    for imgs, labels in tqdm(train_loader):\n        imgs, labels = imgs.to(device), labels.to(device)\n\n        # Forward\n        outputs = model(imgs)\n        preds = torch.argmax(outputs, dim=1)\n        loss = loss_fn(outputs, labels)\n\n        # Backward\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n\n        train_loss += loss.item() * imgs.size(0)\n        train_accuracy += torch.sum(preds == labels).item()\n\n    train_loss /= len(train_loader.dataset)\n    train_accuracy /= len(train_loader.dataset)\n    print(f\"Train Loss: {train_loss:.4f}, Train Accuracy: {train_accuracy:.4f}\")\n\n    # Đánh giá trên validation\n    model.eval()\n    with torch.no_grad():\n        for imgs, labels in val_loader:\n            imgs, labels = imgs.to(device), labels.to(device)\n\n            outputs = model(imgs)\n            preds = torch.argmax(outputs, dim=1)\n            loss = loss_fn(outputs, labels)\n\n            val_loss += loss.item() * imgs.size(0)\n            val_accuracy += torch.sum(preds == labels).item()\n\n    val_loss /= len(val_loader.dataset)\n    val_accuracy /= len(val_loader.dataset)\n    print(f\"Validation Loss: {val_loss:.4f}, Validation Accuracy: {val_accuracy:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-20T08:12:11.445939Z","iopub.execute_input":"2024-11-20T08:12:11.446315Z","iopub.status.idle":"2024-11-20T08:32:52.044399Z","shell.execute_reply.started":"2024-11-20T08:12:11.446276Z","shell.execute_reply":"2024-11-20T08:32:52.043322Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Lưu mô hình\ntorch.save(model.state_dict(), \"DogandCat_resnet34.pth\")\nprint(\"Model saved to DogandCat_resnet34.pth\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-20T08:36:22.467749Z","iopub.execute_input":"2024-11-20T08:36:22.468438Z","iopub.status.idle":"2024-11-20T08:36:22.597628Z","shell.execute_reply.started":"2024-11-20T08:36:22.468402Z","shell.execute_reply":"2024-11-20T08:36:22.596774Z"}},"outputs":[],"execution_count":null}]}