コンピューター ビジョン - フライング パドル ディープラーニングの実践 - 画像分類アルゴリズムの原理と実践

基本理論:

画像分類は、深層学習が視覚分野で画期的な結果を達成した最初のタスクです。この章ではまず、画像分類タスクの開発経緯と評価指標を紹介します。次に、画像分類の分野で重要な役割を果たす 3 つのモデルを 3 つの観点から紹介します。1 つ目は残差ネットワークに基づくモデルであり、この章では ResNet、DenseNet、および DPN に焦点を当てます。2 つ目は、Transformer のアイデアに基づいたモデルであり、この章では ViT モデルと Swin-Transformer モデルに焦点を当てます。3 番目のタイプはモバイル デバイス向けの軽量モデルであり、この章では MobileNet と PP-LCNet に焦点を当てます。最後に、この章では、フライング パドル フレームワークを使用した桃の選別プロジェクトを完了します。この章を学習した後、読者が次の知識ポイントを習得できることを願っています。

  1. 画像分類の開発の歴史を理解する。
  2. 残されたアイデアに基づいてモデルの特性を習得します。
  3. トランスフォーマーのアイデアに基づいたモデルの特性をマスターします。
  4. 軽量ネットワーク モデルの特性をマスターします。

画像分類タスクは、深層学習手法を使用した最も初期のコンピューター ビジョン タスクです。多くの古典的なネットワーク アーキテクチャは、最初に画像分類タスクに適用されました。したがって、画像分類における深層学習ネットワーク モデルは、他のコンピューター ビジョン タスクの基礎とみなすことができます。

初期の画像分類手法は、手動で特徴を抽出して画像全体を記述し、分類器を使用して画像カテゴリを決定することが主であったため、画像分類の核心は特徴を分類することであり、画像の特徴をどのように抽出するかが重要です。基礎となる特徴には大量の冗長ノイズが含まれるため、特徴表現の堅牢性を向上させるためには、特徴変換アルゴリズムを使用して基礎となる特徴をエンコードする必要があります。これを特徴エンコーディングと呼びます。特徴量のエンコード後は、一般に特徴量集約とも呼ばれる空間特徴量制約が適用され、空間的な範囲内で各特徴量の最大値または平均値のみが取得され、一定の特徴量不変性を持つ特徴量表現が得られます。


基礎的な特徴抽出、特徴エンコード、および特徴集約を経た後、画像は固定次元ベクトル記述として表現され、分類器を通じて特徴ベクトルを分類することによって画像を分類できます。
カーネル法に基づく SVM は、従来の手法の中で最も広く使用されている分類器であり、従来の画像分類タスクで非常に優れた性能を発揮します。従来の画像分類手法は、一部の単純で明白な画像分類シナリオには効果的ですが、実際の状況が複雑であるため、複雑なシーンに直面した場合、従来の分類手法では満足のいく分類結果を得ることができません。分類方法では画像の特徴を包括的かつ正確に記述することができず、手動で抽出した特徴では、複数の視点、複数の角度、同じオブジェクトの異なる照明と遮蔽、および複数の形態などの問題に対処できません。
 

CNN から Transformer への変化は、ローカル重視からグローバル特化への変化と似ており、人間の視覚特性により一致しています (人間はグローバルな特徴を素早く捉えるのが得意です)。正確な情報を得ることができますが、抽出能力が不十分であるという欠点があります。Transformer はグローバルな長距離モデリングに依存しており、局所的な情報には注意を払わないため、CNN の特徴である並進不変性や反転不変性が失われ、情報の冗長性とより大きなデータ要件をキャプチャすることの欠点。


まとめると、深層学習手法は、画像分類問題における単純な MLP、CNN、Transformer、複雑な MLP およびその他のモデルの開発プロセスを経てきました。これらのモデルには独自の特徴があります。畳み込みはローカル接続のみを含むため計算が効率的です。セルフアテンションは動的重みを使用するためモデル容量が大きく、大域的な受容野も持っています。MLP も大域的な受容野を持ち、ただし、動的重みは使用されません。畳み込みと自己注意には相補的な特性があり、畳み込みが最も優れた汎化能力を持ち、Transformer が 3 つのアーキテクチャの中で最大のモデル容量を備えていることがわかります。Convolution は軽量モデルを設計する場合に最適な選択ですが、大規模なモデルを設計する場合は Transformer を考慮する必要があります。したがって、畳み込みローカル モデリングを使用して、Transformer と MLP のパフォーマンスを向上させることを検討できます。上記の構造の特性を考慮すると、スパース接続は汎化パフォーマンスの向上に役立ち、動的重みとグローバル受容野はモデル能力の向上に役立ちます。したがって、画像分類タスクでは革新的な手法が常に登場し、コンピューター ビジョンに幅広い応用範囲を提供しています。

実験名:桃分類モデルの構築と学習

1. 実験の目標

この実験では主に次のことを説明します。 パドルパドル深層学習フレームワークを使用して桃分類モデルを構築し、トレーニングとテストのプロセス全体を完了します。

この実験を完了すると、次のような能力を習得できるようになります。

  • パドルパドルディープラーニングフレームワークの使用法をマスターします。
  • パドルパドル深層学習フレームワークを使用して桃の分類モデルを構築する方法をマスターします。
  • モデルのトレーニング、評価、保存、予測などの深層学習の作業プロセスを完了する方法をマスターします。

2. 実験背景の紹介

画像分類は、コンピューター ビジョンやその他の複雑なコンピューター タスクの基礎です。ディープラーニング技術の発展により、多くの優れた画像分類アルゴリズムが誕生しました。この桃のソートには、 resnetで代表される典型的なアルゴリズムを使用します

3. パドルパドルフレームワークを使用する一般的なプロセスの紹介

本日、paddlepaddle はバージョン 2.0 をリリースしました。バージョン 2.0 では、高レベルの API がリリースされ、コードがよりシンプルでプログラミングしやすくなりました。

現在、Flying Paddle の高レベル API は、データ読み込み、モデル構築、モデルトレーニング、モデル視覚化、および高レベル使用の 5 つのモジュールで構成されています。以下に示すように:

 

パドルパドル フレームワークを使用してディープ ラーニング プロジェクトを実行するのは非常に簡単で、一般的なプロセスに従ってディープ ラーニング プロジェクトを完了できます (下図はプロジェクト実装の一般的なプロセスを示しています)。このプロセスには主に、データ処理、モデル設計、トレーニング構成、トレーニング プロセス、モデルの保存という 5 つの主要なステップが含まれます。データ処理段階では、ローカルまたはネットワーク データの収集と前処理など、モデルで準利用可能なデータを取得することが主な目的となります。モデル設計段階は、深層学習プロジェクトで最も議論されるモデル構築です。この段階での鍵となるのは、ネットワーク構造の設計と実装です。フライング パドル フレームワークは、工業的に検証された多数のモデル ライブラリと事前トレーニングされたモデルを用意しています。開発者が開発を容易にするために使用するか、直接使用します。トレーニング構成フェーズでは、開発者はオプティマイザーのタイプや学習率の減衰などのパラメーターを設定する必要があり、計算を完了するために GPU と CPU のどちらを使用するかを指定する必要もあります。トレーニング プロセス ステージは、フレームワークが実際に計算プロセスを実行するステージです。この段階では、フライング パドル フレームワークは順伝播、逆伝播、および勾配降下法のプロセスを継続的に完了します。最後のステップはモデルの保存です。モデルが所定の指標に達するか、所定のトレーニング回数に達すると、開発者は次のトレーニングまたはデプロイのために「トレーニング済み」モデルを保存できます。

深層学習プロジェクトプロセスにパドルパドルフレームワークを使用する

4. 実験内容

4.1 データセットの概要

今回の実験で使用したデータセットは 4 種類の桃で、これらの桃は 4 つのフォルダに分かれており、各フォルダの名前は桃の種類に対応しています。

桃のデータセット

 

目で観察すると、桃は大きさや色によって4種類に分けられるように思えますが、本当にそうなのでしょうか?この実験が完了すると、深層学習モデルは分類が何に基づいているかを自ら判断できるようになります。

この実験では、全員にデータセットが提供されており、データセットは 「data/enhancement/」 フォルダーに保存されています。画像は 2 つのフォルダーに分かれており、1 つはトレーニング セット、もう 1 つはテスト セットです。各フォルダーには、R0、B1、M2、S3 の 4 つのカテゴリがあります。元のピーチ分類データ セットには、「train」と「test」の 2 つのフォルダーが含まれています。
各フォルダーには、「B1」、「M2」、「R0」、および「S3」が含まれています。
トレーニング セット:
    train_B1: 1601 枚の画像
    train_M2: 1800 枚の画像
    train_R0: 1601 枚
    train_S3: 1635 枚
