{"cells":[{"metadata":{},"cell_type":"markdown","source":"This notebook aims to use simple percent features calculated from `train_label_masks` to predict `isup_grade`.\nThe idea is from this discussion: https://www.kaggle.com/c/prostate-cancer-grade-assessment/discussion/145144\n\nThey first train a stage-1 segmentation model to predict masks (similar to mask provided by radboud in this competition), then use kNN as stage-2 classifier.\nSo I wonder how well the simple classifiers can perform using the percent features, and the results is this notebook:\n\n5-fold cross-validation QWK scores in training data provided by radboud.\n* kNN: 0.85+\n* RFC: 0.91+\n* lightgbm: 0.94+\n\nAdding count features:\n* kNN: 0.73+\n* RFC: 0.94+\n* lightgbm: 0.94+\n\nThis may provide some information for those who want to train segmentation models."},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import os\nimport gc\nimport sys\nimport cv2\nimport glob\nimport time\nimport signal\nimport shutil\nimport numpy as np\nimport pandas as pd\nfrom collections import OrderedDict, Counter\n\nfrom PIL import Image\nimport skimage.io\nimport cv2\nimport matplotlib.pyplot as plt\n\nfrom sklearn.metrics import cohen_kappa_score\nfrom sklearn.model_selection import StratifiedKFold\n\nfrom tqdm.notebook import tqdm","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"DATA = \"/kaggle/input/prostate-cancer-grade-assessment\"\ngls2isu = {\"0+0\":0,'negative':0,'3+3':1,'3+4':2,'4+3':3,'4+4':4,'3+5':4,'5+3':4,'4+5':5,'5+4':5,'5+5':5}","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train = pd.read_csv(os.path.join(DATA, \"train.csv\"))\ndf_train = df_train[df_train.data_provider == 'radboud']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def extract_features(mask):\n    counts = []\n    for i in range(1,6):\n        counts.append(np.count_nonzero(mask == i))\n    percents = np.array(counts).astype(np.float32)\n    percents /= percents.sum()\n    return counts, percents\n\ndef quadratic_weighted_kappa(y_hat, y):\n    return cohen_kappa_score(y_hat, y, weights='quadratic')\n\nfor label in range(1,6):\n    df_train[f'percent_{label}'] = None\n    df_train[f'count_{label}'] = None\n    \nfor i in tqdm(range(len(df_train))):\n    idx = df_train.iloc[i, 0]\n    isup = df_train.iloc[i, 2]\n    gleason = df_train.iloc[i, 3]\n    \n    mask_file = os.path.join(DATA, 'train_label_masks', f'{idx}_mask.tiff')\n    if os.path.exists(mask_file):\n        mask = skimage.io.MultiImage(mask_file)\n        mask = np.array(mask[2]) # smallest resolution\n        cnt, feat = extract_features(mask)\n        for label in range(1,6):\n            df_train[f'count_{label}'].iloc[i] = cnt[label-1]\n            df_train[f'percent_{label}'].iloc[i] = feat[label-1]\n    else:\n        continue","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train = df_train.replace(to_replace='None', value=np.nan).dropna()\ndf_train.reset_index(drop=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"skf = StratifiedKFold(5, shuffle=True, random_state=42)\nsplits = list(skf.split(df_train, df_train.isup_grade))\n\n#features = [f\"percent_{label}\" for label in range(1, 6)] \nfeatures = [f\"percent_{label}\" for label in range(1, 6)] + [f\"count_{label}\" for label in range(1, 6)]\ntarget = 'isup_grade'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# kNN\nfrom sklearn.neighbors import KNeighborsClassifier\n\nscores = []\nfor fold in range(5):\n    train = df_train.iloc[splits[fold][0]]\n    valid = df_train.iloc[splits[fold][1]]\n    \n    model = KNeighborsClassifier(n_neighbors=5)\n    \n    model.fit(train[features], train[target])\n    \n    preds = model.predict(valid[features])\n    \n    score = quadratic_weighted_kappa(preds, valid[target])\n    scores.append(score)\n    print(f\"Fold = {fold}, QWK = {score:.4f}\")\n    \nprint(f\"Mean = {np.mean(scores):.4f}\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# rfc\nfrom sklearn.ensemble import RandomForestClassifier\n\nscores = []\nfor fold in range(5):\n    train = df_train.iloc[splits[fold][0]]\n    valid = df_train.iloc[splits[fold][1]]\n    \n    model = RandomForestClassifier(random_state=42)\n    \n    model.fit(train[features], train[target])\n    \n    preds = model.predict(valid[features])\n    \n    score = quadratic_weighted_kappa(preds, valid[target])\n    scores.append(score)\n    print(f\"Fold = {fold}, QWK = {score:.4f}\")\n    \nprint(f\"Mean = {np.mean(scores):.4f}\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# lgb\nimport lightgbm as lgb\n\ndef QWK(preds, dtrain):\n    labels = dtrain.get_label()\n    preds = np.rint(preds)\n    score = quadratic_weighted_kappa(preds, labels)\n    return (\"QWK\", score, True)\n\nscores = []\nfor fold in range(5):\n    train = df_train.iloc[splits[fold][0]]\n    valid = df_train.iloc[splits[fold][1]]\n    \n    train_dataset = lgb.Dataset(train[features], train[target])\n    valid_dataset = lgb.Dataset(valid[features], valid[target])\n    \n    params = {\n                \"objective\": 'regression',\n                \"metric\": 'rmse',\n                \"seed\": 42,\n                \"learning_rate\": 0.01,\n                \"boosting\": \"gbdt\",\n            }\n        \n    model = lgb.train(\n                params=params,\n                num_boost_round=1000,\n                early_stopping_rounds=200,\n                train_set=train_dataset,\n                valid_sets=[train_dataset, valid_dataset],\n                verbose_eval=100,\n                feval=QWK,\n            )\n        \n    \n    preds = model.predict(valid[features], num_iteration=model.best_iteration)\n    preds = np.rint(preds)\n    \n    score = quadratic_weighted_kappa(preds, valid[target])\n    scores.append(score)\n    \n    print(f\"Fold = {fold}, QWK = {score:.4f}\")\n    \nprint(f\"Mean = {np.mean(scores):.4f}\")","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}