HUOXIU

AI入門:ディープラーニング - 基本概念

1. ディープラーニングとは何ですか?

1.1 機械学習





図1:コンピュータが効果的に動作するための一般的な方法。プログラマーがルール(プログラム)を記述し、コンピュータはこれらのルールに従って入力データを適切な答えに変換します。この方法はシンボリック人工知能と呼ばれ、五目並べのような初期のPCゲームのように、明確に定義された論理的問題を解くのに適しています。しかし、画像分類、音声認識、自然言語翻訳など、より複雑で曖昧なタスクでは、明示的なルールを提供することが困難です。

図2:機械学習はこのプロセスを逆転させます。機械は入力データとそれに対応する回答を読み取り、適切なルールを見つけます。機械学習システムはトレーニングされるものであり、明示的にプログラムされるものではありません。例えば、休暇中の写真にタグを追加してこのタスクを自動化したい場合、手動でタグ付けされた多数の写真を機械学習システムに入力することで、特定の写真と特定のタグを関​​連付ける統計的ルールを学習します。

定義: 機械学習とは、フィードバック信号に従って、事前に定義された可能性の空間内で入力データから有用な表現とルールを見つけるプロセスです。





1.2 ディープラーニング

ディープラーニングは、連続する表現層からの学習に重点を置いた機械学習の一分野です。現代のディープラーニングモデルは通常、数十、あるいは数百もの連続した表現層で構成されており、それらはすべてトレーニングデータから自動的に学習されます。対照的に、機械学習は「浅い学習」と呼ばれることもあります。

ディープラーニングでは、これらの階層的表現はニューラルネットワークと呼ばれるモデルを通じて学習されます。ディープニューラルネットワークは、多段階の情報蒸留プロセスと捉えることができます。情報は連続したフィルターを通過し、次第に純度を増していきます。

技術的な定義:データ表現の多層学習方法。





1.3 ディープラーニングの動作原理

a. ニューラルネットワークの重み(レイヤーのパラメータと呼ばれることもあります)にランダムに値を割り当てます。

b. 一連のランダム変換の後、予測値Y'が得られます。

c.損失関数(目的関数またはコスト関数と呼ばれることもあります)を使用して、予測値Y'と真の値Yの間の損失値を取得します。

d. 損失値をフィードバック信号として使用し、オプティマイザーを通じて重み値を微調整することで、現在の例に対応する損失値を削減します。

e. このプロセスを十分な回数 (bd) 繰り返して、損失値が最小となるニューラル ネットワークを取得します。これが、十分にトレーニングされたニューラル ネットワークです。





2. ニューラルネットワークの数学的基礎

2.1 ニューラルネットワークのデータ表現

現在、すべての機械学習システムは、基本的なデータ構造としてテンソルを使用しています。テンソルはこの分野で非常に重要であり、TensorFlowはテンソルにちなんで名付けられています。

テンソルの核となる概念は、データのコンテナであるということです。テンソルは通常、数値データを含むため、数値コンテナと呼ばれます。2階テンソルである行列についてはご存知かもしれません。テンソルは行列を任意の次元に一般化したものです。テンソルの次元は通常、軸と呼ばれます。

テンソルは次の 3 つの主要なプロパティによって定義されます。

: 軸の数。 形状: 各軸に沿ったテンソルのサイズ(要素数)。 データ型(dtype): データ型。float16、float32、float64、unit8、string などになります。
2.1.1 スカラー(0次テンソル)

1 つの数値のみを含むテンソルはスカラー (SCALAR) と呼ばれ、ゼロ次テンソルまたはゼロ次元テンソルとも呼ばれます。

以下はNumPyスカラーです

numpyをnpとしてインポートする
x = np.array(3)x.ndim // 軸: 0、形状: ()
2.1.2 ベクトル(1次テンソル)

数値の配列はベクトルと呼ばれ、1 次テンソルまたは 1 次元テンソルとも呼ばれます。

以下はNumPyベクトルです

x = np.array([4, 1, 5])x.ndim // 軸: 1、形状: (3,)

このベクトルは3つの要素を含むため、3Dベクトルとも呼ばれます。3Dベクトルと3Dテンソルを混同しないでください。3Dベクトルには1つの軸しかなく、その軸に沿って3つの次元があります。

2.1.3 行列(2次テンソル)

ベクトルの配列は行列と呼ばれ、2階テンソル、あるいは2次元テンソルとも呼ばれます。行列には行と列という2つの軸があります。

以下はNumPy行列です

x = np.array([
[4, 6, 7],
[7, 3, 9],
[1, 2, 5]])x.ndim // 軸: 2、形状: (3, 3)

実際のベクトルの例:

ベクトル データ: 形状が (サンプル、特徴) である 2 次テンソル。各サンプルは数値 (特徴) ベクトルであり、ベクトル データベース内の基本的なストレージ単位です。

