TensorFlow の基礎から実践まで: 交通標識分類ニューラル ネットワークの作成方法を段階的に学習します

TensorFlow の基礎から実践まで: 交通標識分類ニューラル ネットワークの作成方法を段階的に学習します

[[198754]]

TensorFlow は、最も人気のあるディープラーニングフレームワークになりました。人工知能やディープラーニングに興味がある人なら、ぜひ試してみたいという人も多いのではないでしょうか。初心者にとって、TensorFlow も非常に良い選択肢です。非常に豊富な入門学習教材と大規模な開発者コミュニティがあります。最近、データ サイエンス学習プラットフォームである DataCamp が、ベクトルとテンソルの基本概念から始めて、交通標識の画像を分類するためのニューラル ネットワークを段階的に実装する TensorFlow 初心者向けのチュートリアルを公開しました。

ディープラーニングは、脳の構造と機能に着想を得たさまざまなアルゴリズムを網羅する機械学習のサブフィールドです。

[[198755]]

TensorFlow は、Google が開発した 2 番目の機械学習フレームワークであり、ディープラーニング モデルの設計、構築、トレーニングに使用できます。 TensorFlow ライブラリを使用して数値計算を実行できます。それ自体は特別なことではないようですが、これらの計算はデータフロー グラフを使用して実行されます。これらのグラフでは、ノードは数学演算を表し、エッジはノード間で渡されるデータ (通常は多次元配列またはテンソル) を表します。

わかりましたか? TensorFlow は、ニューラル ネットワークが多次元配列またはテンソルに対して実行する操作にちなんで名付けられました。基本的にはテンソルのフローです。テンソルについて今のところ知っておくべきことはこれだけですが、次の章でさらに詳しく説明します。

この TensorFlow 入門チュートリアルでは、インタラクティブな方法でディープラーニングを行う方法を説明します。

  • まずテンソルについて学びます。
  • このチュートリアルでは、TensorFlow をシステムにインストールして、ワークスペースにデータをロードするためのいくつかの方法について簡単に説明します。
  • その後、TensorFlow の基本を学び、簡単な計算を簡単に実行できることが分かります。
  • その後、実際に作業に取り掛かります。ベルギーの交通標識データを読み込み、簡単な統計ツールとグラフ作成ツールを使用してデータを調べます。
  • 調査を進めると、データをモデルに取り込むためにデータを操作する必要があることがわかります。したがって、時間をかけて画像のサイズを変更し、グレースケールに変換する必要があります。
  • 次に、ついに独自のニューラル ネットワーク モデルの作成を開始できます。モデルをレイヤーごとに構築します。
  • アーキテクチャを設定したら、それを使用してモデルを繰り返しトレーニングし、最終的にテスト データを入力してモデルを評価できます。
  • 最後に、構築したモデルで何ができるのか、TensorFlow でどのように学習を継続できるのかを理解できるように、今後の進捗に関する推奨ガイドラインがいくつか示されます。

このチュートリアルはここからダウンロードすることもできます: https://github.com/Kacawi/datacamp-community/blob/master/TensorFlow%20Tutorial%20For%20Beginners/TensorFlow%20Tutorial%20For%20Beginners.ipynb

さらに、次の 3 つのコースにも興味があるかもしれません。

  • Python でのディープラーニング: https://www.datacamp.com/courses/deep-learning-in-python
  • DataCamp の Keras チュートリアル: https://www.datacamp.com/community/tutorials/deep-learning-python
  • R を使用した Keras チュートリアル: https://www.datacamp.com/community/tutorials/keras-r-deep-learning

テンソルの紹介

テンソルをよく理解するには、まず線形代数とベクトル数学を少し知っておくのが最善です。テンソルは TensorFlow で多次元データ配列として実装されていると紹介で説明しましたが、テンソルと機械学習分野でのその応用を完全に理解するには、もう少し詳しい紹介が必要かもしれません。

平面ベクトル

平面ベクトルを理解する前に、「ベクトル」の概念を簡単に説明しましょう。ベクトルは、特殊なタイプの行列 (つまり、数値の長方形配列) です。ベクトルは順序付けられた数値の集合であるため、列行列として考えられることが多く、1 つの列と特定の数の行だけを持ちます。言い換えれば、ベクトルは方向を持つスカラーと考えることもできます。

覚えておいてください: スカラー量は「5 メートル」や「60 メートル/秒」のような量であり、ベクトル量は「5 メートル北」や「60 メートル/秒東」のような量です。両者の違いは明らかです。ベクトルには方向があります。ただし、これまで見てきた例は、機械学習の問題で実際に操作するベクトルとは大きく異なる可能性があります。これは正常です。数学的なベクトルの長さは純粋な数値であり、絶対的です。一方、方向は相対的です。つまり、何らかの基準方向に対して測定され、ラジアンまたは度という単位を持ちます。通常、方向は正であり、基準方向から反時計回りに回転すると想定されます。

もちろん、視覚的には、上に示すようにベクトルを矢印として表すこともできます。つまり、ベクトルは方向と長さを持つ矢印と考えることができます。方向は矢印の先で示され、長さは矢印の長さで示されます。

では平面ベクトルとは何でしょうか?

フラット ベクトルは最も単純なテンソル構成です。これらは上で見た通常のベクトルとまったく同じですが、唯一の違いはベクトル空間内にあることです。これをよりよく理解するために、例から始めましょう。2×1 ベクトルがあります。つまり、ベクトルは一度に 2 つの数値をペアにする実数の集合に属します。言い換えれば、それらは 2 次元空間の一部です。この場合、矢印または光線を使用して、座標 (x,y) 平面内のベクトルを表すことができます。

