{"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":"# !pip install -qU wandb kaggle现在依旧默认安装了wandb\n!pip install -qU bbox-utility # check https://github.com/awsaf49/bbox for source code","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:03:24.040683Z","iopub.execute_input":"2023-05-27T16:03:24.041744Z","iopub.status.idle":"2023-05-27T16:03:36.631725Z","shell.execute_reply.started":"2023-05-27T16:03:24.041702Z","shell.execute_reply":"2023-05-27T16:03:36.630633Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nfrom tqdm.notebook import tqdm\ntqdm.pandas() # 可以显示pandas操作的进度条\nimport pandas as pd\nimport os\nimport cv2\nimport matplotlib.pyplot as plt\nimport glob\n\nimport shutil\nimport sys\nsys.path.append('../input/tensorflow-great-barrier-reef')\n\nfrom joblib import Parallel, delayed\nfrom IPython.display import display\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:03:36.635156Z","iopub.execute_input":"2023-05-27T16:03:36.635802Z","iopub.status.idle":"2023-05-27T16:03:36.982947Z","shell.execute_reply.started":"2023-05-27T16:03:36.635764Z","shell.execute_reply":"2023-05-27T16:03:36.982064Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"FOLD      = 1 # which fold to train\nREMOVE_NOBBOX = True # remove images with no bbox\nROOT_DIR  = '../input/tensorflow-great-barrier-reef/' # 原始数据集的路径\nIMAGE_DIR = './kaggle/images' # 新的训练集图片路径\nLABEL_DIR = './kaggle/labels' # 新的训练集图片标签路径\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:03:36.985221Z","iopub.execute_input":"2023-05-27T16:03:36.985931Z","iopub.status.idle":"2023-05-27T16:03:36.990874Z","shell.execute_reply.started":"2023-05-27T16:03:36.985898Z","shell.execute_reply":"2023-05-27T16:03:36.989985Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mkdir -p {IMAGE_DIR}\n!mkdir -p {LABEL_DIR}\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:03:36.993609Z","iopub.execute_input":"2023-05-27T16:03:36.993937Z","iopub.status.idle":"2023-05-27T16:03:38.959335Z","shell.execute_reply.started":"2023-05-27T16:03:36.993908Z","shell.execute_reply":"2023-05-27T16:03:38.957919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train Data\ndf = pd.read_csv(f'{ROOT_DIR}/train.csv')\ndf['old_image_path'] = f'{ROOT_DIR}/train_images/video_'+df.video_id.astype(str)+'/'+df.video_frame.astype(str)+'.jpg'\n# image_id 已经包含了video_id和video_frame，直接以此作为图片样本编号\ndf['image_path']  = f'{IMAGE_DIR}/'+df.image_id+'.jpg'\ndf['label_path']  = f'{LABEL_DIR}/'+df.image_id+'.txt'\ndf['annotations'] = df['annotations'].progress_apply(eval) # progress_apply可以监视运行进度\ndisplay(df.head(2))\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:03:38.961700Z","iopub.execute_input":"2023-05-27T16:03:38.962444Z","iopub.status.idle":"2023-05-27T16:03:39.451118Z","shell.execute_reply.started":"2023-05-27T16:03:38.962402Z","shell.execute_reply":"2023-05-27T16:03:39.450137Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['num_bbox'] = df['annotations'].progress_apply(lambda x: len(x))\ndata = (df.num_bbox>0).value_counts(normalize=True)*100\nprint(f\"No BBox: {data[0]:0.2f}% | With BBox: {data[1]:0.2f}%\")\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:03:39.452556Z","iopub.execute_input":"2023-05-27T16:03:39.452965Z","iopub.status.idle":"2023-05-27T16:03:39.548617Z","shell.execute_reply.started":"2023-05-27T16:03:39.452933Z","shell.execute_reply":"2023-05-27T16:03:39.547705Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = df.query(\"num_bbox>0\")\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:03:39.550036Z","iopub.execute_input":"2023-05-27T16:03:39.550378Z","iopub.status.idle":"2023-05-27T16:03:39.568212Z","shell.execute_reply.started":"2023-05-27T16:03:39.550348Z","shell.execute_reply":"2023-05-27T16:03:39.567387Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def make_copy(row):\n    shutil.copyfile(row.old_image_path, row.image_path)\n    return\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:03:39.569440Z","iopub.execute_input":"2023-05-27T16:03:39.570343Z","iopub.status.idle":"2023-05-27T16:03:39.574928Z","shell.execute_reply.started":"2023-05-27T16:03:39.570311Z","shell.execute_reply":"2023-05-27T16:03:39.573915Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_paths = df.old_image_path.tolist()\n_ = Parallel(n_jobs=-1, backend='threading')(delayed(make_copy)(row) for _, row in tqdm(df.iterrows(), total=len(df)))\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:03:39.576213Z","iopub.execute_input":"2023-05-27T16:03:39.576728Z","iopub.status.idle":"2023-05-27T16:04:11.264665Z","shell.execute_reply.started":"2023-05-27T16:03:39.576695Z","shell.execute_reply":"2023-05-27T16:04:11.263771Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from bbox.utils import coco2yolo, coco2voc, voc2yolo\nfrom bbox.utils import draw_bboxes, load_image\nfrom bbox.utils import clip_bbox, str2annot, annot2str\n\ndef get_bbox(annots):\n    bboxes = [list(annot.values()) for annot in annots]\n    return bboxes\n\ndef get_imgsize(row):\n    row['width'], row['height'] = imagesize.get(row['image_path'])\n    return row\n\nnp.random.seed(32)\ncolors = [(np.random.randint(255), np.random.randint(255), np.random.randint(255))\\\n          for idx in range(1)]\n\ndf['bboxes'] = df.annotations.progress_apply(get_bbox) # 直接得到标注框的[xmin，ymin，w，h]信息\ncolors\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:04:11.268988Z","iopub.execute_input":"2023-05-27T16:04:11.269265Z","iopub.status.idle":"2023-05-27T16:04:12.014864Z","shell.execute_reply.started":"2023-05-27T16:04:11.269241Z","shell.execute_reply":"2023-05-27T16:04:12.013855Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['width']  = 1280\ndf['height'] = 720\ndf\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:04:12.016403Z","iopub.execute_input":"2023-05-27T16:04:12.016763Z","iopub.status.idle":"2023-05-27T16:04:12.054870Z","shell.execute_reply.started":"2023-05-27T16:04:12.016726Z","shell.execute_reply":"2023-05-27T16:04:12.054037Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cnt = 0\nall_bboxes = []\nbboxes_info = []\nfor row_idx in tqdm(range(df.shape[0])):\n    row = df.iloc[row_idx] # 读取df的一行数据\n    image_height = row.height\n    image_width  = row.width\n    # 读取coco格式的标注框信息，比如array([[559., 213.,  50.,  32.]], dtype=float32)\n    bboxes_coco  = np.array(row.bboxes).astype(np.float32).copy() \n    num_bbox     = len(bboxes_coco) # 标注框个数\n    names        = ['cots']*num_bbox # 每个标注框名字都是cots（刺海星冠）\n    labels       = np.array([0]*num_bbox)[..., None].astype(str) #  array([['0'],['0']],[..., None]表示增加一个维度\n    ## Create Annotation(YOLO)\n    with open(row.label_path, 'w') as f:\n    \t# 这一步表示如果读取的行没有标注框，标注信息就填''，且表示'Missing:'的cnt+1\n        if num_bbox<1:\n            annot = ''\n            f.write(annot)\n            cnt+=1\n            continue\n        # 将coco格式标注框[xmin,ymin,w,h]转为voc格式标注框[xmin,ymin,xmax,ymax]比如array([[559., 213., 609., 245.]])\n        bboxes_voc  = coco2voc(bboxes_coco, image_height, image_width)\n        bboxes_voc  = clip_bbox(bboxes_voc, image_height, image_width)\n        # 将voc格式标注框[xmin,ymin,w,h]转为yolo格式标注框[xcenter,ycenter,w,h]\n        # 比如array([['0.5407407', '0.31805557', '0.0462963', '0.04444447']])，标准格式\n        bboxes_yolo = voc2yolo(bboxes_voc, image_height, image_width).astype(str)\n        \n        all_bboxes.extend(bboxes_yolo.astype(float))\n        bboxes_info.extend([[row.image_id, row.video_id, row.sequence]]*len(bboxes_yolo))\n        # 将标签信息连上标注框信息\n        annots = np.concatenate([labels, bboxes_yolo], axis=1)\n        string = annot2str(annots) # 转为字符格式，比如'0 0.5407407 0.31805557 0.0462963 0.04444447'\n        f.write(string) # 将转换完的标签和yolo格式标注框信息写入label文件夹下对应名字的txt文件，每行为一个目标样本\nprint('Missing:',cnt)\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:04:12.056238Z","iopub.execute_input":"2023-05-27T16:04:12.056594Z","iopub.status.idle":"2023-05-27T16:04:16.929243Z","shell.execute_reply.started":"2023-05-27T16:04:12.056565Z","shell.execute_reply":"2023-05-27T16:04:16.928301Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import GroupKFold\nkf = GroupKFold(n_splits = 3)\ndf = df.reset_index(drop=True) # 重设索引，之前索引是原始train.csv中的索引，不连续\ndf['fold'] = -1\n# 根据video_id给df每一行添加fold字段，其值等于video_id\nfor fold, (train_idx, val_idx) in enumerate(kf.split(df, groups=df.video_id.tolist())):\n    df.loc[val_idx, 'fold'] = fold\ndisplay(df.fold.value_counts()) # # 三段视频分别有2143、2099和677张有标注的图片\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:04:16.930807Z","iopub.execute_input":"2023-05-27T16:04:16.932103Z","iopub.status.idle":"2023-05-27T16:04:17.307873Z","shell.execute_reply.started":"2023-05-27T16:04:16.932061Z","shell.execute_reply":"2023-05-27T16:04:17.306854Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 前面设定了FOLD = 1，query引用外部变量，前面要加@\ntrain_files = []\nval_files   = []\ntrain_df = df.query(\"fold!=@FOLD\")\nvalid_df = df.query(\"fold==@FOLD\")\ntrain_files += list(train_df.image_path.unique())\nval_files += list(valid_df.image_path.unique())\nlen(train_files), len(val_files)\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:04:17.309354Z","iopub.execute_input":"2023-05-27T16:04:17.309792Z","iopub.status.idle":"2023-05-27T16:04:17.328136Z","shell.execute_reply.started":"2023-05-27T16:04:17.309752Z","shell.execute_reply":"2023-05-27T16:04:17.327096Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"bbox_df = pd.DataFrame(np.concatenate([bboxes_info, all_bboxes], axis=1),\n             columns=['image_id','video_id','sequence',\n                     'xmid','ymid','w','h'])\nbbox_df[['xmid','ymid','w','h']] = bbox_df[['xmid','ymid','w','h']].astype(float)\nbbox_df['area'] = bbox_df.w * bbox_df.h * 1280 * 720\nbbox_df = bbox_df.merge(df[['image_id','fold']], on='image_id', how='left')\nbbox_df.head(2)\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:04:17.329688Z","iopub.execute_input":"2023-05-27T16:04:17.330020Z","iopub.status.idle":"2023-05-27T16:04:17.497615Z","shell.execute_reply.started":"2023-05-27T16:04:17.329990Z","shell.execute_reply":"2023-05-27T16:04:17.496677Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib as mpl\nimport seaborn as sns\n\nf, ax = plt.subplots(figsize=(12, 6))\nsns.despine(f)\n\nsns.histplot(\n    bbox_df,\n    x=\"area\", hue=\"fold\",\n    multiple=\"stack\",\n    palette=\"viridis\",\n    edgecolor=\".3\",\n    linewidth=.5,\n    log_scale=True,\n)\nax.xaxis.set_major_formatter(mpl.ticker.ScalarFormatter())\nax.set_xticks([500, 1000, 2000, 5000, 10000]);\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:04:17.498925Z","iopub.execute_input":"2023-05-27T16:04:17.499532Z","iopub.status.idle":"2023-05-27T16:04:18.572942Z","shell.execute_reply.started":"2023-05-27T16:04:17.499497Z","shell.execute_reply":"2023-05-27T16:04:18.571893Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df2 = df[(df.num_bbox>0)].sample(100) # takes samples with bbox\ny = 3; x = 2\nplt.figure(figsize=(12.8*x, 7.2*y))\nfor idx in range(x*y):\n    row = df2.iloc[idx]\n    img           = load_image(row.image_path)\n    image_height  = row.height\n    image_width   = row.width\n    with open(row.label_path) as f:\n        annot = str2annot(f.read())\n    bboxes_yolo = annot[...,1:]\n    labels      = annot[..., 0].astype(int).tolist()\n    names         = ['cots']*len(bboxes_yolo)\n    plt.subplot(y, x, idx+1)\n    plt.imshow(draw_bboxes(img = img,\n                           bboxes = bboxes_yolo, \n                           classes = names,\n                           class_ids = labels,\n                           class_name = True, \n                           colors = colors, \n                           bbox_format = 'yolo',\n                           line_thickness = 2))\n    plt.axis('OFF')\nplt.tight_layout()\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:04:18.574506Z","iopub.execute_input":"2023-05-27T16:04:18.574862Z","iopub.status.idle":"2023-05-27T16:04:23.127332Z","shell.execute_reply.started":"2023-05-27T16:04:18.574828Z","shell.execute_reply":"2023-05-27T16:04:23.125629Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import wandb\n\ntry:\n    from kaggle_secrets import UserSecretsClient\n    user_secrets = UserSecretsClient()\n    api_key = user_secrets.get_secret(\"WANDB\")\n    wandb.login(key=api_key)\n    anonymous = None\nexcept:\n    wandb.login(anonymous='must')\n    print('To use your W&B account,\\nGo to Add-ons -> Secrets and provide your W&B access token. Use the Label name as WANDB. \\nGet your W&B access token from here: https://wandb.ai/authorize')\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:04:23.128769Z","iopub.execute_input":"2023-05-27T16:04:23.129258Z","iopub.status.idle":"2023-05-27T16:04:28.941986Z","shell.execute_reply.started":"2023-05-27T16:04:23.129218Z","shell.execute_reply":"2023-05-27T16:04:28.940975Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import yaml\n\ncwd = '/kaggle/working/'\n\n# 创建train.txt和val.txt，每一行都是一个图片名，比如'./kaggle/images/1-461.jpg'\nwith open(os.path.join( cwd , 'train.txt'), 'w') as f:\n    for path in train_df.image_path.tolist():\n        f.write(path+'\\n')\n            \nwith open(os.path.join(cwd , 'val.txt'), 'w') as f:\n    for path in valid_df.image_path.tolist():\n        f.write(path+'\\n')\n\ndata = dict(\n    path  = '/kaggle/working',\n    train =  os.path.join( cwd , 'train.txt') ,\n    val   =  os.path.join( cwd , 'val.txt' ),\n    nc    = 1,\n    names = ['cots'],\n    )\n\nwith open(os.path.join( cwd , 'gbr.yaml'), 'w') as outfile:\n    yaml.dump(data, outfile, default_flow_style=False)\n\nf = open(os.path.join( cwd , 'gbr.yaml'), 'r')\nprint('\\nyaml:')\nprint(f.read())\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:04:28.943305Z","iopub.execute_input":"2023-05-27T16:04:28.943969Z","iopub.status.idle":"2023-05-27T16:04:28.957907Z","shell.execute_reply.started":"2023-05-27T16:04:28.943934Z","shell.execute_reply":"2023-05-27T16:04:28.956670Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%writefile /kaggle/working/hyp.yaml\nlr0: 0.01  # 初始学习率 (SGD=1E-2, Adam=1E-3)\nlrf: 0.1  # 最终OneCycleLR学习率 (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.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)\n# 下面是数据增强策略\ndegrees: 0.0  # image rotation (+/- deg)\ntranslate: 0.10  # 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.5  # image flip up-down (probability)\nfliplr: 0.5  # image flip left-right (probability)\nmosaic: 0.5  # image mosaic (probability)\nmixup: 0.5 # image mixup (probability)\ncopy_paste: 0.0  # segment copy-paste (probability)\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:04:28.959533Z","iopub.execute_input":"2023-05-27T16:04:28.960417Z","iopub.status.idle":"2023-05-27T16:04:28.969989Z","shell.execute_reply.started":"2023-05-27T16:04:28.960202Z","shell.execute_reply":"2023-05-27T16:04:28.968859Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%cd /kaggle/working\n!rm -r /kaggle/working/yolov5\n# !git clone https://github.com/ultralytics/yolov5 # clone\n!cp -r /kaggle/input/yolov5-lib-ds /kaggle/working/yolov5 #\n%cd yolov5\n%pip install -qr requirements.txt  # install\n\nfrom yolov5 import utils\ndisplay = utils.notebook_init()  # check\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:04:28.971668Z","iopub.execute_input":"2023-05-27T16:04:28.972040Z","iopub.status.idle":"2023-05-27T16:04:46.935688Z","shell.execute_reply.started":"2023-05-27T16:04:28.972009Z","shell.execute_reply":"2023-05-27T16:04:46.934672Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"DIM       = 3000 \nMODEL     = 'yolov5s6'\nBATCH     = 4\nEPOCHS    = 12\nOPTMIZER  = 'Adam'\n\nPROJECT   = 'great-barrier-reef-public' # w&b in yolov5\nNAME      = f'{MODEL}-dim{DIM}-fold{FOLD}' # w&b for yolov5\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:04:46.937565Z","iopub.execute_input":"2023-05-27T16:04:46.938685Z","iopub.status.idle":"2023-05-27T16:04:46.944230Z","shell.execute_reply.started":"2023-05-27T16:04:46.938647Z","shell.execute_reply":"2023-05-27T16:04:46.943136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!python train.py --img {DIM}\\\n--batch {BATCH}\\\n--epochs {EPOCHS}\\\n--optimizer {OPTMIZER}\\\n--data /kaggle/working/gbr.yaml\\\n--hyp /kaggle/working/hyp.yaml\\\n--weights {MODEL}.pt\\\n--project {PROJECT} --name {NAME}\\\n--exist-ok\n","metadata":{"execution":{"iopub.status.busy":"2023-05-27T16:04:46.945690Z","iopub.execute_input":"2023-05-27T16:04:46.946022Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"OUTPUT_DIR = '{}/{}'.format(PROJECT, NAME)\n!ls {OUTPUT_DIR}\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 也就是刚打开的Wandb界面的Labels（index=0）\n\nplt.figure(figsize = (10,10))\nplt.axis('off')\nplt.imshow(plt.imread(f'{OUTPUT_DIR}/labels_correlogram.jpg'));\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Wandb界面的Labels（index=1）\n\nplt.figure(figsize = (10,10))\nplt.axis('off')\nplt.imshow(plt.imread(f'{OUTPUT_DIR}/labels.jpg'));\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Wandb界面的Mosaics(yolov5s6-dim3000-fold1)\n\nimport matplotlib.pyplot as plt\nplt.figure(figsize = (10, 10))\nplt.imshow(plt.imread(f'{OUTPUT_DIR}/train_batch0.jpg'))\n\nplt.figure(figsize = (10, 10))\nplt.imshow(plt.imread(f'{OUTPUT_DIR}/train_batch1.jpg'))\n\nplt.figure(figsize = (10, 10))\nplt.imshow(plt.imread(f'{OUTPUT_DIR}/train_batch2.jpg'))\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(3, 2, figsize = (2*9,3*5), constrained_layout = True)\nfor row in range(3):\n    ax[row][0].imshow(plt.imread(f'{OUTPUT_DIR}/val_batch{row}_labels.jpg'))\n    ax[row][0].set_xticks([])\n    ax[row][0].set_yticks([])\n    ax[row][0].set_title(f'{OUTPUT_DIR}/val_batch{row}_labels.jpg', fontsize = 12)\n    \n    ax[row][1].imshow(plt.imread(f'{OUTPUT_DIR}/val_batch{row}_pred.jpg'))\n    ax[row][1].set_xticks([])\n    ax[row][1].set_yticks([])\n    ax[row][1].set_title(f'{OUTPUT_DIR}/val_batch{row}_pred.jpg', fontsize = 12)\nplt.show()\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}