{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.6.6","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"}],"dockerImageVersionId":29853,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport cv2\nimport random\nimport warnings\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom sklearn.metrics import confusion_matrix, cohen_kappa_score\nfrom keras.models import Model\nfrom keras import optimizers, applications\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.callbacks import EarlyStopping, ReduceLROnPlateau\nfrom keras.layers import Dense, Dropout, GlobalAveragePooling2D, Input\nimport tensorflow as tf\n\ndef seed_everything(seed=0):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    tf.random.set_seed(seed)\n\nseed_everything()\n\n%matplotlib inline\nsns.set(style=\"whitegrid\")\nwarnings.filterwarnings(\"ignore\", category=ImportWarning)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-03-10T13:16:08.899169Z","iopub.execute_input":"2025-03-10T13:16:08.899473Z","iopub.status.idle":"2025-03-10T13:16:16.108599Z","shell.execute_reply.started":"2025-03-10T13:16:08.899414Z","shell.execute_reply":"2025-03-10T13:16:16.107714Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train = pd.read_csv('../input/aptos2019-blindness-detection/train.csv')\nprint('Number of train samples: ', train.shape[0])\ndisplay(train.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-10T13:16:16.110191Z","iopub.execute_input":"2025-03-10T13:16:16.110425Z","iopub.status.idle":"2025-03-10T13:16:16.144995Z","shell.execute_reply.started":"2025-03-10T13:16:16.110378Z","shell.execute_reply":"2025-03-10T13:16:16.144328Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"f, ax = plt.subplots(figsize=(14, 8.7))\nax = sns.countplot(x=\"diagnosis\", data=train, palette=\"GnBu_d\")\nsns.despine()\nplt.show()","metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true,"execution":{"iopub.status.busy":"2025-03-10T13:16:16.145991Z","iopub.execute_input":"2025-03-10T13:16:16.146181Z","iopub.status.idle":"2025-03-10T13:16:16.433943Z","shell.execute_reply.started":"2025-03-10T13:16:16.146146Z","shell.execute_reply":"2025-03-10T13:16:16.432793Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport cv2\nimport matplotlib.pyplot as plt\n\nsns.set_style(\"white\")\n\ncount = 1\nplt.figure(figsize=[20, 20])\n\nfor img_name in train['id_code'][:15]:\n    image_id = img_name  # 使用train中的id_code作为image_id\n    img_path = os.path.join(f'../input/aptos2019-blindness-detection/train_images/{image_id}.png')\n    img = cv2.imread(img_path)[..., [2, 1, 0]]  # 读取图像并转换颜色通道\n    plt.subplot(5, 5, count)\n    plt.imshow(img)\n    plt.title(f'Image ID: {image_id}')\n    plt.axis('off')\n    count += 1\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-10T13:16:16.435566Z","iopub.execute_input":"2025-03-10T13:16:16.435957Z","iopub.status.idle":"2025-03-10T13:16:22.558931Z","shell.execute_reply.started":"2025-03-10T13:16:16.435898Z","shell.execute_reply":"2025-03-10T13:16:22.557905Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train[\"id_code\"] = train[\"id_code\"].apply(lambda x: x + \".png\")\ntrain['diagnosis'] = train['diagnosis'].astype('str')\ntrain.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-10T13:16:22.56145Z","iopub.execute_input":"2025-03-10T13:16:22.561671Z","iopub.status.idle":"2025-03-10T13:16:22.574413Z","shell.execute_reply.started":"2025-03-10T13:16:22.561634Z","shell.execute_reply":"2025-03-10T13:16:22.573819Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def 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 preprocess_image(image, sigmaX=10):\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n    image = crop_image_from_gray(image)\n    image = cv2.resize(image, (200, 200))\n    image=cv2.addWeighted ( image,4, cv2.GaussianBlur( image , (0,0) , sigmaX) ,-4 ,128)\n        \n    return image","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-10T13:16:22.576016Z","iopub.execute_input":"2025-03-10T13:16:22.576306Z","iopub.status.idle":"2025-03-10T13:16:22.600845Z","shell.execute_reply.started":"2025-03-10T13:16:22.576255Z","shell.execute_reply":"2025-03-10T13:16:22.600002Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import cv2\nimport matplotlib.pyplot as plt\nimport pandas as pd\n\nfig, ax = plt.subplots(1, 5, figsize=(15, 6))\nfor i in range(5):\n    sample = train[train['diagnosis'] == str(i)].sample(1)\n    image_name = sample['id_code'].item()\n    \n    if not image_name.lower().endswith('.png'):\n        image_name += '.png'\n    \n    image_path = f'../input/aptos2019-blindness-detection/train_images/{image_id}.png'\n    \n   # print(f\"Trying to read image at: {image_path}\")\n    \n    image = cv2.imread(image_path)\n    if image is None:\n        print(f\"Error: Could not read image at {image_path}\")\n        continue\n    \n    X = preprocess_image(image)\n    \n    ax[i].set_title(f\"Image: {image_name}\\nLabel = {sample['diagnosis'].item()}\", weight='bold', fontsize=10)\n    ax[i].axis('off')\n    ax[i].imshow(X)\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-10T13:16:22.601818Z","iopub.execute_input":"2025-03-10T13:16:22.602008Z","iopub.status.idle":"2025-03-10T13:16:24.282806Z","shell.execute_reply.started":"2025-03-10T13:16:22.601974Z","shell.execute_reply":"2025-03-10T13:16:24.282007Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"BATCH_SIZE = 8\nEPOCHS = 20\nWARMUP_EPOCHS = 2\nLEARNING_RATE = 1e-3\nWARMUP_LEARNING_RATE = 1e-3\nHEIGHT = 256\nWIDTH = 256\nCANAL = 3\nN_CLASSES = train['diagnosis'].nunique()\nES_PATIENCE = 5\nRLROP_PATIENCE = 3\nDECAY_DROP = 0.5","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-10T13:16:24.284269Z","iopub.execute_input":"2025-03-10T13:16:24.28459Z","iopub.status.idle":"2025-03-10T13:16:24.290861Z","shell.execute_reply.started":"2025-03-10T13:16:24.284515Z","shell.execute_reply":"2025-03-10T13:16:24.290093Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\n\ntrain_data, temp_data = train_test_split(train, test_size=0.2, stratify=train['diagnosis'], random_state=66)\nvalid_data, test_data = train_test_split(temp_data, test_size=0.5, stratify=temp_data['diagnosis'], random_state=66)\n\ntrain_datagen = ImageDataGenerator(rescale=1./255, \n                                   horizontal_flip=True,\n                                   rotation_range=20,\n                                   fill_mode='nearest')\nval_datagen = ImageDataGenerator(rescale=1./255)\ntest_datagen = ImageDataGenerator(rescale=1./255)  # 定义test_datagen\n\ntrain_generator = train_datagen.flow_from_dataframe(\n    dataframe=train_data,\n    directory='../input/aptos2019-blindness-detection/train_images/',\n    x_col=\"id_code\",\n    y_col=\"diagnosis\",\n    batch_size=BATCH_SIZE,\n    class_mode=\"categorical\",\n    shuffle=True, \n    target_size=(HEIGHT, WIDTH),\n    seed=66\n)\n\n# 验证数据生成器\nvalid_generator = val_datagen.flow_from_dataframe(\n    dataframe=valid_data, \n    directory='../input/aptos2019-blindness-detection/train_images/', \n    x_col=\"id_code\",\n    y_col=\"diagnosis\",\n    batch_size=BATCH_SIZE,\n    class_mode=\"categorical\",    \n    shuffle=True,\n    target_size=(HEIGHT, WIDTH),\n    seed=66\n)\n\n# 测试数据生成器\ntest_generator = test_datagen.flow_from_dataframe(\n    dataframe=test_data,  \n    directory='../input/aptos2019-blindness-detection/train_images/', \n    x_col=\"id_code\",\n    y_col=\"diagnosis\",  \n    target_size=(HEIGHT, WIDTH),\n    batch_size=1,\n    shuffle=False,\n    class_mode=\"categorical\" \n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-10T13:16:24.292156Z","iopub.execute_input":"2025-03-10T13:16:24.292385Z","iopub.status.idle":"2025-03-10T13:16:28.625703Z","shell.execute_reply.started":"2025-03-10T13:16:24.292338Z","shell.execute_reply":"2025-03-10T13:16:28.624877Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install --upgrade tensorflow","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-10T13:19:41.336904Z","iopub.execute_input":"2025-03-10T13:19:41.337221Z","iopub.status.idle":"2025-03-10T13:20:58.420614Z","shell.execute_reply.started":"2025-03-10T13:19:41.337165Z","shell.execute_reply":"2025-03-10T13:20:58.419921Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras import layers, models, applications, Input\nfrom tensorflow.keras.layers import Layer, Dense, GlobalAveragePooling2D, Dropout\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.optimizers import SGD\nfrom tensorflow.keras.applications import DenseNet201\nclass SelfAttention(tf.keras.layers.Layer):\n    def __init__(self, **kwargs):\n        super(SelfAttention, self).__init__(**kwargs)\n\n    def build(self, input_shape):\n        self.W_q = self.add_weight(shape=(input_shape[-1], input_shape[-1]),\n                                   initializer='glorot_uniform',\n                                   trainable=True,\n                                   name='W_q')\n        self.W_k = self.add_weight(shape=(input_shape[-1], input_shape[-1]),\n                                   initializer='glorot_uniform',\n                                   trainable=True,\n                                   name='W_k')\n        self.W_v = self.add_weight(shape=(input_shape[-1], input_shape[-1]),\n                                   initializer='glorot_uniform',\n                                   trainable=True,\n                                   name='W_v')\n        super(SelfAttention, self).build(input_shape)\n\n    def call(self, inputs):\n        Q = tf.matmul(inputs, self.W_q)\n        K = tf.matmul(inputs, self.W_k)\n        V = tf.matmul(inputs, self.W_v)\n        \n        attention_scores = tf.matmul(Q, K, transpose_b=True)\n        attention_scores /= tf.sqrt(tf.cast(tf.shape(K)[-1], tf.float32))\n        attention_weights = tf.nn.softmax(attention_scores, axis=-1)\n\n        output = tf.matmul(attention_weights, V)\n        return output\n\n    def compute_output_shape(self, input_shape):\n        return input_shape\n\n\ndef build_model(input_shape=(256, 256, 3), num_classes=5):\n    inputs = Input(shape=input_shape)\n    \n    base_model = DenseNet201(include_top=False, input_tensor=inputs, input_shape=input_shape)\n    x = base_model.output\n\n    x = Dropout(0.3)(x)\n    \n    x = GlobalAveragePooling2D()(x)\n    \n    x = Dropout(0.5)(x)\n    \n    outputs = Dense(num_classes, activation='softmax')(x)\n    \n    model = Model(inputs=inputs, outputs=outputs)\n    \n    return model\n\nmodel = build_model(input_shape=(256, 256, 3), num_classes=5)\n\noptimizer = SGD(learning_rate=0.0001, momentum=0.9, nesterov=True)\nmodel.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])\n\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-10T13:21:58.76031Z","iopub.execute_input":"2025-03-10T13:21:58.760568Z","iopub.status.idle":"2025-03-10T13:22:09.838099Z","shell.execute_reply.started":"2025-03-10T13:21:58.760534Z","shell.execute_reply":"2025-03-10T13:22:09.837303Z"},"collapsed":true,"jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history_finetunning = model.fit(\n    x=train_generator,\n    validation_data=valid_generator,\n    epochs=20,\n)\n\nhistory = {\n    'loss': history_finetunning.history['loss'],\n    'val_loss': history_finetunning.history['val_loss'],\n    'accuracy': history_finetunning.history['accuracy'],\n    'val_accuracy': history_finetunning.history['val_accuracy']\n}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-10T13:22:29.514293Z","iopub.execute_input":"2025-03-10T13:22:29.514556Z","iopub.status.idle":"2025-03-10T15:23:42.539589Z","shell.execute_reply.started":"2025-03-10T13:22:29.51451Z","shell.execute_reply":"2025-03-10T15:23:42.538978Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.save('/kaggle/working/my_model.h5')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-10T13:16:29.038463Z","iopub.status.idle":"2025-03-10T13:16:29.039076Z","shell.execute_reply":"2025-03-10T13:16:29.038845Z"}},"outputs":[],"execution_count":null}]}