標準位置の座標平面(ベクトルの起点が (0,0))から始めて、ベクトルの最初の行を見て x 座標を推測し、2 番目の行を見て y 座標を見つけることができます。もちろん、この標準位置を常に維持する必要はなく、ベクトルを変更せずに平面に平行に移動することもできます。

注: 同様に、サイズが 3×1 のベクトルの場合は、3 次元空間について説明しています。このベクトルは、ベクトル速度の位置を指す矢印を持つ 3 次元グラフとして表すことができます。矢印は標準の x 軸、y 軸、z 軸上にプロットされます。

これらのベクトルを座標平面上で表現するのは非常に良いことですが、本質的にはこれらのベクトルを使用して演算を実行でき、これを実現するためにベクトルを基底ベクトルまたは単位ベクトルとして表現することができます。

単位ベクトルは大きさが 1 のベクトルであり、通常は「ハット」付きの小文字で表されます。 2 次元または 3 次元のベクトルを 2 つまたは 3 つの直交成分 (x 軸、y 軸、z 軸など) の合計として表す場合は、単位ベクトルが非常に便利です。

たとえば、ベクトルを成分の和として表すことを考えると、成分ベクトル、つまり 2 つまたは 3 つのベクトルの合計が元のベクトルであるということを知ることができます。

ヒント: このビデオでは、簡単な家庭用品を使ってテンソルを説明しています: https://www.youtube.com/watch?v=f5liqUk0ZTw

テンソル

平面ベクトルには、共ベクトルや線形演算子とともに、共通点が 1 つあります。それは、これらはすべてテンソルの特殊なケースであるということです。前のセクションで、ベクトルが方向を持つスカラーとしてどのように特徴付けられるかをまだ覚えています。テンソルは、大きさと複数の方向を持つ物理的実体の数学的表現です。

さらに、スカラーを 1 つの数値で表し、3D 空間のベクトルを 3 つの数値のシーケンスで表すのと同様に、3D 空間のテンソルは 3R 数値の配列で表すことができます。

ここで、R はテンソルの階数を表します。たとえば、3 次元空間では、2 階のテンソルは 3^2=9 個の数値で表すことができます。 N 次元空間では、スカラーには依然として 1 つの数値のみが必要ですが、ベクトルには N 個の数値が必要であり、テンソルには N^R 個の数値が必要です。スカラーはランク 0 のテンソルであるとよく言われるのは、このためです。スカラーには方向がないため、単一の数値で表すことができます。

これを念頭に置くと、スカラー、ベクトル、テンソルを識別して区別するのは簡単です。スカラーは単一の数値で表すことができ、ベクトルは数値の順序付けられた集合であり、テンソルは数値の配列です。

テンソルのユニークな点は、その成分と基底ベクトルの組み合わせです。基底ベクトルは参照フレーム間で一方向に変換され、成分は成分と基底ベクトルの組み合わせが変更されないようにのみ変換されます。

TensorFlowをインストールする

TensorFlow の基本を理解できたので、ライブラリのインストールから始めましょう。ここで注目すべきは、TensorFlow が Python、C++、Haskell、Java、Go、Rust 用の API を提供していることです。R 言語用のサードパーティ パッケージ tensorflow もあります。

ヒント: R のディープラーニング パッケージについて詳しく知りたい場合は、「keras: R でのディープラーニング」を参照してください: https://www.datacamp.com/community/tutorials/keras-r-deep-learning#gs.aLGxTIg

このチュートリアルでは、Python でディープラーニング プロジェクトを作成するために使用できる TensorFlow のバージョンをダウンロードします。 TensorFlow インストール ページ https://www.tensorflow.org/install/ では、virtualenc、pip、Docker を使用して TensorFlow をインストールするための最も一般的な方法と最新の手順を確認できます。もちろん、個人のコンピューターに TensorFlow をインストールする他の方法もあります。

注: Windows を使用している場合は、Conda を使用して TensorFlow をインストールすることもできます。ただし、このインストール方法はコミュニティでサポートされているため、公式のインストール手順を参照することをお勧めします: https://www.tensorflow.org/install/install_windows

これでインストールは完了です。TensorFlow が正しくインストールされていることを再度確認する必要があります。エイリアス tf でワークスペースにインポートできます。

  1. テンソルフローをtfとしてインポートする

注: 上記のコードで使用されているエイリアス tf は慣例です。このエイリアスを使用すると、データ サイエンス プロジェクトで TensorFlow を使用する他の開発者と連携し、オープン ソースの TensorFlow プロジェクトに貢献することができます。

TensorFlow を使い始める: 基礎

通常の TensorFlow プログラムを作成し、それをチャンクとして実行できるようになります。これは、Python を使用している場合、一見すると少し矛盾しているように見えるかもしれません。ただし、必要に応じて、TensorFlow のインタラクティブ セッションを使用することもできます。これにより、TensorFlow でよりインタラクティブな操作を実行できます。これは、IPython に慣れると非常に便利です。

このチュートリアルでは、2 番目のオプションに焦点を当てます。これは、TensorFlow を使用したディープラーニングの開始に役立ちます。しかし、始める前に、まずは軽量級のトレーニングを試してから、重量級のトレーニングに移りましょう。

まず、前のセクションで見たように、エイリアス tf で tensorflow ライブラリをインポートします。次に、実際には定数である 2 つの変数が初期化されます。 4 つの数値の配列を constant() 関数に渡します。