テストセット:
    test_B1: 16 枚
    test_M2: 18 枚
    test_R0: 18 枚
    test_S3: 15 枚

# データの解凍。すでに一度解凍している場合は、このコードをコメントアウトしてください。
# !unzip /home/aistudio/data/data103593/data.zip - d /home/aistudio/data/enhancement_data/
実験ファイルの紹介

この実験のファイル構造は次のとおりです。

この実験用のコードとデータセットは皆さんのために用意されており、ディレクトリ構造は以下のとおりです。

この実験のファイル構造


 

4.2 実験に必要なライブラリをインポートする

実験の最初のステップでは、関連するライブラリをインポートする必要があります。最も重要なものは次のとおりです。

  • os: OS モジュールは、ファイルとディレクトリを処理するための非常に豊富な方法を提供します。
  • sys: sys モジュールは、Python 実行環境に関連する一連の変数と関数を提供します。
  • shutil: ファイルコピー用モジュール
  • Numpy: Numpy は、多数の次元配列および行列演算をサポートする Python 言語の拡張ライブラリであり、さらに、配列演算用の多数の数学関数ライブラリも提供します。
  • ランダム: Python のランダム モジュールは、乱数を生成するために使用されます。
  • paddle.vision.datasets: このモジュールにはデータのロードに関連する関数が含まれており、たとえば、mnist などの一般的に使用されるデータ セットをロードするために使用できます。
  • paddle.vision.transforms: このモジュールには、HWC 形式のイメージを CHW モードの入力テンソルに変換するなど、イメージを変換するための関数が含まれています。また、フライング パドル フレームワークの画像前処理メソッドも含まれており、色相、コントラスト、画像サイズなどの調整など、一般的な画像前処理を迅速に完了できます。
  • paddle.io.Dataset: このモジュールには、データのバッチ読み込みと非同期読み込みを「ワンクリック」で完了できるパドルフレームワークのデータ読み込みメソッドが含まれています。
#os: OS モジュールは、ファイルとディレクトリを処理するための非常に豊富な方法を提供します。
#sys: sys モジュールは、Python 実行環境に関連する一連の変数と関数を提供します。
#shutil: ファイルコピー用モジュール 
#numpy: Numpy は、 多数の次元配列および行列演算をサポートする Python 言語の拡張ライブラリであり、さらに、配列演算用の多数の数学関数ライブラリも提供します。
#random: Python のランダム モジュールは、乱数を生成するために使用されます。
#paddle.vision.datasets: このモジュールにはデータのロードに関連する関数が含まれており、たとえば、mnist などの一般的に使用されるデータ セットをロードするために使用できます。
#paddle.vision.transforms: このモジュールには、HWC 形式のイメージを CHW モードの入力テンソルに変換するなど、イメージを変換するための関数が含まれています。また、フライング パドル フレームワークの画像前処理メソッドも含まれており、色相、コントラスト、画像サイズなどの調整など、一般的な画像前処理を迅速に完了できます。
#paddle.io.Dataset: 高モジュールには、データのバッチ読み込みと非同期読み込みを「ワンクリック」で完了できる Paddle Framework データ読み込みメソッドが含まれています。
 私たちを輸入してください
インポート システム
インポート シュティル
 numpyを  npとしてインポート
輸入 パドル
 ランダムにインポート
 paddle.io から データセット、データローダーをインポート
 paddle.vision.datasets から DatasetFolder、ImageFolderをインポート
 paddle.vision から Tとして 変換 をインポートします

4.3 データセットの準備

この実験では、全員にデータセットが提供されており、データセットは 「data/enhancement/」 フォルダーに保存されています。

この実験のデータ前処理には次のものが含まれます。

1. txt ファイルを生成します。
2. トレーニング セットと検証セットを分割します。

4.3.1 txtファイルの生成

txt ファイルを生成する理由 データ セットでは、各フォルダーがカテゴリに対応していることがわかりますが、ラベルを指定する txt ファイルがないため、最初に txt ファイルを生成する必要があります。

コードをすっきりと簡潔にするために、グローバル変数train_parametersでデータセットのパスなどのパラメーターを構成します。説明は次のとおりです。

  • 「train_data_dir」は、提供される拡張されたオリジナルのトレーニング セットです。
  • 「test_image_dir」は、提供されている元のテスト セットです。
  • 「train_image_dir」と「eval_image_dir」は、元のトレーニング セットを分割して生成された実際のトレーニング セットと検証セットです。
  • 「train_list_dir」と「test_list_dir」は生成された txt ファイルのパスです
  • トレーニング結果が保存される「saved_model」フォルダー
「」
パラメータ設定:
「train_data_dir」は、提供される拡張されたオリジナルのトレーニング セットです。
「test_image_dir」は、提供されている元のテスト セットです。
「train_image_dir」と「eval_image_dir」は、元のトレーニング セットを分割して生成された実際のトレーニング セットと検証セットです。
「train_list_dir」と「test_list_dir」は生成された txt ファイルのパスです
トレーニング結果が保存される「saved_model」フォルダー
「」
train_parameters = {          
    'train_image_dir' './data/splitted_training_data/train_images' ,
    'eval_image_dir' './data/splitted_training_data/eval_images' ,
    'test_image_dir' './data/enhancement_data/test' ,
    'train_data_dir' : './data/enhancement_data/train' ,
    'train_list_dir' : './data/enhancement_data/train.txt' ,
    'test_list_dir' : './data/enhancement_data/test.txt' ,  
    'saved_model' : './saved_model/'
}
#4 データセットのカテゴリラベル
ラベル = [ 'R0' 、  'B1' 、  'M2' 、  'S3' ]
ラベル.sort()
#トレーニング セットのファイル名とラベル名を含む txt ファイルを生成する準備をします
write_file_name = train_parameters[  'train_list_dir' ]
#write_file_name ファイルを書き込みモードで開きます
 open (write_file_name,  "w" ) を write_fileとして使用 :
    #異なる分類タグを個別に入力します
    ラベル内の ラベル の場合 :
        #画像名を保存する空のリストを作成する
        ファイルリスト = [] 
        # このラベルのパスの下にあるすべての画像を検索するために使用されます。
        train_txt_dir = train_parameters[  'train_data_dir' ]+ '/' +label+ '/'     
        os.listdir(train_txt_dir)の file_name の場合 :
            dir_name = ラベル        
            temp_line = ディレクトリ名 +  '/'  + ファイル名 +  '\t'  + ラベル +  '\n'     # 例:"B1/101.png B1"
            write_file.write(temp_line)
    
#テスト セットのファイル名とタグ名を含む txt ファイルを生成する準備をする
write_file_name = train_parameters[  'test_list_dir' ]
#write_file_name ファイルを書き込みモードで開きます
 open (write_file_name,  "w" ) を write_fileとして使用 :
    #異なる分類タグを個別に入力します
    ラベル内の ラベル の場合 :
        #画像名を保存する空のリストを作成する
        ファイルリスト = [] 
        # このラベルのパスの下にあるすべての画像を検索するために使用されます。
        train_txt_dir = train_parameters[  'test_image_dir' ]+ '/' +label+ '/'     
        os.listdir(train_txt_dir)の file_name の場合 :
            dir_name = ラベル        
            temp_line = ディレクトリ名 +  '/'  + ファイル名 +  '\t'  + ラベル +  '\n'     # 例:"B1/101.png B1"
            write_file.write(temp_line)

上記の手順を完了すると、data/enhancement_data/ ディレクトリに train.txt test.txt の 2 つのファイルが生成されます。


 
4.3.2 トレーニングセットと検証セットの分割
  • トレーニング セットとテスト セットはすでに存在します。トレーニング セットを再度分割し、トレーニング セットから検証セットを分割するのが最善です。
  • このように、トレーニング時に検証セットを使用してモデルのトレーニング効果を検証することができ、トレーニング効果をリアルタイムで観察することで、パラメーターをタイムリーに調整できます。
#splitted_training_data フォルダーが存在するかどうかを確認し、存在しない場合は、新しいフォルダーを作成します。
 そうでない場合 os.path.exists( 'data/splitted_training_data' ):
    os.makedirs( 'data/splitted_training_data' )
