---
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
```

(全体で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ファイルが作成されデータセットを読み込んで学習が始まりました。

(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/)