注: 整数を渡すこともできますが、通常は配列を操作することはありません。はじめに述べたように、テンソルは配列に関するものです。そのため、配列を渡すようにしてください。次に、multiply() を使用して 2 つの変数を乗算します。結果は result 変数に格納されます。最後に、print() 関数を使用して結果が表示されます。

注: 上記の DataCamp Light コード ブロックでは定数を定義しましたが、プレースホルダーと変数という他の 2 種類の値も使用できます。プレースホルダーは、セッションの実行を開始するときに初期化される未割り当ての値です。名前が示すように、これはセッションの実行中に常に供給されるテンソルの単なるプレースホルダーです。変数とは、値が変化する可能性のある量です。上記で見た定数の値は変更されません。

これらの数行のコードの結果は、計算グラフ内の抽象テンソルです。しかし、予想に反して、結果は実際には計算されません。モデルを定義するだけで、結果を計算するためのプロセスは実行されません。表示出力を見ると、期待する結果 (30 など) が存在しないことがわかります。これは、TensorFlow の評価が遅延していることを意味します。

ただし、実際に結果を確認したい場合は、対話型セッションでコードを実行する必要があります。これを行うにはいくつかの方法がありますが、DataCamp Light コード ブロックでは次のようになります。

注: 次のコードを使用すると、対話型セッションを開始し、結果を実行し、出力を表示した後にセッションを自動的に閉じることができます。

上記のコード ブロックでは、デフォルトのセッションを定義しましたが、オプションを渡すこともできることに注意してください。たとえば、config パラメータを指定し、ConfigProto プロトコル バッファを使用してセッションに構成オプションを追加できます。

たとえば、セッションに config=tf.ConfigProto(log_device_placement=True) を追加すると、操作が割り当てられている GPU および CPU デバイスをログに記録できるようになります。その後、そのセッションの各操作にどのデバイスが使用されたかを確認できます。たとえば、デバイス構成にソフト制約を使用する場合は、次の構成セッションも使用できます: config=tf.ConfigProto(allow_soft_placement=True)。

TensorFlow をインストールしてワークスペースにインポートしたので、パッケージの操作の基本を理解できました。今こそ方向を調整し、データに注意を払うときです。他のことと同様、ニューラル ネットワークのモデリングを開始する前に、まず時間をかけてデータを調査して理解を深める必要があります。

ベルギーの交通標識:背景

交通は一般的によく知られているトピックですが、始める前にこのデータセットのデータにざっと目を通し、すべてを理解しているかどうかを確認することも役立ちます。基本的に、このセクションでは、このチュートリアルをさらに進めるために必要なドメイン知識の概要を簡単に説明します。

もちろん、私はベルギー人なので、ベルギーの交通標識データを使用しました。ここにいくつかの興味深い逸話があります:

  • ベルギーの交通標識は通常オランダ語とフランス語で書かれています。これは確かに知っておくと良いことですが、操作するデータセットにとっては重要ではありません。
  • ベルギーの交通標識は、警告標識、優先標識、禁止標識、義務標識、駐車や道路上での待機に関する標識、看板の 6 つのカテゴリに分かれています。
  • 2017年1月1日、ベルギーでは3万以上の交通標識が撤去されました。どちらも速度に関する優先標識です。
  • 撤去といえば、交通標識の数が多すぎることはベルギー(ひいてはEU全体)で長い間議論されてきた話題だ。

データの読み込みと探索

背景情報が少しわかったので、データをダウンロードしてみましょう: http://btsd.ethz.ch/shareddata/。分類用 BelgiumTS (切り取られた画像) の右側にある 2 つのアーカイブ (BelgiumTSC_Training と BelgiumTSC_Testing) をダウンロードする必要があります。

ヒント: すでにファイルをダウンロードしている場合、またはこのチュートリアルを完了した後にダウンロードする場合は、ダウンロードしたデータのフォルダー構造を確認してください。テスト データ フォルダーとトレーニング データ フォルダーには 61 個のサブフォルダーが含まれています。これらは、このチュートリアルの分類タスクで使用する 62 種類の交通標識です。さらに、これらのファイルには、Portable Pixmap Format の略である .ppm というファイル拡張子が付いています。交通標識の画像をダウンロードしました。

まず、このデータをワークスペースにインポートしてみましょう。まず、ユーザー定義関数 (UDF) load_data() の下に表示されるコード行から始めましょう。

  • まず、ROOT_PATH を設定します。このパスは、トレーニング データとテスト データが含まれるディレクトリです。
  • 次に、join() 関数を使用して、ROOT_PATH に特定のパスを追加できます。これら2つの特定のパスをtrain_data_directoryとtest_data_directoryに保存します。
  • その後、load_data() 関数を呼び出して、train_data_directory を引数として渡すことができます。
  • ここで、load_data() が起動し、train_data_directory のすべてのサブディレクトリを独自に収集し始めます。これは、リストを作成する自然な方法であるリスト内包表記の助けを借りて行われます。基本的に、これは次のことを意味します: train_data_directory で何かが見つかった場合は、これがディレクトリであるかどうかを再確認し、そうであれば、リストに追加します。注: 各サブディレクトリはタグを表します。
  • 次に、これらのサブディレクトリをループする必要があります。まず、ラベルと画像の 2 つのリストを初期化する必要があります。次に、これらのサブディレクトリへのパスと、そこに保存されている画像のファイル名を収集します。その後、append() 関数を使用して両方のリストのデータを収集できます。
  1. def load_data(データディレクトリ):
  2. ディレクトリ = [d for d in os.listdir(data_directory)
  3. os.path.isdir( os.path.join (data_directory, d))]
  4. ラベル = []
  5. 画像 = []
  6. ディレクトリ内のdの場合:
  7. ラベルディレクトリ = os.path.join (データディレクトリ、d)
  8. ファイル名 = [ os.path.join (label_directory, f)
  9. os.listdir(label_directory)内のfの場合
  10. f.endswith( ".ppm" )]の場合
  11. file_names内のfの場合:
  12. 画像を追加します(skimage.data.imread(f))
  13. ラベル.append( int (d))
  14. 画像、ラベルを返す
  15.  
  16. ROOT_PATH = "/your/root/path"  
  17. train_data_directory = os.path.join (ROOT_PATH、 "TrafficSigns/Training" )
  18. test_data_directory = os.path.join (ROOT_PATH、 "TrafficSigns/Testing" )
  19.  
  20. 画像、ラベル = load_data(train_data_directory)

