{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.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":4104,"databundleVersionId":46661,"sourceType":"competition"}],"dockerImageVersionId":31089,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\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","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-08-02T03:03:53.91155Z","iopub.execute_input":"2025-08-02T03:03:53.911783Z","iopub.status.idle":"2025-08-02T03:03:53.930715Z","shell.execute_reply.started":"2025-08-02T03:03:53.911763Z","shell.execute_reply":"2025-08-02T03:03:53.929788Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-02T03:05:22.35711Z","iopub.execute_input":"2025-08-02T03:05:22.357648Z","iopub.status.idle":"2025-08-02T03:05:22.366422Z","shell.execute_reply.started":"2025-08-02T03:05:22.35761Z","shell.execute_reply":"2025-08-02T03:05:22.36551Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ---\n# 2. Xử lý một phần nhỏ của dữ liệu TEST\n# ---\nprint(\"\\nĐang xử lý một phần nhỏ của dữ liệu TEST...\")\n\n# Ghép các file test.zip.001 và test.zip.002\ntest_zip_parts = [os.path.join(input_path, f'test.zip.{i:03d}') for i in range(1, 3)]\ncomplete_test_zip = os.path.join(output_path, 'test.zip')\n\nprint(\"Đang ghép các file test.zip.001 và test.zip.002...\")\nwith open(complete_test_zip, 'wb') as outfile:\n    for fname in test_zip_parts:\n        with open(fname, 'rb') as infile:\n            outfile.write(infile.read())\nprint(\"Đã ghép thành công. Đang giải nén...\")\n\n# Giải nén file test.zip đã ghép\ntry:\n    with zipfile.ZipFile(complete_test_zip, 'r') as zip_ref:\n        zip_ref.extractall(data_dir)\n    print(\"Đã giải nén dữ liệu test thành công.\")\nexcept zipfile.BadZipFile as e:\n    print(f\"Lỗi khi giải nén dữ liệu test: {e}. Vui lòng kiểm tra lại các phần của file zip.\")\n\n# Xóa file test.zip tạm thời để giải phóng không gian\nos.remove(complete_test_zip)\nprint(\"Đã xóa file test.zip để giải phóng không gian.\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!python --version\n!pip show torch","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport numpy as np\nimport torch\nimport torch.nn as nn\nimport torchvision.models as models\nfrom torch.autograd import Variable\nimport torch.cuda\nimport torchvision.transforms as transforms\nimport torch.nn.functional as F\nimport random\nimport torchvision\nfrom torchvision import transforms, utils\nfrom torch.utils.data.sampler import  WeightedRandomSampler\nimport argparse\nimport torch.optim as optim\nfrom tqdm import tqdm\nfrom tensorboardX import SummaryWriter","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"batch_size = 30\nepochs = 10\nlr = 0.0002\nno_cuda = False # Đặt True nếu bạn muốn buộc dùng CPU, False để dùng GPU nếu có\nseed = 1\nsave_epoch = 5\nweight_decay = 1e-8\nimage_size = 610","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class Args:\n    pass\n\nargs = Args()\nargs.batch_size = batch_size\nargs.epochs = epochs\nargs.lr = lr\nargs.no_cuda = no_cuda\nargs.seed = seed\nargs.save_epoch = save_epoch\nargs.weight_decay = weight_decay\nargs.image_size = image_size","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#kiểm tra xêm có ngăn sử dụng cuda(gpu)\nargs.cuda = not args.no_cuda and torch.cuda.is_available()\nif args.cuda:\n    device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')\n    #tạo đối tượng, gpu đầu tiên\nelse:\n    device = torch.device('cpu')\n\nprint(f\"Using device: {device}\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class Lambda(nn.Module):\n\tdef __init__(self, lambd):\n\t\tsuper(Lambda, self).__init__()\n\t\tself.lambd = lambd\n\tdef forward(self, x):\n\t\treturn self.lambd(x)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class KeNet(nn.Module):\n\tdef __init__(self,classes_num):\n\t\tsuper(KeNet, self).__init__()\n\t\tresNet = models.resnet50(pretrained=True)\n\t\tresNet = list(resNet.children())[:-2]\n\t\tself.features = nn.Sequential(*resNet)\n\n\t\tself.attention = nn.Sequential(\n\t\t\tnn.BatchNorm2d(2048),\n\t\t\tnn.Conv2d(2048,64,kernel_size=1,padding=0),\n\t\t\tnn.ReLU(),\n\t\t\tnn.Conv2d(64,16,kernel_size=1,padding=0),\n\t\t\tnn.ReLU(),\n\t\t\tnn.Conv2d(16,8,kernel_size=1,padding=0),\n\t\t\tnn.ReLU(),\n\t\t\tnn.Conv2d(8,1,kernel_size=1,padding=0),\n\t\t\tnn.Sigmoid()\n\t\t\t)\n\t\tself.up_c2 = nn.Conv2d(1,2048, kernel_size = 1, padding = 0,bias = False)\n\t\tnn.init.constant_(self.up_c2.weight, 1)\n\t\tself.denses = nn.Sequential(\n\t\t\tnn.Linear(2048,256),\n\t\t\tnn.Dropout(0.5),\n\t\t\tnn.Linear(256, classes_num)\n\t\t\t)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def forward(self, x):\n\t\tx = self.features(x)\n\n\t\tatten_layers= self.attention(x)\n\t\tatten_layers = self.up_c2(atten_layers)\n\t\t#print atten_layers.shape\n\t\tmask_features = torch.matmul(atten_layers,x)\n\t\t#print mask_features.shape\n\t\tgap_features =F.avg_pol2d(mask_features,kernel_size=mask_features.size()[2:])\n\t\t#print gap_features.shape\n\t\tgap_mask = F.avg_pool2d(atten_layers,kernel_size=atten_layers.size()[2:])\n\t\t#print gap_mask.shape\n\t\tgap =  torch.squeeze(Lambda(lambda x: x[0]/x[1])([gap_features, gap_mask]))\n\t\t#print gap.shape\n\t\tx = self.denses(gap)\n\t\treturn F.log_softmax(x,dim=1)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def ImageFolder(data_dir, img_size, batch_size, model):\n    std = 1. / 255.\n    means = [109.97 / 255., 127.34 / 255., 123.88 / 255.]\n    if model == 'train':\n\n        train_data = torchvision.datasets.ImageFolder(data_dir,\n                                                    transform=transforms.Compose([\n                                                        transforms.Resize(img_size),\n                                                        transforms.RandomHorizontalFlip(),\n                                                        torchvision.transforms.CenterCrop(size=img_size),\n                                                        transforms.ToTensor(),\n                                                        transforms.Normalize(mean = means, std = [std]*3)\n                                                    ]))\n        weights = [1,10,8,20,21]\n        sampler = WeightedRandomSampler(weights,\\\n                                num_samples=32000,\\\n                                replacement=True)\n        train_data_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, shuffle=True,sampler = sampler)\n\n\n\n        return train_data,train_data_loader\n    elif model == 'test':\n\n        test_data = torchvision.datasets.ImageFolder(data_dir,\n                                                    transform=transforms.Compose([\n                                                        transforms.Resize(img_size),\n                                                        torchvision.transforms.CenterCrop(size=img_size),\n                                                        transforms.ToTensor(),\n                                                        transforms.Normalize(mean=means, std=[std]*3)\n                                                        ]))\n        test_data_loader = torch.utils.data.DataLoader(test_data, batch_size=batch_size, shuffle=False)\n\n        return test_data, test_data_loader","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class InterclassLoss(nn.Module):\n    def __init__(self):\n        super(InterclassLoss, self).__init__()\n    def forward(self, pred, truth):\n        loss = 0.0\n        # loss = Variable(loss.data, requires_grad=True)\n        pred = pred.type(torch.FloatTensor)\n        _, predicted = torch.max(pred.data, 1)\n\n        predicted = torch.Tensor(predicted.type(torch.FloatTensor))\n        predicted = predicted.cuda()\n        pred = pred.cuda()\n\n        for i, p in enumerate(pred):\n            for j in range(0,5):\n                if j == truth[i]:\n                    M = self._getM(truth[i]).cuda()\n\n                    weight = (abs(predicted[i]-truth[i])+1)/(M.cuda())\n                    loss += weight*(-p[j])\n        loss = loss/len(pred)\n        loss = Variable(loss, requires_grad=True)\n        return loss\n\n\n    def _getM(self,label):\n        M = 0.0\n        for i in range(0,5):\n            M += abs(label-i)+1\n        return M\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport shutil\n\ntrain_txt = '/kaggle/working/TrainSet.txt'\nvalid_txt = '/kaggle/working/ValidSet.txt'\ndata_dir = '/kaggle/working/dataset/kaggle_diabetic/raw_data'\ntrain_dir = '/kaggle/working/dataset/diabetic_classified/train'\nvalid_dir = '/kaggle/working/dataset/diabetic_classified/valid'\nwith open(train_txt,'r+') as f:\n\tlines = f.readlines()\n\tfor line in lines:\n\t\tif line != '\\r\\n':\n\t\t\tlis = line.split(' ')\n\t\t\tname = lis[0]\n\t\t\tclss = lis[1].strip()\n\t\t\tshutil.copyfile(os.path.join(data_dir,name+'.jpeg'),os.path.join(train_dir+'/'+clss,name+'.jpeg'))\n\nwith open(valid_txt,'r+') as f:\n\tlines = f.readlines()\n\tfor line in lines:\n\t\tif line != '\\r\\n':\n\t\t\tlis = line.split(' ')\n\t\t\tname = lis[0]\n\t\t\tclss = lis[1].strip()\n\t\t\tshutil.copyfile(os.path.join(data_dir,name+'.jpeg'),os.path.join(valid_dir+'/'+clss,name+'.jpeg'))","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data_dir = '/kaggle/working/dataset/diabetic_classified/train'\nvalid_dir = '/kaggle/working/dataset/diabetic_classified/valid'","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"checkpoint_dir = 'output/weights'\nos.makedirs(checkpoint_dir, exist_ok=True)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class_num = 5\ntorch.manual_seed(args.seed)\nif args.cuda:\n    torch.cuda.manual_seed(args.seed)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train(path):\n    model.train()\n    if path:\n        model.load_state_dict(torch.load(path))\n      #freezing\n    unchanged_params = list(map(id, model.features[:-2].parameters()))\n    unchanged_params += list(map(id, model.up_c2.parameters()))\n    training_params = filter(lambda p: id(p) not in unchanged_params, model.parameters())\n    for param in model.up_c2.parameters():\n        param.requires_grad = False\n    for param in model.features[:-2].parameters():\n        param.requires_grad = False\n        #freezing\n        #tối ưu hóa SGD\n    optimizer = optim.SGD(training_params, lr=args.lr,momentum=0.9, weight_decay=args.weight_decay)\n    # điều chỉnh tốc độ học (Scheduler)\n    scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='max', factor=0.1, patience=6, verbose=True)\n#tải dữ liệu\n    trainset, dataiter = ImageFolder(data_dir, args.image_size, args.batch_size, 'train')\n    #Tính toán số lượng batch trong một epoch.\n    epoch_size = len(trainset) // args.batch_size\n\n    print('开始训练')\n    best_accuracy = 0.\n    best_epoch = 0\n    end_patient = 0\n\n    for e in range(args.epochs):\n      #iterator cho DataLoader để duyệt qua từng batch.\n        batch_iterator = iter(dataiter)\n        #tqdm để hiển thị thanh tiến trình cho mỗi epoch.\n        progress_bar = tqdm(range(epoch_size))\n        #được reset cho mỗi epoch để tính toán mất mát và độ chính xác của epoch\n        loss_sum = 0.\n        correct_num = 0\n        cnt = 0\n        for i in progress_bar:\n          #Lấy hình ảnh và nhãn từ DataLoader.\n            images, labels = next(batch_iterator)\n             #Chuyển Tensor thành Variable\n            images, labels = Variable(images, requires_grad=True), Variable(labels)\n            #Di chuyển dữ liệu lên GPU (hoặc CPU).\n            images, labels = images.to(device), labels.to(device)\n            #Cập nhật tổng số mẫu đã xử lý trong epoch.\n            cnt += labels.size(0)\n\n            logits, softmax = model(images)\n            # Lấy lớp dự đoán bằng cách tìm chỉ số có giá trị log-xác suất cao nhất.\n            _, predicted = torch.max(logits, 1)\n            #Đếm số lượng dự đoán đúng trong batch hiện tại.\n            batch_correct = (predicted == labels).sum()\n            correct_num += batch_correct\n            #Xóa các gradient tích lũy từ lần lặp trước đó\n            optimizer.zero_grad()\n\n            criterion = nn.CrossEntropyLoss()\n            loss = criterion(logits, labels)\n            # loss = loss_fn(softmax, labels)\n            loss_sum += loss.data.cpu().numpy()\n            #tính toán gradient của hàm mất mát đối với tất cả các tham số có requires_grad=True.\n            loss.backward()\n\n            optimizer.step()\n            #tính toán độ chính xác huấn luyện trung bình.\n        accuracy = correct_num.item() / cnt\n        print(\"epoch[%d],loss: %.4f, accuracy:%.4f.\" % (e + 1, loss_sum / epoch_size, accuracy))\n        #Ghi các giá trị này vào TensorBoard\n        writer.add_scalar('data_2/loss', loss_sum/epoch_size, e+1)\n        writer.add_scalar('data_2/accuracy', accuracy, e+1)\n\n        # 输出test的准确率\n        test_accuracy = test(test_data_dir)\n        print('the accuracy of test is: %.4f' % test_accuracy)\n        writer.add_scalar('data_2/test_accuracy', test_accuracy, e+1)\n\n        #Cập nhật scheduler\n        scheduler.step(test_accuracy)\n\n        if test_accuracy > best_accuracy:\n          #Lưu mô hình tốt nhất\n            model_file = os.path.join(checkpoint_dir, 'train_all_epoch_%03d_acc_%.4f.pth' %\n                                      (best_epoch, best_accuracy))\n            if os.path.isfile(model_file):\n                os.remove(model_file)\n\n            end_patient = 0\n            best_accuracy = test_accuracy\n            best_epoch = e + 1\n            print('保存权值')\n            torch.save(model.cpu().state_dict(), os.path.join(checkpoint_dir, 'train_all_epoch_%03d_acc_%.4f.pth' %\n                                                            (best_epoch, best_accuracy)))\n\n\n            model.to(device)\n\n        else:\n            end_patient += 1\n\n        if end_patient >= 10:\n            break","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def test(test_data_dir):\n    with torch.no_grad():#không tính toán hoặc lưu trữ gradient.\n      #Đặt mô hình vào chế độ đánh giá\n        model.eval()\n        # model.load_state_dict(torch.load(path))\n        #tải dữ liệu tập kiểm tra\n        testset, dataiter = ImageFolder(test_data_dir, args.image_size, args.batch_size, 'test')\n        correct_num = 0\n        cnt = 0\n        for test_images, test_labels in dataiter:\n\n            test_images, test_labels = test_images.to(device), test_labels.to(device)\n\n            cnt += test_labels.size(0)\n\n            logits, _ = model(test_images)\n\n            _, predicted = torch.max(logits, 1)\n\n            correct = (predicted == test_labels).sum()\n            correct_num += correct\n\n        accuracy = correct_num.item() / cnt\n    print(correct_num.item())\n    print(cnt)\n    model.train()\n    return accuracy","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"if __name__ == '__main__':\n    train(None)","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}