{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":91448,"databundleVersionId":11249847,"sourceType":"competition"}],"dockerImageVersionId":31011,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:02:27.639977Z","iopub.execute_input":"2025-05-01T16:02:27.640477Z","iopub.status.idle":"2025-05-01T16:02:28.754495Z","shell.execute_reply.started":"2025-05-01T16:02:27.640453Z","shell.execute_reply":"2025-05-01T16:02:28.753916Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data = pd.read_csv(\"/kaggle/input/fungi-clef-2025/metadata/FungiTastic-FewShot/FungiTastic-FewShot-Train.csv\")\ntrain_data.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:02:28.755777Z","iopub.execute_input":"2025-05-01T16:02:28.756337Z","iopub.status.idle":"2025-05-01T16:02:28.898182Z","shell.execute_reply.started":"2025-05-01T16:02:28.756315Z","shell.execute_reply":"2025-05-01T16:02:28.897544Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"validation_data = pd.read_csv(\"/kaggle/input/fungi-clef-2025/metadata/FungiTastic-FewShot/FungiTastic-FewShot-Val.csv\")\ntest_data = pd.read_csv(\"/kaggle/input/fungi-clef-2025/metadata/FungiTastic-FewShot/FungiTastic-FewShot-Test.csv\")\n\ntest_data.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:02:28.898985Z","iopub.execute_input":"2025-05-01T16:02:28.899221Z","iopub.status.idle":"2025-05-01T16:02:28.973509Z","shell.execute_reply.started":"2025-05-01T16:02:28.899196Z","shell.execute_reply":"2025-05-01T16:02:28.972739Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Length of train data before merger:\", len(train_data))\ntrain_data = pd.concat([train_data, validation_data], axis=0)\nprint(\"Length of train data after merger:\", len(train_data))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:02:28.975440Z","iopub.execute_input":"2025-05-01T16:02:28.975700Z","iopub.status.idle":"2025-05-01T16:02:28.983719Z","shell.execute_reply.started":"2025-05-01T16:02:28.975656Z","shell.execute_reply":"2025-05-01T16:02:28.983035Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"numeric_cols = []\nobject_cols = []\nfor i in train_data.columns:\n    if train_data[i].dtypes == \"int64\" or train_data[i].dtypes == \"float64\":\n        numeric_cols.append(i)\n    else:\n        object_cols.append(i)\nnumeric_cols, object_cols","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:02:28.984403Z","iopub.execute_input":"2025-05-01T16:02:28.984714Z","iopub.status.idle":"2025-05-01T16:02:28.999765Z","shell.execute_reply.started":"2025-05-01T16:02:28.984665Z","shell.execute_reply":"2025-05-01T16:02:28.999025Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_numeric = train_data.loc[:, numeric_cols]\ndf_numeric.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:02:29.000434Z","iopub.execute_input":"2025-05-01T16:02:29.000636Z","iopub.status.idle":"2025-05-01T16:02:29.026711Z","shell.execute_reply.started":"2025-05-01T16:02:29.000619Z","shell.execute_reply":"2025-05-01T16:02:29.025892Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"object_df = train_data.loc[:, object_cols]\nobject_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:02:29.027983Z","iopub.execute_input":"2025-05-01T16:02:29.028789Z","iopub.status.idle":"2025-05-01T16:02:29.047732Z","shell.execute_reply.started":"2025-05-01T16:02:29.028742Z","shell.execute_reply":"2025-05-01T16:02:29.047045Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"less_uniques_in_object_cols = []\nfor i in object_cols:\n    print(i)\n    u = len(train_data[i].unique())\n    if u <= 20:\n        print(\"Uniques: \", train_data[i].unique())\n        less_uniques_in_object_cols.append(i)\n    else:\n        print(\"Number of uniques: \", u)\n    print(\"++++++++++++++++\\n\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:02:29.048494Z","iopub.execute_input":"2025-05-01T16:02:29.048740Z","iopub.status.idle":"2025-05-01T16:02:29.072698Z","shell.execute_reply.started":"2025-05-01T16:02:29.048709Z","shell.execute_reply":"2025-05-01T16:02:29.072172Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"less_uniques_in_object_cols.remove(\"hasCoordinate\")\nless_uniques_in_object_cols","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:02:29.073375Z","iopub.execute_input":"2025-05-01T16:02:29.073614Z","iopub.status.idle":"2025-05-01T16:02:29.078410Z","shell.execute_reply.started":"2025-05-01T16:02:29.073593Z","shell.execute_reply":"2025-05-01T16:02:29.077861Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimages_dic_wrt_category_id = {}\niteration_train_data = train_data.loc[:, [\"category_id\", \"filename\"]]\ntrain_image_folder_path = \"/kaggle/input/fungi-clef-2025/images/FungiTastic-FewShot/train/300p\"\nval_image_folder_path = \"/kaggle/input/fungi-clef-2025/images/FungiTastic-FewShot/val/300p\"\ntrain_image_paths = os.listdir(train_image_folder_path)\nfor idx, row in iteration_train_data.iterrows():\n    if row[\"filename\"] not in train_image_paths:\n        filename = os.path.join(val_image_folder_path, row[\"filename\"])\n    else:\n        filename = os.path.join(train_image_folder_path, row[\"filename\"])\n\n    if row[\"category_id\"] not in images_dic_wrt_category_id.keys():\n        images_dic_wrt_category_id[row[\"category_id\"]] = [filename]\n    else:\n        images_dic_wrt_category_id[row[\"category_id\"]].append(filename)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:02:29.080141Z","iopub.execute_input":"2025-05-01T16:02:29.080337Z","iopub.status.idle":"2025-05-01T16:02:30.415124Z","shell.execute_reply.started":"2025-05-01T16:02:29.080324Z","shell.execute_reply":"2025-05-01T16:02:30.414257Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"category_val_counts = train_data.loc[:, [\"category_id\"]].value_counts().reset_index()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:02:30.416106Z","iopub.execute_input":"2025-05-01T16:02:30.416388Z","iopub.status.idle":"2025-05-01T16:02:30.423879Z","shell.execute_reply.started":"2025-05-01T16:02:30.416362Z","shell.execute_reply":"2025-05-01T16:02:30.423246Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class_to_augment = category_val_counts[category_val_counts[\"count\"]<5][\"category_id\"].tolist()\nclass_to_augment[:5]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:02:30.424584Z","iopub.execute_input":"2025-05-01T16:02:30.424867Z","iopub.status.idle":"2025-05-01T16:02:30.438029Z","shell.execute_reply.started":"2025-05-01T16:02:30.424843Z","shell.execute_reply":"2025-05-01T16:02:30.437202Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport numpy as np\nimport shutil\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:02:30.438860Z","iopub.execute_input":"2025-05-01T16:02:30.439052Z","iopub.status.idle":"2025-05-01T16:02:45.252534Z","shell.execute_reply.started":"2025-05-01T16:02:30.439038Z","shell.execute_reply":"2025-05-01T16:02:45.251946Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"num_augmented_image = 5\ndatagen = ImageDataGenerator(\n    rotation_range=30, \n    width_shift_range=0.2,\n    height_shift_range=0.2,\n    shear_range=0.2,\n    zoom_range=0.2,\n    horizontal_flip=True,\n)\n\noutput_dir = \"/kaggle/working/dataset\"\nos.makedirs(output_dir, exist_ok=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:02:45.253223Z","iopub.execute_input":"2025-05-01T16:02:45.253648Z","iopub.status.idle":"2025-05-01T16:02:45.258170Z","shell.execute_reply.started":"2025-05-01T16:02:45.253630Z","shell.execute_reply":"2025-05-01T16:02:45.257422Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import cv2\nfor label, image_list in images_dic_wrt_category_id.items():\n    output_path = os.path.join(output_dir, str(label))\n    os.makedirs(output_path, exist_ok=True)\n    if int(label) not in class_to_augment:\n        a=0\n        for image_path in image_list:\n            img = cv2.imread(image_path)\n            cv2.imwrite(os.path.join(output_path, os.path.basename(image_path)), img)\n            a+=1\n            if a==5:\n                break\n\n    else:\n        number_of_images = len(image_list)\n        for image_path in image_list:\n            img = cv2.imread(image_path)\n            img_array = np.expand_dims(img, axis=0)\n            cv2.imwrite(os.path.join(output_path, os.path.basename(image_path)), img)\n        i=number_of_images\n        for batch in datagen.flow(img_array, batch_size=1, save_to_dir=output_path, save_prefix=\"aug\", save_format=\"jpg\"):\n            i+=1\n            if i>=5:\n                break","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:02:45.259006Z","iopub.execute_input":"2025-05-01T16:02:45.259624Z","iopub.status.idle":"2025-05-01T16:05:19.072529Z","shell.execute_reply.started":"2025-05-01T16:02:45.259601Z","shell.execute_reply":"2025-05-01T16:05:19.071614Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install ftfy regex tqdm git+https://github.com/openai/CLIP.git","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:06:47.811015Z","iopub.execute_input":"2025-05-01T16:06:47.811601Z","iopub.status.idle":"2025-05-01T16:06:52.990554Z","shell.execute_reply.started":"2025-05-01T16:06:47.811569Z","shell.execute_reply":"2025-05-01T16:06:52.989468Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport clip\nimport torch\nfrom PIL import Image\nfrom tqdm import tqdm\nimport numpy as np\nfrom sklearn.metrics.pairwise import cosine_similarity","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:07:30.619541Z","iopub.execute_input":"2025-05-01T16:07:30.620356Z","iopub.status.idle":"2025-05-01T16:07:37.898311Z","shell.execute_reply.started":"2025-05-01T16:07:30.620328Z","shell.execute_reply":"2025-05-01T16:07:37.897620Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\nmodel, preprocess = clip.load(\"ViT-B/32\", device=device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:08:12.029398Z","iopub.execute_input":"2025-05-01T16:08:12.030052Z","iopub.status.idle":"2025-05-01T16:08:23.556174Z","shell.execute_reply.started":"2025-05-01T16:08:12.030026Z","shell.execute_reply":"2025-05-01T16:08:23.555542Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"DATASET_PATH = \"/kaggle/working/dataset\"\n\n# Dict to hold class prototypes\nclass_prototypes = {}\n\ndef get_embedding(image_path):\n    try:\n        image = preprocess(Image.open(image_path).convert(\"RGB\")).unsqueeze(0).to(device)\n        with torch.no_grad():\n            embedding = model.encode_image(image)\n        return embedding.squeeze().cpu().numpy()\n    except Exception as e:\n        print(f\"Error processing {image_path}: {e}\")\n        return None","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:09:21.276288Z","iopub.execute_input":"2025-05-01T16:09:21.277035Z","iopub.status.idle":"2025-05-01T16:09:21.281700Z","shell.execute_reply.started":"2025-05-01T16:09:21.277008Z","shell.execute_reply":"2025-05-01T16:09:21.280846Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for class_name in tqdm(os.listdir(DATASET_PATH), desc=\"Building prototypes\"):\n    class_dir = os.path.join(DATASET_PATH, class_name)\n    if not os.path.isdir(class_dir): continue\n\n    embeddings = []\n    for image_file in os.listdir(class_dir):\n        image_path = os.path.join(class_dir, image_file)\n        emb = get_embedding(image_path)\n        if emb is not None:\n            embeddings.append(emb)\n\n    if len(embeddings) >= 1:\n        prototype = np.mean(embeddings, axis=0)\n        class_prototypes[class_name] = prototype\n    else:\n        print(f\"Skipping {class_name}: no valid embeddings\")\n\nprint(f\"Built prototypes for {len(class_prototypes)} classes.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:10:50.084869Z","iopub.execute_input":"2025-05-01T16:10:50.085519Z","iopub.status.idle":"2025-05-01T16:13:19.464265Z","shell.execute_reply.started":"2025-05-01T16:10:50.085498Z","shell.execute_reply":"2025-05-01T16:13:19.463337Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"embeddings[0]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:14:03.964820Z","iopub.execute_input":"2025-05-01T16:14:03.965124Z","iopub.status.idle":"2025-05-01T16:14:03.974271Z","shell.execute_reply.started":"2025-05-01T16:14:03.965103Z","shell.execute_reply":"2025-05-01T16:14:03.973615Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"a = 0\nfor i in os.listdir(DATASET_PATH):\n    print(i)\n    a+=1\n    if a%5==0:\n        break","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:16:48.485026Z","iopub.execute_input":"2025-05-01T16:16:48.485363Z","iopub.status.idle":"2025-05-01T16:16:48.491922Z","shell.execute_reply.started":"2025-05-01T16:16:48.485326Z","shell.execute_reply":"2025-05-01T16:16:48.491202Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def classify_image(test_image_path, top_k=10):\n    test_emb = get_embedding(test_image_path).reshape(1, -1)\n    all_classes = list(class_prototypes.keys())\n    all_prototypes = np.vstack([class_prototypes[c] for c in all_classes])\n\n    similarities = cosine_similarity(test_emb, all_prototypes)[0]\n    top_indices = similarities.argsort()[::-1][:top_k]\n\n    results = [(all_classes[i], similarities[i]) for i in top_indices]\n    return results","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:26:24.829495Z","iopub.execute_input":"2025-05-01T16:26:24.829832Z","iopub.status.idle":"2025-05-01T16:26:24.835596Z","shell.execute_reply.started":"2025-05-01T16:26:24.829808Z","shell.execute_reply":"2025-05-01T16:26:24.834975Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_path = os.path.join(DATASET_PATH, \"130\")\ntest_path = os.path.join(test_path, os.listdir(test_path)[0])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:26:26.239200Z","iopub.execute_input":"2025-05-01T16:26:26.240117Z","iopub.status.idle":"2025-05-01T16:26:26.279348Z","shell.execute_reply.started":"2025-05-01T16:26:26.240080Z","shell.execute_reply":"2025-05-01T16:26:26.278556Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"results = classify_image(test_path)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:32:53.595155Z","iopub.execute_input":"2025-05-01T16:32:53.595924Z","iopub.status.idle":"2025-05-01T16:32:53.630414Z","shell.execute_reply.started":"2025-05-01T16:32:53.595906Z","shell.execute_reply":"2025-05-01T16:32:53.629637Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:32:59.904661Z","iopub.execute_input":"2025-05-01T16:32:59.905419Z","iopub.status.idle":"2025-05-01T16:32:59.910628Z","shell.execute_reply.started":"2025-05-01T16:32:59.905397Z","shell.execute_reply":"2025-05-01T16:32:59.909818Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_data.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:28:59.334793Z","iopub.execute_input":"2025-05-01T16:28:59.335061Z","iopub.status.idle":"2025-05-01T16:28:59.351772Z","shell.execute_reply.started":"2025-05-01T16:28:59.335045Z","shell.execute_reply":"2025-05-01T16:28:59.350697Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_data_path = \"/kaggle/input/fungi-clef-2025/images/FungiTastic-FewShot/test/300p\"\nresult_dic = {}\nfor oID, filename in test_data.loc[:, [\"observationID\", \"filename\"]].values:\n    test_image_path = os.path.join(test_data_path, filename)\n    results = classify_image(test_image_path)\n    r = []\n    for res in results:\n        r.append(res[0])\n    top_10_class = \" \".join(r)\n    result_dic[oID] = top_10_class","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:40:17.115257Z","iopub.execute_input":"2025-05-01T16:40:17.115538Z","iopub.status.idle":"2025-05-01T16:41:28.050894Z","shell.execute_reply.started":"2025-05-01T16:40:17.115519Z","shell.execute_reply":"2025-05-01T16:41:28.050096Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"result_dic","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:36:06.239427Z","iopub.execute_input":"2025-05-01T16:36:06.240087Z","iopub.status.idle":"2025-05-01T16:36:06.245472Z","shell.execute_reply.started":"2025-05-01T16:36:06.240056Z","shell.execute_reply":"2025-05-01T16:36:06.244582Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sub_df = pd.DataFrame(list(result_dic.items()), columns=[\"observationId\", \"predictions\"])\nsub_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:41:54.934924Z","iopub.execute_input":"2025-05-01T16:41:54.935510Z","iopub.status.idle":"2025-05-01T16:41:54.944568Z","shell.execute_reply.started":"2025-05-01T16:41:54.935484Z","shell.execute_reply":"2025-05-01T16:41:54.943772Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sub_df.to_csv(\"submission.csv\", index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-01T16:42:18.080168Z","iopub.execute_input":"2025-05-01T16:42:18.080432Z","iopub.status.idle":"2025-05-01T16:42:18.094267Z","shell.execute_reply.started":"2025-05-01T16:42:18.080413Z","shell.execute_reply":"2025-05-01T16:42:18.093659Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}