2.1.4 3階テンソルと高階テンソル

複数の行列を新しい配列に詰め込むと、3 次テンソル (または 3 次元テンソル) が生成されます。

以下は3次NumPyテンソルである

x = np.array([
[[4, 6, 7],
[7, 3, 9],
[1, 2, 5]],
[[5, 7, 1],
[9, 4, 3],
[3, 5, 2]]])x.ndim // 軸: 3、形状: (2, 3, 3)

複数の 3 次テンソルを配列に詰め込むことで 4 次テンソルを作成できます。

実際の例:

時系列データまたはシーケンス データ: 形状 (サンプル、タイム ステップ、特徴) の 3 次テンソル。各サンプルは特徴ベクトルのシーケンスです (シーケンスの長さはタイム ステップです)。

画像データ: 形状の 4 次テンソル (サンプル、高さ、幅、チャネル)。各サンプルはピクセルの 2 次元グリッドであり、各ピクセルは「チャネル」ベクトルによって表されます。

ビデオ データ: 形状の 5 次テンソル (サンプル、フレーム、高さ、幅、チャネル)。各サンプルは画像のシーケンスです (シーケンスの長さはフレームです)。





2.2 ニューラルネットワークの「歯車」:テンソル演算

すべてのコンピュータプログラムは、最終的にはバイナリ入力に対するバイナリ演算に還元できます。同様に、ディープニューラルネットワークによって学習されたすべての変換は、数値データテンソルに対するテンソル演算またはテンソル関数に還元できます。

2.2.1 要素ごとの演算

要素ごとの演算とは、テンソルの各要素に演算を適用することを意味します。演算に関係するテンソルは同じ形状でなければなりません。

 numpyをnpとしてインポートする
z = x + y // 要素ごとの加算 z = x - y // 要素ごとの加算 z = x * y // 要素ごとの積 z = x / y // 要素ごとの除算 z = np.maximum(z, 0.) // 要素ごとの ReLU、出力が 0 より大きい場合は入力と等しく、0 より小さい場合は出力が 0

ルール操作は、よく使用される活性化関数です。rule(x) は max(x, 0) と同等です。入力 x が 0 より大きい場合、出力は入力値と等しくなります。入力 x が 0 以下の場合、出力は 0 になります。

2.2.2 テンソル積

テンソル積、あるいはドット積は、最も一般的で有用なテンソル演算の一つです。要素ごとの乗算と混同しないように注意してください。

NumPyでは、テンソル積は`np.dot`関数を使って実装されます: `z = np.dot(x, y)`

数学的記法では、(·)はドット積演算を表す:z = x · y

2つのベクトルのドット積はスカラー値であり、ドット積演算には要素数が同じベクトルのみを使用できます。 行列xとベクトルyのドット積演算は、各要素がyとxの各行のドット積であるベクトルを返します。 行列xとyの場合、ドット積はx.shape[1] == y.shape[0]の場合にのみ計算できます。結果は形状(x.shape[0], y.shape[1])の行列で、その要素はxの行とyの列のベクトルドット積です。





2.2.3 テンソル変形

テンソル変換とは、テンソルの行と列を並べ替えて目的の形状を得ることを指します。変換後、テンソルの要素数は元のテンソルと同じになります。

 numpyをnpとしてインポートする
x = np.array([[0, 1],
              [23]
[4, 5]])x.shape //(3, 2)x = x.reshape((6, 1))>>> x
配列([[0],
[1]
[2]
[3]
[4]
[5]])x = x.reshape(2, 3)>>> x
配列([[0, 1, 2],
[3, 4, 5]])

テンソル変換の一般的な特殊型は転置です。行列の転置とは、行列の行と列を入れ替えることを指します。つまり、x[i, :]はx[:, i]になります。

 x = np.zeros((300, 20)) // 形状 (300, 20) のゼロ行列を作成します x = np.transpose(x) >>> x.shape(20, 300)
2.2.4 テンソル演算の幾何学的解釈

平行移動、回転、拡大縮小、傾斜などの基本的な幾何学的演算はすべて、テンソル演算として表現できます。





線形変換:任意の行列のドット積演算を実行することで線形変換を実現できます。スケーリングと回転はどちらも線形変換です。 アフィン変換:線形変換と平行移動を組み合わせたものです。 規則活性化関数を用いたアフィン変換:複数のアフィン変換は1つのアフィン変換に相当します。したがって、活性化関数を持たない多層ニューラルネットワークは単層ニューラルネットワークに相当します。この種の「ディープ」ニューラルネットワークは、実際には線形モデルです。





2.2.5 深層学習の幾何学的解釈

ニューラルネットワークは、入力データの幾何学的変換に過ぎない一連のテンソル演算によって構成されています。したがって、ニューラルネットワークは、高次元空間における非常に複雑な幾何学的変換を、一連の単純なステップで実現したものと考えることができます。