#トレーニングセットと検証セットを分割する関数を定義する
def  create_train_eval():
    「」
    トレーニングセットと検証セットを分割する
    「」
    train_dir = train_parameters[ 'train_image_dir' ]
    eval_dir = train_parameters[ 'eval_image_dir' ]
    train_list_path = train_parameters[ 'train_list_dir' ]  
    train_data_dir = train_parameters[  'train_data_dir'
    
    print ( 'トレーニングおよび評価イメージの作成' )
    #フォルダーが存在しない場合は、対応するフォルダーを作成します
      os.path.exists(train_dir)でない場合:
        os.mkdir(train_dir)
      os.path.exists(eval_dir)でない場合:
        os.mkdir(eval_dir) 
    #txtファイルを開いてデータを分割する
    ファイル名 = トレインリストのパス
    f = オープン(ファイル名,  'r'
    #データを行ごとに読み取ります
    行 = f.readlines()
    f.close()
        
    範囲内の i の場合( len (行)): 
        #データの各行をスペースに従って 2 つの部分に分割し、最初の部分のパス名と画像ファイル名を取得します。例: R0/1.png
        img_path = 行[i].split( '\t' )[ 0
        #2 番目の部分のラベルを取得します。例: R0
        class_label = Lines[i].split( '\t' )[ 1 ].strip( '\n' )
        # 8 枚ごとに 1 枚を検証データとして撮影し、残りはトレーニングに使用します
         i %  8  ==  0の場合:
            #ディレクトリとファイル名を 1 つのパスに結合する
            eval_target_dir = os.path.join(eval_di r, class_label) 
            # 合計ファイル パスと現在の画像のファイル名を組み合わせます。実際には、トレーニング セットの画像が配置されているフォルダー内の画像名が取得されます。   
            eval_img_path = os.path.join(train_dat a_dir, img_path)
              os.path.exists(eval_target_dir)でない場合:
                    os.mkdir(eval_target_dir)  
            #検証セット内の指定されたラベルを持つフォルダーに画像をコピーします      
            shutil.copy(eval_img_path, eval_target_dir
        それ以外の場合:           
            train_target_dir = os.path.join(train_dir , class_label)                                 
            train_img_path = os.path.join(train_data_dir , img_path)
              os.path.exists(train_target_dir)でない場合:
                os.mkdir(train_target_dir)
            shutil.copy(train_img_path, train_targ et_dir) 
    print  ( '訓練セットと検証セットの分割が完了しました!' )
# データセットを作成します。すでに作成している場合は、コードをコメントアウトしてください。
create_train_eval()
 訓練セットと検証セットを分割するための訓練イメージと評価イメージの作成が完了しました。

上記のコードを実行すると、トレーニング セットと検証セットの分割が完了します。それを分割して ./data/splitted_training_data/ ディレクトリに配置します。


 

4.5 カスタム データ セット クラス

Paddle Framework は、一般的に使用されるデータ セットの一部を API にし、ユーザーに公開しています。対応する API は、paddle.vision.datasets および paddle.text.datasets です。これを使用する場合、これらの API を直接呼び出して、データ セットをダウンロードして使用できます。これらの統合データ セットには次のものが含まれます。

  • ビジョン関連のデータセット: ['DatasetFolder'、'ImageFolder'、'MNIST'、'FashionMNIST'、'Fflowers'、'Cifar10'、'Cifar100'、'VOC2012']
  • 自然言語関連のデータセット: ['Conll05st'、'Imdb'、'Imikolov'、'Movielens'、'UCIHousing'、'WMT14'、'WMT16']

ただし、実際の使用シナリオでは、独自のデータセットを使用する必要があることがよくあります。たとえば、この実験では独自の桃のデータセットを使用しました。

Paddle はユーザーに paddle.io.Dataset 基本クラスを提供し、ユーザーがクラス統合を通じてデータセット定義を迅速に実装できるようにします。

PaddlePaddle のデータセットのロード方法は、一律に Dataset (データセット定義) + DataLoader (マルチプロセスデータセットロード) を使用します。

データセット定義 - データセット
  • まずデータセットを定義します。
  • データセット定義は主に、親クラスの paddle.io.Dataset を継承して、新しい Dataset クラスを実装します。
  • 次に、次の 2 つの抽象メソッド「__getitem__」と「__len__」を親クラスに実装します。


 
クラス PeachDataset(データセット):
    「」
    ステップ 1: paddle.io.Dataset クラスを継承する
    「」
    def  __init__ ( self , mode= 'train' ):
        「」
        ステップ 2: コンストラクターを実装し、データ読み取りメソッドを定義し、トレーニング、検証、テストのデータ セットを分割する
        「」
        super (PeachDataset、  self )。__init__ ()
        train_image_dir = train_parameters[ 'train_image_dir' ] #トレーニング セットのパス
        eval_image_dir = train_parameters[ 'eval_image_dir' ]
        test_image_dir = train_parameters[ 'test_image_dir' ]        
        
        「」「」 
        #transform データ強化関数、ここでは画像の開き方のみが変換されます            
        #ここでは、Transpose()を使って画像の開き方(幅、高さ、 チャンネル数)をPaddlePaddleの読み込み方法(チャンネル数、幅、高さ)に変更します。
        means = [ 127.5 127.5 127.5 # 正規化、平均
        std = [ 127.5 127.5 127.5 # 正規化、ラベルの違い 
        transform_train = T.Compose([T.ColorJitter ( 0.4 0.4 0.4 0.4 )
                                     ,T.Resize(size =( 224 , 224 )) 
                                     ,T.トランスポーズ( )
                                     ,T.Normalize(平均, 標準)
                                    ])
        transform_eval = T.Compose([T.Resize(size= ( 224 , 224 )) 
                                    ,T.Transpose()
                                    ,T.正規化(平均、標準)
                                    ])
        transform_test = T.Compose([T.Resize(size= ( 224 , 224 )) 
                                    ,T.Transpose()
                                    ,T.正規化(平均、標準)
                                    ])
        
        「」         
        # 参考API:https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/Overview_cn.html#about-transforms
        #ここでは、Transpose()を使って画像の開き方(幅、高さ、 チャンネル数)をPaddlePaddleの読み込み方法(チャンネル数、幅、高さ)に変更します。
        # ColorJitter は、画像の明るさ、コントラスト、彩度、色相をランダムに調整します。
        # hflip 入力画像を水平方向に反転します。        
        #正規化を正規化します。平均 = [127.5, 127.5,  127.5]、標準 = [127.5, 127.5, 127.5]
        # Randomhorizo​​ntalFlip は、確率に基づいて画像の水平反転を実行します。
        # RandomVerticalFlip 確率に基づいて画像の垂直反転を実行します。
        means = [127.5, 127.5, 127.5] # 正規化、平均
        std = [127.5, 127.5, 127.5] # 正規化、ラベルの差 
        transform_train = T.Compose([T.Resize(size =(224,224)), 
                                     T.Transpose() 、                                
                                     T.カラージッター(0.4、0.4、0.4、0.4)、
                                     T.RandomHoriz ontalFlip(prob=0.5,),
                                     T.RandomVerticalFlip (prob=0.5,)、
                                     T.正規化(平均値、標準値)])
        Transform_eval = T.Compose([T.Resize(size= (224,224)), T.Transpose()])
        Transform_test = T.Compose([T.Resize(size= (224,224)), T.Transpose()])
        「」 
        #Fei Paddle は、paddle.io.DataLoader を使用して データのロードを完了し、データをロードできるイテレータを生成することを推奨しています。
        #インストールされている API:https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/io/DataLoader_cn.html#cn-api-fluid-io-dataloader
        #トレーニング セットをロードします。train_data_folder はイテレータです。
        参考API:https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/datasets/DatasetFolder_cn.html#datasetfolder
        train_data_folder = DatasetFolder(train_im age_dir、transform=transform_train)
        #検証セットをロードします。eval_data_folder はイテレータです
        eval_data_folder = DatasetFolder(eval_imag e_dir、transform=transform_eval)
        #テスト セットをロードします。test_data_folder はイテレータです。
        test_data_folder = DatasetFolder(test_image_dir 、transform=transform_test)
        self .mode = モード
         self .mode ==  'train'の場合:
            self .data = train_data_folder
        elif  self .mode ==  'eval' :
            self .data = eval_data_folder
        elif  self .mode ==  'テスト' :
            self .data = テストデータフォルダー
    #各反復中にデータと対応するラベルを返します
    def  __getitem__( self , インデックス):
        「」
        ステップ 3: __getitem__ メソッドを実装し、インデックスを指定した場合のデータの取得方法を定義し、単一のデータ (トレーニング データ、対応するラベル) を返す
        「」
        data = np.array( self .data[index][ 0 ]).astype( 'float32' )
        label = np.array([ self .data[index][ 1 ]]).astype( 'int64' )
        戻り データ、ラベル
    # データセット全体の合計数を返す
    def  __len__( self ):
        「」
        ステップ 4: __len__ メソッドを実装し、データ セットの総数を返す
        「」
        戻り値 len ( self .data)
#カスタム PeachDataset クラスを使用して独自のデータセットをロードします
train_dataset = PeachDataset(mode= 'train' )
val_dataset = PeachDataset(mode= 'eval' )
test_dataset = PeachDataset(mode= 'test' )
データセットのロード - DataLoader

DataLoader はイテレータを返します。イテレータによって返されるデータの各要素は Tensor です。呼び出しメソッドは次のとおりです:

class paddle.io.DataLoader(dataset, feed_list=None, places=None, return_list=False, batch_sampler=None, batch_size=1, shuffle=False, drop_last=False, collate_fn=None, num_workers=0, use_buffer_reader=True, use_shared_memory=True, timeout=0, worker_init_fn=None) 

DataLoader は指定されたデータセットを 1 回反復します (順序はbatch_sampler によって与えられます)。DataLoader はシングルプロセスおよびマルチプロセスの
データロードモードをサポートします。num_workers が 0 より大きい場合、マルチプロセスモードを使用してデータが非同期的にロードされます。

詳しい紹介 https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/io/DataLoader_cn.html

次のコードは、DataLoader の使用方法を示しています。

# データローダーのサンプルコード
#ライブラリをロードする
 cv2 を  cv としてインポート#OpenCV を使用
print ( "opencv バージョン番号は:"  + cv.__version__)  #バージョン番号を表示
# 実際には、このクラス ライブラリは OpenCV を使用する前にインストールする必要がありますが、AI-Studio を使用するため 、システムは開発者向けにすでにプリインストールされています: opencv-python 4.1.1.26       
from  matplotlib  import  pyplot  as  plt  #このページに描画
%matplotlib インライン 
#データローダーを構築する
test_loader = DataLoader(test_dataset,
                    バッチサイズ= 2
                    シャッフル= True
                    drop_last= True
                    労働者の数= 2 )
opencv のバージョン番号は 4.1.1 です。 
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/__init__.py:107: DeprecationWarning: 'collections.abc' からではなく 'collections' から ABC を使用またはインポートしていますは非推奨であり、3.8 では コレクションインポート MutableMapping  /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/rcsetup.py:20: DeprecationWarning: 使用またはインポートからの動作を停止します。「collections.abc」ではなく「collections」からの ABC は非推奨になり、3.8 では動作しなくなります 「collections.abc」ではなく「collections」からの ABC は 非推奨になり、3.8 ではコレクションからの /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/colors .py:53: DeprecationWarning: 「collections.abc」ではなく「collections」から ABC を使用またはインポートすることは非推奨であり、3.8 では動作しなくなります。 コレクションのインポートから動作しなくなります。
# DataLoader を使用してデータセットを走査する
for  mini_batch  in  test_loader():  # DataLoader から mini_batch を取得 
    print ( "mini_batch の型は次のとおりです: "  +  str ( type (mini_batch)))
    pic_list = mini_batch[ 0 #画像データ
    label_list = mini_batch[ 1 #label
    print ( "mini_batch のサイズは次のとおりです: "  +  str ( len (pic_list)))
    # 画像表示をnumpy形式に変換し、内部数値を整数型に設定
    pic_1 = pic_list[ 0 ]
    pic_2 = pic_list[ 1 ]
    arr1 = np.asarray(pic_1, dtype=np.float64) 
    print (arr1.shape)
    arr2 = np.asarray(pic_2, dtype=np.float64)    
    印刷(arr2.shape)
    Break  #サンプルなので最初のmini_batchだけを取り出します
    
mini_batch のタイプ: <class 'list'>  mini_batch のサイズ: 2  (3, 224, 224)  (3, 224, 224)
# 取得した画像データを表示する
r = arr1[ 0 ]
g = arr1[ 1 ]
b = arr1[ 2 ]
img = cv.merge([r,g,b])
plt.imshow(img)
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/cbook/__init__.py:2349: DeprecationWarning: 「コレクション」からではなく「コレクション」から ABC を使用またはインポートしています。 abc' は非推奨であり、3.8 では isinstance(obj, collections.Iterator):  /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/cbook/__init__の場合に動作を停止します。 .py:2366: 非推奨警告: 'collections.abc' からではなく 'collections' から ABC を使用またはインポートすることは非推奨であり、3.8 では動作を停止します return list(data) if isinstance(data, collections.MappingView) else data 入力データを RGB データ (浮動小数点の場合は [0..1]、整数の場合は [0..255]) を使用して imshow の有効な範囲にクリッピングします。
<matplotlib.image.AxesImage 0x7fb4678d8350>

上の図に示すように、この時点で取得された画像は元の画像とは異なります。これは、PeachDataset クラスで、画像データに対してtransform メソッドが使用され、画像にいくつかの変更が加えられるためです。この点を説明するために、次の方法を比較に使用できます。

下の図は、起こった変化を示しています。

比較と説明のために、PeachDataset クラスのコードを変更し、コメント記号を追加してください。コードは次のとおりです:
これの目的は、画像のサイズを変更してパドルの要件を満たすことと、データの変更によるデータの変更を回避することです。正規化によって。

transform_test = T.Compose([ T.Resize(size=(224,224)) ,T.Transpose() #,T.Normalize(mean, std) ]) 

コードを変更した後、以下のコードのコメントを開いて実行プログラムを再起動し、右上隅の「実行 -> 現在選択されているセルと以前のセルを実行」をクリックしてください。

以下に示すように、元のデータ セット内の画像を確認できます。

データを表示した後、忘れずに PeachDataset クラスのコメントを開きます。そして、以下のコードにコメントを追加します。

「」
# 取得した画像データを表示する
arr1 = arr1 / 255 # 各ピクセルを 0 ~ 1 の間で変更します
r = arr1[0]
g = arr1[1]
b = arr1[2]
img = cv.merge([r,g,b])
plt.imshow(img)
「」

4.6 分類モデルの構築

次に、桃のデータセットを分類するために使用できる画像分類モデルを構築します。

分類モデルを構築するにはどうすればよいですか?

  • DNN ネットワーク モデル、CNN ネットワーク モデル、またはその他のネットワーク モデルを独自のアイデアに従って構築できますが、これには非常に高度なアルゴリズム研究能力が必要です。
  • VGG、ResNet などの成熟した古典的なネットワーク モデルを使用できます。パドル フレームワークを使用して、これらのモデルを構築して使用できます。

この実験では、分類モデルとして 50 層の残差ネットワーク ResNet を使用しました。

さらに、この実験では、モデルの効果を高めるために、やはり転移学習法を使用しました。では、なぜ転移学習を使用するのでしょうか? 転移学習をどのように使用するか?

4.6.1 転移学習

実際のエンジニアリング開発では、完全なニューラル ネットワークをゼロからトレーニングする人はほとんどいません。

なぜ?

一般にデータセットはそれほど大きくないため、トレーニングされたモデルの一般化能力は強力ではないことがよくあります。そしてトレーニングには非常に時間がかかります。

どうやってするの?

一般的な方法は、大規模な公開データ セット (120 万枚の写真と 1,000 のカテゴリを含む ImageNet など) を見つけて、最初にこのデータ セットでニューラル ネットワーク モデル A をトレーニングすることです (この A は通常、他の人によってトレーニングされています)。次に、この A を開始点として使用し、微調整して、独自のデータセットをトレーニングします。この A は 「事前学習モデル」とも呼ばれます。

これは 転移学習 の方法 であり、ファインチューンとも呼ばれます。

では、ファインチューニングの理論的基礎は何でしょうか? つまり、なぜ他の人がトレーニングしたモデルに基づいて微調整できるのでしょうか? これには、畳み込みニューラル ネットワークの構造原理からの分析が必要です。

  • 畳み込みネットワークの場合: 最初の数層は画像のエッジなどの一般的な特徴を学習します。ネットワーク層が深くなるにつれて、後続のネットワークは体の部分、顔、その他の組み合わせた特徴などの特定の特徴の学習に重点を置きます。
  • 最後の全結合層は、通常、対応するタスクの解決に関連する情報を取得すると考えられます。たとえば、AlexNet の全結合層は、抽出された特徴がオブジェクトの 1000 カテゴリのうちのどのカテゴリに属する​​かを示すことができます。
  • たとえば、顔認識プロセスでは、畳み込みのいくつかの主要層で直線や曲線などの一般的な特徴が抽出され、畳み込みのいくつかの中間層で目や鼻などの特定の部分がさらに学習され、高レベルの畳み込みで組み合わせられた特徴を学習できます。したがって、これは顔画像であると判断される。-畳み込みニューラル ネットワークのこの特性は、微調整の理論的基礎です。

学生の中には、「他の人が大規模なデータセット (ImageNet など) でトレーニングしたモデルを使用するだけでなく、微調整も行うのはなぜではないのですか?」と疑問に思う人もいるかもしれません。

  • 他の人によってトレーニングされたモデルが私たち自身のタスクに完全に適しているとは限らないためです。もしかしたら、他の人のネットワークは私たちのタスクよりも多くのことを実行できるかもしれません。おそらく、他の人のネットワークはより複雑で、私たちのタスクはより単純であるかもしれません。- たとえば、猫と犬の画像の二値分類のためにネットワークをトレーニングしたい場合、まず、ImageNet で他の人がトレーニングしたネットワーク モデルを直接使用することを考えます。しかし、ImageNet には 1000 のカテゴリがあり、必要なカテゴリは 2 つだけです。現時点では、独自のタスクを微調整する必要があります。たとえば、元のネットワークの関連層を修正したり、ネットワークの出力層を変更して、結果がよりニーズに合ったものになるようにすることができます。

PaddlePaddle2.0 では、事前トレーニング済みモデルを使用するには、モデル パラメーター protected=True を設定するだけで済みます。

4.6.2 モデルの構築

Flying Paddle の使用で非常に便利なのは、Flying Paddle フレームワークに多くの組み込みモデルがあり、実際のコード行で深層学習モデルを実装できることです。

現在、パドル フレームワークに組み込まれているモデルは CV フィールド内のすべてのモデルであり、paddle.vision.models ディレクトリには、具体的には次のモデルが含まれています。

フライング パドル フレームワークの組み込みモデル: ['ResNet'、'resnet18'、'resnet34'、'resnet50'、'resnet101'、'resnet152'、'VGG'、'vgg11'、'vgg13'、'vgg16' 、'vgg19'、'MobileNetV1'、'mobilenet_v1'、'MobileNetV2'、'mobilenet_v2'、'LeNet']

たとえば、今回使用した resnet50 にはすでにモデルが組み込まれています。


 
# 組み込みモデルを使用すると、さまざまなネットワークを選択できます。ここでは resnet50 ネットワークが選択されています。
#pretrained (bool、オプション) - 事前トレーニングされた重みを imagenet データセットにロードするかどうか
モデル = paddle.vision.models.resnet18(事前トレーニング = True 、num_classes= 4 )    
#さまざまなネットワーク構造を試してください: MobileNetV2
MobileNetV2 リファレンスドキュメント: https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/vision/models/MobileNetV2_cn.html
# model = paddle.vision.models.mobilenet_v2(pretra ined=True, num_classes=4)    
#paddle.Model を使用してモデルのカプセル化を完了し、トレーニングと予測に高レベルの API をすばやく使用できるクラスにネットワーク構造を結合します。
モデル = パドル.モデル(モデル)
100%|██████████| 69183/69183 [00:01<00:00、47292.60it/s]  /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/dygraph/layers.py: 1301: UserWarning: fc.weight の読み込みをスキップします。fc.weight は形状 [512, 1000] を受け取りますが、期待される形状は [512, 4] です。 warnings.warn(("{} の読み込みをスキップします。".format(key) + str(err)))  /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/ Fluid/dygraph/layers.py:1301: UserWarning: fc.bias の読み込みをスキップします。fc.bias は形状 [1000] を受け取りますが、予期される形状は [4] です。 warnings.warn(("{} の読み込みをスキップします。".format(key) + str(err)))

model.summary を使用してネットワークの状態を観察する

参考ドキュメント: https://github.com/PaddlePaddle/Paddle/blob/release/2.1/python/paddle/hapi/model.py#L883

API ドキュメントと実際のコードにはわずかな違いがあります

# 以下为源代码 def summary(self, input_size=None, dtype=None): """Prints a string summary of the network. Args: input_size (tuple|InputSpec|list[tuple|InputSpec], optional): size of input tensor. if not set, input_size will get from ``self._inputs`` if network only have one input, input_size can be tuple or InputSpec. if model have multiple input, input_size must be a list which contain every input's shape. Default: None. dtypes (str, optional): if dtypes is None, 'float32' will be used, Default: None. Returns: Dict: a summary of the network including total params and total trainable params. Examples: .. code-block:: python import paddle from paddle.static import InputSpec input = InputSpec([None, 1, 28, 28], 'float32', 'image') label = InputSpec([None, 1], 'int64', 'label') model = paddle.Model(paddle.vision.models.LeNet(), input, label) optim = paddle.optimizer.Adam( learning_rate=0.001, parameters=model.parameters()) model.prepare( optim, paddle.nn.CrossEntropyLoss()) params_info = model.summary() print(params_info) """ assert (input_size is not None or self._inputs is not None ), "'input_size' or 'self._input' must be set" if input_size is not None: _input_size = input_size else: _input_size = self._inputs return summary(self.network, _input_size, dtype) 

パラメータ:

  • input_size (tuple|InputSpec|list) – 入力テンソルのサイズ。ネットワークに入力が 1 つしかない場合、この値をタプルまたは InputSpec に設定する必要があります。モデルに複数の入力がある場合。次に、各入力の形状を含む値を list[tuple|InputSpec] に設定する必要があります。この値が設定されていない場合は、self._inputs が入力として使用されます。デフォルト値: なし。
  • dtypes (str、オプション) - 入力テンソルのデータ型 (指定されていない場合、デフォルトで float32 が使用されます)。デフォルト値: なし。

戻り値: 辞書。ネットワークのすべてのパラメータのサイズと、トレーニング可能なすべてのパラメータのサイズが含まれます。

# summary を使用してネットワーク情報を観察します
model.summary(input_size=( 1 3 224 224 ), dtype= 'float32'
-------------------------------------------------- ----------------------------- レイヤー (タイプ) 入力形状 出力形状 パラメータ #  =========== ================================================= ==================  Conv2D-1 [[1, 3, 224, 224]] [1, 64, 112, 112] 9,408  BatchNorm2D-1 [[1, 64] 、112、112]] [1、64、112、112] 256  ReLU-1 [[1、64、112、112]] [1、64、112、112] 0  MaxPool2D-1 [[1、64、112] , 112]] [1, 64, 56, 56] 0  Conv2D-2 [[1, 64, 56, 56]] [1, 64, 56, 56] 36,864  BatchNorm2D-2 [[1, 64, 56, 56 ] ]] [1、64、56、56] 256  ReLU-2 [[1, 64, 56, 56 ] ]] [1, 64, 56, 56] 0  Conv2D-3 [[1, 64, 56, 56]] [1, 64, 56, 56] 36.864 BatchNorm2D  -3 [[1, 64, 56, 56]] [1, 64, 56, 56] 256  BasicBlock- 1 [[1, 64, 56, 56]] [1, 64, 56, 56] 0  Conv2D-4 [[1, 64, 56, 56]] [1, 64, 56, 56] 36.864 BatchNorm2D  -4 [ [1, 64, 56, 56]] [1, 64, 56, 56] 256  ReLU-3 [[1, 64, 56, 56]] [1, 64, 56, 56] 0  Conv2D-5 [[1 、64、56、56]] [1、64、56、56] 36.864  BatchNorm2D-5 [[1、64 、56、56]] [1、64、56、56] 256  BasicBlock-2 [[1、64、56、56]] [1、64、56、56] 0  Conv2D-7 [[1、64 、56、56]] [1、128、28、28] 73,728  BatchNorm2D-7 [[1, 128, 28, 28]] [1, 128, 28, 28] 512  ReLU- 4 [[1, 128, 28, 28]] [1, 128, 28, 28] 0  Conv2D-8 [[1, 128, 28, 28]] [1, 128, 28, 28] 147.456  BatchNorm2D-8 [ [1, 128, 28, 28]] [1, 128, 28, 28] 512  Conv2D-6 [[1, 64, 56, 56]] [1, 128, 28, 28] 8.192  BatchNorm2D-6 [[1 、128、28、28]] [1、128、28、28] 512  BasicBlock-3 [[1、64、56、56]] [1、128、28、28] 0  Conv2D-9 [[1、128] 、28、28]] [1、128、28、28] 147,456  BatchNorm2D-9 [[1、128、28、28]] [1、128、28、28] 512  ReLU-5 [[1、128] 、28、28]] [1、128、28、28] 0  Conv2D-10 [[1, 128, 28, 28]] [1, 128, 28, 28] 147.456  BatchNorm2D-10 [[1, 128, 28, 28]] [1, 128, 28, 28] 512  BasicBlock- 4 [[1, 128, 28, 28]] [1, 128, 28, 28] 0  Conv2D-12 [[1, 128, 28, 28]] [1, 256, 14, 14] 294.912 BatchNorm2D  -12 [ [1, 256, 14, 14]] [1, 256, 14, 14] 1.024  ReLU-6 [[1, 256, 14, 14]] [1, 256, 14, 14] 0 Conv2D  -13 [[1 、256、14、14]] [1、256、14、14] 589.824  BatchNorm2D-13 [[1, 256] 、14、14]] [1、256、14、14] 1.024  Conv2D-11 [[1、128、28、28]] [1、256、14、14] 32.768  BatchNorm2D-11 [[1、256 、14、14]] [1、256、14、14] 1.024  BasicBlock-5 [[1, 128, 28, 28]] [1, 256, 14, 14] 0  Conv2D-14 [[1, 256, 14, 14]] [1, 256, 14, 14] 589.824  BatchNorm2D- 14 [[1, 256, 14, 14]] [1, 256, 14, 14] 1.024  ReLU-7 [[1, 256, 14, 14]] [1, 256, 14, 14] 0 Conv2D  -15 [ [1, 256, 14, 14]] [1, 256, 14, 14] 589.824  BatchNorm2D-15 [[1, 256, 14, 14]] [1, 256, 14, 14] 1.024  BasicBlock-6 [[1 , 256, 14, 14]] [1, 256, 14, 14] 0  [[1、256] , 14, 14]] [1, 512, 7, 7] 1,179,648  BatchNorm2D-17 [[1, 512, 7, 7]] [1, 512, 7, 7] 2.048  ReLU-8 [[1, 512 、7、7]] [1、512、7、7] 0  Conv2D-18 [[1, 512, 7, 7]] [1, 512, 7, 7] 2,359,296  BatchNorm2D-18 [[1, 512, 7, 7]] [1, 512, 7, 7] 2,048  Conv2D- 16 [[1, 256, 14, 14]] [1, 512, 7, 7] 131,072  BatchNorm2D-16 [[1, 512, 7, 7]] [1, 512, 7, 7] 2,048  BasicBlock-7 [ [1, 256, 14, 14]] [1, 512, 7, 7] 0  Conv2D-19 [[1, 512, 7, 7]] [1, 512, 7, 7] 2,359,296  BatchNorm2D-19 [[1 , 512, 7, 7]] [1, 512, 7, 7] 2,048  BatchNorm2D-20 [[1, 512 、7、7]] [1、512、7、7] 2,048  ReLU-9 [[1, 512 、7、7]] [1、512、7、7] 0  Conv2D-20 [[1, 512, 7, 7]] [1, 512, 7, 7] 2,359,296  BasicBlock-8 [[1, 512, 7, 7]] [1, 512, 7, 7] 0  AdaptiveAvgPool2D- 1 [[1, 512, 7, 7]] [1, 512, 1, 1] 0  線形-1 [[1, 512]] [1, 4] 2,052  ============ ================================================= ================= 合計パラメータ: 11,188,164 トレーニング可能なパラメータ: 11,168,964 トレーニング不可能なパラメータ: 19,200  ------------------- -------------------------------------------------- ---------- 入力サイズ (MB): 0.57 前方/後方パス サイズ (MB): 57.04 パラメータ サイズ (MB): 42.68 推定合計サイズ (MB): 100.30 -------------------------------------- --------------------------------------

{'total_params': 11188164, 'trainable_params': 11168964}
# Paddle の VisualDL モジュールを呼び出し、情報をディレクトリに保存します。
#log_dir (str) - 出力ログが保存されるパス。
コールバック = paddle.callbacks.VisualDL(log_dir= 'visualdl_log_dir' )

4.6.3 トレーニング構成

オプティマイザーの構成

paddle.Model でモデルをカプセル化した後、トレーニング前にモデルを構成する必要があります。Model.prepare インターフェイスを使用して、モデル オプティマイザー、損失計算方法、精度計算方法などの設定を含む、トレーニングのための事前構成の準備を行います。

 
  • 学習率 (learning_rate) パラメーターは重要です。
  • トレーニング プロセス中に正解率が高から低まで変動する場合は、学習率を下げてみることができます。
#Model.prepare インターフェイスを使用して、モデル オプティマイザー、損失計算方法、精度計算方法などの設定を含むトレーニングの事前構成と準備を行います。
# オプティマイザー API ドキュメント:  https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/optimizer/Overview_cn.html#paddle-optimizer
# 学習率減衰戦略
# 学習率減衰戦略 API ドキュメント: https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/optimizer/Overview_cn.html#about-lr
scheduler_StepDecay = paddle.optimizer.lr.StepDecay (learning_rate= 0.1 、step_size= 50 、gamma= 0.9 、verbose= False )
Scheduler_PiecewiseDecay = paddle.optimizer.lr.Pie cewiseDecay(boundaries=[ 100 1000 4000 5000 6000 ]、values=[ 0.1 0.5 0.01 0.005 ]、verbose= False )
# SGD、Momentum メソッドを使用してみる
sgd = パドル.オプティマイザー.SGD(
                learning_rate=scheduler_StepDecay, 
                パラメータ=モデル.パラメータ())
アダム = パドル.オプティマイザー.アダム( 
                learning_rate= 0.01 #パラメータを調整する
                パラメータ=モデル.パラメータ())
model.prepare(optimizer= adam,  # adam
              loss=paddle.nn.CrossEntropyLoss(),
              メトリクス=paddle.metric.Accuracy())
コンピューティングリソースの構成

この計算に使用される特定のコンピューティング リソースを設定します。
まず、現在使用しているコンピューティング デバイスを表示できます。(この手順は必須ではありません。)
次に、このトレーニングに使用するコンピューティング デバイスをセットアップします。

# 現在のコンピューティングデバイスを確認する
デバイス = パドル.デバイス.get_device()
印刷(デバイス)
# GPU トレーニングを使用する
device = paddle.set_device( 'gpu' # または 'cpu'
印刷(デバイス)

4.6.4 トレーニングモデル

モデル トレーニングの事前準備が完了したら、正式に fit() インターフェイスを呼び出してトレーニング プロセスを開始します。少なくとも次の 3 つの重要なパラメーターを指定する必要があります: トレーニング データ セット、トレーニング ラウンド、単一トレーニング データのバッチ サイズ。


 

トレーニング時間の説明:

  • CPU で 10 エポックを実行するには約 1.5 時間かかります。
  • GPU で 10 エポックを実行するには約 30 分かかります。
# フィット API ドキュメント:  https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/Model_cn.html#fit-train-data-none-eval-data-none-batch-size-1 -epochs-1-eval-freq-1-log-freq-10-save-dir-none-save-freq-1-verbose-2-drop-last-false-shuffle-true-num-workers-0-callbacks -なし
# モデルのトレーニングを開始し、トレーニング データ セットを指定し、トレーニング ラウンドを設定し、各データ セットの計算のバッチ サイズを設定し、ログ形式を設定します。
#epochs: トレーニング エポックの総数
#batch_size: バッチ内のサンプル数
#メモリ不足を要求された場合は、batch_size を小さくしてみてください。
#verbose: ログ表示、0 は標準出力ストリームにログ情報を出力しないことを意味します、1 はプログレス バー レコードを出力することを意味します、2 はエポックごとに 1 行のレコードを出力することを意味します。1 はプログレス バー レコードを出力することを意味し、2 は 1 行のレコードを出力することを意味しますそれぞれの時代ごとに。
model.fit(train_dataset,
          val_dataset、
          エポック = 1
          バッチサイズ= 2
          コールバック=コールバック、
          冗長= 1 )
ログに出力される損失値は現在のステップであり、メトリックは前のステップの平均値です。 エポック1/1
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/layers/utils.py:77: DeprecationWarning: ' からではなく 'コレクション' から ABC を使用またはインポートしていますcollections.abc' は非推奨であり、3.8 では動作を停止します。 return (isinstance(seq, collections.Sequence) および /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/ nn/layer/norm.py:641: UserWarning: トレーニング時は常にグローバル平均と分散を追跡するようになりました。 「トレーニング時は常にグローバル平均と分散を追跡するようになりました。」)
ステップ 2904/2904 [==============================] - 損失: 0.0549 - acc: 0.5786 - 62ms/ステップ  評価開始... ステップ 415/415 [=============================] - 損失: 0.0867 - acc: 0.7819 - 23ms/ステップ  評価サンプル: 830

4.6.5 モデルの評価と保存

モデルのトレーニングが完了すると、トレーニングされたモデルが得られますが、このモデルがどの程度効果的であるかについては、まだ詳細に評価する必要があります。

モデル評価とは何ですか?

  • モデル評価とは実際には、結果のモデルに予約したテスト データを使用して実際の予測を行い、ラベルに基づいて検証してモデルがテスト セットでどのように実行されるかを確認することを意味します。
  • モデル評価のコード実装も高レベル API で非常にシンプルです。評価用のデータセットを事前に定義した後、model.evaluate インターフェイスを使用してトレーニング済みモデルを評価できます。操作が完了した後、prepare が実行されます。インターフェイスが使用されます。損失とメトリックを設定して、関連するインジケーターを計算して返します。

この実験の評価指標:

今回の実験では、評価指標として 精度(accuracy、略してacc)を使用しました。

学生の皆さん、モデルの評価結果を比べてみていかがでしょうか? あなたのacc値は何ですか?

この実験で適切なデータ補正が行われれば、精度は非常に高くなる可能性があります。acc 値が 90% 以上になるように頑張ってください。

#モデルの評価
#トレーニングされたモデルの評価操作には、model.evaluate インターフェイスを使用できます。操作の完了後、 準備インターフェイスで設定された損失とメトリックに従って、関連するインジケーターが計算されて返されます。
#評価 指標のリファレンスドキュメント: https://www.paddlepaddle.org.cn/documentation/docs/zh/api/paddle/Model_cn.html#evaluate-eval-data-batch-size-1-log-freq-10-冗長-2-num-workers-0-callbacks-none
model.evaluate(test_dataset,verbose= 1 )
評価開始... ステップ 67/67 [==============================] - 損失: 0.0052 - acc: 0.7910 - 13ms/ステップ  評価サンプル: 67
{'損失': [0.0051732725]、'acc': 0.7910447761194029}
#モデルの保存
model.save( './saved_model/saved_model' )   # トレーニング用に保存

4.6.6 モデルの予測

上記の手順でモデルのトレーニング、モデルの評価、モデルの保存が完了しました。評価後にモデルのパフォーマンスが良好であれば、そのモデルを使用できます。この保存されたモデルを使用して予測を行うことができます。

モデル予測を行うにはどうすればよいですか?

  • model.predict インターフェイスは、ユーザーがトレーニング済みモデルを予測しやすくするために、Flying Paddle の高レベル API で提供されています。
  • 「予測データ + 保存されたモデル」を model.predict インターフェースに入力して計算するだけで、インターフェースはモデルによって計算された予測結果を返し、タスクを完了します。
#予測モデル
結果 = model.predict(test_dataset)
予測開始... ステップ 67/67 [==============================] - 12ms/ステップ  予測サンプル: 67
# 結果を観察する
print ( type (結果))  #list
print ( len (結果))  #len == 1
#結果を一行ずつ出力します
 結果[ 0 ] i の場合:
    印刷(i)
<クラス 'リスト'>  1  [[ 0.4494054 1.8589294 -2.709025 -0.98785317]]  [[ 0.80108535 2.0312922 -2.3985271 -1.667168 ]] [[-0.487098 2.5169828 -3.  8384209 0.09941977]] [  [ 1.1755923 1.9356494 -2.7956083 -1.824508 ]] [  [ 0.6587918 1.5227697 -1.9370861 -1.2466118]]  [[ 1.9423198 1.8514836 -2.0579038 -3.0512297]]  [[-0.12070499 2.1658874 -3.2705145 -0.2214822 ]] [[ 2.30185 1.9300838 -2.6378424 -3.3231502]  ] [  [ 1.7931688 1.7564571 -2.713827 -2.3772974]] [  [ 1.018136 1.9348547 -2.1037087 -2.093875 ]]  [[ 1.2455556 1.7356219 -2.3573794 -1.9229555]]  [[ 1.3166553 2.0454793 -2.1393437 -2.51 54655]] [  [ 2.2485528 2.5826378 -2.3228188 -4.113832 ]] [[ 0.6856951 1.9657588 -2.340539 -1.5627216]]  [[ 0.34038985 2.5555618 -3.4037375 -1.1876322 ]]  [[ 1.7155951 2.2181606 -2.2069125 - 3.0874062]] [[-0.9589406 2.3568041 -3.914858  0.8861027]] [[-2.2687616 3.561953 -6.1434994  2.204158 ]]  [[-0.8965972 2.812673 -4.498936 0.67248255]]  [[-1.7266133 3.0567627 -5.3219457 1.823607 ]]  [[-1.2236824 2.9153998 -5.2624416 1. 1972692]] [[-1.6313993  2.393093 -4.390437 1.8520648]] [[  -2.261466 3.1709478 -5.7391357 2.475055 ]]  [[-2.0998657 2.7529852 -5.1272326 2.396462 ]]  [[-1.6497151 2.9010382 -5.0573497 1.7648369]]  [[-2.6754675 2.9362612 -5.56551 2.9 678605]] [[-1.073315 2.3352654 -4.07773 1.1857122]]  [[-0.88414484 2.4533503 -4.0443926 0.775055 ]] [[-1.7560171  3.3508494 -5.375548 1.40 13046]] [[-2.615417  4.013784 -6.8865647 2.4297483]] [[-1.829337 3.1974657 -5.3266735  1.5116838]]  [[-1.1488906 2.4435222 -4.151718 1.1106087]]  [[-2.672726 3.7604275 -6.60363 2.6530373]] [[  -1.3436769 2.810868 -4.783174 1.33638] 45]] [[-7.1727552  -4.178957 6.645717 1.3258969]] [[  -10.802859 -8.898961 13.038587 0.8829916]]  [[-6.100724 -3.6756551 5.3887143 2.429795 ]]  [[-6.956199 -4.8285522 7.192293 1.4987972]]  [[-6.806343 -4.737133 7.0949545 1.9803] 424]] [[-10.631139 -8.797351 12.851841 0.9559243]]  [[-9.890509 -7.7998743 11.965744 1.0906614]] [[  -6.637445 -4.125729 6.246958 2.3932] 679]] [[-4.850948 -3.7300088 5.50579  -0.28020984]] [  [-5.89312 -3.9382315 5.5570445 1.115171 ] ]  [[-9.489717 -7.5113807 11.062157 1.4899993]]  [[-4.060526 -4.7304277 7.44195 -1.7170902]] [[  -6.123046 -5.145837 7.891695 -0.3783] 728]] [[  -6.7471647 -5.1568007 7.3376994 -0.14631017]] [  [-5.768033 -6.0288777 9.360904 -1.9037125]]  [[-7.037687 -5.0647235 7.345336 1.0650041]] [[  -6.3333025 -4.003666 6.096233 2.0686429]]  [[-8.165305 -4.097] 1665 5.59594 4.208836 ]] [[-6.3591156 -0.0809775 -2.1494312 5.8446784]]  [[-5.998541 -0.3071279 -1.633659 5.444659 ]] [[  -5.982375 -0.13737446 -2.0219755 5.5 88227 ]] [[  -6.2784123 -0.28474385 -1.8074901 5.720227 ]] [  [-5.9097333 0.21499354 - 2.4844441 5.4800773 ]]  [[-5.815046 0.34615326 -2.749436 5.516311 ]]  [[-6.144201 0.20839332 -2.5092714 5.6507225 ]] [[  -6.217258 -0.11974069 -2.2099724 5.8341565 ]]  [[-6.0395765 0.08458082 -2.2998967 5.641852 ]] [  [-6.292765 - 0.22815469 -1.8958219 5.7871137 ]]  [[-5.9349203 0.03097157 -2.209548 5.578063 ]] [  [-4.8454432 0.6837326 -2.8405902 4.569208 ]] [[  -5.5436296 -0.4322207 -1.2610528 5.0055714]] [[-5.8578863 -0.32924837 -1.6607574 5.3581743 ]]  [[-5.7073674 0.08094054 -2.3335297 5.431057 ]]
# 結果をsoftmaxで処理して確率値に変換する
x = paddle.to_tensor(結果[ 0 ])
m = paddle.nn.Softmax()
アウト = m(x)
印刷(アウト)
Tensor(shape=[67, 1, 4], dtype=float32, place=CUDAPlace(0), stop_gradient=True, [[[0.18607847, 0.76180643, 0.00790692, 0.04420818]], [[0.21990354, 0.75249618] 、 0.00896723、0.01863303 
 ] ]、
 [[0.04347746、0.87683898、0.00152336、0.07816018]]、
 [[0.31181487、0.66678441、0.00587796、0.01552279]]、[[0.27809274、0.6 5979725、0.02074026、0.04136980]]、[[ 
 0.51592660、0.47112727、0.00944741、0.00349878]] 

 [[0.08482961、0.83483732、0.00363582、0.07669736]]、
 [[0.58813888、0.40553078、0.00420919、0.00212116]]、[[0.50240386、0.4842 9418、0.00554229、0.00775965]]、[[0.27857813、0.69674349、0.01227855、0.01239989] 
 ] 

 [[0.37013263, 0.60421354, 0.01008376, 0.01557007]], 
 [[0.31991184, 0.66306269, 0.01009506, 0.00693045]], [[0.41515639, 0.5798] 3309、0.00429428、0.00071625]]、
 [[0.21048497、0.75708681、0.01020809、0.02222010]] 

 [[ 0.09612054、0.88075089、0.00227385、0.02085473]]、
 [[0.37300166、0.61655551、0.00738223、0.00306051]]、[[0.02863417、0.78866 822、0.00148986、0.18120776]]、[[ 
 0.00232973、0.79350960、0.00004836、0.20411235]] 
 、[ 
 [0.02143462、 0.87504727、0.00058431、0.10293392]]、
 [[0.00643685、0.76924914、0.00017670、0.22413737]]、[[0.01332989、0.83638644、0.00023] 
 486、0.15004875]]、
 [[0.01116226, 0.62454951, 0.00070716, 0.36358106]], 
 [[0.00290894, 0.66527551, 0.00008983, 0.33172569]], [[0.00456953, 0.5853] 8061、0.00022136、0.40982854]]、
 [[0.00792769、0.75078166、0.00026256、0.24102813]] 

 [[ 0.00179510、0.49116838、0.00009976、0.50693673]]、
 [[0.02448242、0.73991507、0.00121354、0.23438902]]、[[0.02903091、0.81717] 736、0.00123135、0.15256041]]、[[0.00527186、0.87065840、0.00014126、0.12392850]] 

 [ 
 [0.00109510、 0.82885396、0.00001529、0.17003568]]、
 [[0.00550288、0.83888549、0.00016662、0.15544505]]、[[0.02129946、0.77363062、0.00105] 
 744、0.20401244]]、
 [[0.00120668, 0.75071740, 0.00002368, 0.24805219]], 
 [[0.01260382, 0.80315262, 0.00040434, 0.18383917]], [[0.00000099, 0.0000] 1980、0.99510950、0.00486970]]、
 [[0.00000000、0.00000000、0.99999475、0.00000526]] 

 [[ 0.00000973、0.00011000、0.95056945、0.04931074]]、
 [[0.00000071、0.00000600、0.99663687、0.00335647]]、[[0.00000091、0.00000 722、0.99401951、0.00597238]]、[[0.00000000、0.00000000、0.99999321、0.00000682 
 ]] 
 、[ 
 [0.00000000, 0.00000000、0.99998105、0.00001892]]、
 [[0.00000248、0.00003062、0.97920632、0.02076050]]、[[0.00003168、0.00009718、0.99681 
 073、0.00306045]]、
 [[0.00001052, 0.00007432, 0.98827934, 0.01163586]], 
 [[0.00000000, 0.00000001, 0.99993038, 0.00006964]], [[0.00001010, 0.0000] 
 0517、0.99987948、0.00010525]]、[[0.00000082、0.00000218、0.99974102、0.00025600]] 

 [[ 0.00000076、0.00000375、0.99943382、0.00056168]]、
 [[0.00000027、0.00000021、0.99998665、0.00001282]]、[[0.00000057、0.00000 407、0.99812609、0.00186927]]、[[0.00000393、0.00004036、0.98245114、0.01750455 
 ]] 

 [[0.00000084、 0.00004937、0.80008936、0.19986045]]、
 [[0.00000500、0.00266204、0.00033643、0.99699652]]、[[0.00001068、0.00316434、0.00083] 
 980、0.99598515]]、
 [[0.00000940, 0.00324916, 0.00049351, 0.99624795]], 
 [[0.00000613, 0.00245906, 0.00053635, 0.99699843]], [[0.00001125, 0.0051] 4054、0.00034567、0.99450254]]、[[0.00001192、0.00565004、0.00025565、0.99408239 
 ]] 

 [[ 0.00000751、0.00430946、0.00028455、0.99539846]]、
 [[0.00000582、0.00258814、0.00032005、0.99708599]]、[[0.00000841、0.00384 306、0.00035409、0.99579442]]、[[ 
 0.00000566、0.00243412、0.00045929、0.99710089]] 
 、[ 
 [0.00000996、 0.00388200、0.00041306、0.99569499]]、
 [[0.00007983、0.02011120、0.00059271、0.97921628]]、[[0.00002605、0.00432196、0.00188 679、0.99376523] 
 ]、
 [[0.00001340, 0.00337382, 0.00089095, 0.99572182]], 
 [[0.00001447, 0.00472310, 0.00042231, 0.99484009]]])
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/tensor/creation.py:125: 非推奨警告: `np.object` は組み込みの `object` の非推奨のエイリアスです。この警告を表示しないようにするには、「object」を単独で使用します。これを実行しても動作は変更されず、安全です。 NumPy 1.20 では非推奨になりました。詳細とガイダンス: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations  if data.dtype == np.object:

