{"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":"gpu","dataSources":[{"sourceId":84616,"databundleVersionId":9494719,"sourceType":"competition"}],"dockerImageVersionId":30761,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"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":"2024-09-06T07:31:09.315505Z","iopub.execute_input":"2024-09-06T07:31:09.316802Z","iopub.status.idle":"2024-09-06T07:31:09.331626Z","shell.execute_reply.started":"2024-09-06T07:31:09.316746Z","shell.execute_reply":"2024-09-06T07:31:09.330610Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport re\nimport time\nimport json\nimport pickle\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torchvision.transforms as transforms\nfrom torch.utils.data import Dataset, DataLoader\nfrom PIL import Image\nimport numpy as np\nimport torch.nn.functional as F\n\ndef load_cifar10_batch(file):\n    with open(file, 'rb') as fo:\n        batch = pickle.load(fo, encoding='bytes')\n    data = batch[b'data']\n    labels = batch[b'labels']\n    return data, labels\n\ndef load_cifar10_data():\n    train_data = []\n    train_labels = []\n    for i in range(1, 6):\n        file = f\"/kaggle/input/2024-zju/data_batch_{i}\"\n        data, labels = load_cifar10_batch(file)\n        train_data.append(data)\n        train_labels.extend(labels)\n    train_data = np.concatenate(train_data)\n    \n    test_data, test_labels = load_cifar10_batch(\"/kaggle/input/2024-zju/test_batch\")\n\n    train_data = train_data.reshape(-1, 3, 32, 32).transpose(0, 2, 3, 1)\n    test_data = test_data.reshape(-1, 3, 32, 32).transpose(0, 2, 3, 1)\n    \n    return (train_data, train_labels), (test_data, test_labels)\n\n(train_data, train_labels), (test_data, test_labels) = load_cifar10_data()\n\n","metadata":{"execution":{"iopub.status.busy":"2024-09-06T07:31:09.333349Z","iopub.execute_input":"2024-09-06T07:31:09.333643Z","iopub.status.idle":"2024-09-06T07:31:09.626183Z","shell.execute_reply.started":"2024-09-06T07:31:09.333611Z","shell.execute_reply":"2024-09-06T07:31:09.625333Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# 显示图片和标签\ndef show_images(data, labels, num_images=5):\n    plt.figure(figsize=(10, 2))\n    for i in range(num_images):\n        plt.subplot(1, num_images, i + 1)\n        plt.imshow(data[i])\n        plt.title(f'Label: {labels[i]}')\n        plt.axis('off')\n    plt.show()\n\n# 显示训练集的前5个图像和标签\nprint(\"Train Data Head:\")\nshow_images(train_data, train_labels, num_images=5)\n\n# 显示测试集的前5个图像和标签\nprint(\"Test Data Head:\")\nshow_images(test_data, test_labels, num_images=5)\n","metadata":{"execution":{"iopub.status.busy":"2024-09-06T07:31:09.627782Z","iopub.execute_input":"2024-09-06T07:31:09.628125Z","iopub.status.idle":"2024-09-06T07:31:10.351018Z","shell.execute_reply.started":"2024-09-06T07:31:09.628091Z","shell.execute_reply":"2024-09-06T07:31:10.350010Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.utils.data import Dataset, DataLoader\n\nclass CustomDataset(Dataset):\n    def __init__(self, images, labels, transform=None):\n        self.images = images\n        self.labels = labels\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.images)\n\n    def __getitem__(self, idx):\n        image = self.images[idx]\n        label = self.labels[idx]\n        if self.transform:\n            image = Image.fromarray(np.uint8(image)).convert('RGB')\n            image = self.transform(image)\n        return image, label\n\n# 数据变换类\nclass GetTransforms:\n    def __init__(self):\n        pass\n\n    def trainparams(self):\n        train_transformations = [\n            transforms.RandomCrop(32, padding=4),\n            transforms.RandomHorizontalFlip(),\n            transforms.RandomRotation((-7, 7)),\n            transforms.RandomAffine(0, shear=10, scale=(0.8, 1.2)),\n            transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2),\n            transforms.ToTensor(),\n            transforms.Normalize((0.491, 0.482, 0.446), (0.247, 0.243, 0.261))\n        ]\n        return train_transformations\n\n    def testparams(self):\n        test_transforms = [\n            transforms.ToTensor(),\n            transforms.Normalize((0.491, 0.482, 0.446), (0.247, 0.243, 0.261))\n        ]\n        return test_transforms\n\ntransformations = GetTransforms()\ntrain_transforms = transforms.Compose(transformations.trainparams())\ntest_transforms = transforms.Compose(transformations.testparams())\n\n# 数据加载\ntrainset = CustomDataset(train_data, train_labels, transform=train_transforms)\ntestset = CustomDataset(test_data, test_labels, transform=test_transforms)\n\n# 减少批次大小以适应内存\ntrain_loader = DataLoader(trainset, batch_size=16, shuffle=True, num_workers=2)\ntest_loader = DataLoader(testset, batch_size=16, shuffle=False, num_workers=2)","metadata":{"execution":{"iopub.status.busy":"2024-09-06T07:31:10.352399Z","iopub.execute_input":"2024-09-06T07:31:10.352733Z","iopub.status.idle":"2024-09-06T07:31:10.368716Z","shell.execute_reply.started":"2024-09-06T07:31:10.352697Z","shell.execute_reply":"2024-09-06T07:31:10.367764Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nclass BasicBlock(nn.Module):\n    expansion = 1\n    \n\n    def __init__(self, in_planes, planes, stride=1):\n        super(BasicBlock, self).__init__()\n\n        DROPOUT = 0.1\n\n        self.conv1 = nn.Conv2d(\n            in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)\n        self.bn1 = nn.BatchNorm2d(planes)\n        self.dropout = nn.Dropout(DROPOUT)\n        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3,\n                               stride=1, padding=1, bias=False)\n        self.bn2 = nn.BatchNorm2d(planes)\n        self.dropout = nn.Dropout(DROPOUT)\n\n        self.shortcut = nn.Sequential()\n        if stride != 1 or in_planes != self.expansion*planes:\n            self.shortcut = nn.Sequential(\n                nn.Conv2d(in_planes, self.expansion*planes,\n                          kernel_size=1, stride=stride, bias=False),\n                nn.BatchNorm2d(self.expansion*planes),\n                nn.Dropout(DROPOUT)\n            )\n\n    def forward(self, x):\n        out = F.relu(self.dropout(self.bn1(self.conv1(x))))\n        out = self.dropout(self.bn2(self.conv2(out)))\n        out += self.shortcut(x)\n        out = F.relu(out)\n        return out\n\n\nclass ResNet(nn.Module):\n    def __init__(self, block, num_blocks, num_classes=10):\n        super(ResNet, self).__init__()\n        self.in_planes = 64\n\n        self.conv1 = nn.Conv2d(3, 64, kernel_size=3,\n                               stride=1, padding=1, bias=False)\n        self.bn1 = nn.BatchNorm2d(64)\n        self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)\n        self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)\n        self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)\n        self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)\n        self.linear = nn.Linear(512*block.expansion, num_classes)\n\n    def _make_layer(self, block, planes, num_blocks, stride):\n        strides = [stride] + [1]*(num_blocks-1)\n        layers = []\n        for stride in strides:\n            layers.append(block(self.in_planes, planes, stride))\n            self.in_planes = planes * block.expansion\n        return nn.Sequential(*layers)\n\n    def forward(self, x):\n        out = F.relu(self.bn1(self.conv1(x)))\n        out = self.layer1(out)\n        out = self.layer2(out)\n        out = self.layer3(out)\n        out = self.layer4(out)\n        out = F.avg_pool2d(out, 4)\n        out = out.view(out.size(0), -1)\n        out = self.linear(out)\n        return F.log_softmax(out, dim=-1)\n\n\ndef ResNet18():\n    return ResNet(BasicBlock, [2, 2, 2, 2])\n# Importing Model and printing Summary\nmodel = ResNet18().to(device)","metadata":{"execution":{"iopub.status.busy":"2024-09-06T07:31:10.370855Z","iopub.execute_input":"2024-09-06T07:31:10.371314Z","iopub.status.idle":"2024-09-06T07:31:10.493566Z","shell.execute_reply.started":"2024-09-06T07:31:10.371279Z","shell.execute_reply":"2024-09-06T07:31:10.492743Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\n\ndef define_compile_model(model):\n    criterion = nn.CrossEntropyLoss()\n    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9, weight_decay=5e-4)\n    return criterion, optimizer\n\ndef evaluate_accuracy(model, dataloader, device):\n    model.eval()\n    correct = 0\n    total = 0\n    \n    with torch.no_grad():\n        for inputs, labels in dataloader:\n            inputs, labels = inputs.to(device), labels.to(device)\n            outputs = model(inputs)\n            _, predicted = torch.max(outputs.data, 1)\n            total += labels.size(0)\n            correct += (predicted == labels).sum().item()\n    \n    return 100 * correct / total\n\ndef train_model(model, criterion, optimizer, train_loader, test_loader, device, epochs=100, save_path='best_model.pth'):\n    best_accuracy = 0.0\n    \n    for epoch in range(epochs):\n        model.train()\n        running_loss = 0.0\n        \n        # Training phase\n        for inputs, labels in 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            torch.cuda.empty_cache()  # Clear cache if using GPU\n        \n        epoch_loss = running_loss / len(train_loader.dataset)\n        \n        # Calculate training accuracy\n        train_accuracy = evaluate_accuracy(model, train_loader, device)\n        \n        # Validation phase\n        model.eval()\n        val_loss = 0.0\n        with torch.no_grad():\n            for inputs, labels in test_loader:\n                inputs, labels = inputs.to(device), labels.to(device)\n                outputs = model(inputs)\n                loss = criterion(outputs, labels)\n                val_loss += loss.item() * inputs.size(0)\n        \n        val_loss /= len(test_loader.dataset)\n        \n        # Calculate validation accuracy\n        test_accuracy = evaluate_accuracy(model, test_loader, device)\n        \n        # Print epoch results\n        print(f'Epoch [{epoch+1}/{epochs}], '\n              f'Training Loss: {epoch_loss:.4f}, '\n              f'Training Accuracy: {train_accuracy:.2f}%, '\n              f'Validation Loss: {val_loss:.4f}, '\n              f'Validation Accuracy: {test_accuracy:.2f}%')\n        \n        # Save the model if the current accuracy is better than the best accuracy\n        if test_accuracy > best_accuracy:\n            best_accuracy = test_accuracy\n            torch.save(model.state_dict(), save_path)\n            print(f'Saved best model with accuracy: {best_accuracy:.2f}%')\n\n# Initialize model\nmodel = ResNet18().to(device)\n\n# Initialize and compile model\ncriterion, optimizer = define_compile_model(model)\n\n# Start training\ntrain_model(model, criterion, optimizer, train_loader, test_loader, device, epochs=100, save_path='best_model.pth')","metadata":{"execution":{"iopub.status.busy":"2024-09-06T07:31:10.494765Z","iopub.execute_input":"2024-09-06T07:31:10.495195Z","iopub.status.idle":"2024-09-06T10:33:29.090593Z","shell.execute_reply.started":"2024-09-06T07:31:10.495110Z","shell.execute_reply":"2024-09-06T10:33:29.088486Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"net = ResNet18().to(device)\n\n# 加载保存的模型权重\nnet.load_state_dict(torch.load('best_model.pth'))\n\n# 将模型设置为评估模式\nnet.eval()","metadata":{"execution":{"iopub.status.busy":"2024-09-06T10:33:29.092725Z","iopub.execute_input":"2024-09-06T10:33:29.093144Z","iopub.status.idle":"2024-09-06T10:33:29.273070Z","shell.execute_reply.started":"2024-09-06T10:33:29.093104Z","shell.execute_reply":"2024-09-06T10:33:29.272006Z"},"trusted":true},"execution_count":null,"outputs":[]}]}