yolov5--完全な錬金術ガイド

序文

最近、yolov5 ジェスチャ認識プロジェクトに取り組んでいます。たくさんの穴を登り、多くのバグを排除しました。記録させてください。先人の経験を参考にして、良い記事に出会ったらお勧めします。主にこれらのバグについてお話していきますが、不備がございましたらコメントやご指摘をお願いいたします。

錬金術の方法

データセットを収集する

1. クロール データ。
ここでは主にオンライン クローラー コードを指します。コードはありますが、私が書いたわけではないので共有しません。
メリット:大量のデータが簡単に入手できる
デメリット:インターネットからクロールしただけのデータは品質にばらつきがあり、基本的な品質が非常に悪い

2.plotplayer を使用して
データセット要件を作成します。
次の 2 つのリンクが詳細に示されていますが、1 つの点を追加したいと思います。実際のニーズに応じて柔軟であり、使用環境に近いものであることです。
参考リンク:
リンクの説明を
追加 リンクの説明を追加

ビデオを準備し、potplayer を開き、ショートカット キー (alt+g) を押します。
ここに画像の説明を挿入

プロットプレイヤーの他の設定を自分で調べることができます。推奨される方法を示します。
取得数は 99999 (ビデオ全体のキャプチャが保証されます)、キャプチャは 200 ミリ秒です。

データを手動で少し処理して、ぼやけた画像や低品質の画像を削除します。

データセットを分割する

インターネット上にある方法はVOCデータセットを分割する方法が多いですが、私の場合はYOLO形式のデータセットです。

1. まずブロガーのコードを使用してデータ セットを分割し、ソース ファイル パスと新しいファイル パスを変更してデータ セット コードを分割します。

import os
import random
from shutil import copy2
 
# 源文件夹路径
file_path = r"D:/Code/Data/centerlinedata/tem_voc/JPEGImages/"
# 新文件路径
new_file_path = r"D:/Code/Data/GREENTdata/"
# 划分数据比例6:2:2
split_rate = [0.6, 0.2, 0.2]
class_names = os.listdir(file_path)
# 目标文件夹下创建文件夹
split_names = ['train', 'val', 'test']
print(class_names)  # ['00000.jpg', '00001.jpg', '00002.jpg'... ]
 
# 判断是否存在目标文件夹,不存在则创建---->创建train\val\test文件夹
if os.path.isdir(new_file_path):
    pass
else:
    os.makedirs(new_file_path)
for split_name in split_names:
    split_path = new_file_path + "/" + split_name
    print(split_path)   # D:/Code/Data/GREENTdata/train, val, test
    if os.path.isdir(split_path):
        pass
    else:
        os.makedirs(split_path)
 
# 按照比例划分数据集,并进行数据图片的复制
for class_name in class_names:
    current_data_path = file_path  # D:/Code/Data/centerlinedata/tem_voc/JPEGImages/
    current_all_data = os.listdir(current_data_path)
    current_data_length = len(current_all_data)  # 文件夹下的图片个数
    current_data_index_list = list(range(current_data_length))
    random.shuffle(current_data_index_list)
 
    train_path = os.path.join(new_file_path, 'train/')   # D:/Code/Data/GREENTdata/train/
    val_path = os.path.join(new_file_path, 'val/')       # D:/Code/Data/GREENTdata/val/
    test_path = os.path.join(new_file_path, 'test/')     # D:/Code/Data/GREENTdata/test/
 
    train_stop_flag = current_data_length * split_rate[0]
    val_stop_flag = current_data_length * (split_rate[0] + split_rate[1])
 
 
current_idx = 0
train_num = 0
val_num = 0
test_num = 0
# 图片复制到文件夹中
for i in current_data_index_list:
    src_img_path = os.path.join(current_data_path, current_all_data[i])
    if current_idx <= train_stop_flag:
        copy2(src_img_path, train_path)
        train_num += 1
    elif (current_idx > train_stop_flag) and (current_idx <= val_stop_flag):
        copy2(src_img_path, val_path)
        val_num += 1
    else:
        copy2(src_img_path, test_path)
        test_num += 1
    current_idx += 1
print("Done!", train_num, val_num, test_num)
 

分割完了
ここに画像の説明を挿入