予測結果を観察するには、ラベルを変換する必要もあります。


 
#辞書を使用してタグに対応する値に名前を付けます
label_dic = {}
iの場合、列挙内の ラベル (ラベル): 
    label_dic[i] = ラベル
#予測されたラベルの結果をpredict_labelsに書き込みます
予測ラベル = []
#results[0] 内の各ピクチャの予測配列を順番に取得します
 results[ 0 ] 結果 の場合
    #np.argmax: numpy 配列の最大値のインデックスを返します
    #注意: インデックスはラベルであり、返されるデータの最大値ではありません
    lab_index = np.argmax(結果)
    lab = label_dic[lab_index]
    予測ラベル.append(ラボ)
#予測結果を見る
印刷(predict_labels)
['M2', 'M2', 'M2', 'M2', 'M2', 'B1', 'M2', 'B1', 'B1', 'M2', 'M2', 'M2', ' M2'、'M2'、'M2'、'M2'、'M2'、'M2'、'M2'、'M2'、'M2'、'M2'、'M2'、'M2'、'M2' 、'S3'、'M2'、'M2'、'M2'、'M2'、'M2'、'M2'、'M2'、'M2'、'R0'、'R0'、'R0'、' R0'、'R0'、'R0'、'R0'、'R0'、'R0'、'R0'、'R0'、'R0'、'R0'、'R0'、'R0'、'R0' 、'R0'、'R0'、'S3'、'S3'、'S3'、'S3'、'S3'、'S3'、'S3'、'S3'、'S3'、「S3」、「S3」、「S3」、「S3」、「S3」、「S3」] 