上記のコード ブロックでは、トレーニング データとテスト データがそれぞれ Training および Testing という名前のフォルダーに配置されており、どちらも TrafficSigns という別のディレクトリのサブディレクトリであることに注意してください。ローカル マシンでは、パスは次のようになります: /Users/yourName/Downloads/TrafficSigns、その後に 2 つのサブフォルダー (Training と Testing) が続きます。

交通標識統計

データが読み込まれたら、データの検査を行います。まず、画像配列の ndim 属性と size 属性を使用して、かなり簡単な分析を行うことができます。

画像とラベルの変数はリストなので、ワークスペース内でこれらの変数を配列に変換するには np.array() を使用する必要があることに注意してください。ここではすでに完了しています!

注: images[0] 応答出力は、実際には配列内の配列によって表される単一の画像です。これは最初は直感に反するように思えるかもしれませんが、機械学習やディープラーニングアプリケーションにおける画像操作についての理解が深まるにつれて、慣れてきます。

次に、ラベルをざっと見てみましょう。ただし、それほど驚く必要はありません。

これらの数値から、インポートがどの程度成功したか、データの正確なサイズがわかります。一見すると、すべてが期待どおりに動作しているように見えますが、配列の配列を扱っていることを考慮すると、配列のサイズがかなり大きいことがわかります。

ヒント: 配列に次の属性を追加してみてください。メモリ レイアウト、配列要素のバイト長、消費された合計バイト数に関する詳細情報を取得するには、flags、itemsize、nbytes 属性を使用します。上記の DataCamp Light ブロックの IPython コンソールでこれらのプロパティをテストできます。

次に、これらの交通標識データの分布を確認することもできます。

素晴らしいです!では、ヒストグラムを詳しく見てみましょう。

このデータセットでは、すべての種類の交通標識が均等に表現されていることがはっきりとわかります。これは、ニューラル ネットワークのモデリングを開始する前にデータを操作する際に後で処理する必要があるものです。

一見すると、このデータセット内の一部のラベルが他のラベルよりも重要度が高いことがわかります。ラベル 22、32、38、および 61 が明らかに目立っています。今のところこれを念頭に置いてください。次のセクションでさらに詳しく学習します。

交通標識データの視覚化

これまでの簡単な分析と検査で、すでにデータについてある程度理解できましたが、データが基本的に画像で構成されている場合は、データを視覚的に調査する必要があります。

まず、いくつかの交通標識を見てみましょう。

  • まず、共通エイリアス plt の下の matplotlib パッケージから pyplot モジュールをインポートしていることを確認します。
  • 次に、4 つのランダムな数字を含むリストを作成する必要があります。これらは、前のセクションで調べた交通標識を画像配列から選択するために使用されます。この場合、300、2250、3650、4000 を選択します。
  • 次に、リストの長さ (0 から 4 まで) の各要素に対して、軸のないサブプロットを作成します (すべてに焦点を合わせるのではなく、画像だけに焦点を当てるため)。これらのサブ図では、インデックス i の番号に対応する画像配列内の特定の画像を表示します。ループの最初のパスでは、images[] に 300 を渡し、2 番目のパスでは 2250 を渡すというようになります。最後に、サブプロット間に十分な幅が確保されるようにサブプロットを調整する必要があります。
  • 最後に、show() 関数を使用してチャートを表示します。

コードは次のとおりです。

  1. # `matplotlib``pyplot` モジュールをインポートします
  2. matplotlib.pyplot をpltとしてインポートします。
  3.  
  4. #表示したい画像(ランダムな)インデックスを決定します
  5. 交通標識 = [300, 2250, 3650, 4000]
  6.  
  7. #定義したランダムな画像サブプロットを埋めます
  8. i が範囲(len(traffic_signs))内である場合:
  9. plt.subplot(1, 4, i+1)
  10. plt.axis( 'オフ' )
  11. plt.imshow(画像[交通標識[i]])
  12. plt.subplots_adjust(wspace=0.5)
  13.  
  14. plt.show()

データセットには 62 個のラベルが含まれているため、交通標識はそれぞれ異なるものであると推測できます。

しかし、他に何に気づきましたか? 下の画像を詳しく見てみましょう:

[[198757]]

4 つの画像のサイズが同じではありません。

明らかに、traffic_signs リストに含まれる数字を調整して、この観察をより包括的に追跡することもできます。しかし、実際には、これは重要な観察であり、データをニューラル ネットワークに入力するためにデータを操作するときには考慮する必要があります。