2. 次のファイル構造を作成します。 all_split # これは、   イメージを
分割したフォルダーです     train # 分割したばかりのトレーニング画像     val # 分割したばかりの検証画像   label train # トレーニング ラベル、labelimg     val     でラベル付けするパス# 検証ラベル、labelimg test でラベルへのパス   # A.yaml を分割したばかりのテストイメージ   # 設定ファイル







A.yaml は次のように構成されています。
ここに画像の説明を挿入

3. 次に、labelimg を使用してトレーニング セットと検証セットにラベルを付けます。
参考リンク:リンクの説明を追加リンクの説明を
追加

yolov5 モデルのトレーニング

錬金術は主にこのブロガーの手法を参考にしており、注意点をいくつか挙げておきます
チュートリアル: ゼロから作る超詳細なyolov5モデルトレーニング

1. バッチはより小さく設定する必要があります。
どのくらい大きくできるかわからない場合は、自動バッチ パラメーターを使用できます。つまり、-1に設定します。

python train.py --img 640 --batch -1 --data ./yolo_A/A.yaml --weights yolov5s.pt --cache     

以下に示すように、このコード行を実行すると、バッチ パラメーターとして 15 が自動的に選択されます
ここに画像の説明を挿入
。これは 2080ti グラフィックス カードなので、グラフィックス カードがどれだけ使用できるかを検討する必要があります。実際、このパラメータはネットワークの複雑さに関連しています。同じデータ セットの場合、ネットワークが複雑になればなるほど、バッチ サイズは小さくなります。ここでは yolov5l.pt を使用します。以前に yolov5s.pt を使用したとき、自動バッチは 47 と表示されました。ディープラーニング、笑、コンピューティングパワーを学びましょう

提案: バッチ設定の大きさを把握し、GPU 操作に便利なインデックス 2 に手動で設定します。

バッチ設定の一部のエラーが大きすぎます。
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
要約すると、cuDNN に関連するエラー、メモリ エラーなど、バッチ パラメータを疑う必要があります。

2. ブロガーはデータセットを分割していないため、科学的なトレーニングデータセットが必要です。しかし、ブロガーが人々を始めさせているのは当然です。
データセットの分割は上で紹介した方法が参考になります。
データセット分割の意味

トレーニング効果を高める簡単な対策

1. 高品質の写真を選択し、相互検証のためにデータセットを分割します

2. yolov5l.pt – 妥協の選択
図に示すように、yolov5l は遅いですが、AP インデックスを大幅に改善できます。
ここに画像の説明を挿入
3. マルチ GPU トレーニング、バッチ サイズを増やす
バッチ サイズをあまり高く設定しないほうがよいと前に言いましたが、これはハードウェア機器に基づいています。ラボに利用可能な GPU がある場合は、マルチ GPU トレーニングを検討し、バッチ サイズを増やしてください。この効果は顕著です。
バッチサイズの理解には、
マルチ GPU トレーニング前の検証状況を使用しませんでした。
ここに画像の説明を挿入
マルチ GPU トレーニングを使用した後の検証状況:
ここに画像の説明を挿入
もちろん、これは特殊なケースにすぎませんが、この方法は試す価値があり、必要はありません原則を知りすぎます。

下図のように、マルチGPUトレーニングバッチの設定が高すぎるとエラーとなります。ちなみにマルチGPUトレーニングではオートバッチは使えません。
ここに画像の説明を挿入
3 GPU トレーニング、バッチ サイズを 64 に設定するとエラーが報告され、3 で割り切れないようです。48 の設定で十分です。
ここに画像の説明を挿入

公式サイトの紹介リンク
torch.distributed.run が pytorch の最新バージョン、古いバージョンは torch.distributed.launch を使用します

4. トレーニング戦略については、この記事がよく書かれていますので、読んでください。
リンクの説明を追加

パラメータの説明

