{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.9","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":20270,"databundleVersionId":1222630,"sourceType":"competition"},{"sourceId":1339680,"sourceType":"datasetVersion","datasetId":756214}],"dockerImageVersionId":30086,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"\n#import all required library\nimport os\nimport cv2\nimport numpy as np\nimport random as rn\nimport pandas as pd\nfrom tqdm import tqdm\nimport matplotlib.pyplot as plt\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:05.742259Z","iopub.execute_input":"2024-11-21T05:42:05.742660Z","iopub.status.idle":"2024-11-21T05:42:05.864798Z","shell.execute_reply.started":"2024-11-21T05:42:05.742574Z","shell.execute_reply":"2024-11-21T05:42:05.864203Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import all tensorflow and keras library \n\nimport tensorflow as tf\nimport keras\nfrom keras import initializers\nfrom keras import regularizers\nfrom keras import constraints\nfrom keras import backend as K\nfrom keras.activations import elu\nfrom keras.optimizers import Adam\nfrom keras.models import Sequential\nfrom keras.engine import Layer, InputSpec\nfrom keras.utils.generic_utils import get_custom_objects\nfrom keras.callbacks import Callback, EarlyStopping, ReduceLROnPlateau\nfrom keras.layers import Dense, Conv2D, Flatten, GlobalAveragePooling2D, Dropout,MaxPooling2D,BatchNormalization,GlobalMaxPooling2D","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:05.866598Z","iopub.execute_input":"2024-11-21T05:42:05.866933Z","iopub.status.idle":"2024-11-21T05:42:11.166724Z","shell.execute_reply.started":"2024-11-21T05:42:05.866899Z","shell.execute_reply":"2024-11-21T05:42:11.165952Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# set seed for reproducability\nseed=1234\nrn.seed(seed)\nnp.random.seed(seed)\ntf.random.set_seed(seed)\nos.environ[\"PYTHONHASHSEED\"]=str(seed)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:11.168103Z","iopub.execute_input":"2024-11-21T05:42:11.168441Z","iopub.status.idle":"2024-11-21T05:42:11.172250Z","shell.execute_reply.started":"2024-11-21T05:42:11.168408Z","shell.execute_reply":"2024-11-21T05:42:11.171581Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"base_model=tf.keras.applications.MobileNetV2(input_shape=(256,256,3),include_top=False,weights=\"imagenet\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:11.173380Z","iopub.execute_input":"2024-11-21T05:42:11.173606Z","iopub.status.idle":"2024-11-21T05:42:14.708093Z","shell.execute_reply.started":"2024-11-21T05:42:11.173585Z","shell.execute_reply":"2024-11-21T05:42:14.707323Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Get the last convolutional layer name\nlast_conv_layer_name = None\nfor layer in base_model.layers[::-1]:\n    if isinstance(layer, tf.keras.layers.Conv2D):\n        last_conv_layer_name = layer.name\n        break\n\nprint('Last convolutional layer:', last_conv_layer_name)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:14.711303Z","iopub.execute_input":"2024-11-21T05:42:14.711589Z","iopub.status.idle":"2024-11-21T05:42:14.716866Z","shell.execute_reply.started":"2024-11-21T05:42:14.711564Z","shell.execute_reply":"2024-11-21T05:42:14.716160Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Set all layer trainable\nfor layer in base_model.layers:\n    layer.trainable=True","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:14.719727Z","iopub.execute_input":"2024-11-21T05:42:14.720052Z","iopub.status.idle":"2024-11-21T05:42:14.732276Z","shell.execute_reply.started":"2024-11-21T05:42:14.720018Z","shell.execute_reply":"2024-11-21T05:42:14.731640Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.layers import Input, GlobalAveragePooling2D, Dropout, Dense\nfrom tensorflow.keras.models import Model\n\ndef build_cam_model():\n    inputs = Input(shape=(256, 256, 3))\n    \n    base_model = tf.keras.applications.MobileNetV2(\n        input_shape=(256, 256, 3),\n        include_top=False,\n        weights='imagenet',\n        input_tensor=inputs\n    )\n    base_model.trainable = True\n    \n    # Get feature maps from the last conv layer\n    last_conv_layer_name = 'Conv_1'  # Update if necessary\n    last_conv_layer = base_model.get_layer(last_conv_layer_name)\n    feature_maps = last_conv_layer.output\n    \n    # Classification head\n    x = base_model.output\n    x = GlobalAveragePooling2D()(x)\n    x = Dropout(0.3)(x)\n    predictions = Dense(1, activation='sigmoid', name='predictions')(x)\n    \n    # Create the model\n    model = Model(inputs=inputs, outputs=[predictions, feature_maps])\n    \n    return model\n\nmodel = build_cam_model()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:14.733210Z","iopub.execute_input":"2024-11-21T05:42:14.733460Z","iopub.status.idle":"2024-11-21T05:42:15.664507Z","shell.execute_reply.started":"2024-11-21T05:42:14.733423Z","shell.execute_reply":"2024-11-21T05:42:15.663906Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df=pd.read_csv(\"../input/jpeg-melanoma-256x256/train.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:15.665422Z","iopub.execute_input":"2024-11-21T05:42:15.665662Z","iopub.status.idle":"2024-11-21T05:42:15.754894Z","shell.execute_reply.started":"2024-11-21T05:42:15.665637Z","shell.execute_reply":"2024-11-21T05:42:15.754124Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df # we will use only image_name and target","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:15.755948Z","iopub.execute_input":"2024-11-21T05:42:15.756191Z","iopub.status.idle":"2024-11-21T05:42:15.782795Z","shell.execute_reply.started":"2024-11-21T05:42:15.756167Z","shell.execute_reply":"2024-11-21T05:42:15.781891Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\na,b=np.unique(df[\"target\"],return_counts=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:15.783824Z","iopub.execute_input":"2024-11-21T05:42:15.784069Z","iopub.status.idle":"2024-11-21T05:42:15.789653Z","shell.execute_reply.started":"2024-11-21T05:42:15.784046Z","shell.execute_reply":"2024-11-21T05:42:15.788622Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"a","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:15.790809Z","iopub.execute_input":"2024-11-21T05:42:15.791050Z","iopub.status.idle":"2024-11-21T05:42:15.798110Z","shell.execute_reply.started":"2024-11-21T05:42:15.791026Z","shell.execute_reply":"2024-11-21T05:42:15.797466Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"b # 32542 negative image and only 584 positive image\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:15.799029Z","iopub.execute_input":"2024-11-21T05:42:15.799233Z","iopub.status.idle":"2024-11-21T05:42:15.807109Z","shell.execute_reply.started":"2024-11-21T05:42:15.799214Z","shell.execute_reply":"2024-11-21T05:42:15.806159Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# split train dataframe into training and validation","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:15.808168Z","iopub.execute_input":"2024-11-21T05:42:15.808500Z","iopub.status.idle":"2024-11-21T05:42:15.816883Z","shell.execute_reply.started":"2024-11-21T05:42:15.808469Z","shell.execute_reply":"2024-11-21T05:42:15.816251Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\ntrain,valid=train_test_split(df,test_size=0.2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:15.817852Z","iopub.execute_input":"2024-11-21T05:42:15.818046Z","iopub.status.idle":"2024-11-21T05:42:16.465881Z","shell.execute_reply.started":"2024-11-21T05:42:15.818027Z","shell.execute_reply":"2024-11-21T05:42:16.465243Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\ntrain,test=train_test_split(train,test_size=0.01)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:16.466851Z","iopub.execute_input":"2024-11-21T05:42:16.467065Z","iopub.status.idle":"2024-11-21T05:42:16.475891Z","shell.execute_reply.started":"2024-11-21T05:42:16.467044Z","shell.execute_reply":"2024-11-21T05:42:16.475247Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train[\"image_name_jpg\"]=train[\"image_name\"]+\".jpg\"\ntest[\"image_name_jpg\"]=test[\"image_name\"]+\".jpg\"\nvalid[\"image_name_jpg\"]=valid[\"image_name\"]+\".jpg\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:16.476943Z","iopub.execute_input":"2024-11-21T05:42:16.477165Z","iopub.status.idle":"2024-11-21T05:42:16.504007Z","shell.execute_reply.started":"2024-11-21T05:42:16.477142Z","shell.execute_reply":"2024-11-21T05:42:16.503375Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# now convert target in string\ntrain[\"target\"]=train[\"target\"].astype(str)\ntest[\"target\"]=test[\"target\"].astype(str)\nvalid[\"target\"]=valid[\"target\"].astype(str)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:16.504972Z","iopub.execute_input":"2024-11-21T05:42:16.505165Z","iopub.status.idle":"2024-11-21T05:42:16.532012Z","shell.execute_reply.started":"2024-11-21T05:42:16.505145Z","shell.execute_reply":"2024-11-21T05:42:16.531118Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# now create train_generator and validation_generator\n# you can add other augmentation example vertical_flip, random cropping ,etc to get bettter accuracy\ntrain_datagen=tf.keras.preprocessing.image.ImageDataGenerator(\n    rescale=1/255,\n    horizontal_flip=True\n    )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:16.533093Z","iopub.execute_input":"2024-11-21T05:42:16.533437Z","iopub.status.idle":"2024-11-21T05:42:16.536896Z","shell.execute_reply.started":"2024-11-21T05:42:16.533382Z","shell.execute_reply":"2024-11-21T05:42:16.536198Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_datagen=tf.keras.preprocessing.image.ImageDataGenerator(rescale=1/255) # we have to divide by 255 for testing in android app","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:16.538032Z","iopub.execute_input":"2024-11-21T05:42:16.538376Z","iopub.status.idle":"2024-11-21T05:42:16.546742Z","shell.execute_reply.started":"2024-11-21T05:42:16.538343Z","shell.execute_reply":"2024-11-21T05:42:16.546100Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_generator =train_datagen.flow_from_dataframe(\n    dataframe=train,\n    directory=\"../input/jpeg-melanoma-256x256/train/\",\n    x_col=\"image_name_jpg\", # name +\".jpg\"\n    y_col=\"target\",\n    target_size=(256,256),\n    batch_size=32,\n    class_mode=\"binary\"\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:42:16.547670Z","iopub.execute_input":"2024-11-21T05:42:16.547894Z","iopub.status.idle":"2024-11-21T05:43:10.968193Z","shell.execute_reply.started":"2024-11-21T05:42:16.547866Z","shell.execute_reply":"2024-11-21T05:43:10.967333Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"validation_generator =test_datagen.flow_from_dataframe(\n    dataframe=valid,\n    directory=\"../input/jpeg-melanoma-256x256/train/\",\n    x_col=\"image_name_jpg\",\n    y_col=\"target\",\n    target_size=(256,256),\n    batch_size=16,\n    class_mode=\"binary\"\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:43:10.969613Z","iopub.execute_input":"2024-11-21T05:43:10.969962Z","iopub.status.idle":"2024-11-21T05:43:25.728802Z","shell.execute_reply.started":"2024-11-21T05:43:10.969926Z","shell.execute_reply":"2024-11-21T05:43:25.727948Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"optimizer = keras.optimizers.Adam(learning_rate=0.00005)\nmodel.compile(\n    optimizer=optimizer,\n    loss={'predictions': 'binary_crossentropy'},\n    metrics={'predictions': tf.keras.metrics.AUC(name='auc')}\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:43:25.730090Z","iopub.execute_input":"2024-11-21T05:43:25.730442Z","iopub.status.idle":"2024-11-21T05:43:25.757780Z","shell.execute_reply.started":"2024-11-21T05:43:25.730404Z","shell.execute_reply":"2024-11-21T05:43:25.757073Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def adjust_generator(generator):\n    while True:\n        batch = next(generator)\n        images, labels = batch\n        # Create dummy labels for feature maps (they won't be used)\n        dummy_labels = np.zeros((labels.shape[0],))  # Or any shape that matches the feature maps\n        yield images, {'predictions': labels, 'feature_maps': dummy_labels}\n\ntrain_generator_adj = adjust_generator(train_generator)\nvalidation_generator_adj = adjust_generator(validation_generator)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:43:25.758655Z","iopub.execute_input":"2024-11-21T05:43:25.758861Z","iopub.status.idle":"2024-11-21T05:43:25.763035Z","shell.execute_reply.started":"2024-11-21T05:43:25.758841Z","shell.execute_reply":"2024-11-21T05:43:25.762210Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.fit(\n    train_generator,\n    epochs=3,\n    validation_data=validation_generator\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:43:25.764166Z","iopub.execute_input":"2024-11-21T05:43:25.764411Z","iopub.status.idle":"2024-11-21T05:53:17.479115Z","shell.execute_reply.started":"2024-11-21T05:43:25.764368Z","shell.execute_reply":"2024-11-21T05:53:17.478127Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# This is most basic version of training with decent accuracy ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:53:17.480433Z","iopub.execute_input":"2024-11-21T05:53:17.480710Z","iopub.status.idle":"2024-11-21T05:53:17.483954Z","shell.execute_reply.started":"2024-11-21T05:53:17.480679Z","shell.execute_reply":"2024-11-21T05:53:17.483211Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# After 3 epoch it start to overfit \n#When the training is done save model in tflite formate which is much faster but accuracy decreases\nconverter=tf.lite.TFLiteConverter.from_keras_model(model)\ntflite_model=converter.convert()\n# save model\nwith open (\"model.tflite\",\"wb\") as f:\n    f.write(tflite_model)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T05:53:17.485321Z","iopub.execute_input":"2024-11-21T05:53:17.485606Z","iopub.status.idle":"2024-11-21T05:53:39.812243Z","shell.execute_reply.started":"2024-11-21T05:53:17.485575Z","shell.execute_reply":"2024-11-21T05:53:39.811572Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.layers import Input, GlobalAveragePooling2D, Dropout, Dense\nfrom tensorflow.keras.models import Model\nimport numpy as np\n\ndef build_cam_model():\n    inputs = Input(shape=(256, 256, 3))\n    \n    base_model = tf.keras.applications.MobileNetV2(\n        input_shape=(256, 256, 3),\n        include_top=False,\n        weights='imagenet',\n        input_tensor=inputs\n    )\n    base_model.trainable = True\n    \n    # Get feature maps from the last conv layer\n    last_conv_layer_name = 'out_relu'  # Correct layer name for MobileNetV2\n    last_conv_layer = base_model.get_layer(last_conv_layer_name)\n    feature_maps = last_conv_layer.output\n    \n    # Classification head\n    x = base_model.output\n    x = GlobalAveragePooling2D()(x)\n    x = Dropout(0.3)(x)\n    predictions = Dense(1, activation='sigmoid', name='predictions')(x)\n    \n    # Create the model\n    model = Model(inputs=inputs, outputs=[predictions, feature_maps])\n    \n    return model\n\n# Build the model\nmodel = build_cam_model()\n\n# Compile the model\nmodel.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])\n\n# (Optional) Train the model\n# Replace 'train_data' and 'validation_data' with your actual datasets\n# history = model.fit(train_data, epochs=10, validation_data=validation_data)\n\n# After training (or loading pre-trained weights), extract the class weights\nclassification_layer = model.get_layer('predictions')\nweights, biases = classification_layer.get_weights()\n\n# Flatten the weights to create a 1D array\nweights = weights.flatten()\n\n# Verify shapes\nprint(\"Weights shape:\", weights.shape)  # Should be (num_channels,)\nprint(\"Expected number of weights (channels):\", model.get_layer('out_relu').output_shape[-1])\n\n# Save the weights to 'class_weights.txt'\nnp.savetxt('class_weights.txt', weights, fmt='%f')\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T18:08:13.232237Z","iopub.execute_input":"2024-11-21T18:08:13.232620Z","iopub.status.idle":"2024-11-21T18:08:22.590505Z","shell.execute_reply.started":"2024-11-21T18:08:13.232535Z","shell.execute_reply":"2024-11-21T18:08:22.589777Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"weights = np.loadtxt('class_weights.txt')\nprint(\"Number of weights in class_weights.txt:\", len(weights))\n# Should output: Number of weights in class_weights.txt: 1280\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-21T18:08:44.013386Z","iopub.execute_input":"2024-11-21T18:08:44.013731Z","iopub.status.idle":"2024-11-21T18:08:44.054144Z","shell.execute_reply.started":"2024-11-21T18:08:44.013698Z","shell.execute_reply":"2024-11-21T18:08:44.053401Z"}},"outputs":[],"execution_count":null}]}