これらのサブグラフに含まれる特定の画像の形状、最小値、最大値を出力して、画像のサイズが異なるという仮定を確認しましょう。

次のコードは、上の図を作成するために使用したコードと非常に似ていますが、違いは、画像を次々に描画するのではなく、サイズと画像を交互に描画することです。

  1. # `matplotlib` をインポートする
  2. matplotlib.pyplot をpltとしてインポートします。
  3.  
  4. #画像(ランダムな)インデックスを決定する
  5. 交通標識 = [300, 2250, 3650, 4000]
  6.  
  7. #ランダムな画像サブプロット埋め 形状を追加最小 そして 最大 価値観 
  8. i が範囲(len(traffic_signs))内である場合:
  9. plt.サブプロット(1, 4, i+1)
  10. plt.axis( 'オフ' )
  11. plt.imshow(画像[交通標識[i]])
  12. plt.subplots_adjust(wspace=0.5)
  13. plt.show()
  14. print( "形状: {0}、最小: {1}、最大: {2}" .format(images[traffic_signs[i]].shape,
  15. 画像[交通標識[i]]. min ()、
  16. 画像[交通標識[i]]. max ()))

注: 定義したパラメータ {0}、{1}、および {2} を入力するために、shape: {0}、min: {1}、max: {2} 文字列で format() メソッドを使用する方法。

ここまで、画像の概要を見てきましたが、データ探索の最初に出力したヒストグラムをもう一度見てみましょう。これは、全体で 62 クラスすべてをプロットし、各クラスに属する 1 つの画像を表示することで簡単に行うことができます。

  1. # `pyplot` モジュール`plt`としてインポートします
  2. matplotlib.pyplot をpltとしてインポートします。
  3.  
  4. #ユニークなラベルを取得する
  5. unique_labels =セット(ラベル)
  6.  
  7. # 図を初期化する
  8. plt.figure(図のサイズ=(15, 15))
  9.  
  10. #カウンターを設定する
  11. 私 = 1
  12.  
  13. #それぞれの固有のラベルについて
  14. unique_labelsラベルの場合:
  15. #各ラベル最初の画像を選択します
  16. image = 画像[ labels.index (ラベル)]
  17. # 64個のサブプロットを定義する
  18. plt.subplot(8, 8, i)
  19. # 軸を含めない
  20. plt.axis( 'オフ' )
  21. #各サブプロットタイトルを追加する
  22. plt.title( "ラベル {0} ({1})" .format (label, labels.count (label)))
  23. #カウンター1を加える
  24. 私 += 1
  25. #そしてこの最初の画像をプロットします
  26. plt.imshow(画像)
  27.      
  28. # プロットを表示
  29. plt.show()

注: 64 個のサブグラフを定義しても、すべてのサブグラフに画像が表示されるわけではありません (ラベルは合計で 62 個しかないため)。もう一度言いますが、読者の注意がメインの主題である交通標識から逸れないようにするために、軸を含める必要はありません。

上記のヒストグラムから基本的に推測できるように、ラベル 22、32、38、および 61 の交通標識の方がはるかに多くあります。上記の仮定はこの画像で確認されています。ラベル 22 には 375 個のインスタンスが、ラベル 32 には 316 個のインスタンスが、ラベル 38 には 285 個のインスタンスが、ラベル 61 には 282 個のインスタンスがあることがわかります。

興味深い質問としては、これらすべての事例の間に何らかの関連性があるか、あるいはそれらはすべて指標なのだろうか、というものがあります。

詳しく見てみましょう。ラベル 22 と 32 は禁止標識であり、ラベル 38 と 61 はそれぞれ指示標識と優先標識であることがわかります。つまり、4 つの間には直接的なつながりはありませんが、禁止標識が多数存在し、データセットの半分を占めています。

特徴抽出

データの調査が終わったので、次はそれを実践してみましょう。途中で忘れた手順がないか確認するために、調査結果を簡単に確認してみましょう。

  • 画像のサイズが異なります。
  • ラベルまたはターゲット値は 62 個あります (ラベルは 0 から始まり 61 で終わるため)。
  • 交通標識の値の分布は非常に不均衡です。データセットには、実際には相互に何のつながりもない標識が多数あります。

何を改善する必要があるかがよくわかったので、データを処理してニューラル ネットワークや使用したいモデルで使用できるようにします。画像のサイズを変更し、画像配列でグレースケールに変換します。この色変換を行う主な理由は、解決しようとしている分類問題の種類では色が大きな役割を果たさないからです。しかし、検出タスクでは、色が大きな役割を果たします。したがって、これらの場合には、このような変換は必要ありません。

画像のサイズ変更

画像サイズが異なる問題を解決するには、画像のサイズを変更する必要があります。 skimage または Scikit-Image ライブラリを使用すると、これを簡単に実現できます。Scikit-Image は、画像処理用のアルゴリズムのコレクションです。

この場合、resize() 関数を提供する transform モジュールが便利です。リストの内包表記 (再び!) を使用して各画像を 28×28 ピクセルにサイズ変更することがわかります。もう一度、リストを実際に構築する方法を確認します。images 配列で見つかった各画像に対して、skimage ライブラリから借用した変換操作を実行できます。最後に、結果を images28 変数に保存します。

  1. # `skimage`から`transform` モジュールをインポートします
  2. skimageからインポート変換
  3.  
  4. # `images`配列内の画像のサイズを変更する
  5. images28 = [transform.resize(image, (28, 28)) 画像内の画像]

シンプルですよね?