機械学習の目標は、高次元空間において複雑で高度に折り畳まれたデータストリーム(連続面)の簡潔な表現を見つけることです。ディープラーニングは、複雑な幾何学的変換を一連の基本的な変換へと段階的に分解することができます。

2.3 ニューラルネットワークの「エンジン」:勾配ベース最適化

第1.3章「ディープラーニングの仕組み」を振り返ると、ステップaは入出力(I/O)コードだけなので簡単そうに見えます。ステップbとcは、テンソル演算を適用するだけです。問題はステップd、つまりモデルの重みの更新にあります。モデル内の特定の重み係数に対して、その係数を増やすべきか減らすべきか、そしてどの程度増やすべきかをどのように判断するのでしょうか?

簡単な解決策は、モデルの他の重みを一定に保ち、スカラー係数を1つだけ考慮し、異なる値を試すことです。このプロセスをモデルのすべての係数に対して繰り返す必要があります。しかし、係数の数が多い(通常は数千、あるいは数百万)ため、このアプローチは非常に非効率的です。幸いなことに、より優れた方法があります。それは、勾配降下法です。

2.3.1 導関数

滑らかで連続的な関数 f(x) = y があるとします。この関数は連続なので、x の小さな変化は y の小さな変化しか引き起こしません。したがって、点 p の近傍において、x の変化が十分に小さい場合、f は傾き a を持つ線形関数として近似できます。

傾き「a」は、点pにおけるfの微分係数と呼ばれます。a < 0の場合、点p付近のxがわずかに増加するとf(x)は減少します。a > 0の場合、点p付近のxがわずかに増加するとf(x)は増加します。







2.3.2 勾配

微分の概念は、関数に対応する曲面が連続かつ滑らかである限り、あらゆる関数に適用できます。テンソル演算の微分は勾配と呼ばれます。スカラー関数の場合、微分は関数の曲線の局所的な傾きを表します。テンソル関数の場合、勾配はその関数に対応する多次元曲面の曲率を表します。

たとえば、時間に対する物体の位置の勾配は物体の速度であり、2 番目の勾配は加速度です。

2.3.3 確率的勾配降下法

ステップdでは、モデルの重みが更新されます。微分可能な関数を扱っていると仮定すると、その勾配を計算し、勾配の反対方向に重みを更新することで、損失が毎回少しずつ減少するようにすることができます。

(1)トレーニングサンプルxと対応するターゲットy_trueのバッチを抽出します。

(2)xに対してモデルを実行し、予測値y_predを得る(順伝播)

(3)このデータバッチに対するモデルの損失値を計算します。

(4)モデルパラメータに対する損失の勾配を計算する(バックプロパゲーション)

(5)損失値を減らすために、パラメータを勾配の反対方向に少し移動します。

この手法はミニバッチ確率的勾配降下法(SGD)と呼ばれます。確率的とは、各バッチのデータがランダムに選択されることを意味します。各反復処理をすべてのデータに対して実行する手法はバッチ勾配降下法と呼ばれますが、計算コストは​​はるかに高くなります。妥協策として、適切なミニバッチサイズを選択します。

ニューラルネットワークにおける各重み係数は、空間上の自由次元です。損失面をより直感的に理解するために、2次元の損失面に沿った勾配降下法を視覚化することができます。しかし、100万次元の空間を人間が理解できる形で視覚化することは不可能であるため、ニューラルネットワークの実際の学習プロセスを視覚化することは不可能です。このような低次元表現に基づく直感は、実際には必ずしも正確ではありません。





2.3.4 連鎖微分:バックプロパゲーション

前のアルゴリズムでは、関数は微分可能(微分できる)と仮定していたため、勾配の計算は簡単でした。しかし、実際には複雑な式の勾配はどのように計算するのでしょうか?ここで、バックプロパゲーションアルゴリズムが登場します。

(1)チェーンルール

単純な演算(加算、規則演算、テンソル積など)の導関数を用いることで、これらの基本演算を複雑に組み合わせた勾配を簡単に計算できます。連鎖律はgrad(y, x) == grad(y, x1) * grad(x1, x)と定義されるため、fとgの導関数が分かれば、fgの導関数を求めることができます。中間関数をさらに追加することで、連鎖律に似たものになります。ニューラルネットワークにおける勾配値の計算に連鎖律を適用すると、バックプロパゲーションと呼ばれるアルゴリズムが得られます。

(2)計算グラフを用いた自動微分

バックプロパゲーションへの有用なアプローチは、計算グラフを活用することです。計算グラフは、TensorFlowとディープラーニング革命における中核的なデータ構造です。計算グラフは、演算で構成される有向非巡回グラフです。TensorFlowのような最新のフレームワークは、計算グラフに基づく自動微分をサポートしており、任意のテンソル演算の組み合わせに対する勾配の計算が可能で、追加の作業なしに順伝播コードのみを記述するだけで済みます。

