{"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":"markdown","source":"创建ConvertCOCOToYOLO.py文件，模块化","metadata":{"_uuid":"a9415496-afad-4971-9f70-6352a246d52c","_cell_guid":"43492c0e-13a6-4acc-9837-c6565a79db0f","trusted":true}},{"cell_type":"code","source":"import json\nimport os\nimport shutil\nfrom tqdm import tqdm\n\ndef MakeFolders(path=None):\n    # Create folders\n    if os.path.exists(path):\n        shutil.rmtree(path)  # delete output folder\n    os.makedirs(path)  # make new output folder\n    return path\n\ndef CreateCategoryIDMap(categoriesData):\n    num = 0\n    category_id_map = {}\n    for category in categoriesData:\n        category_id_map[category['id']] = num\n        num+=1\n    return category_id_map\n\ndef ConvertBoundingBoxFromCOCOToYOLO(image_width, image_height, bounding_box):\n    dw = 1. / image_width\n    dh = 1. / image_height\n    x = bounding_box[0] + bounding_box[2] / 2.0\n    y = bounding_box[1] + bounding_box[3] / 2.0\n    w = bounding_box[2]\n    h = bounding_box[3]\n \n    # 归一化\n    x = x * dw\n    w = w * dw\n    y = y * dh\n    h = h * dh\n    return (x, y, w, h)\n\ndef ConvertCOCOToYOLOv5(json_dir='', fileName=''):\n    labels_path = MakeFolders(json_dir + 'labels/')  # label directory\n    jsonsData = json.load(open(json_dir + fileName))\n    category_id_map = CreateCategoryIDMap(jsonsData['categories'])\n\n    # transfer the annotationtation, and generated a train dataframe file\n    f = open(json_dir+'train.csv','w')\n    f.write('id,file_name\\n')\n    for i in tqdm(range(len(jsonsData['images']))):\n        file_name = jsonsData['images'][i]['file_name']\n        image_width = jsonsData['images'][i]['width']\n        image_height = jsonsData['images'][i]['height']\n        image_id = jsonsData['images'][i]['id']\n        yolo_txt_name = file_name.split('.')[0] + '.txt' #remove .jpg\n        \n        f.write('{},{}\\n'.format(image_id, file_name))\n        yolo_txt_file = open(os.path.join(labels_path, yolo_txt_name), 'w')\n        \n        for annotation in jsonsData['annotations']:\n            if annotation['image_id'] == image_id:\n                yolo_bbox = ConvertBoundingBoxFromCOCOToYOLO(image_width, image_height, annotation['bbox']) # \"bbox\": [x,y,width,height]        \n                yolo_txt_file.write('{} {} {} {} {}\\n'.format(category_id_map[annotation['category_id']], yolo_bbox[0], yolo_bbox[1], yolo_bbox[2], yolo_bbox[3]))\n        yolo_txt_file.close()\n    f.close()\n    return category_id_map","metadata":{"_uuid":"6f0833cf-76ba-4696-9c66-5a69b92ab879","_cell_guid":"d30354d2-5f85-4444-a034-d512963df35f","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"创建CowboyOutfitsDetection.py","metadata":{"_uuid":"cfc74191-be0c-4dbf-be74-cd48fce34af1","_cell_guid":"89dec91b-0cf7-4b4f-9047-63acabdcddcd","trusted":true}},{"cell_type":"code","source":"from pandas.core.indexes import category\nfrom ConvertCOCOToYOLO import ConvertCOCOToYOLOv5\nimport pandas as pd\nimport os","metadata":{"_uuid":"44a3bd18-c91d-4f16-8411-a1ee03ed1826","_cell_guid":"a37d38c3-3117-484f-a038-f8256922d026","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"filePath = 'E:\\DeepLearning\\CowboyOutfitsDetection\\cowboyoutfits\\\\'\ntrainPath = filePath + 'train.json'\ntestPath = filePath + 'test.csv'\nvalidPath = filePath + 'valid.csv'\nimagesPath = filePath + 'images\\\\'","metadata":{"_uuid":"88b1c469-5209-4620-8fe1-e460477c5343","_cell_guid":"214d37d9-c02a-4bb9-bcd8-5ba631536a47","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"从ConvertCOCOToYOLO.py文件加载进的function","metadata":{"_uuid":"214a3eaa-0c87-4089-805c-b2917db60456","_cell_guid":"74f958d6-8c61-42ab-aa85-073d57f6f773","trusted":true}},{"cell_type":"code","source":"categoryIDMap = ConvertCOCOToYOLOv5(filePath, 'train.json')","metadata":{"_uuid":"dfb7362c-496f-482b-9d1b-668f35af4324","_cell_guid":"5c304935-65ea-4414-87ff-9f0eee57ed81","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainList = pd.read_csv(filePath + 'train.csv')\nvalidList = pd.read_csv(filePath + 'valid.csv')\ntestList = pd.read_csv(filePath + 'test.csv')\n\n# 添加数据集/验证集标签\ntrainList.loc[:, 'split'] = 'train'\nvalidList.loc[:, 'split'] = 'valid'\ntestList.loc[:, 'split'] = 'test'\ntrainAndValidData = pd.concat([trainList, validList, testList]).reset_index(drop=True)","metadata":{"_uuid":"f98d1d42-4d79-4fa7-919d-a34422da9eda","_cell_guid":"21d9932b-d469-4ae0-8a4b-d857ee5192b2","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# make directory for traning section\nos.makedirs(filePath + 'images/train', exist_ok=True)\nos.makedirs(filePath + 'images/valid', exist_ok=True)\nos.makedirs(filePath + 'images/test', exist_ok=True)\nos.makedirs(filePath +'labels/train', exist_ok=True)\nos.makedirs(filePath +'labels/valid', exist_ok=True)","metadata":{"_uuid":"1c6ae0ca-553c-46d1-baf4-8f59412b02ca","_cell_guid":"55cecc0a-89cd-4355-b4ba-3cdefc1350d0","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"这里的验证集是我自己手动从999张图片中，在[makesense](https://www.makesense.ai/)上标注了近400张图，这样获得的结果相对更准确","metadata":{"_uuid":"58141eb8-32bc-4111-a13f-51aea026055e","_cell_guid":"770ecf3f-efde-4a80-bbdc-b33d14cbddbb","trusted":true}},{"cell_type":"code","source":"# 移动图像/标签至对应文件夹\nfrom tqdm import tqdm\nfrom shutil import copyfile\n\nmissList = []\nfor i in tqdm(range(len(trainAndValidData))):\n    row = trainAndValidData.loc[i]\n    name = row.file_name.split('.')[0]\n    if row.split == 'train':\n        copyfile(filePath + f'images/{name}.jpg', filePath + f'images/train/{name}.jpg')\n        copyfile(filePath + f'labels/{name}.txt', filePath + f'/labels/train/{name}.txt')\n    elif row.split == 'valid':\n        try:\n            copyfile(filePath + f'labels/{name}.txt', filePath + f'/labels/valid/{name}.txt')\n        except:\n            name=name+'.jpg'\n            missList.append(name)\n            continue\n        copyfile(filePath + f'images/{name}.jpg', filePath + f'images/valid/{name}.jpg')\n    elif row.split == 'test':\n        copyfile(filePath + f'images/{name}.jpg', filePath + f'images/test/{name}.jpg')\nprint(len(missList))","metadata":{"_uuid":"2ae63331-bc87-44f9-8a24-1c44f85fee63","_cell_guid":"b51566a4-249c-4117-b050-551ef815d3ba","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"创建yolov5-cowboy-outfit.yaml","metadata":{"_uuid":"6c016525-ceb0-466c-a95e-3535a024cfbf","_cell_guid":"b85f4f75-c76f-431c-b5fe-26eb707ac0bd","trusted":true}},{"cell_type":"code","source":"# train and val data as 1) directory: path/images/, 2) file: path/images.txt, or 3) list: [path1/images/, path2/images/]\ntrain: E:/DeepLearning/CowboyOutfitsDetection/cowboyoutfits/images/train\nval: E:/DeepLearning/CowboyOutfitsDetection/cowboyoutfits/images/valid\n\n# number of classes\nnc: 5\n\n# class names\nnames: [\"belt\", \"sunglasses\", \"boot\", \"cowboy_hat\", \"jacket\"]","metadata":{"_uuid":"906708f8-b5f2-4274-b84c-a4f2a4e59046","_cell_guid":"2402d178-4186-4b23-83d7-11bd905ae80c","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"接下来是用yolov5训练，large网络是平衡了性能和效果的选择。\n第一轮直接用的是默认的超参数，训练了200轮，但看图50轮之后就没啥区别了。\n下面是我自己写的bat文件","metadata":{"_uuid":"8427212a-f090-4405-9a7e-006720cd257d","_cell_guid":"772f2e62-3de5-4608-a073-2e1656777933","trusted":true}},{"cell_type":"code","source":"@echo on\nset YOLO_PATH=D:\\Anaconda3\\Lib\\site-packages\\yolov5\nset DATA_YAML_PATH=E:\\DeepLearning\\CowboyOutfitsDetection\\cowboyoutfits\\yolov5-cowboy-outfit.yaml\nset NAME=RTX3070_local_first\nset NUM_EPOCHS=200\nset BATCH_SIZE=4\n\ncd /d d:\ncd %YOLO_PATH%\npython train.py --data %DATA_YAML_PATH%  ^\n                        --cfg .\\models\\yolov5l.yaml ^\n                        --weights .\\weights\\yolov5l.pt ^\n                        --batch-size %BATCH_SIZE% ^\n                        --epochs %NUM_EPOCHS% ^\n                        --name %NAME%\npause","metadata":{"_uuid":"3c6a14f3-2474-43ae-be3f-1092712f905c","_cell_guid":"ea14bf89-b359-4df5-b3e4-acabd92d1662","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"第一轮训练完成后提交，map就已经达到57.63了。第二轮在第一轮的遗传权重下继续训练了100轮，更改了超参数。没有再用mosaic和mixup，optimizer换成Adam","metadata":{"_uuid":"7f351718-b9a6-4f1c-a540-ca79f3bdd9ed","_cell_guid":"462f8d22-e6d5-4f9c-a1e4-20971ea4e560","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Hyperparameters for COCO training from scratch\n# python train.py --batch 40 --cfg yolov5m.yaml --weights '' --data coco.yaml --img 640 --epochs 300\n# See tutorials for hyperparameter evolution https://github.com/ultralytics/yolov5#tutorials\n\n\nlr0: 0.001  # initial learning rate (SGD=1E-2, Adam=1E-3)\nlrf: 0.2  # final OneCycleLR learning rate (lr0 * lrf)\nmomentum: 0.843  # SGD momentum/Adam beta1\nweight_decay: 0.0005  # optimizer weight decay 5e-4\nwarmup_epochs: 0.0  # warmup epochs (fractions ok)\nwarmup_momentum: 0.8  # warmup initial momentum\nwarmup_bias_lr: 0.1  # warmup initial bias lr\nbox: 0.05  # box loss gain\ncls: 0.5  # cls loss gain\ncls_pw: 1.0  # cls BCELoss positive_weight\nobj: 1.0  # obj loss gain (scale with pixels)\nobj_pw: 1.0  # obj BCELoss positive_weight\niou_t: 0.20  # IoU training threshold\nanchor_t: 4.0  # anchor-multiple threshold\n# anchors: 3  # 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: 5.0  # image rotation (+/- deg)\ntranslate: 0.245  # image translation (+/- fraction)\nscale: 0.898  # image scale (+/- gain)\nshear: 0.602  # 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: 0.0  # image mosaic (probability)\nmixup: 0.0  # image mixup (probability)\ncopy_paste: 0.0  # segment copy-paste (probability)","metadata":{"_uuid":"f0149edf-69b7-4a95-9427-ec0b4fdd1ad8","_cell_guid":"0cb1ed9e-f307-46d4-9c41-bb9832e41369","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"@echo on\nset YOLO_PATH=D:\\Anaconda3\\Lib\\site-packages\\yolov5\nset DATA_YAML_PATH=E:\\DeepLearning\\CowboyOutfitsDetection\\cowboyoutfits\\yolov5-cowboy-outfit.yaml\nset NAME=RTX3070_local_second\nset NUM_EPOCHS=100\nset BATCH_SIZE=4\n\ncd /d d:\ncd %YOLO_PATH%\npython train.py --data %DATA_YAML_PATH%  ^\n                        --cfg .\\models\\yolov5l.yaml ^\n                        --weights  .\\weights\\best-first.pt ^\n                        --batch-size %BATCH_SIZE% ^\n                        --epochs %NUM_EPOCHS% ^\n                        --adam\n                        --name %NAME%\npause","metadata":{"_uuid":"d28f1157-4593-4a20-a1c8-a0d94294ec7a","_cell_guid":"9c771502-ec69-46a2-9a04-c2a938cc1a90","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"第二轮提交后map已经突破60了，接下来是第三轮。取消了所有hsv和其他的图像增强，使用了focal loss，据说能提升教小样本的学习效果","metadata":{"_uuid":"7db3e083-ddd3-4127-9a8d-f7f421689b8c","_cell_guid":"e2032e76-03f1-47bb-b0b1-1c8e24c1ae6b","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Hyperparameters for COCO training from scratch\n# python train.py --batch 40 --cfg yolov5m.yaml --weights '' --data coco.yaml --img 640 --epochs 300\n# See tutorials for hyperparameter evolution https://github.com/ultralytics/yolov5#tutorials\n\n\nlr0: 0.01  # initial learning rate (SGD=1E-2, Adam=1E-3)\nlrf: 0.2  # final OneCycleLR learning rate (lr0 * lrf)\nmomentum: 0.843  # SGD momentum/Adam beta1\nweight_decay: 0.0005  # optimizer weight decay 5e-4\nwarmup_epochs: 0.0  # warmup epochs (fractions ok)\nwarmup_momentum: 0.8  # warmup initial momentum\nwarmup_bias_lr: 0.1  # warmup initial bias lr\nbox: 0.05  # box loss gain\ncls: 0.5  # cls loss gain\ncls_pw: 1.0  # cls BCELoss positive_weight\nobj: 1.0  # obj loss gain (scale with pixels)\nobj_pw: 1.0  # obj BCELoss positive_weight\niou_t: 0.20  # IoU training threshold\nanchor_t: 4.0  # anchor-multiple threshold\n# anchors: 3  # anchors per output layer (0 to ignore)\nfl_gamma: 1.5  # focal loss gamma (efficientDet default gamma=1.5)\nhsv_h: 0.0  # image HSV-Hue augmentation (fraction)\nhsv_s: 0.0  # image HSV-Saturation augmentation (fraction)\nhsv_v: 0.0  # image HSV-Value augmentation (fraction)\ndegrees: 0.0  # image rotation (+/- deg)\ntranslate: 0.0  # image translation (+/- fraction)\nscale: 0.0  # 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: 0.0  # image mosaic (probability)\nmixup: 0.0  # image mixup (probability)\ncopy_paste: 0.0  # segment copy-paste (probability)","metadata":{"_uuid":"6fa5d4af-e3ae-4c8c-9488-16fabd7b1801","_cell_guid":"54835598-8a9d-4558-9071-7044af505fed","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"@echo on\nset YOLO_PATH=D:\\Anaconda3\\Lib\\site-packages\\yolov5\nset DATA_YAML_PATH=E:\\DeepLearning\\CowboyOutfitsDetection\\cowboyoutfits\\yolov5-cowboy-outfit.yaml\nset NAME=RTX3070_local_third\nset NUM_EPOCHS=100\nset BATCH_SIZE=4\n\ncd /d d:\ncd %YOLO_PATH%\npython train.py --data %DATA_YAML_PATH%  ^\n                        --cfg .\\models\\yolov5l.yaml ^\n                        --weights .\\weights\\best-60.pt ^\n                        --batch-size %BATCH_SIZE% ^\n                        --epochs %NUM_EPOCHS% ^\n                        --multi-scale ^\n                        --rect ^\n                        --name %NAME%\npause","metadata":{"_uuid":"94eb54b0-f81e-4dbd-bf8b-25997f17fa56","_cell_guid":"b8a1f833-64b8-4de2-84f6-e07846cdc90f","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"最后生成submission","metadata":{"_uuid":"495e6b6e-483f-462a-9879-5775241e8a9b","_cell_guid":"d5d1f1b3-2640-4817-a0b3-580575bf88aa","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":" [code]","metadata":{"_uuid":"7dde340c-337e-4887-9e93-48b2472cf192","_cell_guid":"f55d5e8f-f559-4c6e-bef2-593df9968a1c","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport pandas as pd\nfrom tqdm import tqdm\nfrom PIL import Image\nimport zipfile\n\nfilePath = 'E:/DeepLearning/CowboyOutfitsDetection/cowboyoutfits/'\nexperimentName = 'RTX3070_local_third'\nvalidList = pd.read_csv(filePath + 'test.csv')\nvalidList.head()\ncate_id_map = {87: 0, 1034: 1, 131: 2, 318: 3, 588: 4}\nPRED_PATH = 'D:/Anaconda3/Lib/site-packages/yolov5/runs/detect/' + experimentName +'/labels'\nIMAGE_PATH = 'E:/DeepLearning/CowboyOutfitsDetection/cowboyoutfits/images'\n\n# list our prediction files path\nprediction_files = os.listdir(PRED_PATH)\nprint('Number of test images with detections: ', len(prediction_files))\n\n# convert yolo to coco annotation format\ndef yolo2cc_bbox(img_width, img_height, bbox):\n    x = (bbox[0] - bbox[2] * 0.5) * img_width\n    y = (bbox[1] - bbox[3] * 0.5) * img_height\n    w = bbox[2] * img_width\n    h = bbox[3] * img_height\n    return (x, y, w, h)\n\n# reverse the categories numer to the origin id\nre_cate_id_map = dict(zip(cate_id_map.values(), cate_id_map.keys()))\nprint(re_cate_id_map)\n\ndef make_submission(df, PRED_PATH, IMAGE_PATH):\n    output = []\n    for i in tqdm(range(len(df))):\n        row = df.loc[i]\n        image_id = row['id']\n        file_name = row['file_name'].split('.')[0]\n        if f'{file_name}.txt' in prediction_files:\n            img = Image.open(f'{IMAGE_PATH}/{file_name}.jpg')\n            width, height = img.size\n            with open(f'{PRED_PATH}/{file_name}.txt', 'r') as file:\n                for line in file:\n                    preds = line.strip('\\n').split(' ')\n                    preds = list(map(float, preds))  # conver string to float\n                    cc_bbox = yolo2cc_bbox(width, height, preds[1:-1])\n                    result = {\n                        'image_id': image_id,\n                        'category_id': re_cate_id_map[preds[0]],\n                        'bbox': cc_bbox,\n                        'score': preds[-1]\n                    }\n\n                    output.append(result)\n    return output\n\n\nsub_data = make_submission(validList, PRED_PATH, IMAGE_PATH)\n\nop_pd = pd.DataFrame(sub_data)\n\nos.makedirs(filePath + experimentName, exist_ok=True)\nop_pd.to_json(filePath + experimentName + '/answer.json', orient='records')\nsubmissionZipFile = zipfile.ZipFile(filePath + experimentName +'/sample_answer.zip', 'w')\nsubmissionZipFile.write(filePath + experimentName +'/answer.json', 'answer.json')\nsubmissionZipFile.close()","metadata":{"_uuid":"7a3139a0-b89a-4049-bad7-b926cd49a911","_cell_guid":"0e965ec3-5005-4200-9e57-48f7c38aec1a","collapsed":false,"jupyter":{"outputs_hidden":false},"trusted":true},"execution_count":null,"outputs":[]}]}