--- tag: YOLOv7 --- # YOLO v7の実行 12月15日の小原先生の発表にあったYOLOについてまとめます。せっかくなので、新しいV7を細胞診WSIでobject detectionするところまで、やりたいと思います。 まずは、COCO datasetダウンロードして、そこから特定のカテゴリのデータを取り出し、データセットを作成して、train.pyを実行する予定です。 [論文:https://arxiv.org/pdf/2207.02696.pdf](https://arxiv.org/pdf/2207.02696.pdf) 2022/7/6に公開されているので、新しいですね。 # *LabelImg* Anotation tool YOLO用のデータセットLabelImg自体はpythonで実行できるようになっています。なので、python環境のpipコマンドでインストールすれば起動します。 ```shell! # install command pip install labelImg # execute labelImg ``` すると、labelimgのウィンドウが表示されるので、画像を指定して、設定を"YOLO"にすればOK! ------------------------- # *COCO* YOLO用のデータセット準備 YOLOで使うデータセットとして、"COCO"があるそうなので、そちらをダウンロードします。 ダウンロード用にシェルスクリプトが用意されています。 それ以外にも、APIが公開されており、実際にはファイルをダウンロードしなくても学習に使えるようになっています。今回は、細胞診でどのみち自作のデータセットを使うことになるので、事前にディレクトリ構造を知るためにもダウンロードします。 [COCO download link:https://gist.github.com~](https://gist.github.com/mkocabas/a6177fc00315403d31572e17700d7fd9) ただ、windowsであったりすると、shコマンドが使えなかったり、うまく動作しなかったので、pythonにて実行しました。 - [github download.py](https://github.com/jsakaguc/NCCEPOC/tree/jsakaguc/YOLO) 実行前に、保存先のsave_dirを指定してください。 ```python= # 70行目くらい save_dir = Path("") # 実行 ! python download.py ``` ![](https://i.imgur.com/1xMjyHe.jpg) (全体で2時間くらいと、<span style="color:red;">40GB</span>くらいになるので保存先の容量に注意してください。) ダウンロードすると、こんな感じになります。 ``` coco ├── annotations │ ├── _deprecated-challenge2017 │ │ ├── train-ids.txt │ │ └── val-ids.txt │ ├── captions_train2017.json │ ├── captions_val2017.json │ ├── image_info_test-dev2017.json │ ├── image_info_test2017.json │ ├── image_info_unlabeled2017.json │ ├── instances_train2017.json │ ├── instances_val2017.json │ ├── person_keypoints_train2017.json │ ├── person_keypoints_val2017.json │ ├── stuff_train2017_pixelmaps.zip │ ├── stuff_train2017.json │ ├── stuff_val2017_pixelmaps.zip │ └── stuff_val2017.json │ └── images ├── test2017 ├── train2017 ├── unlabeled2017 └── val2017 ``` annotationsフォルダ内の.jsonファイルは'info', 'licenses', 'images', 'annotations'のkeyがあります。それぞれのvalueはリスト構造をしていて、'file_name', 'width', 'height', 'id', ...などが入っています。 [coco datasetsについて(Qiita)](https://qiita.com/kHz/items/8c06d0cb620f268f4b3e) とりあえず、必要になるのは画像ファイル名とbboxの座標、instance名(instance id)があればいいはなので、取り出します。今回は、カテゴリ"vehicle"の検出を行います。 vehicleには、motorcycle, airplane, bus, train, truck, boatがあります。なので、これらが含まれる画像をimagesから取り出してdatasetsを作成します。作成にはconfig.yamlを編集して、extract_data.pyを実行します。 その後、保存したcsvファイルを使って、.txtファイルのlabelフォルダを作成します。 ### download - [extract_data.py](https://github.com/jsakaguc/NCCEPOC/tree/jsakaguc) - config.yamlの編集 ```yaml preprocess: coco_path: ***/YOLO/COCO  # ダウンロードしたCOCOがあるディレクトリ save_csv_path: ***/vehicles.csv # 保存するcsvファイルのパス save_img_dir: ***/train2017_vehicles # 保存する画像ファイルのパス save_label_dir: ***/train2017_vehicles/abs_labels save_norm_label_dir: ***/train2017_vehicles/labels ... ``` ```python= python extract_data.py ``` <span style="color:#f5452a; font-weight: 500;">※hydraによるエラーがあった場合</span> ```shell ! pip install hydra-core==1.1.0 ``` すると、だいたい96,000件くらいのデータセットになります。 | name | num | |---|---| |bicycle | 7,113 | |car | 43,867 | |motorcycle | 8,725 | |airplane | 5,135 | |bus | 6,069 | |train | 4,571 | |truck | 9,973 | |boat | 10,759 | 実行後のlabelsデータセットの座標は画像に対しての絶対値になっていて、これをnormalizeしないと、train.pyが動作しなかったので、normalize.pyを実行して新しくlabelsを作成します。 ```python= python normalize.py ``` 結果としては、labelsが2つできることになりました。もし必要なければ、save_label_dirのほうは削除しても大丈夫です。 ここまでで、前準備は終了になります。 ------------ # YOLO ## 1. YOLOのコードをGithubから取得します。 [YOLO Github: https://github.com/WongKinYiu/yolov7](https://github.com/WongKinYiu/yolov7) ## 2.yolov7/data/coco.yamlの設定ファイルを変更します。 ひとまず、作成したデータセットのディレクトリをcoco.yamlのtrainとvalに指定します。 veichlesは8種類あるので、ncには8を指定します。 データセットの構成は ``` └─root ├─train │ ├─images │ │ 2022-07-07_07-40-32.jpg │ │ ... │ └─labels │ 2022-07-07_07-40-32.txt │ ... └─valid ├─images │ 2022-07-07_09-43-43.jpg │ ... └─labels 2022-07-07_09-43-43.txt ... ``` のような感じになっています。 ```yaml train: ***/train2017_vehicles/images/train # 118287 images val: ***/train2017_vehicles/images/val # 5000 images # number of classes nc: 8 # class names names: ['bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat'] ``` train, valの指定の仕方は3パターンあるそうです。 > \# train and val data as > 1) directory: path/images/ > 2) file: path/images.txt, or > 3) list: [path1/images/, path2/images/] # 実行します。 実行のコマンドは以下のようにしました。 ```shell python train_aux.py --workers 2 --batch-size 1 --data data/coco.yaml --cfg cfg/training/yolov7-e6.yaml --weights 'checkpoints/yolov7-e6.pt' --name yolov7-vichel --hyp data/hyp.scratch.p6.yaml --epochs 300 --device 0 ``` 実行すると、モデルのロード、labels内に.cacheファイルが作成されデータセットを読み込んで学習が始まりました。 ![](https://i.imgur.com/MRbTL9R.jpg) (GPU 8GBでやっていますが、めちゃくちゃ時間がかかりそうです。)←今ここ ------------------ ### 途中で発生したエラーとその対応(正しいかの保証はありません。) - <span style="color:#f5452a;">AssertError: Label class %g exceeds nc=%g in %s. Possible class labels are 0-%g</span> ラベルの.txtファイルの最終行に'\n\があったためクラス数とラベル数が合わなかった - <span style="color:#f5452a;">TypeError: 'InfiniteDataLoader' object is not subscriptable</span> train.py 250行目あたりのdataloaderのnbがコードの感じだとだめらしいので、単純な長さにしました。 ```python= - \# nb = len(dataloader[:, 0]) # number of batches + nb = len(dataloader) # number of batches ``` - <span style="color:#f5452a;">RuntimeError: indices should be either on cpu or on the same device as the indexed tensor (cpu)</span> ※ 742, 1342, 1580行目くらいの3か所くらいあります。 ```python= -\# atching_matrix = torch.zeros_like(cost) + atching_matrix = torch.zeros_like(cost, device="cpu") ``` - <span style="color:#f5452a;">OMPからなんか警告が出ました。</span> 下のコードを最初のほうに入れました。たぶん、あまりよろしくありません。 ```python= os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE" ``` ---- # 参考 - [YOLOv7を使って自作データセットで物体検出してみた](https://dev.classmethod.jp/articles/yolov7-train-with-customize-dataset/)