予測効果をより直観的に観察するために、result.csv ファイルを生成し、この csv ファイルに予測結果をリストし、次のコードを実行して現在のディレクトリに result.csv ファイルを生成します。

result.csv ファイルを開くと、結果が表示されます。


 
最終結果 = [ ]
file_name_test = train_parameters[ 'test_list_dir'
f = オープン(file_name_test,  'r'
#データを行ごとに読み取ります
データ = f.readlines()
範囲内の i の場合( len (データ)): 
    #データの各行をスペースに従って 2 つの部分に分割し、最初の部分のパス名と画像ファイル名を取得します。例: R0/1.png
    img_path = data[i].split( '\t' )[ 0 ]
    Final_result.append(img_path +  ','  +  str (predict_labels[i]) +  '\n' )
f.close()
 open ( 'result.csv' , "w" f  : 
    f.writelines(final_result)

5. まとめ

この実験では、パドルパドル深層学習フレームワークを使用して画像分類モデルを構築し、桃分類タスクを完了しました。

この実験を通じて、私たちは次のことを学びました。

  • パドルパドルディープラーニングフレームワークの使用方法;
  • パドルパドル深層学習フレームワークを使用して桃分類モデルを構築する方法。
  • モデルのトレーニング、評価、保存、予測などの深層学習の作業プロセスを完了する方法。

画像分類タスクは、コンピューター ビジョン (CV) の分野における基本的なタスクであり、難しいことではありませんが、非常に重要であり、他のコンピューター ビジョン タスクの基礎となります。私たちは、より多くの実践的な作業を行い、より多くのコードをデバッグし、熟練度を高め、より複雑な深層学習プロジェクトの基礎を築く必要があります。

記事の一部は 画像分類-桃分類-Paddle AI Studio Galaxy Community (baidu.com) に転載されており、 他の部分はオリジナルを組み合わせたものです。この記事が気に入ったらいいね 、集め、フォローお願いします!

おすすめ

転載: blog.csdn.net/m0_63309778/article/details/133513426