{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":14774,"databundleVersionId":875431,"sourceType":"competition"},{"sourceId":418031,"sourceType":"datasetVersion","datasetId":131128},{"sourceId":11321791,"sourceType":"datasetVersion","datasetId":7081289},{"sourceId":11433353,"sourceType":"datasetVersion","datasetId":7122064},{"sourceId":11601967,"sourceType":"datasetVersion","datasetId":7276234}],"dockerImageVersionId":31011,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.applications.inception_v3 import InceptionV3\nfrom tensorflow.keras.applications.resnet50 import ResNet50\nfrom tensorflow.keras.layers import Dense, Flatten, Concatenate, Input\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.preprocessing.image import load_img, img_to_array\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.callbacks import EarlyStopping, Callback\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport json\nfrom PIL import Image  # 添加这一行，用于使用 Image 类\n%matplotlib inline\n\n# 定义相关参数\nimg_width_inception = 299\nimg_height_inception = 299\nimg_width_resnet = 224\nimg_height_resnet = 224\nbatch_size = 32\nepochs = 120\nnum_classes = 5\n\n# 读取 CSV 文件\ntrain_csv_path = '/kaggle/input/pre-aptos/train.csv'\ntest_csv_path = '/kaggle/input/pre-aptos/val.csv'\ntrain_df = pd.read_csv(train_csv_path)\ntest_df = pd.read_csv(test_csv_path)\n\n# 定义数据生成函数\ndef data_generator(df, batch_size):\n    num_samples = len(df)\n    while True:\n        for offset in range(0, num_samples, batch_size):\n            batch_df = df.iloc[offset:offset + batch_size]\n            batch_images_inception = []\n            batch_images_resnet = []\n            batch_labels = []\n            for index, row in batch_df.iterrows():\n                img_path = row['path']\n                img_inception = load_img(img_path, target_size=(img_width_inception, img_height_inception))\n                img_inception = img_inception.resize((img_width_inception, img_height_inception))\n                img_inception = img_to_array(img_inception) / 255.0\n                img_resnet = load_img(img_path, target_size=(img_width_resnet, img_height_resnet))\n                img_resnet = img_resnet.resize((img_width_resnet, img_height_resnet))\n                img_resnet = img_to_array(img_resnet) / 255.0\n                label = row['label']\n                label = tf.keras.utils.to_categorical(label, num_classes=num_classes)\n                batch_images_inception.append(img_inception)\n                batch_images_resnet.append(img_resnet)\n                batch_labels.append(label)\n            batch_images_inception = np.array(batch_images_inception)\n            batch_images_resnet = np.array(batch_images_resnet)\n            batch_labels = np.array(batch_labels)\n            batch_images_inception = tf.convert_to_tensor(batch_images_inception)\n            batch_images_resnet = tf.convert_to_tensor(batch_images_resnet)\n            batch_labels = tf.convert_to_tensor(batch_labels)\n            yield (batch_images_inception, batch_images_resnet), batch_labels\n\n# 生成训练和测试数据生成器\ntrain_generator = data_generator(train_df, batch_size)\ntest_generator = data_generator(test_df, batch_size)\n\n# 加载预训练的 Inception V3 和 ResNet50 模型，去除最后一层\ninception_base = InceptionV3(weights='imagenet', include_top=False, input_shape=(img_width_inception, img_height_inception, 3))\nresnet_base = ResNet50(weights='imagenet', include_top=False, input_shape=(img_width_resnet, img_height_resnet, 3))\n\n# 冻结预训练模型的所有层\nfor layer in inception_base.layers:\n    layer.trainable = False\nfor layer in resnet_base.layers:\n    layer.trainable = False\n\n# 定义输入层\ninput_inception = Input(shape=(img_width_inception, img_height_inception, 3))\ninput_resnet = Input(shape=(img_width_resnet, img_height_resnet, 3))\n\n# 提取特征\ninception_features = inception_base(input_inception)\nresnet_features = resnet_base(input_resnet)\n\n# 展平特征\ninception_flat = Flatten()(inception_features)\nresnet_flat = Flatten()(resnet_features)\n\n# 拼接特征\nconcatenated_features = Concatenate()([inception_flat, resnet_flat])\n\n# 添加全连接层进行分类\nx = Dense(512, activation='relu')(concatenated_features)\noutput = Dense(num_classes, activation='softmax')(x)\n\n# 定义最终模型\nmodel = Model(inputs=[input_inception, input_resnet], outputs=output)\n\n# 编译模型\nmodel.compile(optimizer=Adam(learning_rate=0.001),\n              loss='categorical_crossentropy',\n              metrics=['accuracy'])\n\n# 定义早停回调函数\nearly_stopping = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True)\n\n# 自定义回调函数，每 n 个周期保存一次模型权重和训练结果\nclass CustomCheckpoint(Callback):\n    def __init__(self, save_freq):\n        super(CustomCheckpoint, self).__init__()\n        self.save_freq = save_freq\n        self.history = {'loss': [], 'accuracy': [], 'val_loss': [], 'val_accuracy': []}\n\n    def on_epoch_end(self, epoch, logs=None):\n        # 保存训练结果\n        self.history['loss'].append(logs['loss'])\n        self.history['accuracy'].append(logs['accuracy'])\n        self.history['val_loss'].append(logs['val_loss'])\n        self.history['val_accuracy'].append(logs['val_accuracy'])\n\n        if (epoch + 1) % self.save_freq == 0:\n            # 保存模型权重\n            model.save_weights(f'model_epoch_{epoch + 1}.weights.h5')\n            print(f'Epoch {epoch + 1}: 模型权重已保存到 model_epoch_{epoch + 1}.weights.h5')\n            # 保存训练结果\n            with open(f'training_history_epoch_{epoch + 1}.json', 'w') as f:\n                json.dump(self.history, f)\n            print(f'Epoch {epoch + 1}: 训练结果已保存到 training_history_epoch_{epoch + 1}.json')\n\n# 设置每 5 个周期保存一次模型权重\ncustom_checkpoint = CustomCheckpoint(save_freq=5)\n\n# 训练模型\nhistory = model.fit(\n    train_generator,\n    steps_per_epoch=len(train_df) // batch_size,\n    epochs=epochs,\n    validation_data=test_generator,\n    validation_steps=len(test_df) // batch_size,\n    callbacks=[early_stopping, custom_checkpoint]\n)\n\n# 打印训练过程\nfor epoch in range(len(history.history['loss'])):\n    print(f'Epoch {epoch + 1}/{epochs}')\n    print(f'Train Loss: {history.history[\"loss\"][epoch]:.4f}, Train Accuracy: {history.history[\"accuracy\"][epoch]:.4f}')\n    print(f'Val Loss: {history.history[\"val_loss\"][epoch]:.4f}, Val Accuracy: {history.history[\"val_accuracy\"][epoch]:.4f}')\n\n# 保存最终模型权重\nmodel.save_weights('final_model_weights.weights.h5')\n\n# 保存训练历史信息\nwith open('training_history.json', 'w') as f:\n    json.dump(history.history, f)\n\n# 定义可视化函数\ndef visualize_training_results():\n    try:\n        with open('training_history.json', 'r') as f:\n            history = json.load(f)\n        plt.figure(figsize=(12, 4))\n\n        # 绘制损失曲线\n        plt.subplot(1, 2, 1)\n        plt.plot(history['loss'], label='Train Loss')\n        plt.plot(history['val_loss'], label='Val Loss')\n        plt.title('Loss Curve')\n        plt.xlabel('Epochs')\n        plt.ylabel('Loss')\n        plt.legend()\n\n        # 绘制准确率曲线\n        plt.subplot(1, 2, 2)\n        plt.plot(history['accuracy'], label='Train Accuracy')\n        plt.plot(history['val_accuracy'], label='Val Accuracy')\n        plt.title('Accuracy Curve')\n        plt.xlabel('Epochs')\n        plt.ylabel('Accuracy')\n        plt.legend()\n\n        # 保存可视化结果\n        plt.savefig('training_results_visualization.png')\n        plt.show()\n    except FileNotFoundError:\n        print(\"训练历史文件未找到，请先训练模型。\")\n\n# 调用可视化函数进行可视化\nvisualize_training_results()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-29T10:29:34.494726Z","iopub.execute_input":"2025-04-29T10:29:34.494994Z","iopub.status.idle":"2025-04-29T10:58:49.875933Z","shell.execute_reply.started":"2025-04-29T10:29:34.494970Z","shell.execute_reply":"2025-04-29T10:58:49.875213Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport shutil\n\n# 定义要删除的文件路径\nfile_path = '/kaggle/working/processed_train_images'\n# 检查文件是否存在\nif os.path.exists(file_path):\n    # 删除文件\n    shutil.rmtree(file_path)\n    print(f\"文件 {file_path} 已成功删除。\")\nelse:\n    print(f\"文件 {file_path} 不存在。\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-28T14:36:07.559009Z","iopub.execute_input":"2025-04-28T14:36:07.559280Z","iopub.status.idle":"2025-04-28T14:36:07.890141Z","shell.execute_reply.started":"2025-04-28T14:36:07.559259Z","shell.execute_reply":"2025-04-28T14:36:07.889456Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.applications.inception_v3 import InceptionV3\nfrom tensorflow.keras.applications.resnet50 import ResNet50\nfrom tensorflow.keras.layers import Dense, Flatten, Concatenate, Input\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.preprocessing.image import load_img, img_to_array\nimport numpy as np\n\n# 定义相关参数\nimg_width_inception = 299\nimg_height_inception = 299\nimg_width_resnet = 224\nimg_height_resnet = 224\nnum_classes = 5\n\n# 构建模型\ninput_inception = Input(shape=(img_width_inception, img_height_inception, 3))\ninput_resnet = Input(shape=(img_width_resnet, img_height_resnet, 3))\n\ninception_base = InceptionV3(weights='imagenet', include_top=False)(input_inception)\nresnet_base = ResNet50(weights='imagenet', include_top=False)(input_resnet)\n\ninception_flat = Flatten()(inception_base)\nresnet_flat = Flatten()(resnet_base)\n\nconcatenated_features = Concatenate()([inception_flat, resnet_flat])\nx = Dense(512, activation='relu')(concatenated_features)\noutput = Dense(num_classes, activation='softmax')(x)\n\nmodel = Model(inputs=[input_inception, input_resnet], outputs=output)\n\n# 加载模型权重\nmodel.load_weights('/kaggle/working/model_epoch_5.weights.h5')\n\ndef preprocess_image(img_path):\n    \"\"\"\n    对输入的图片进行预处理\n    :param img_path: 图片的路径\n    :return: 处理后的 Inception 和 ResNet 输入\n    \"\"\"\n    img_inception = load_img(img_path, target_size=(img_width_inception, img_height_inception))\n    img_inception = img_to_array(img_inception) / 255.0\n    img_inception = np.expand_dims(img_inception, axis=0)\n\n    img_resnet = load_img(img_path, target_size=(img_width_resnet, img_height_resnet))\n    img_resnet = img_to_array(img_resnet) / 255.0\n    img_resnet = np.expand_dims(img_resnet, axis=0)\n\n    return img_inception, img_resnet\n\n# 替换为你要测试的图片路径\nimage_path = '/kaggle/input/22222/colored_images/data1/2/31411_left.png'\nimg_inception, img_resnet = preprocess_image(image_path)\n\n# 进行预测\npredictions = model.predict([img_inception, img_resnet])\npredicted_class = np.argmax(predictions)\n\nprint(f\"预测的类别是: {predicted_class}\")\n    ","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch.nn as nn\nimport torch\n\n\nclass AlexNet(nn.Module):\n    def __init__(self, num_classes=1000, init_weights=False):\n        super(AlexNet, self).__init__()\n        self.features = nn.Sequential(\n            nn.Conv2d(3, 48, kernel_size=11, stride=4, padding=2),  # input[3, 224, 224]  output[48, 55, 55]\n            nn.ReLU(inplace=True),\n            nn.MaxPool2d(kernel_size=3, stride=2),                  # output[48, 27, 27]\n            nn.Conv2d(48, 128, kernel_size=5, padding=2),           # output[128, 27, 27]\n            nn.ReLU(inplace=True),\n            nn.MaxPool2d(kernel_size=3, stride=2),                  # output[128, 13, 13]\n            nn.Conv2d(128, 192, kernel_size=3, padding=1),          # output[192, 13, 13]\n            nn.ReLU(inplace=True),\n            nn.Conv2d(192, 192, kernel_size=3, padding=1),          # output[192, 13, 13]\n            nn.ReLU(inplace=True),\n            nn.Conv2d(192, 128, kernel_size=3, padding=1),          # output[128, 13, 13]\n            nn.ReLU(inplace=True),\n            nn.MaxPool2d(kernel_size=3, stride=2),                  # output[128, 6, 6]\n        )\n        self.classifier = nn.Sequential(\n            nn.Dropout(p=0.5),\n            nn.Linear(128 * 6 * 6, 2048),\n            nn.ReLU(inplace=True),\n            nn.Dropout(p=0.5),\n            nn.Linear(2048, 2048),\n            nn.ReLU(inplace=True),\n            nn.Linear(2048, num_classes),\n        )\n        if init_weights:\n            self._initialize_weights()\n\n    def forward(self, x):\n        x = self.features(x)\n        x = torch.flatten(x, start_dim=1)\n        x = self.classifier(x)\n        return x\n\n    def _initialize_weights(self):\n        for m in self.modules():\n            if isinstance(m, nn.Conv2d):\n                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')\n                if m.bias is not None:\n                    nn.init.constant_(m.bias, 0)\n            elif isinstance(m, nn.Linear):\n                nn.init.normal_(m.weight, 0, 0.01)\n                nn.init.constant_(m.bias, 0)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-29T05:00:04.911331Z","iopub.execute_input":"2025-04-29T05:00:04.912212Z","iopub.status.idle":"2025-04-29T05:00:04.923866Z","shell.execute_reply.started":"2025-04-29T05:00:04.912171Z","shell.execute_reply":"2025-04-29T05:00:04.922951Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport sys\nimport json\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\nimport torch.nn.functional as F\nfrom torchvision import transforms, datasets, utils\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport torch.optim as optim\nfrom tqdm import tqdm\nfrom PIL import Image\n\n# 定义 FocalLoss 类\n# class FocalLoss(nn.Module):\n#     def __init__(self, alpha=0.5, gamma=3):\n#         super().__init__()\n#         self.alpha = alpha\n#         self.gamma = gamma\n\n#     def forward(self, inputs, targets):\n#         BCE_loss = F.cross_entropy(inputs, targets, reduction='none')\n#         pt = torch.exp(-BCE_loss)\n#         focal_loss = self.alpha * (1 - pt) ** self.gamma * BCE_loss\n#         return focal_loss.mean()\n\n# 自定义数据集类\nclass CustomDataset(Dataset):\n    def __init__(self, csv_file, transform=None):\n        self.data = pd.read_csv(csv_file)\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, idx):\n        if torch.is_tensor(idx):\n            idx = idx.tolist()\n\n        img_path = self.data.iloc[idx]['path']\n        image = Image.open(img_path).convert('RGB')\n        label = self.data.iloc[idx]['label']\n\n        if self.transform:\n            image = self.transform(image)\n\n        return image, label\n\n\ntrain_losses = []\nval_losses = []\ntrain_accuracies = []\nval_accuracies = []\n\ndef main():\n    device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n    print(\"using {} device.\".format(device))\n\n    data_transform = {\n        \"train\": transforms.Compose([transforms.RandomResizedCrop(224),\n                                     transforms.RandomHorizontalFlip(),\n                                     transforms.ColorJitter(0.1, 0.1, 0.1),\n                                     transforms.RandomRotation(degrees=15),\n                                     transforms.ToTensor(),\n                                     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]),\n        \"val\": transforms.Compose([transforms.Resize((224, 224)),\n                                   transforms.ToTensor(),\n                                   transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])}\n\n    # 加载训练集和验证集\n    train_csv_path = '/kaggle/input/pre-aptos/train.csv'\n    val_csv_path = '/kaggle/input/pre-aptos/val.csv'\n    train_dataset = CustomDataset(csv_file=train_csv_path, transform=data_transform[\"train\"])\n    val_dataset = CustomDataset(csv_file=val_csv_path, transform=data_transform[\"val\"])\n\n    # 获取类别列表并生成类别字典\n    class_list = sorted(train_dataset.data['label'].unique())\n    cla_dict = {i: class_list[i] for i in range(len(class_list))}\n    cla_dict = {int(key): int(value) if isinstance(value, np.int64) else value for key, value in cla_dict.items()}\n    # 将类别字典写入JSON文件\n    json_str = json.dumps(cla_dict, indent=4)\n    with open('class_indices.json', 'w') as json_file:\n        json_file.write(json_str)\n\n    batch_size = 32\n    nw = min([os.cpu_count(), batch_size if batch_size > 1 else 0, 8])\n    print('Using {} dataloader workers every process'.format(nw))\n\n    train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=nw)\n    val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=True, num_workers=nw)\n\n    print(\"using {} images for training, {} images for validation.\".format(len(train_dataset), len(val_dataset)))\n\n    net = AlexNet(num_classes=5, init_weights=True)\n\n    net.to(device)\n    loss_function = nn.CrossEntropyLoss()\n    optimizer = optim.Adam(net.parameters(), lr=0.0001)\n\n    epochs = 300\n    save_path = '/kaggle/working/AlexNet.pth'\n    best_acc = 0.0\n    train_steps = len(train_loader)\n    for epoch in range(epochs):\n        # train\n        net.train()\n        running_loss = 0.0\n        train_acc = 0.0\n        train_bar = tqdm(train_loader, file=sys.stdout)\n        for step, data in enumerate(train_bar):\n            images, labels = data\n            optimizer.zero_grad()\n            outputs = net(images.to(device))\n            loss = loss_function(outputs, labels.to(device))\n            loss.backward()\n            optimizer.step()\n\n            # print statistics\n            running_loss += loss.item()\n            predict_y = torch.max(outputs, dim=1)[1]\n            train_acc += torch.eq(predict_y, labels.to(device)).sum().item()\n            train_bar.desc = \"train epoch[{}/{}] loss:{:.3f}\".format(epoch + 1, epochs, loss)\n\n        train_accurate = train_acc / len(train_loader.dataset)\n        train_loss = running_loss / train_steps\n        train_losses.append(train_loss)\n        train_accuracies.append(train_accurate)\n\n        # validate\n        net.eval()\n        acc = 0.0  # accumulate accurate number / epoch\n        val_running_loss = 0.0\n        with torch.no_grad():\n            val_bar = tqdm(val_loader, file=sys.stdout)\n            for val_data in val_bar:\n                val_images, val_labels = val_data\n                outputs = net(val_images.to(device))\n                loss = loss_function(outputs, val_labels.to(device))\n                val_running_loss += loss.item()\n                predict_y = torch.max(outputs, dim=1)[1]\n                acc += torch.eq(predict_y, val_labels.to(device)).sum().item()\n                val_bar.desc = \"valid epoch[{}/{}]\".format(epoch + 1, epochs)\n\n        val_accurate = acc / len(val_dataset)\n        val_loss = val_running_loss / len(val_loader)\n        val_losses.append(val_loss)\n        val_accuracies.append(val_accurate)\n\n        print('[epoch %d] train_loss: %.3f  train_accuracy: %.3f  val_loss: %.3f  val_accuracy: %.3f' % (epoch + 1, train_loss, train_accurate, val_loss, val_accurate))\n\n        if val_accurate > best_acc:\n            best_acc = val_accurate\n            torch.save(net.state_dict(), save_path)\n\n    print('Finished Training')\n\n    plt.figure(figsize=(12, 6))\n    # 损失曲线\n    plt.subplot(1, 2, 1)\n    plt.plot(train_losses, label='Train Loss')\n    plt.plot(val_losses, label='Val Loss')\n    plt.xlabel('Epoch')\n    plt.ylabel('Loss')\n    plt.title('Training and Validation Loss')\n    plt.legend()\n\n    # 准确率曲线\n    plt.subplot(1, 2, 2)\n    plt.plot(train_accuracies, label='Train Accuracy')\n    plt.plot(val_accuracies, label='Val Accuracy')\n    plt.xlabel('Epoch')\n    plt.ylabel('Accuracy')\n    plt.title('Training and Validation Accuracy')\n    plt.legend()\n\n    # 保存可视化结果\n    plt.savefig('/kaggle/working/training_results.png')\n    plt.close()\n\n\nif __name__ == '__main__':\n    main()\n    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-29T05:01:47.827614Z","iopub.execute_input":"2025-04-29T05:01:47.828213Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import shutil\nimport os\n\n# 定义要压缩的文件夹路径\nfolder_to_compress = '/kaggle/working/processed_train_images'\n# 定义压缩文件的输出路径和名称\nzip_file_path = '/kaggle/working/processed_train_images_zip'\n\n# 压缩文件夹\nshutil.make_archive(zip_file_path, 'zip', folder_to_compress)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-29T16:13:11.386087Z","iopub.execute_input":"2025-04-29T16:13:11.386762Z","iopub.status.idle":"2025-04-29T16:13:59.510240Z","shell.execute_reply.started":"2025-04-29T16:13:11.386739Z","shell.execute_reply":"2025-04-29T16:13:59.509654Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nos.chdir('/kaggle/working')\nprint(os.getcwd())\nprint(os.listdir(\"/kaggle/working\"))\nfrom IPython.display import FileLink\nFileLink('/kaggle/working/processed_train_images_zip.zip')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-29T16:14:26.697651Z","iopub.execute_input":"2025-04-29T16:14:26.698204Z","iopub.status.idle":"2025-04-29T16:14:26.704959Z","shell.execute_reply.started":"2025-04-29T16:14:26.698183Z","shell.execute_reply":"2025-04-29T16:14:26.704264Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n%matplotlib inline\n\nplt.figure(figsize=(12, 6))\n    # 损失曲线\nplt.subplot(1, 2, 1)\nplt.plot(train_losses, label='Train Loss')\nplt.plot(val_losses, label='Val Loss')\nplt.xlabel('Epoch')\nplt.ylabel('Loss')\nplt.title('Training and Validation Loss')\nplt.legend()\n\n# 准确率曲线\nplt.subplot(1, 2, 2)\nplt.plot(train_accuracies, label='Train Accuracy')\nplt.plot(val_accuracies, label='Val Accuracy')\nplt.xlabel('Epoch')\nplt.ylabel('Accuracy')\nplt.title('Training and Validation Accuracy')\nplt.legend()\n\n# 保存可视化结果\nplt.savefig('/kaggle/working/training_results.png')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-28T16:48:39.397081Z","iopub.execute_input":"2025-04-28T16:48:39.397926Z","iopub.status.idle":"2025-04-28T16:48:39.881279Z","shell.execute_reply.started":"2025-04-28T16:48:39.397898Z","shell.execute_reply":"2025-04-28T16:48:39.880562Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport cv2\nimport numpy as np\nfrom PIL import Image\nfrom tqdm import tqdm\nimport matplotlib.pyplot as plt\n\ndef crop_image_from_gray(img, tol=7):\n    if img.ndim == 2:\n        mask = img > tol\n        return img[np.ix_(mask.any(1), mask.any(0))]\n    elif img.ndim == 3:\n        gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)\n        mask = gray_img > tol\n\n        check_shape = img[:, :, 0][np.ix_(mask.any(1), mask.any(0))].shape[0]\n        if (check_shape == 0):\n            return img\n        else:\n            img1 = img[:, :, 0][np.ix_(mask.any(1), mask.any(0))]\n            img2 = img[:, :, 1][np.ix_(mask.any(1), mask.any(0))]\n            img3 = img[:, :, 2][np.ix_(mask.any(1), mask.any(0))]\n            img = np.stack([img1, img2, img3], axis=-1)\n        return img\n\ndef load_ben_color(image, sigmaX=10):\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n    image = crop_image_from_gray(image)\n    image = cv2.resize(image, (512, 512))\n    image = cv2.addWeighted(image, 4, cv2.GaussianBlur(image, (0, 0), sigmaX), -4, 128)\n    return image\n\ntrain_images_dir = '/kaggle/input/diabetic-retinopathy-resized/resized_train_cropped/resized_train_cropped'\noutput_dir = '/kaggle/working/processed_train_images'\nos.makedirs(output_dir, exist_ok=True)\n\nimage_files = [f for f in os.listdir(train_images_dir) if f.endswith('.jpeg')]\nbatch_size = 5000  # 设置批次大小，可以根据内存情况调整\n\nfor i in tqdm(range(0, len(image_files), batch_size)):\n    batch_files = image_files[i:i + batch_size]\n    for img_file in batch_files:\n        img_path = os.path.join(train_images_dir, img_file)\n        image = cv2.imread(img_path)\n\n        if image is not None:\n            processed_image = load_ben_color(image)\n            output_path = os.path.join(output_dir, img_file)\n            # 使用PIL库来保存RGB图像\n            img_to_save = Image.fromarray(processed_image.astype('uint8'), 'RGB')\n            img_to_save.save(output_path)\n        else:\n            print(f\"无法读取图像: {img_path}\")\n\nprint(\"对train数据集所有图片的数据预处理并保存完成！\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-29T15:31:29.689837Z","iopub.execute_input":"2025-04-29T15:31:29.690043Z","iopub.status.idle":"2025-04-29T16:02:04.245402Z","shell.execute_reply.started":"2025-04-29T15:31:29.690002Z","shell.execute_reply":"2025-04-29T16:02:04.244645Z"}},"outputs":[],"execution_count":null}]}