{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceType":"competition","sourceId":3362,"databundleVersionId":31148,"isSourceIdPinned":false}],"dockerImageVersionId":31329,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd \nfrom keras.src.legacy.preprocessing.image import ImageDataGenerator\nfrom keras.utils import image_dataset_from_directory\nfrom keras.utils import to_categorical\nfrom sklearn.model_selection import train_test_split\nimport matplotlib.pyplot as plt\nimport random\nimport os\nimport zipfile\nprint(os.listdir(\"../input\"))\n!pip install timm\nimport timm\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torchvision import transforms\nfrom torch.utils.data import Dataset, DataLoader\nfrom PIL import Image","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-05-08T09:06:43.431968Z","iopub.execute_input":"2026-05-08T09:06:43.432464Z","iopub.status.idle":"2026-05-08T09:07:23.960047Z","shell.execute_reply.started":"2026-05-08T09:06:43.432433Z","shell.execute_reply":"2026-05-08T09:07:23.959113Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with zipfile.ZipFile('/kaggle/input/competitions/dogs-vs-cats/train.zip', 'r') as zip_ref:\n    zip_ref.extractall('/kaggle/working/')\n\nwith zipfile.ZipFile('/kaggle/input/competitions/dogs-vs-cats/test1.zip', 'r') as zip_ref:\n    zip_ref.extractall('/kaggle/working/')\n\nprint(\"Giải nén xong!\")\nprint(f\"Số lượng ảnh train: {len(os.listdir('/kaggle/working/train'))}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-08T09:07:23.961454Z","iopub.execute_input":"2026-05-08T09:07:23.961959Z","iopub.status.idle":"2026-05-08T09:07:32.714692Z","shell.execute_reply.started":"2026-05-08T09:07:23.961931Z","shell.execute_reply":"2026-05-08T09:07:32.714004Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_path = \"/kaggle/working/train\"\nfilenames = os.listdir(train_path)\n\ncategories = []\nfor name in filenames:\n    category = name.split('.')[0]\n    if category == 'dog':\n        categories.append(1)\n    else:\n        categories.append(0)\n\ndf = pd.DataFrame({\n    'filename':filenames, 'category':categories\n})\ntrain_df, val_df = train_test_split(df, test_size=0.2, random_state=42)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-08T09:07:32.715616Z","iopub.execute_input":"2026-05-08T09:07:32.716002Z","iopub.status.idle":"2026-05-08T09:07:32.764833Z","shell.execute_reply.started":"2026-05-08T09:07:32.715970Z","shell.execute_reply":"2026-05-08T09:07:32.764250Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class DogsCatsDataset(Dataset):\n    def __init__(self, dataframe, root_dir, transform=None):\n        self.dataframe = dataframe\n        self.root_dir = root_dir\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.dataframe)\n\n    def __getitem__(self, idx):\n        img_name = self.dataframe.iloc[idx,0]\n        label = self.dataframe.iloc[idx,1]\n        img_path = os.path.join(self.root_dir, img_name)\n\n        image = Image.open(img_path).convert('RGB')\n        if self.transform:\n            image = self.transform(image)\n        return image, label","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-08T09:07:32.766491Z","iopub.execute_input":"2026-05-08T09:07:32.766866Z","iopub.status.idle":"2026-05-08T09:07:32.785738Z","shell.execute_reply.started":"2026-05-08T09:07:32.766842Z","shell.execute_reply":"2026-05-08T09:07:32.785024Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"transform = transforms.Compose([\n    transforms.Resize((224,224)),\n    transforms.RandomHorizontalFlip(),\n    transforms.ToTensor(),\n    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n])\n\ntrain_dataset = DogsCatsDataset(train_df, train_path, transform=transform)\nval_dataset = DogsCatsDataset(val_df, train_path, transform=transform)\n\ntrain_loader = DataLoader(train_dataset, batch_size=32, shuffle=True, num_workers=2)\nval_loader = DataLoader(val_dataset, batch_size=32, shuffle=False, num_workers=2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-08T09:07:32.786989Z","iopub.execute_input":"2026-05-08T09:07:32.787320Z","iopub.status.idle":"2026-05-08T09:07:32.802845Z","shell.execute_reply.started":"2026-05-08T09:07:32.787282Z","shell.execute_reply":"2026-05-08T09:07:32.802124Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class ViTModel(nn.Module):\n    def __init__(self, n_classes=1):\n        super(ViTModel, self).__init__()\n        self.model = timm.create_model('vit_tiny_patch16_224', pretrained=True)\n\n        n_features = self.model.head.in_features\n        self.model.head = nn.Linear(n_features, n_classes)\n\n    def forward(self, x):\n        return self.model(x)\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = ViTModel().to(device)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-08T09:07:32.803938Z","iopub.execute_input":"2026-05-08T09:07:32.804261Z","iopub.status.idle":"2026-05-08T09:07:34.945650Z","shell.execute_reply.started":"2026-05-08T09:07:32.804238Z","shell.execute_reply":"2026-05-08T09:07:34.944914Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = model.to(device)\n\ncriterion = nn.BCEWithLogitsLoss()\noptimizer = optim.AdamW(model.parameters(), lr = 1e-4, weight_decay = 1e-2)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-08T09:07:34.946793Z","iopub.execute_input":"2026-05-08T09:07:34.947113Z","iopub.status.idle":"2026-05-08T09:07:34.955947Z","shell.execute_reply.started":"2026-05-08T09:07:34.947080Z","shell.execute_reply":"2026-05-08T09:07:34.955364Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train_epoch(model, dataloader, criterion, optimizer, device):\n    model.train()\n    running_loss = 0.0\n\n    for images, labels in dataloader:\n        images, labels = images.to(device), labels.to(device).float().view(-1,1)\n\n        optimizer.zero_grad()\n        outputs = model(images)\n        loss = criterion(outputs, labels)\n\n        loss.backward()\n        optimizer.step()\n        running_loss += loss.item() * images.size(0)\n\n    return running_loss / len(dataloader.dataset)\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-08T09:07:34.956766Z","iopub.execute_input":"2026-05-08T09:07:34.957084Z","iopub.status.idle":"2026-05-08T09:07:36.667368Z","shell.execute_reply.started":"2026-05-08T09:07:34.957060Z","shell.execute_reply":"2026-05-08T09:07:36.666590Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def validate(model, dataloader, criterion, device):\n    model.eval()\n    running_loss = 0.0\n    corrects = 0\n\n    with torch.no_grad():\n        for images, labels in dataloader:\n            images, labels = images.to(device), labels.to(device).float().view(-1,1)\n            outputs = model(images)\n            loss = criterion(outputs, labels)\n\n            running_loss += loss.item() * images.size(0)\n            preds = (torch.sigmoid(outputs) > 0.5).float()\n            corrects += torch.sum(preds == labels.data)\n\n    return running_loss / len(dataloader.dataset), corrects.double() / len(dataloader.dataset)\n    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-08T09:07:36.668394Z","iopub.execute_input":"2026-05-08T09:07:36.668673Z","iopub.status.idle":"2026-05-08T09:07:36.682886Z","shell.execute_reply.started":"2026-05-08T09:07:36.668649Z","shell.execute_reply":"2026-05-08T09:07:36.681998Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"epochs = 5\nfor epoch in range(epochs):\n    train_loss = train_epoch(model, train_loader, criterion, optimizer, device)\n    val_loss, val_acc = validate(model, val_loader, criterion, device)\n\n    print(f\"Epoch {epoch+1}/{epochs}\")\n    print(f\"Train Loss: {train_loss:.4f} | Val Loss: {val_loss:.4f} | Val Acc: {val_acc:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-08T09:07:36.684698Z","iopub.execute_input":"2026-05-08T09:07:36.685312Z","iopub.status.idle":"2026-05-08T09:15:34.627497Z","shell.execute_reply.started":"2026-05-08T09:07:36.685287Z","shell.execute_reply":"2026-05-08T09:15:34.626003Z"}},"outputs":[],"execution_count":null}]}