注: 画像は 4 次元になりました。images28 を配列に変換し、それに属性 shape を連結すると、出力で images28 の次元が (4575, 28, 28, 3) であることがわかります。これらの画像は 784 次元です (画像が 28×28 ピクセルであるため)。

上記で使用したコードを再利用して、traffic_signs 変数を使用して 4 つのランダムな画像のグラフを生成することで、サイズ変更操作を確認できます。すべての参照を images から images28 に変更することを忘れないでください。

結果は次のとおりです。

注: サイズを変更したため、最小値と最大値が変更されました。これで、すべて同じ範囲内に表示されるようになりました。これは、データを正規化する必要がなくなったため、非常に良いことです。

画像をグレースケールに変換する

このセクションの冒頭で述べたように、分類問題を解決する際に画像の色はそれほど重要な役割を果たしません。したがって、画像をグレースケールに変換する手間もかかります。ただし、この手順を実行しなくても、モデルの最終結果にどのような影響があるかを自分で試してみることもできます。画像のサイズ変更と同様に、Scikit-Image ライブラリを使用してこの問題を解決することもできます。この場合、必要な場所でカラー モジュールの rgb2gray() 関数を使用します。これは本当にうまく機能し、とても簡単です!

ただし、rgb2gray() 関数は配列を引数として受け取らないため、image28 変数を配列に変換することを忘れないでください。

  1. # `skimage.color`から`rgb2gray` をインポートします
  2. skimage.colorからrgb2grayをインポート
  3.  
  4. # `images28`配列変換する
  5. 画像28 = np.array(画像28)
  6.  
  7. # `images28`グレースケール変換する
  8. 画像28 = rgb2gray(画像28)

画像のグラフをいくつか出力して、グレースケール変換を再度確認します。ここで、コードを再利用して少し調整し、調整された画像を表示できます。

  1. matplotlib.pyplot をpltとしてインポートします。
  2.  
  3. 交通標識 = [300, 2250, 3650, 4000]
  4.  
  5. i が範囲(len(traffic_signs))内である場合:
  6. plt.サブプロット(1, 4, i+1)
  7. plt.axis( 'オフ' )
  8. plt.imshow(images28[交通標識[i]], cmap= "グレー" )
  9. plt.subplots_adjust(wspace=0.5)
  10.      
  11. # プロットを表示
  12. plt.show()

注: グラフとしてグレースケール画像を表示するには、カラーマップ (つまり cmap) を指定してグレーに設定する必要があります。これは、imshow() がデフォルトでヒートマップのようなカラーマップを使用するためです。詳細については、https://stackoverflow.com/questions/39805697/skimage-why-does-rgb2gray-from-skimage-color-result-in-a-colored-image を参照してください。

ヒント: このチュートリアルではこの関数を何度も再利用しているので、どのように関数化したかがわかります :)

これら 2 つの手順は非常に基本的なものです。データに対して試すことができるその他の操作には、データ拡張 (回転、ぼかし、シフト、明るさの変更など) などがあります。必要に応じて、画像の送信方法によってデータ操作フロー全体を設定することもできます。

TensorFlow によるディープラーニング

データの調査と操作が完了したら、TensorFlow パッケージを使用してニューラル ネットワーク アーキテクチャを構築します。

ニューラルネットワークのモデリング

Keras と同じように、今度はニューラル ネットワークをレイヤーごとに構築します。

まだ試していない場合は、まず、規則エイリアス tf を使用して tensorflow をワークスペースにインポートします。その後、Graph() を使用してグラフを初期化できます。この関数を使用して計算を定義できます。このグラフだけの場合は、値が保持されていないため、何も計算できないことに注意してください。後で実行する操作を定義するだけです。

この場合、as_default() を使用してデフォルトの背景を設定できます。これにより、この特定のプロットをデフォルトのプロットにする背景マネージャーが返されます。同じプロセスで複数のグラフを作成する場合も、このアプローチを使用できます。この機能を使用すると、新しいグラフを明示的に作成しない場合は、追加されるすべての操作に対してグローバルなデフォルト グラフが設定されます。

  • 次に、グラフに操作を追加できます。 Keras では、最初にモデルを構築し、コンパイル時に損失関数、オプティマイザー、メトリックを定義する必要があります。 TensorFlow を使用すると、これを 1 つのステップで実行できます。
  • まず、「実際の」データをまだ入力していないため、入力とラベルのプレースホルダーを定義します。プレースホルダーは、実行時にセッションによって初期化される未割り当ての値であることを覚えておいてください。したがって、セッションを最後まで実行すると、これらのプレースホルダーは run() 関数で渡したデータセットから値を取得します。
  • 次にネットワークを構築します。まず、flatten() 関数を使用して入力を平坦化します。これにより、グレースケール画像の形状である [None, 28, 28] ではなく [None, 784] の形状を持つ配列が生成されます。
  • 入力を平坦化した後、サイズ[None、62]のロジットを生成する完全接続層を構築します。 Logits は、以前のレイヤーのスケールされていない出力に対して動作し、相対スケールを使用して単位が線形であるかどうかを理解する関数です。
  • 多層パーセプトロンを構築したので、損失関数を定義できます。損失関数の選択は、手元のタスクに依存します。この場合、sparse_softmax_cross_entropy_with_logits()を使用できます。これは、ロジットとラベルの間のスパースソフトマックスクロスエントロピーを計算します。言い換えれば、カテゴリが相互に排他的である離散分類タスクの確率誤差を測定します。これは、各エントリが個別のカテゴリであることを意味します。この場合、トラフィックサインには1つのラベルのみがあります。これを念頭に置いて、回帰は連続値を予測するために使用されますが、分類は個別の値またはデータポイントのクラスを予測するために使用されます。この関数は、テンソル内の各要素の平均を計算するresid_mean()でラップできます。
  • また、トレーニングオプティマイザーを定義する必要があります。選択したアルゴリズムに応じて、学習率や勢いなど、特定のパラメーターを調整する必要があります。この場合、Adamを選択し、学習率を0.001として定義します。
  • 最後に、トレーニングに入る前に、実行する操作を初期化できます。