def parse_opt(known=False):
    parser = argparse.ArgumentParser()
    parser.add_argument('--weights', type=str, default=ROOT / 'yolov5s.pt', help='initial weights path')
    parser.add_argument('--cfg', type=str, default='', help='model.yaml path')
    parser.add_argument('--data', type=str, default=ROOT / 'data/coco128.yaml', help='dataset.yaml path')
    parser.add_argument('--hyp', type=str, default=ROOT / 'data/hyps/hyp.scratch-low.yaml', help='hyperparameters path')
    parser.add_argument('--epochs', type=int, default=100, help='total training epochs')
    parser.add_argument('--batch-size', type=int, default=16, help='total batch size for all GPUs, -1 for autobatch')
    parser.add_argument('--imgsz', '--img', '--img-size', type=int, default=640, help='train, val image size (pixels)')
    parser.add_argument('--rect', action='store_true', help='rectangular training')
    parser.add_argument('--resume', nargs='?', const=True, default=False, help='resume most recent training')
    parser.add_argument('--nosave', action='store_true', help='only save final checkpoint')
    parser.add_argument('--noval', action='store_true', help='only validate final epoch')
    parser.add_argument('--noautoanchor', action='store_true', help='disable AutoAnchor')
    parser.add_argument('--noplots', action='store_true', help='save no plot files')
    parser.add_argument('--evolve', type=int, nargs='?', const=300, help='evolve hyperparameters for x generations')
    parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')
    parser.add_argument('--cache', type=str, nargs='?', const='ram', help='image --cache ram/disk')
    parser.add_argument('--image-weights', action='store_true', help='use weighted image selection for training')
    parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
    parser.add_argument('--multi-scale', action='store_true', help='vary img-size +/- 50%%')
    parser.add_argument('--single-cls', action='store_true', help='train multi-class data as single-class')
    parser.add_argument('--optimizer', type=str, choices=['SGD', 'Adam', 'AdamW'], default='SGD', help='optimizer')
    parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode')
    parser.add_argument('--workers', type=int, default=8, help='max dataloader workers (per RANK in DDP mode)')
    parser.add_argument('--project', default=ROOT / 'runs/train', help='save to project/name')
    parser.add_argument('--name', default='exp', help='save to project/name')
    parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
    parser.add_argument('--quad', action='store_true', help='quad dataloader')
    parser.add_argument('--cos-lr', action='store_true', help='cosine LR scheduler')
    parser.add_argument('--label-smoothing', type=float, default=0.0, help='Label smoothing epsilon')
    parser.add_argument('--patience', type=int, default=100, help='EarlyStopping patience (epochs without improvement)')
    parser.add_argument('--freeze', nargs='+', type=int, default=[0], help='Freeze layers: backbone=10, first3=0 1 2')
    parser.add_argument('--save-period', type=int, default=-1, help='Save checkpoint every x epochs (disabled if < 1)')
    parser.add_argument('--seed', type=int, default=0, help='Global training seed')
    parser.add_argument('--local_rank', type=int, default=-1, help='Automatic DDP Multi-GPU argument, do not modify')

    # Logger arguments
    parser.add_argument('--entity', default=None, help='Entity')
    parser.add_argument('--upload_dataset', nargs='?', const=True, default=False, help='Upload data, "val" option')
    parser.add_argument('--bbox_interval', type=int, default=-1, help='Set bounding-box image logging interval')
    parser.add_argument('--artifact_alias', type=str, default='latest', help='Version of dataset artifact to use')

    return parser.parse_known_args()[0] if known else parser.parse_args()

–weight パラメーター: 事前トレーニングされた重みファイル、例: yolov5s.pt、yolov5l.pt
–cfg: トレーニングされたモデル ファイル、デフォルトは yolov5s.yaml (コードはデフォルトでは空です。指定しない場合、モデル パラメーターは重みパラメータに従って決定されます。指定されている場合、指定されたモデル ファイルがメインになります。 )
–data: トレーニング データの場所
–hyp: ハイパーパラメータ、通常は使用されません
–epochs: トレーニング ラウンドの数、デフォルトは 100
–batch-size : デフォルトは 16
–imgsize または --img または --imgsz: デフォルトは 640、32 倍高速でなければなりません、今のところ変更する必要はありません
–resume: ブレークポイント トレーニング
–nosave: 最後のチェックポイント データのみを保存します
–device: cuda デバイスを使用します
–cache: キャッシュを使用して高速化
– ワーカー: CPU がデータをロードする作業プロセス。これはトレーニング速度に影響し、CPU メモリを占有します。サイズが大きいほど、トレーニング速度は速くなります。ただし、ボトルネックに達すると上昇せずに低下し、CPU 負荷を超えてエラーが報告される場合もあります。
–hyp: ハイパーパラメータの進化、これを試すことができます

注: トレーニング パラメーターに一貫性があり、データが変更されない限り、何回トレーニングしても、プロンプト情報や result.png などの結果は同じになります。複数のトレーニングなどというものはありません。平均的な効果を確認するには

エピローグ

錬金術にハマって抜け出せない!
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/private_Jack/article/details/128345434