{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport torch\n\nimport matplotlib.pyplot as plt\nfrom PIL import Image\nimport SimpleITK as sitk\nimport cv2\n\nimport os\nfrom os import listdir, mkdir\nfrom tqdm.auto import tqdm\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-08-07T15:06:52.203619Z","iopub.execute_input":"2021-08-07T15:06:52.204043Z","iopub.status.idle":"2021-08-07T15:06:53.953750Z","shell.execute_reply.started":"2021-08-07T15:06:52.203957Z","shell.execute_reply":"2021-08-07T15:06:53.952948Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv('/kaggle/input/data-covid-png-640/train.csv')","metadata":{"execution":{"iopub.status.busy":"2021-08-07T15:06:53.955131Z","iopub.execute_input":"2021-08-07T15:06:53.955460Z","iopub.status.idle":"2021-08-07T15:06:54.015666Z","shell.execute_reply.started":"2021-08-07T15:06:53.955426Z","shell.execute_reply":"2021-08-07T15:06:54.014815Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['path'] = df['image'].apply(lambda x:'/kaggle/input/data-covid-png-640/train/'+ x + '.png')","metadata":{"execution":{"iopub.status.busy":"2021-08-07T15:06:54.017482Z","iopub.execute_input":"2021-08-07T15:06:54.017836Z","iopub.status.idle":"2021-08-07T15:06:54.031679Z","shell.execute_reply.started":"2021-08-07T15:06:54.017797Z","shell.execute_reply":"2021-08-07T15:06:54.030832Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"添加opacity标签","metadata":{}},{"cell_type":"code","source":"df['image_label'] = 0\ndf['image_label'] = np.where(df['boxes'].isnull(),0,1)","metadata":{"execution":{"iopub.status.busy":"2021-08-07T15:06:54.033525Z","iopub.execute_input":"2021-08-07T15:06:54.034090Z","iopub.status.idle":"2021-08-07T15:06:54.042770Z","shell.execute_reply.started":"2021-08-07T15:06:54.034035Z","shell.execute_reply":"2021-08-07T15:06:54.041968Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 生成训练集和验证级","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\ndf_train, df_valid = train_test_split(df, test_size=0.2, random_state=42, stratify=df.image_label.values, shuffle=True)\n\ndf_train.loc[:, 'split'] = 'train'\ndf_valid.loc[:, 'split'] = 'valid'\n\ndf = pd.concat([df_train, df_valid])","metadata":{"execution":{"iopub.status.busy":"2021-08-07T15:06:54.044067Z","iopub.execute_input":"2021-08-07T15:06:54.044512Z","iopub.status.idle":"2021-08-07T15:06:54.898429Z","shell.execute_reply.started":"2021-08-07T15:06:54.044475Z","shell.execute_reply":"2021-08-07T15:06:54.896793Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 模型下载","metadata":{}},{"cell_type":"code","source":"%cd /kaggle/working","metadata":{"execution":{"iopub.status.busy":"2021-08-07T15:06:54.899728Z","iopub.execute_input":"2021-08-07T15:06:54.900080Z","iopub.status.idle":"2021-08-07T15:06:54.907808Z","shell.execute_reply.started":"2021-08-07T15:06:54.900043Z","shell.execute_reply":"2021-08-07T15:06:54.906747Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!git clone https://github.com/ultralytics/yolov5  # clone repo\n%cd yolov5\n# Install dependencies\n%pip install -qr requirements.txt  # install dependencies\n\n%cd ../\nprint(f\"Setup complete. Using torch {torch.__version__}({torch.cuda.get_device_properties(0).name if torch.cuda.is_available() else 'CPU'})\")","metadata":{"execution":{"iopub.status.busy":"2021-08-07T15:06:54.909410Z","iopub.execute_input":"2021-08-07T15:06:54.909799Z","iopub.status.idle":"2021-08-07T15:07:05.372348Z","shell.execute_reply.started":"2021-08-07T15:06:54.909762Z","shell.execute_reply":"2021-08-07T15:07:05.371413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import wandb\nfrom kaggle_secrets import UserSecretsClient\n\nuser_secrets = UserSecretsClient()\n\n# I have saved my API token with \"wandb_api\" as Label. \n# If you use some other Label make sure to change the same below. \nwandb_api = user_secrets.get_secret(\"wandb_key\") \n\nwandb.login(key=wandb_api)","metadata":{"execution":{"iopub.status.busy":"2021-08-07T15:07:05.375438Z","iopub.execute_input":"2021-08-07T15:07:05.375715Z","iopub.status.idle":"2021-08-07T15:07:06.611171Z","shell.execute_reply.started":"2021-08-07T15:07:05.375684Z","shell.execute_reply":"2021-08-07T15:07:06.610196Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 准备数据集","metadata":{}},{"cell_type":"code","source":"os.makedirs('/kaggle/covid/images/train', exist_ok=True)\nos.makedirs('/kaggle/covid/images/valid', exist_ok=True)\n\nos.makedirs('/kaggle/covid/labels/train', exist_ok=True)\nos.makedirs('/kaggle/covid/labels/valid', exist_ok=True)\n\n! ls /kaggle/covid/images","metadata":{"execution":{"iopub.status.busy":"2021-08-07T15:07:06.614582Z","iopub.execute_input":"2021-08-07T15:07:06.614883Z","iopub.status.idle":"2021-08-07T15:07:07.302375Z","shell.execute_reply.started":"2021-08-07T15:07:06.614850Z","shell.execute_reply":"2021-08-07T15:07:07.301431Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%cd /kaggle/working","metadata":{"execution":{"iopub.status.busy":"2021-08-07T15:07:07.303966Z","iopub.execute_input":"2021-08-07T15:07:07.304323Z","iopub.status.idle":"2021-08-07T15:07:07.311152Z","shell.execute_reply.started":"2021-08-07T15:07:07.304273Z","shell.execute_reply":"2021-08-07T15:07:07.309178Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IMG_SIZE = 640\n\nfor i in tqdm(df.index):\n    image = cv2.imread(df.loc[i,'path'],0)\n    if df.loc[i,'split']=='train':\n        png_path = '/kaggle/covid/images/train/' + df.loc[i,'image'] +'.png'\n    else:\n        png_path = '/kaggle/covid/images/valid/' + df.loc[i,'image'] +'.png'\n    cv2.imwrite(png_path,image,[int(cv2.IMWRITE_PNG_COMPRESSION), 0])  ","metadata":{"execution":{"iopub.status.busy":"2021-08-07T15:07:07.312909Z","iopub.execute_input":"2021-08-07T15:07:07.313325Z","iopub.status.idle":"2021-08-07T15:09:38.962888Z","shell.execute_reply.started":"2021-08-07T15:07:07.313284Z","shell.execute_reply":"2021-08-07T15:09:38.961890Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get the raw bounding box by parsing the row value of the label column.\n# Ref: https://www.kaggle.com/yujiariyasu/plot-3positive-classes\ndef get_bbox(row):\n    bboxes = []\n    bbox = []\n    for i, l in enumerate(row.label.split(' ')):\n        if (i % 6 == 0) | (i % 6 == 1):\n            continue\n        bbox.append(float(l))\n        if i % 6 == 5:\n            bboxes.append(bbox)\n            bbox = []  \n            \n    return bboxes\n\n# Scale the bounding boxes according to the size of the resized image. \ndef scale_bbox(row, bboxes):\n    # Get scaling factor\n    scale_x = IMG_SIZE/row.dim_w\n    scale_y = IMG_SIZE/row.dim_h\n    \n    scaled_bboxes = []\n    for bbox in bboxes:\n        x = np.round(bbox[0]*scale_x, 4)\n        y = np.round(bbox[1]*scale_y, 4)\n        x1 = np.round(bbox[2]*(scale_x), 4)\n        y1=  np.round(bbox[3]*scale_y, 4)\n\n        scaled_bboxes.append([x, y, x1, y1]) # xmin, ymin, xmax, ymax\n        \n    return scaled_bboxes\n\n# Convert the bounding boxes in YOLO format.\ndef get_yolo_format_bbox(IMG_SIZE, bboxes):\n    yolo_boxes = []\n    for bbox in bboxes:\n        w = bbox[2] - bbox[0] # xmax - xmin\n        h = bbox[3] - bbox[1] # ymax - ymin\n        xc = bbox[0] + np.round(w/2) # xmin + width/2\n        yc = bbox[1] + np.round(h/2) # ymin + height/2\n        \n        yolo_boxes.append([xc/IMG_SIZE, yc/IMG_SIZE, w/IMG_SIZE, h/IMG_SIZE]) # x_center y_center width height\n    \n    return yolo_boxes","metadata":{"execution":{"iopub.status.busy":"2021-08-07T15:09:38.964551Z","iopub.execute_input":"2021-08-07T15:09:38.965137Z","iopub.status.idle":"2021-08-07T15:09:38.977870Z","shell.execute_reply.started":"2021-08-07T15:09:38.965090Z","shell.execute_reply":"2021-08-07T15:09:38.977102Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Prepare the txt files for bounding box\nfor i in tqdm(df.index):\n    row = df.loc[i]\n    # Get split\n    split = row.split\n    # Get image-level label\n    label = row.image_label\n    \n    if row.split=='train':\n        file_name = f'/kaggle/covid/labels/train/{row.image}.txt'\n    else:\n        file_name = f'/kaggle/covid/labels/valid/{row.image}.txt'\n        \n    \n    if label == 1:\n        # Get bboxes\n        bboxes = get_bbox(row)\n        # Scale bounding boxes\n        scale_bboxes = scale_bbox(row, bboxes)\n        # Format for YOLOv5\n        yolo_bboxes = get_yolo_format_bbox(IMG_SIZE, scale_bboxes)\n        \n        with open(file_name, 'w') as f:\n            for bbox in yolo_bboxes:\n                bbox = [0]+bbox\n                bbox = [str(i) for i in bbox]\n                bbox = ' '.join(bbox)\n                f.write(bbox)\n                f.write('\\n')","metadata":{"execution":{"iopub.status.busy":"2021-08-07T15:09:38.979226Z","iopub.execute_input":"2021-08-07T15:09:38.979603Z","iopub.status.idle":"2021-08-07T15:09:42.445022Z","shell.execute_reply.started":"2021-08-07T15:09:38.979566Z","shell.execute_reply":"2021-08-07T15:09:42.444143Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 模型训练","metadata":{}},{"cell_type":"code","source":"# Create .yaml file \nimport yaml\n\ndata_yaml = dict(\n    train = '/kaggle/covid/images/train',\n    val = '/kaggle/covid/images/valid',\n    nc = 1,\n    names = ['opacity']\n)\n\n# Note that I am creating the file in the yolov5/data/ directory.\nwith open('/kaggle/working/yolov5/data/data.yaml', 'w') as outfile:\n    yaml.dump(data_yaml, outfile, default_flow_style=True)\n\n%cat /kaggle/working/yolov5/data/data.yaml","metadata":{"execution":{"iopub.status.busy":"2021-08-07T15:09:42.446296Z","iopub.execute_input":"2021-08-07T15:09:42.446791Z","iopub.status.idle":"2021-08-07T15:09:43.095318Z","shell.execute_reply.started":"2021-08-07T15:09:42.446740Z","shell.execute_reply":"2021-08-07T15:09:43.093701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"hyp_yaml = dict(\nlr0= 0.01,  # initial learning rate (SGD=1E-2, Adam=1E-3)\nlrf= 0.02 , # final OneCycleLR learning rate (lr0 * lrf)\nmomentum= 0.937 , # SGD momentum/Adam beta1\nweight_decay= 0.0005 , # optimizer weight decay 5e-4\nwarmup_epochs= 3.0 , # warmup epochs (fractions ok)\nwarmup_momentum= 0.8 , # warmup initial momentum\nwarmup_bias_lr= 0.1 , # warmup initial bias lr\nbox= 0.1 , # box loss gain\ncls= 0.0 , # cls loss gain\ncls_pw= 0.0 , # cls BCELoss positive_weight\nobj= 3.0 , # obj loss gain (scale with pixels)\nobj_pw= 1.5 , # obj BCELoss positive_weight\niou_t= 0.0 , # IoU training threshold\nanchor_t= 4.0 , # anchor-multiple threshold\nanchors= 0 , # anchors per output layer (0 to ignore)\nfl_gamma= 0.0 , # focal loss gamma (efficientDet default gamma=1.5)\nhsv_h= 0.015 , # image HSV-Hue augmentation (fraction)\nhsv_s= 0.7 , # image HSV-Saturation augmentation (fraction)\nhsv_v= 0.4 , # image HSV-Value augmentation (fraction)\ndegrees= 0.0 , # image rotation (+/- deg)\ntranslate= 0.2 , # image translation (+/- fraction)\nscale= 0.5 , # image scale (+/- gain)\nshear= 0.0 , # image shear (+/- deg)\nperspective= 0.0 , # image perspective (+/- fraction), range 0-0.001\nflipud= 0.0 , # image flip up-down (probability)\nfliplr= 0.5 , # image flip left-right (probability)\nmosaic= 1.0 , # image mosaic (probability)\nmixup= 0.0 , # image mixup (probability)\ncopy_paste= 0.0  # segment copy-paste (probability) \n)\n\nwith open('/kaggle/working/yolov5/data/hyps/hyp.scratch.yaml', 'w') as hypfile:\n    yaml.dump(hyp_yaml,  hypfile, default_flow_style=True)\n\n%cat /kaggle/working/yolov5/data/hyps/hyp.scratch.yaml","metadata":{"execution":{"iopub.status.busy":"2021-08-07T15:09:43.097895Z","iopub.execute_input":"2021-08-07T15:09:43.098196Z","iopub.status.idle":"2021-08-07T15:09:43.821523Z","shell.execute_reply.started":"2021-08-07T15:09:43.098166Z","shell.execute_reply":"2021-08-07T15:09:43.820524Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BATCH_SIZE = 32\nEPOCHS =30","metadata":{"execution":{"iopub.status.busy":"2021-08-07T15:09:43.823025Z","iopub.execute_input":"2021-08-07T15:09:43.823313Z","iopub.status.idle":"2021-08-07T15:09:43.831050Z","shell.execute_reply.started":"2021-08-07T15:09:43.823282Z","shell.execute_reply":"2021-08-07T15:09:43.828525Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%cd /kaggle/working/yolov5","metadata":{"execution":{"iopub.status.busy":"2021-08-07T15:09:43.832260Z","iopub.execute_input":"2021-08-07T15:09:43.832561Z","iopub.status.idle":"2021-08-07T15:09:43.860438Z","shell.execute_reply.started":"2021-08-07T15:09:43.832534Z","shell.execute_reply":"2021-08-07T15:09:43.859403Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!python train.py --img {IMG_SIZE} \\\n                 --batch {BATCH_SIZE} \\\n                 --epochs {EPOCHS} \\\n                 --data data.yaml \\\n                 --cfg yolov5m.yaml \\\n                 --weights /kaggle/input/image-detection-model-1/yolov5/kaggle-siim-covid/exp/weights/best.pt \\\n                 --save_period 1\\\n                 --hyp /kaggle/working/yolov5/data/hyps/hyp.scratch.yaml\\\n                 --project kaggle-siim-covid","metadata":{"execution":{"iopub.status.busy":"2021-08-07T15:16:46.440366Z","iopub.execute_input":"2021-08-07T15:16:46.440766Z","iopub.status.idle":"2021-08-07T15:30:16.842828Z","shell.execute_reply.started":"2021-08-07T15:16:46.440728Z","shell.execute_reply":"2021-08-07T15:30:16.841820Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}