Tensorflowを使用して、最初のニューラルネットワークを作成しました!

  1. #「tensorflow」をインポートします
  2. テンソルフローをtfとしてインポートする
  3.  
  4. #プレースホルダーを初期化します
  5. x = tf.placeholder(dtype = tf.float32、shape = [none、28、28])
  6. y = tf.placeholder(dtype = tf.int32、shape = [none])
  7.  
  8. #入力データをフラット化します
  9. Images_flat = tf.contrib.layers.flatten(x)
  10.  
  11. #完全に接続されたレイヤー
  12. logits = tf.contrib.layers.fuly_connected(images_flat、62、tf.nn.relu)
  13.  
  14. #損失関数を定義します 
  15. loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(labels = y、
  16. ロジット=ロジット))
  17. #オプティマイザーを定義します
  18. train_op = tf.train.adamoptimizer(Learning_rate = 0.001).minimize(loss)
  19.  
  20. ロジットをラベルインデックス変換します
  21. record_pred = tf.argmax(logits、1)
  22.  
  23. #精度メトリックを定義します
  24. 精度= tf.reduce_mean( tf.cast (record_pred、tf.float32)))

必要に応じて、ほとんどの変数の値を印刷して、作成したものをすばやく理解して確認できます。

  1. print( "images_flat:" 、images_flat)
  2.  
  3. print( "logits:" 、logits)
  4.  
  5. print( "loss:" 、loss)
  6.  
  7. print( "Predicted_labels:" 、recort_pred)

ヒント:「モジュール 'Pandas'には属性「計算」がない」などのエラーメッセージが表示されている場合、コマンドラインにPIPインストールダスクを実行してDaskパッケージをアップグレードできます。詳細については、この投稿を参照してください:https://stackoverflow.com/questions/43833081/attributeerror-module-object-has-no-attribute-computation

ニューラルネットワークの実行

レイヤーごとにモデルレイヤーを作成したので、これを実行するには、最初にセッション()を使用してセッションを初期化する必要があります。次に、前のセクションで定義された初期化操作init変数を渡し、()を実行し、関数を介してセッションを実行します。

次に、これらの初期化されたセッションを使用して、エポックまたはトレーニングループを開始できます。この場合、最新のloss_valueを登録する必要があるため、201を選択できます。トレーニングオプティマイザーと損失(または精度)メトリックを使用してこのセッションを実行します。 Feed_dictパラメーターを渡すこともできます。これは、データをモデルに渡すために使用できます。 10個の時代ごとに、モデルの損失またはコストに関する詳細情報を提供するログが表示されます。

Tensorflowの基本セクションでわかるように、セッションを手動で閉じる必要はありません。ただし、別の設定を試してみたい場合は、セッションをsessとして定義する場合、次のコードブロックと同じように、sess.close()を使用する必要がある場合があります。

  1. tf.set_random_seed(1234)
  2. sess = tf.Session()
  3.  
  4. sess.run(tf.global_variables_initializer())
  5.  
  6. 範囲Iのために(201):
  7. print( 'epoch' 、i)
  8. _、quarchacy_val = sess.run([train_op、surcosity]、feed_dict = {x:images28、y:labels})
  9. Iの場合、10 == 0の場合:
  10. print( "loss:" 、loss)
  11. print( 'エポックで完了'

次のコードを実行することもできますが、このチュートリアルの紹介で見ることができるように、このコードはすぐにセッションを閉じます。

  1. tf.set_random_seed(1234)
  2.  
  3. tf.Session()を sessとして使用:
  4. sess.run(tf.global_variables_initializer())
  5. 範囲Iのために(201):
  6. _、loss_value = sess.run([train_op、loss]、feed_dict = {x:images28、y:labels})
  7. Iの場合、10 == 0の場合:
  8. print( "loss:" 、loss)

注:intialize_all_variables()関数が推奨されないため、global_variables_initializer()を使用します。

あなたはあなたのモデルをうまく訓練したので、そうです!

あなたのニューラルネットワークを評価します

トレーニングは終わりではありません。この場合、ランダムな10画像を選択し、予測されたタグと実際のタグを比較することにより、モデルのパフォーマンスを単純に理解できます。

最初に出力を表示できますが、Matplotlibを使用してトラフィックサイン自体のグラフを取得して視覚的な比較を行いませんか?

  1. #インポート `matplotlib`
  2. matplotlib.pyplot をpltとしてインポートします。
  3. ランダムにインポート
  4.  
  5. #10のランダム画像を選択します
  6. sample_indexes = random.sample(range(mage28))、10)
  7. sample_images = [images28 [i] for i in sample_indexes]
  8. sample_labels = [ sample_indexesiラベル[i]]
  9.  
  10. 「recort_pred」操作を実行します
  11. Predicted = sess.run([record_pred]、feed_dict = {x:sample_images})[0]
  12.                          
  13. リアルを印刷します 予測ラベル
  14. 印刷(sample_labels)
  15. 印刷(予測)
  16.  
  17. #予測グラウンドトゥルースを視覚的に表示します。
  18. fig = plt.figure(figsize =(10、10))
  19. 範囲のi len(sample_images)):
  20. Truth = sample_labels [i]
  21. 予測=予測[i]
  22. plt.subplot(5、2,1+i)
  23. plt.axis( 'off'
  24. color = 'green' truth == prediction else   '赤'  
  25. plt.text(40、10、 "Truth:{0} \ nprediction:{1}" .Format(Truth、Prediction)、
  26. fontsize = 12、color = color)
  27. plt.imshow(sample_images [i]、cmap = "gray"
  28.  
  29. plt.show()

ただし、ランダムな画像を見るだけでは、モデルがどのように機能するかについてのアイデアが得られません。したがって、テストデータをロードする必要があります。

  1. #「スキメージ」をインポートします
  2. スキメージのインポート変換から
  3.  
  4. テストデータをロードします
  5. test_images、test_labels = load_data(test_data_directory)
  6.  
  7. #画像を28 x 28ピクセル変換します
  8. test_images28 = [transform.resize( image 、(28、28)) for test_images ]
  9.  
  10. 変換する グレースケール
  11. Skimage.ColorインポートRGB2Grayから
  12. test_images28 = rgb2gray(np.array(test_images28))
  13.  
  14. 完全なテストセットに対して予測を実行します
  15. Predicted = sess.run([record_pred]、feed_dict = {x:test_images28})[0]
  16.  
  17. #正しい一致を計算します
  18. match_count = sum ([ int (y == y_) y、y_ in zip(test_labels、predicted)])))
  19.  
  20. #精度を計算します
  21. 精度= match_count / len(test_labels)
  22.  
  23. #精度を印刷します
  24. print( "精度:{:.3f}" .format(精度)))

