{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":94147,"databundleVersionId":11390004,"sourceType":"competition"}],"dockerImageVersionId":30918,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\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# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-03-18T11:40:09.168174Z","iopub.execute_input":"2025-03-18T11:40:09.168721Z","iopub.status.idle":"2025-03-18T11:40:09.600001Z","shell.execute_reply.started":"2025-03-18T11:40:09.168673Z","shell.execute_reply":"2025-03-18T11:40:09.598861Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import h5py\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom sklearn.preprocessing import StandardScaler\nfrom sklearn.cluster import KMeans\nfrom sklearn.neighbors import NearestNeighbors\nfrom sklearn.model_selection import train_test_split\nfrom lightgbm import LGBMRegressor\nfrom sklearn.multioutput import MultiOutputRegressor\nimport optuna\n\ndef load_h5_data(file_path, dataset_path):\n    with h5py.File(file_path, \"r\") as h5file:\n        return {key: np.array(h5file[dataset_path][key]) for key in h5file[dataset_path].keys()}\n\nfile_path = \"/kaggle/input/el-hackathon-2025/elucidata_ai_challenge_data.h5\"\ntrain_images = load_h5_data(file_path, \"images/Train\")\ntrain_spots = load_h5_data(file_path, \"spots/Train\")\ntest_images = load_h5_data(file_path, \"images/Test\")\ntest_spots = load_h5_data(file_path, \"spots/Test\")\n\ndef create_spot_tables(spots_data):\n    return {slide: pd.DataFrame(spots_data[slide]) for slide in spots_data}\n\ntrain_spot_tables = create_spot_tables(train_spots)\ntest_spot_table = pd.DataFrame(test_spots['S_7'])\n\ndef add_features(df, n_clusters=10):\n    kmeans = KMeans(n_clusters=n_clusters, n_init=10, random_state=42)\n    df['cluster'] = kmeans.fit_predict(df[['x', 'y']])\n    df['density'] = df.groupby('cluster')['x'].transform('count')\n    \n    # Calculate distance from slide center\n    center_x, center_y = df['x'].mean(), df['y'].mean()\n    df['distance_to_center'] = np.sqrt((df['x'] - center_x)**2 + (df['y'] - center_y)**2)\n    \n    # Nearest neighbor distance\n    nn = NearestNeighbors(n_neighbors=2)\n    nn.fit(df[['x', 'y']])\n    distances, _ = nn.kneighbors(df[['x', 'y']])\n    df['nearest_neighbor_dist'] = distances[:, 1]  # Second closest point (self is closest)\n    \n    # Local spot density (spots within a 50-pixel radius)\n    nn_radius = NearestNeighbors(radius=50)\n    nn_radius.fit(df[['x', 'y']])\n    density_within_radius = nn_radius.radius_neighbors_graph(df[['x', 'y']]).sum(axis=1)\n    df['local_density'] = np.array(density_within_radius).flatten()\n    \n    return df\n\ntrain_data = pd.concat(train_spot_tables.values())\ntrain_data = add_features(train_data)\ntest_spot_table = add_features(test_spot_table)\n\nX = train_data[['x', 'y', 'cluster', 'density', 'distance_to_center', 'nearest_neighbor_dist', 'local_density']]\ny = train_data.iloc[:, 2:-5]\n\nscaler = StandardScaler()\nX_scaled = scaler.fit_transform(X)\nX_test_scaled = scaler.transform(test_spot_table[['x', 'y', 'cluster', 'density', 'distance_to_center', 'nearest_neighbor_dist', 'local_density']])\n\nX_train, X_val, y_train, y_val = train_test_split(X_scaled, y, test_size=0.2, random_state=42)\n\ndef objective(trial):\n    params = {\n        'n_estimators': trial.suggest_int('n_estimators', 1000, 3000),\n        'learning_rate': trial.suggest_float('learning_rate', 0.005, 0.05),\n        'max_depth': trial.suggest_int('max_depth', 7, 20),\n        'num_leaves': trial.suggest_int('num_leaves', 31, 150),\n        'min_child_samples': trial.suggest_int('min_child_samples', 2, 50)\n    }\n    model = MultiOutputRegressor(LGBMRegressor(**params, random_state=42))\n    model.fit(X_train, y_train)\n    return -model.score(X_val, y_val)\n\nstudy = optuna.create_study()\nstudy.optimize(objective, n_trials=50)\nbest_params = study.best_params\n\nlgb_model = MultiOutputRegressor(LGBMRegressor(**best_params, random_state=42))\nlgb_model.fit(X_scaled, y)\n\npredictions = lgb_model.predict(X_test_scaled)\npredicted_labels = pd.DataFrame(predictions, columns=y.columns)\n\nsubmission_df = predicted_labels.copy()\nsubmission_df.insert(0, 'ID', test_spot_table.index)\nsubmission_df.to_csv(\"./submission.csv\", index=False)\nprint(\"Submission file created!\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-18T11:40:09.601015Z","iopub.execute_input":"2025-03-18T11:40:09.601512Z"}},"outputs":[],"execution_count":null}]}