GradientTapeは、TensorFlowの強力な自動微分機能を最大限に活用できるAPIです。計算グラフ(テープ)内で実行されたテンソル演算を記録するPythonスコープです。

3. 練習: Python の Kears ライブラリを使用して手書きの数字を認識します。

この例では、手書き数字のグレースケール画像(28ピクセル×28ピクセル)を10のカテゴリ(0から9)に分類する問題を解きます。機械学習分野では古典的なデータセットであるMNISTデータセットを使用します。MNIST問題の解決は、ディープラーニングにおける「Hello World」シナリオと考えることができます。

3.1 KearsからMNISTデータセットをロードする

tensorflow.keras.datasets から mnist(train_images, train_labels) をインポートし、(test_images, test_labels) = mnist.load_data() を実行します。

トレーニングセットは `train_images` と `train_labels` で構成され、モデルはこれらから学習します。テストセット `test_images` と `test_labels` でモデルをテストします。

データセットの形状を表示します。

 >>> train_images.shape(60000, 28, 28) // トレーニング セットは、それぞれ 28×28 ピクセルの 60,000 枚の画像で構成されています。 >>> test_images.shape(10000, 28, 28) // テスト セットは、それぞれ 28×28 ピクセルの 10,000 枚の画像で構成されています。

3.2 ニューラルネットワークアーキテクチャモデル

tensorflowからkerasをインポートtensorflow.kerasからレイヤーをインポート
モデル = keras.Sequential([
    layers.Dense(512,activation="relu"),
レイヤー.Dense(10, アクティベーション="softmax")])

ニューラルネットワークの中核となる構成要素はレイヤーです。ほとんどのディープラーニング設計では、単純なレイヤーを連結することで段階的なデータ蒸留を実現し、入力データから表現を抽出します。

この例のモデルには2つのDense層が含まれています。各層は入力データに対していくつかの単純なテンソル演算(ReLU、ソフトマックス)を実行します。これらの演算には重みテンソルが関与します。重みテンソルは各層の属性またはパラメータであり、モデルによって学習された知識を格納します。

3.3 モデルのコンパイル

モデル.コンパイル(
オプティマイザー="rmsprop",
損失="sparse_categorical_crossentropy",
メトリック=["精度"])

これは、コンパイルの 3 つのステップ(オプティマイザー、損失関数、および監視メトリック)を指定します。`sparse_categorical_crossentropy` は、重みテンソルのフィードバック信号を学習するために使用される損失関数です。`rmsprop` オプティマイザーは、ミニバッチ確率的勾配降下法 (SGD)を通じて損失値を減らすために使用されます。

3.4 画像データの準備

train_images = train_images.reshape((60000, 28*28))train_images = train_images.astype("float32") / 255test_images = test_images.reshape((10000, 28*28))test_images = test_images.astype("float32") / 255

トレーニングを始める前に、データを前処理してモデルに必要な形状に変換し、すべての値が [0, 1] の範囲になるようにスケーリングします。

3.5 モデルのフィッティング

model.fit(train_images, train_labels, epochs=5, batch_size=128)

Kerasでは、モデルの`fit`メソッドを呼び出すことで、モデルをトレーニングデータに適合させます。モデルはトレーニングデータ(各ミニバッチには128個のサンプルが含まれます)に対して反復処理を開始し、合計5回の反復処理を行います。各データバッチについて、モデルは重みに対する損失の勾配を計算し、そのバッチに対応する損失値が減少する方向に重みを調整します。5回の反復処理後、トレーニング精度は98.9%に達します。

3.6 予測モデルの使用

>>> test_digits = test_images[0:10]>>> predictions = model.predict(test_digits)>>> predictions[0]//読みやすくするために、以下のデータはすべて例です。array([1.07, 1.69, 6.13, 8.41, 2.99, 3.03, 8.36, 9.99, 2.66, 3.81], dtype=float32)

この配列の各値は、対応する数字画像 test_digits[0] が0~9のカテゴリに属する​​確率を表しています。7番目の値が最も高い確率を持つため、この数値は7である必要があります。テストラベルが一致するかどうかを確認します。

 >>> テストラベル[0]7

3.7 新しいデータでモデルを評価する

>>> test_loss, test_acc = model.evaluate(test_images, test_lables)>>> print(f"test_acc: {test_acc}")test_acc: 0.9785

テスト精度は約97.8%で、トレーニング精度98.9%を大幅に下回りました。このトレーニング精度とテスト精度の差は、過学習によって生じています。

4. 参考文献

書籍: Python によるディープラーニング (第 2 版)

著者:フランソワ・ショーレ(アメリカ)、張良訳

リンク: https://item.jd.com/13378515.html