注:このチュートリアルの冒頭で定義したLoad_Data()関数を使用する必要があります。

sess.close()を使用してセッションを閉じることを忘れないでください。tf.session()を使用してsess:tensorflowセッションを開始します。

次は何を見ますか?

このチュートリアルでデータセットとモデルの使用を続けたい場合は、以下を試すことができます。

モデルに適用する前に、データに正規化されたLDAを適用します。この提案は、このデータセットを収集して分析した研究者によって書かれたhttp://btsd.eth.ch/shareddata/publications/mathias-ijcnn-2013.pdfからのものです。

このチュートリアルで述べたように、これらのトラフィックサインデータで他のデータ強化操作を実行することもできます。さらに、このネットワークをさらに調整することもできます。現在作成しているネットワークは非常に簡単です。

早期停止:ニューラルネットワークをトレーニングするときは、常にトレーニングとテストエラーに注意してください。両方のエラーが低下して突然上昇したときにトレーニングを停止します - これは、ニューラルネットワークがトレーニングデータに過剰にでもい始めた兆候です。

Nishant Shuklaによって書かれた本「Machine Learning with Tensorflow」を読む必要があります:https://www.manning.com/books/machine-learning-with-tensorflow

ヒント:Tensorflow Playground(http://playground.tensorflow.org)およびTensorboard(https://www.tensorflow.org/get_started/summaries_and_tensorboard)もチェックしてください。

画像の作業を続けたい場合は、DatacampのScikit-Learnチュートリアルをお見逃しなく:https://www.datacamp.com/community/tutorials/machine-rearning-python。また、https://github.com/waleedka/traffic-signs-tensorflow/blob/blob/note/notebook1.ipynbなど、ベルギーのトラフィックサインデータセットを使用する他のチュートリアルをご覧ください。

<<:  TensorFlow で RNN 実装を開く正しい方法

>>:  ディープラーニングを用いた医療画像解析: ファイル形式

ブログ    
ブログ    
ブログ    

推薦する

【WOT2018】蘇寧ドットコム高超:AI技術+短編動画を電子商取引プラットフォームに応用

[51CTO.comより引用] 2013年頃、携帯電話やパソコンに短編動画が大量に登場し、低コスト、...

...

AIとスマート信号機が通勤を変えるかもしれない

世界的なパンデミックの影響で、世界各地でロックダウンが実施されたことにより、街の交通量は減少し、地域...

...

2020年の人工知能レビュー:AIが時代に知性をもたらす

2020年は人工知能(AI)にとって節目の年です。今年、新型コロナウイルス感染症のパンデミックが世界...

機械学習をサポートする 8 つのデータ ウェアハウス

[[399333]] [51CTO.com クイック翻訳]非常に大きなデータセットの場合、理想的な状...

信頼できる GNN を構築するにはどうすればよいでしょうか?最新のレビューはコチラ!信頼できるグラフニューラルネットワーク: 次元、方法、傾向

序文ここ数年、ニューラルネットワークを中心とした人工知能技術は、さまざまな種類のデータを深く掘り下げ...

...

物議を醸すClearview AI:顔認識アプリケーションは民間企業には販売されなくなった

生体認証技術といえば、アメリカの Clearview AI 社を挙げなければなりません。同社は最も包...

NVIDIA DLSS 3.5 がリリースされました!新しいAI「光再構成」は超リアルな光と影を実現し、新旧両方のグラフィックカードでサポートされています。

人工知能は世界を変えており、グラフィックス コンピューティングも例外ではありません。 5 年前、NV...

...

人間と踊る!中国の6団体が制作したヒューマノイドロボットがストリートショーに進出

注意してください、小帥は振り向きましたが、スウェットシャツのフードの中には何もありませんでした。さて...

...

...