(セッション#2) 機械学習のための数学

AI入門
この記事は約56分で読めます。

この動画は機械学習における数学の基礎を包括的に解説する講座である。AIを支える4つの数学的柱として線形代数、微積分、確率、統計を取り上げ、それぞれがどのように機械学習で応用されるかを実例とコード実装を交えて説明している。線形代数では行列の基本概念から演算、ニューラルネットワークでの活用まで、微積分では導関数の概念から連鎖律、偏微分による最適化まで、確率統計では条件付き確率からベイズ定理を用いたスパムフィルター実装まで幅広くカバーしている。理論だけでなくNumPyとPyTorchを使った実践的なコーディング例も豊富に含まれており、数学概念を実際の機械学習問題に適用する方法を学べる構成となっている。

(Session #2) Math for Machine Learning
This is Session #2 of our workshop series - Getting Started with Machine LearningIn this session, you will learn about t...

機械学習における数学の重要性

今日は、AI分野でさまざまな状況に応じて適切なアルゴリズムを選択するために必要な数学について学んでいきます。また、この分野に日々投入される最先端の研究技術についても最新の状況を把握できるようになります。

AIを支える数学の4つの主要な柱は、線形代数、微積分、確率、そして統計です。これらについて今日詳しく学んでいきます。もちろん、AIモデルを構築するためには他にも多くの要素がありますが、これらがスタート地点となります。

では、現在の機械学習において数学はどのように使われているのでしょうか。

まず、データの理解です。データそのものを理解することは、AIアプリケーションを構築する上で最も重要な部分です。なぜなら、扱っているデータを理解できなければ、どのようなモデルが必要なのかを理解することは決してできないからです。

データを理解するために、主に線形代数、確率、統計を使用します。そして、モデルの構築を始める前に、データから理解を得るためにそのデータを処理します。そのためには、通常線形代数と微積分を使用します。

モデルの訓練が完了した後、そのモデルが実際に良いものかどうかをどのように確認するのでしょうか。そこでメトリクスを生成します。そのために確率と統計を使用します。

線形代数の基礎

最初のプレイヤーである線形代数から始めましょう。これは、現在見られる多くのAIモデルの基盤を形成しています。

線形代数は、高校で始めた従来の代数とどのように異なるのでしょうか。これら2つの分野の焦点は非常に異なります。通常の代数が数値と単一変数を持つ方程式の解法と式の操作に焦点を当てる一方で、線形代数は主に多変数方程式、つまり複数の変数を持つ方程式に焦点を当てます。また、多変数方程式の背後にある理論の理解にも焦点を当てています。

また、これらの分野で扱う主要なデータオブジェクトも非常に異なります。通常の代数では、主に数値、定数、変数を操作します。しかし、線形代数では、ベクトル、行列、ベクトル空間、線形変換に移行します。これらについては、進めていく中でより詳しく学んでいきます。

また、これらの分野の構造も非常に異なります。通常の代数は通常単一の項目で動作するため、一度に1つの項目を扱うことになります。しかし、線形代数は、オブジェクトのコレクションを同時に操作することで、そのプロセス全体を合理化するため、処理を並列化できます。これについてはすぐに見ていきます。

また、これら2つの分野の応用も大きく異なります。代数は高次数学の基礎を形成します。これが現在私たちの多くがいる場所です。一方、線形代数はコンピューターグラフィックス、データサイエンス、機械学習、物理学などの分野で使用されています。これが今日のセッション終了までに到達したい場所です。

行列とは何か

最初に思い浮かぶ質問は、行列とは何かということでしょう。行列は、データを行と列に整理して、それらの間に非常に意味のある表現を持たせるデータ構造に他なりません。これはどういう意味でしょうか。例を見てみましょう。

簡単な高校の問題を考えてみましょう。6になる3つの数があります。3番目の数に3を掛けて、2番目の数を加えると11になります。そして、1番目と3番目の数を足すと、2番目の数の2倍になります。

これらが、サンプル問題で与えられた3つの条件です。現在の知識に基づいて、これをどのように解決すると思いますか。おそらく、高校で学んだように3つの方程式を作るでしょう。X + Y + Z = 6、ここでX、Y、Zは必要な3つの数です。

次に、2番目の数 + 3 × 3番目の数 = 11となります。再び、1番目の数 + 3番目の数 = 2番目の数の2倍です。これが方程式3です。

現在の知識では、XをYとZで表すかもしれません。次に、そのXの値を方程式3に代入します。そして、そこからYを計算します。

次に、先ほど見つけたY = 2を方程式2に代入してZを求め、その後YとZの値を代入してXを求めます。かなり面倒に思えませんか。これらの変数をそれぞれ別々に計算しており、注目すべきは、2番目の質問にはXさえないということです。これにより作業がとても簡単になります。もしXがあったとしたら、処理がとても難しくなりますよね。

線形代数でこれをどのように行い、どのようにそれが私たちにとって簡単になるのでしょうか。すべての方程式を行列に変換するだけです。データの行と列への整理された表現です。

3つすべての方程式における変数のすべての係数は、すべて関連する量だからです。それらはすべて方程式内の変数の係数だからです。すべて関連するデータ型である係数が1つのデータ構造にグループ化されます。

次に、すべての変数を取ります。これらも再び、すべて同質のデータ型です。それらはすべて未知数で、私たちはそれらを知りません。そこで、それらすべてを取って、単一の行列にグループ化します。

そして、それを係数行列と等しくします。これらもまた、すべて同質のデータ型です。これらはすべて係数であり、方程式ではすべて定数です。そこで、それらすべてを取って、単一の行列に入れます。

このように、類似の表現を持つすべての同質のデータを取り、線形方程式での変数、定数、係数の混合物を持つのではなく、それらすべてを1つのデータ構造にグループ化し、意味のある表現を与えたことがわかります。

行列は、私たちがデータを理解することを非常に簡単にしてくれます。さらに、すべての計算がすべての変数の値を同時に計算することになります。

どのようにそれが起こっているかは、数秒後に行列演算について議論するときに学びますが、今のところ、3つの変数すべてが同時に処理されていることに注目してください。X、Y、Zの値が同時に計算され、まったく同じ答えが得られます。

これが、行列と線形代数が複数の変数を同時に計算するプロセスを並列化できる方法です。

なぜ行列計算が線形方程式を解くよりも優れているのでしょうか。今見たように、構造化されたデータ表現を提供してくれます。データ変換を実装しやすくします。

また、すべての計算を同時に並列化し、すべての変数を同時に計算できるため、処理も高速になります。

また、GPUとの互換性もあります。GPUは並列計算用に設計されたハードウェアデバイスです。これらのハードウェアデバイスは行列の処理に特化しています。

この時点で、これまでのところ質問がある方はいらっしゃいますか。質問はありませんか。素晴らしい、先に進みましょう。

行列とベクトルの詳細理解

行列についてもう少し深く掘り下げて、さらに理解しようと思います。最初に理解する必要があるのは、行列とベクトルの次数とは一体何なのかということです。

行列は、最初のスライドで議論したように、データを行と列に順序付けて表現するデータ構造にすぎません。これにより、同質のデータを単一のデータ構造にまとめ、意味を与えることができます。

線形方程式の例に戻ると、行列を使用して、異なる変数の係数をすべて単一のデータ構造にグループ化しました。これにより、3つの方程式に散らばって変数と掛け合わされ、そこに定数も含まれているのではなく、すべての同質のデータを1か所に配置できました。

これは読みやすくなりますよね。これらすべてが何を表しているかが正確にわかります。これらは変数の係数です。これが私たちにとって読みやすくなる方法がわかりますか。それはただの行列です。単純にデータ構造です。

他に質問はありますか。先に進む前に質問はありますか。行列演算の部分を完了した後、実際にコードに入って、これらの行列を使用していくつかの問題を解決していきます。

他に質問はありますか。はい、どうぞ。2X + Y + Y + Xは可能ですか。

短い答えは、いいえです。方程式の順序も変更できます。たとえば、最初に2番目の方程式を作るとしましょう。それほど重要ではありません。それらは依然として存在します。

方程式の順序は関係ありません。重要なのは、すべての行に係数があることです。つまり、1つの方程式の係数は1つの行にあるべきです。それだけです。

しかし、方程式自体の順序は実際には重要ではありません。なぜなら、この方程式を方程式番号1として定義し、これを2、これを3として定義しただけだからです。しかし、方程式2を方程式1にすることを選択しても、実際には重要ではありません。

それが行列の柔軟性でもあります。順序や順序の変更によって実際には変わりません。少なくとも線形方程式については。

他に質問はありますか。素晴らしい、先に進みましょう。

行列の次数

行列自体をもう少し理解してみましょう。次数と呼ばれるもので始めましょう。次数は機械学習において非常に重要な役割を果たします。これについてはすぐに見ていきます。

行列の次数は、単純に行列に存在する行と列の数です。これは正確には数値ではありません。むしろ記法です。R行とC列を持つ行列の場合、定義する次数はR、C、または一部の人が好んで呼ぶR × Cとなります。

この次数に基づいて、異なるタイプの行列があります。それらが表す形状に基づいてです。

長方形行列は、まさに長方形のように見えます。行数が列数と等しくないため、ここで見る長方形の形状になります。

最初に行数を書き、次に列を書きます。誰かがM × Nの行列を持っていると言ったとき、それは単純に彼らの行列がM行とN列を持つことを意味します。これは私たちが持つ事前定義された慣例です。

1行2列の行列の場合、次数は1,2と言います。2行3列の行列の場合、次数は2,3と言います。3行2列の行列の場合、次数は3,2と言います。

正方行列と呼ばれる特別な種類の行列があります。そのような行列では、行は常に列数と等しくなります。そのような行列はM × Mの形式になります。行数は常に列数と等しく、常に正方形のように見えます。

注目すべきは、次数を使用して行列内の要素数を非常に迅速に計算できることです。行に列数を掛けるだけで、行列にいくつの要素があるかがわかります。1 × 2行列の場合、1 × 2 = 2なので2つの要素があります。2 × 3行列の場合、2 × 3 = 6個の要素があります。

これは行列内の要素数を計算するための非常に便利なツールでもあります。

先に進みましょう。

行列演算

行列は、実数や実数値関数と同様に、ある種の演算も定義します。これらに入る前に、次数について質問がある方はいらっしゃいますか。これは行列演算自体の理解を始めるために非常に重要だからです。

行列演算に入りましょう。行列演算は2つのタイプがあります。1つは行列演算自体で、2つ目は要素ごとの行列演算です。

要素ごとの行列演算から始めましょう。名前が示すように、これらの演算は2つの行列の対応する各要素に適用されます。これらの演算はすべて二項演算であり、2つの入力を必要とします。

行列Aと行列Bがあり、それらを同時に操作し、それらに対して何らかの演算を実行しようとしています。それが単純に要素ごとの演算の意味です。

要素ごとの演算は、AとBの両方が同じ次数、つまり同じ形状を持つ場合にのみ定義されます。なぜでしょうか。

要素ごとの演算は、両方の行列の対応する要素で動作しているからです。行列Aの各要素に対して、その演算が成功するためには、行列Bに対応する要素が存在する必要があります。

つまり、Aの1行目に存在するすべての要素に対して、Bの1行目にも要素が存在する必要があります。同じ論理を異なる行に適用すると、自動的に同じ形状になります。これは、これらの演算が定義されるためには、両方の行列がまったく同じ形状を持つ必要があることを意味します。

要素ごとの演算は、想像できる任意の算術演算に対して定義されます。掛け算、割り算、足し算、引き算。すべてが要素ごとの演算で定義されます。もちろん、これらの演算自体の規則は依然として適用されるため、0で割ることはできません。ここに1があり、この5が代わりに0だった場合、これらの除算は定義されないでしょう。なぜなら1を0で割ると無限大になるからです。

実数の演算の古典的な規則は依然として適用されます。

この場合、要素ごとの加算の例があります。しかし、これを掛け算、加算、減算、除算、好きなものに変更できます。

要素ごとの演算の動作方法は、どの行、どの列からでも要素を選択します。次に、2番目の行列の対応する要素を選択し、その演算(どのようなものであれ)をそれらに適用します。1と5に対して、1 + 5を適用し、それが6になります。残りの要素についても同様です。

要素ごとの演算はこれほど簡単です。

先に進みましょう。

ドット積(行列の掛け算)

これは今日学ぶ行列の最も重要な演算の1つです。ドット積です。ドット積により、2つの行列を一緒に掛けることができます。要素ごとではなく、2つの行列を一緒に掛けることができます。

これには異なる規則のセットがあります。これは、それ自体で異なる規則のセットに対して定義されています。行列の掛け算が定義されるための最初で最も重要な規則は、掛けている最初の行列の列が2番目の行列の行と一致する必要があることです。

繰り返します。注目すべきは、掛ける行列の順序がここでは重要だということです。最初の行列の列数は、2番目の行列の行数と等価でなければなりません。

この点について今質問がある方はいらっしゃいますか。

はい、どうぞ。今はボックスを見ていないので、ここの次数だけに注目してください。次数だけを見ています。覚えているように、次数はR × Cで、行 × 列ですよね。

最初の行列の列、つまりここの次数の2番目の要素が、2番目の行列の行、つまりここの最初の要素と等しくなければならないと言っています。

これから2を選びます。なぜならそれがここの次数の2番目の要素だからです。2番目の行列から再び2を選びます。なぜならそれが最初の要素、つまりここの次数の最初の要素だからです。2は2と等しいので、ここで行列の掛け算が定義されます。どうぞ。

それについては今やります。実際に計算する方法を今学びますが、まず、行列のドット積がいつ定義されるかを理解しましょう。

これについて皆さん明確ですか。実際にいつ定義されるかについて質問はありますか。なぜなら、ニューラルネットワークの開発を始める将来の講義でこれを広範囲に使用するからです。

はい、どうぞ。はい、もちろんです。

行列の掛け算が定義されるための最初の規則は、掛けている最初の行列の列数が、掛けている2番目の行列の行数と等しくなければならないということです。

先ほど行った次数の議論に戻りましょう。行列の次数がR × Cとして定義されると言いました。ここでRは行数、Cは列数です。この定義をここのこの行列の次数に適用すると、次数は2,2です。最初の2は行数で、2番目の2は列数です。

行列Bについても同様です。最初の2は行数です。3は列数です。

ここで規則を適用すると、最初の行列の列数、つまりここのこの2は、2番目の行列の行数、つまりここのこの2と等しくなければなりません。2は2と等しいので、行列AとBに対してドット積が定義されると言えます。

行列を掛け始める前に、最初に行うことは、実際にその2つの行列をドット積できるかどうかを確認することです。その2つの行列に対してドット積が定義されているかどうか確認します。

これについてもっと質問はありますか。よし、先に進みましょう。

ドット積が実際に定義されていることを確認したので、実際にドット積を計算する方法に進みましょう。

その方法は、最初の行列から行を取り、2番目の行列の列でそれを掛けます。つまり、逆さのL字形を形成します。それがドット積を計算する単純な規則です。

これはトリックではなく、私が考え出したものでもありません。いいえ、それがドット積を行う単純な規則です。行を取り、対応する列でそれを掛けます。

たとえば、ここの最初の行と最初の列の要素を計算しようとしているとします。最初の行列から最初の行を選びます。そして、2番目の行列から最初の列を選びます。なぜなら、ここは最初の行と最初の列だからです。

2列目だが最初の行を計算している場合は、最初の行列から最初の行を取り、2番目の行列から2列目を取ります。

覚えておくべき一般的な経験則は、計算している行については、最初の行列からその行を選ぶということです。計算している列については、2番目の行列からその列を選ぶと、その特定の位置の項目が得られます。

これについて質問はありますか。素晴らしい。

では、この値21をどのように実際に得るのでしょうか。単純な規則は、対応する要素を掛け、すべての積を足し合わせることです。

繰り返します。対応する要素を掛け、すべての積を足し合わせます。

行の最初の要素と列の最初の要素を掛けます。次に、行の2番目の要素と列の2番目の要素を掛けます。

覚えておいてください、最初の行列の行数が2番目の行列の列数と等価であるため、この列とこれらの行では常に同じ数の要素があります。

つまり、ここに余分な要素があるが、ここに対応する要素がないということは決してありません。それがまさに最初の規則がある理由です。行列のドット積が定義されているかどうかを確認するためです。

1に5を掛け、2に8を掛けます。次にすべての積を足し合わせます。再び繰り返します。1に5を掛け、2に8を掛けます。次にすべての積を足し合わせます。

1 × 5は5です。2 × 8は16で、両方を足すと21になります。これがここで21を得た方法です。

理解できましたか。素晴らしい。ここでまだ質問はありますか。何か理解できなかったことがあったり、もう一度説明してほしいことがありますか。

はい、どうぞ。えっと。ベクトルについては、今は心配しないでください。プログラミングを始めるときにそれを見ていきます。

どうぞ。X × Yがある場合、それはY × Xと同じですか。ここで、順序があるところで、これはできません。いいえ。

はい。行列の積は可換ではありません。そのため、行列を掛ける順序がここで実際に重要だと先ほど言いました。

行列は実数とは異なるデータ構造だからです。そのため、定義する演算に対して独自の規則があります。要素ごとの演算は数値だけで起こっているので、数値の単純な規則がそこに適用されます。

しかし、これらは通常の数値とは完全に異なるデータ構造であるため、行列演算には適用されません。

掛ける行列の順序は非常に重要で、行列を切り替えると答えが変わります。実際、この場合、行列の掛け算は定義すらされません。

なぜなら、最初の行列の列になる3が、2番目の行列の行になる2と等しくないからです。この場合、行列を切り替えると行列の掛け算は定義すらされません。

良い質問です。他に質問はありますか。はい、どうぞ。はい。

先に進みましょう。このようにして進めていきます。この場合、最初の行、2列目で24を得ました。最初の行、3列目で27を得ました。規則は同じままです。1 × 7 + 2 × 10で27になります。

行列全体を通してこのように進めていきます。2行目については、2行目から始めて、2行目の最初の要素に最初の列の最初の要素を掛けます。それが2行目の最初の要素になります。

次にすべての列を通して進め、この行列で終わります。これが行列AとBのドット積の答えです。

よし、先に進みましょう。

転置行列

これが先ほど言ったデータを非常に迅速に変換できるという意味です。次に、行列の転置と呼ばれる演算を見てみましょう。

先ほど、3が2と等しくないため掛け算が定義されないという問題に遭遇しました。私たちのシナリオでは、行列の掛け算が定義されないことがしばしば起こります。しかし、行と列を切り替えれば、つまり、行列の行数と列数を何らかの方法で切り替えることができれば、行列の掛け算が定義されるようになります。

これが転置が大いに役立つ場合です。転置を取る簡単な方法は、行を取って列に変換することです。最初の行を変換している場合は、最初の行を最初の列に変換し、2行目を2列目に変換します。3行目があれば、それを単純に3列目に変換します。

行番号が何であれ、それは単純に列番号に変換されます。

1, 2, 3の最初の行は、転置を取った後に最初の列になります。456の2行目は、単純に2列目に変換されます。ここで見ることができます。

これは何をもたらすのでしょうか。2つの行列の次数に注目してください。元の行列は次数2, 3で、2行3列でした。しかし、転置の変換を適用することで、3行2列の行列を得ました。

掛け算が転置を取ることで単純に定義されるようになる場合、これは、将来ニューラルネットワークを構築し始めて層が一致しないときに必要になる、未定義の掛け算を再び定義されるようにするのに大いに役立ちます。

それはどういう意味でしょうか。将来の講義で調べて見つけてください。

ここでまだ質問はありますか。やってみて。質問はありますか。

どうぞ。たとえば、2つの行列を掛けようとしているとしましょう。最初の行列は3行2列です。つまり、次数3, 2です。2番目の行列も3行2列です。つまり、次数3, 2です。

それらを掛けようとすると定義されません。なぜなら、最初の行列の列である3が、2番目の行列の行である2と等しくないからです。2は3と等しくないので、定義されません。しかし、2番目の行列の2と3の順序を転置演算を使用して切り替えると、2番目の行列で2,3を得ることになり、最初の行列が次数3, 2で、2番目の行列が次数2, 3になるため、掛け算が定義されるようになります。これで、これらの行列を掛けることができるようになります。

なぜこれを行うかというと、これは単にデータをある表現から別の表現に変換しているだけだからです。機械学習を見るとき、データを変換することを考える必要があります。

データに対応する値は変わりませんが、それをどのように利用できるかが変わります。ここで、以前はドット積が不可能でしたが、この変更を得ると、ドット積が可能になります。

これは単に数学的なトリックです。それは単にデータを何らかの形で利用できるようにしてくれます。なぜ正確にこれを行うのかは、次のセッションで理解できるでしょう。しかし、それが行列の変換の主な意図です。

はい、どうぞ。はい、もちろんです。常に意味するわけではありません。次数は依然として一致する必要があります。しかし、場合によっては、必要な次数が実際に入れ替わっていることがあります。これは、そのような場合を処理するための巧妙なトリックです。スライドの観点から話しています、一般的なものではありません。

他に質問はありますか。よし、先に進みましょう。

機械学習における線形代数の応用

では、皆さんが持っていた質問、線形代数が実際に機械学習でどのように応用されているかについて見てみましょう。

今は理解しないが、今見ているものの線形代数の関与を見るだけで、将来のレッスンで実際に今見ているものを正確にコーディングすることになる、小さな例を見てみましょう。

ここの動画を見てみましょう。これは簡単なニューラルネットワークを示しています。このニューラルネットワークには入力があり、出力を計算しようとしています。

このニューラルネットワークを作成するのに使用されるすべてのパラメータが、ここのこの行列に入れられています。どのようにその行列を得たのか、その行列が正確に何をしているのかは、現時点では心配しません。

それについては来る講義で学びます。今のところそれについて調べてください。しかし、ここで行列をどのように使用しているかを見てみましょう。このニューラルネットワークを表すすべての数値を取り、それらすべてをこの1つの行列に入れました。

すべての同質のデータを一緒にグループ化しました。データの構造化された表現を得ました。

先に進むと、これらの異なる行列は異なる層を表しています。見てのとおり、1、2、3の層があります。入力、隠れ層1、隠れ層2、出力です。3つの層があります。これらの3つの行列のそれぞれがその3つの層を表しています。

それらがその3つの層で正確に何を表しているかは、現時点では関係ありません。将来学ぶことになります。

これらの3つの行列、B1、B2、B3も、これらの3つの層を表していますが、これらの3つの層の異なる側面を表しており、これについても学ぶことになります。

今見たグラフィカルなニューラルネットワークのこの数学的表現を取ると、出力を計算できます。

出力が正確にどのように計算されているかについては、後で心配しましょう。これは順方向パス計算と呼ばれるプロセスで起こり、将来の講義でゼロから実装することになります。今のところそれについて調べてください。

しかし、ここでの線形代数の関与を見てみましょう。入力Xを取り、重みの行列W1でそれを掛け、他の行列Bをそれに加えます。

なぜそれを行うのでしょうか。再び、将来学ぶことになります。それがニューラルネットワークの最初の層の出力を与えてくれます。

すべての3つの層に対して、今アニメーションで見るように、この同じプロセスを繰り返し続けます。それがニューラルネットワークの最終出力を与えてくれます。

これが、ニューラルネットワークが実際に線形代数を現実の生活で応用して、通常見る出力を得る方法です。

これは、ChatGPTがあなたの質問に答える方法の背後にある中核的な基盤でもあります。

実際の生活でこれをどこに適用するかという先ほどの質問に対して、現実の例を見ただけです。将来、この現実の例をコーディングすることになります。

これについて質問はありますか。どうぞ。

ニューラルネットワークは単にAIモデルに他なりません。将来学ぶことになるので、ニューラルネットワークが正確に何か、なぜそれが分野に関連しているのか、それに関連するすべてのことを理解するでしょう。

ニューラルネットワークをAIと考えてください。

他に質問はありますか。他の手が上がっているのを見ました。はい、どうぞ。

数値…あなたの代数で、のように適用されて、単語のように変換されて、接続のように。それについてはレクチャー12で学びます。そこでNLPの探索を始めます。

それ自体が本当に興味深い概念で、そのレクチャーを気に入ってもらえると信じています。

他に質問はありますか。よし、先に進みましょう。

線形代数のコード実装

今度は、理論だけでは楽しくないので、これらのすべての数学的概念に関連付けることができるよう、コードで少し線形代数を実装してみましょう。

すべてを実装し始める前に、コース全体を通して広範囲に使用する2つのPythonライブラリを紹介します。1つはPyTorchと呼ばれ、もう1つはNumPyと呼ばれます。

NumPyは単純にPythonの数値ライブラリで、異なる数値の計算を加速します。見ているこれらのすべての行列演算はすべて加速されています。聞いたことがあるかもしれませんが、Pythonは非常に遅いです。NumPyは数値を扱うときにPythonを高速にしてくれます。PythonはNumPyの上に構築されて、これらすべてのAIモデルの構築をより簡単にしてくれます。

これらのライブラリのいくつかの基本と、それらで線形代数がどのように使用されるかについて説明します。

まず、これら2つのライブラリを自分たちのためにインポートしましょう。import torchとimport numpyをタイプします。

これら2つのステートメントが行っていることは、これらの2つのライブラリへのアクセスを与えてくれることです。ライブラリは単に事前に書かれたコードに他なりません。

素晴らしい会社や開発者が既に私たちのために書いてくれたもので、私たちは自分のコードで彼らのコードを簡単に使用できます。これらの2行がやっているのは、これらのライブラリを私たちが使用できるようにインポートしているだけです。

このインターフェースは実際に…実際に、それも見せましょう。ブラウザを開いて、私についてくる場合は、colab.research.google.comとタイプしてください。

これはGoogleの無料サービスです。それでEnterを押すとすぐに、このようなインターフェースにアクセスできます。個人のGmailアカウントでサインインでき、ASGのGmailアカウントでサインインでき、何でも好きなものでサインインできます。

それが完了したら、New Notebookをクリックしてください。すると、インターフェースにアクセスできます。

これについて質問はありますか。

今のところ先に進みましょう。

2つのライブラリをインポートしたので、この小さな再生ボタンをクリックして、先に進みましょう。

新しいコードブロックを追加します。

まず、NumPyに関して行列を実際にどのように表現するかを見てみましょう。行列Aがあるとしましょう。

NumPyで行列を作成するには、np.arrayをすべて行います。この中で、実際の行列を定義し始めます。最初の行列…最初の行列を定義します…ああ、待って、それはNumPyであるべきです。すみません。

最初の行をリストで再び定義します。要素をコンマ区切りの要素として定義するだけなので、1, 2, 3としましょう。

次に2行目を定義するために、再び、4, 5, 6としましょう。

これは後ろの人たちに見えますか。はい、どうぞ。

これは美しいですか。

これが私たちのための行列を定義するだけです。これがNumPyで簡単な行列を定義する方法です。実際にこれを見ようとすると、この再生ボタンをクリックして定義するか…

ああ、待って、それをインポートするのを忘れたと思います。

ああ、スペルを間違えました。すみません。

素晴らしい。もう一度それをクリックすると、その行列が私のために定義されます。実際にその行列を見ようとすると、matrix_Aをやり、この再生ボタンを再びクリックします。この行列がどのように定義されているかがわかります。先ほど見たように。行があり、列があります。

同様に、PyTorch自体も行列を定義する方法を定義しています。行列Bがあるとして、PyTorchで行列を定義するには、torch.tensorを簡単に行います。

そのテンソルで、先ほど行ったように行列を定義するだけです。最初の行、1, 2, 3を定義し、次に4, 5, 6と言います。次に再び再生ボタンをクリックして定義します。

再び視覚化してみましょう。matrix Bとタイプします。

見てのとおり、別のものを与えてくれます。

配列とテンソルの間には少し違いがあります。テンソルは単に配列のより最適化されたバージョンです。テンソルはNumPyをさらに最適化するように設計されています。NumPyはコードを高速にし、テンソルはそれをさらに高速にします。

テンソルと配列の間に他の主要な違いはありません。

これがPythonで行列を定義する簡単な構文です。これについて質問はありますか。

よし、先に進みましょう。

次に、先ほど探索したのは、行列の次数とは何かということでした。Pythonでもそれを見つける方法があります。

行列を取り、行列…と言って、.shapeと言うだけで、行列の次数が得られます。

見てのとおり、行列Aは2行3列でした。つまり、次数2, 3を得ました。行列Bについても同様です。matrix_b.shapeをやると、再び2, 3を得るでしょう。なぜなら、それらは2列と3…2行と3列を持っていたからです。すみません。

よし。

今それを終えたので、次の質問は、多くの人が持っていた、ベクトルとは何かということでした。

ベクトルは行列に他なりませんが、その次元の1つが1です。つまり、行が1であるか、列が1であるということです。それが単純にベクトルです。

ベクトルを定義したいとしましょう。vector_Aは等しく、今のところNumPyで定義しましょう、arrayと言って、1行だけを持つ配列を定義します。

それを見ると、ベクトルが得られます。

これは行ベクトルと呼ばれるもので、1行しかないからです。同様に、1列しかない場合、これは列ベクトルになります。

それが単純にベクトルです。次元の1つが1である行列です。

よし。

今度は要素ごとの演算に進みましょう。先ほど、行列を加算または減算できることを見ました。

Pythonでそれをどのように行うかを見てみましょう。2番目のNumPy行列を自分たちで定義しましょう。B_Nと言いましょう。

再び2行2列を持つNumPy配列を定義しましょう。覚えておいてください、要素ごとの演算は同じ次元を持つ行列に対してのみ定義されます。

美しい。

再びそれを定義しましょう。

要素ごとの演算は簡単なPython演算です。加算、減算、乗算、そのようなことができます。matrix_A * matrix_B_Nを行い、それを実行すると、配列が得られたことがわかります。それは単純に…2つの行列の積です。1 × 1は1、2 × 2は4、3 × 3は9、同様に。

その同じ演算は加算についても同様です。乗算の代わりに加算に変更し、再びヒットします。今度は1 + 1 = 2、2 + 2 = 4、3 + 3 = 6、同様に。減算、除算についても同様です。もちろん、0で割る場合は除算は定義されません。なぜならそれは算術エラーだからです。

しかし、これが簡単な要素ごとの演算を実装する方法です。

ここで質問はありますか。はい、どうぞ。

はい、もちろんです。

colabノートブックを皆さんと共有し、その間Costaが皆さんを手伝います。

次に学んだのは…はい、どうぞ。

いいえ。互換性のない行列は、両方の形状が同じでない場合はエラーをスローします。要素ごとの乗算では、両方の形状が同じでない場合は定義されないので、エラーをスローします。今すぐ環境で試してみることができます。

問題がある場合は、私たちを呼んでください。周りに多くの人がいます。彼らが来て、エラーや質問の解決を手伝ってくれます。

よし。

今度は行列の乗算に進みましょう。

同じ数の行と同じ数の列を持つ2つの行列が既にあります。2, 3です。

覚えておいてください、皆さんが先ほど尋ねた、なぜ転置を定義するのかということです。これら2つの行列間でドット積を取ろうとすると、それはできません。なぜなら、両方とも2, 3だからです。

2, 3、そして2, 3は、最初の列が2番目の行と等しくないことを意味します。

ここで転置が私たちを助けてくれます。2番目の行列を転置すると、matrix_B_Nを取り、転置します。その方法は.Tです。Tは転置を表します。それほど簡単です。行列を取り、.Tをヒットします。

それが行列を転置します。最初にそれがどのように見えるかを見てみましょう。見てのとおり、今それは変わりました。3列と2行を持ちます。以前は、1, 2, 3が同じ行にありましたが、今は同じ列にあります。

それを異なる行列に保存しましょう。matrix B transpose。それに保存しましょう。

今、ドット積を使用してこれら2つの行列を乗算し始める場合、それは単純に最初の行列、つまり私たちが持っていたNumPy行列であるmatrix A、dotに、作成した互換性のある次元を持つmatrix B transposeを掛けます。それを行うと、両方のその2つの行列のドット積である行列が得られることがわかります。

しかし、転置しないで通常のB行列で行う場合、matrix B numpyを使うと、エラーに遭遇することがわかります。形状2,3と2,3が整列していないと言っています。

これはどういう意味でしょうか。単純に3が2と等しくないということです。最初の行列の列の要素数が2番目の行列の行数と等しくないということです。それを修正する必要があります。そこで転置が役立ちます。

それが転置を取る理由を尋ねた質問に答えているはずです。転置が非常に有用である場所です。

それを通常に戻しましょう。

はい、どうぞ。ああ、はい、もちろんです。

学んだ次の演算に進みましょう。

これで行列の演算についてはすべてです。次に持つかもしれない質問は、実際に線形方程式をそれで解けるのかということです。実際の世界でそれを適用できるのでしょうか。

先ほど見た数値の例から確認してみましょう。

この線形方程式のシステムを解いているとしましょう。先ほど見た例です。

これらの方程式は、先ほど見た例とまったく同じです。

再び、係数行列を自分たちで定義します。

この係数行列とは何でしょうか。この係数行列は、再び先ほど見た行列で、異なる方程式の異なる変数のすべての係数を1つの行列に結合したものです。最初の行列から1があり、そして続きます。

次に、定数行列と呼ぶものも定義します。

定数行列を取ります。自分たちで定数行列を定義します。

この行列の転置を取ります。今。

そこに行きます。

今、この行列の転置を取ります。なぜこの行列の転置を取っているのでしょうか。見てのとおり、行に3つの要素がありますが、列に3つの要素が必要だからです。

再び、転置を使用して行を列に変更できます。そこで転置を再び使用することになります。

今、numpyは実際にnumpy.linalg.solveと呼ばれる非常に便利なメソッドを提供してくれます。これは私たちのためにこの方程式を解いてくれます。試してみましょう。solutionはnumpy.linalg.solveと等しいと言います。

必要なのは係数行列と定数行列だけです。先ほど見たXとYとZを持つ変数行列は、NumPyが自動的に処理してくれます。

便利ですよね。それがNumPyの利点です。

解いた後、実際に解がどうなるかを見てみましょう。

解を印刷しましょう。

何が得られるかを見てみましょう。

見てのとおり、1、2、3が得られました。これは先ほど得た答えと同じです。

これが現実の生活で線形代数を使用する方法、NumPyを使用して実際に動作させる方法です。NumPyを使用すると、線形方程式のシステムを簡単に解けます。

同時に解く10個の方程式があったと想像してください。手で行うには非常に面倒ですよね。NumPyが救助に来ます。すべての10行の係数行列を定義し、すべての10行の定数行列を定義し、それらをlinalg.solveに渡すと、すべての10個の変数を同時に得られます。

どうぞ。

定数行列は、先ほど見たスライドを覚えているなら…ああ、待って、実際にここに方程式がありますよね。それらを見てみましょう。

方程式はX + Y + Z = 6と言っていました。これは各方程式の定数項です。

ああ、すみません。そこに行きます。

今見えるはずです。見えますか。定数行列は方程式の定数項です。6には変数が掛けられていないので、定数です。

11にも変数が掛けられていないので、定数です。すべての定数は1つの行列に入ります。なぜなら、それらはすべて同じ同質のデータだからです。構造化されたデータの原則を使用し、それらすべてを1つの行列に入れます。それが定数行列です。

他に質問はありますか。

よし。

これはコードでの線形代数の概要です。セッションを通して進歩するにつれて、線形代数とその機械学習での応用について多くを学ぶことになります。

今のところ、次のトピックである微積分に進みましょう。

微積分の基礎

微積分は機械学習でニューラルネットワークを訓練するために広範囲に使用されます。ニューラルネットワークの訓練について聞いたことがありますよね。それは単に微積分を一緒につないだものです。

微積分で理解する必要がある最初のことは、導関数とは何かということです。

数学者やオタクは、ある点での関数の導関数は、その与えられた点での関数の変化率として定義されると言うでしょう。

私のような人にとって、それは全く意味がありませんでした。頭の上を通り過ぎました。

心配しないでください、私もそうでした。

自分たちのためにもう少し良くして、それを視覚化してみませんか。

先に進む前に、導関数は主に2つのタイプがあります。全導関数と偏導関数です。全導関数から始めましょう。

導関数は実際にどのように機能するのでしょうか。ある座標平面で関数Fがあると想像しましょう。この関数fで、2つの点AとBを取ります。

高校の代数から、rise over runと呼ばれる簡単な公式を使用してAとB間の傾きを計算できることを知っています。簡単な高校の代数です。

riseとは何でしょうか。riseは単純にΔYで、Bでのfの値、つまりBでのfの値からAでのfの値を引いたものです。

runとは何でしょうか。それは単純にB – Aです。

これは非常に馴染みのある公式ですよね。これら2つの値を割ってMを得ることができます。これはAとB間の関数の傾きです。

導関数は単純に、AとBが同じ点だった場合の傾きです。

AとBが同じ点の場合、B – Aは0になるので、傾きが定義されないと思うかもしれません。

非常に良い観察です。なぜなら、それは数学者も遭遇した問題であり、それを解決するために、BをAに非常に近くしますが、正確にAではなく、Aからもあまり遠くないと言いました。Aが3.2だとしましょう。Bは3.20001になります。

これが行うことは、B – Aが定義されることを確実にしますが、BがAとほぼ等しくもなります。

これをAでのBの極限と呼びます。ここのこの式を見ますか。それは単純に、BをAに非常に近く移動させて、両方が基本的に同じ点になることを意味します。

ここで見ることができるように、Bは元の位置からずっとAまで滑りました。

今、その点で傾きを計算すると、それは変わります。以前はそのような増加する傾きがありましたが、今は減少する傾きがあります。このオレンジ色の線が導関数の意味です。

質問はありますか。

よし、先に進みましょう。

これらはいくつかの標準関数の導関数です。それらがどのように計算されるかは、現時点での議論には関係ありません。

しかし、これらは将来の講義で見ることになるアルゴリズムを実際に計算するために、この形で広範囲に使用されます。

導関数を広範囲に使用するバックプロパゲーションのようなアルゴリズムを見ることになり、これらの公式がその時点で役立ちます。

覚える必要はありません。公式シートとして持っておいてください。はい、どうぞ。

それはsec(x) × tan(x)の負ではありません。sec(x) × tan(x)です。ああ、そうですね。ああ、だめ、その公式を間違えました。

指摘してくれてありがとう。はい、それはcosecantです。そこで間違えたと思います。よし、皆さん。

先に進みましょう。

導関数も、他の数学的構造と同様に、代数式の観点から、代数式の観点での規則を定義します。

1つの単一項自体の導関数を実際に取る必要はありません。代数式全体の導関数を取ることができます。

関数と掛けられた定数がある場合、その定数はそのままで、関数の導関数を取ることができます。

この規則は実際に特に有用で、べき乗則と呼ばれ、Xをある冪nにしたものがある場合、その導関数は単純にn × xのn-1乗であると述べています。

それがどこから来たかは現時点では実際には関係ありません。これが起こることを覚えておいてください。

再び、これを学ぶ必要はありません。公式シートとして持っておいてください。

もう一つの非常に重要で非常に興味深い規則は積の法則です。これは、f(x) × g(x)の導関数は、f'(x) × g'(x)ではないと言っています。

代わりに、それはf'(x) × g(x) + g'(x) × f(x)です。

これらは単に存在する事前定義された規則です。これらは高度な微積分を使用して数学者によって証明されています。それは現時点での議論には関係ありません。

先に進みましょう。

次に学ぶのは連鎖律です。しかし、それに入る前に、代数の規則のようなものについて今話し合ったことについて質問がある方はいらっしゃいますか。

はい、どうぞ。

そういうものはありません。

それは関数がどのように機能するかのためです。最初のスライドに戻ると、導関数は単純に与えられた点での接線、つまり与えられた点での傾きです。

しかし、2つの関数を一緒に掛けると、その関数は同じままではありません。sineとcosineを掛けると、波はsineとcosineと同じままではありません。実際に波を変換することになり、それが導関数が単純にそれらの傾きの両方を掛けたものではない理由です。

関数自体が変わったため、導関数も変わります。これは高度な幾何学に入ってしまうので、理解しやすいままにするためにここでカバーしないことを選択しました。他に質問はありますか。

よし、先に進みましょう。

連鎖律

連鎖律は私の個人的なお気に入りで、非常に興味深い応用です。なぜなら、はるかに複雑な関数の導関数を計算できるからです。

必ずしも何かの関数と何かの関数を足したものがあるとは限りません。sin(2x + 3)のようなものがあるかもしれません。その導関数をどのように得るのでしょうか。

それが連鎖律が教えてくれることです。

非常に簡単で、ループで適用される2つの規則だけです。

まず、これらの規則を順番に適用し、方程式を解決するまでこれらの規則を繰り返し続ける必要があります。

最初の規則は、外側の関数を微分し、内側の関数を変更しないでおくということです。それらが正確に何なのかは1秒後に見ますが、この規則を覚えておいてください。まず外側の関数を微分し、内側の関数は変更しないでおきます。

次に、外側の関数の導関数の結果に内側の関数を掛けます。

内側の関数が残らなくなるまでこれを繰り返し続けます。

非常に混乱しますよね。直感的ではありません。例を取り上げましょう。それが物事を明確にするのに役立ちます。

この場合、関数f(x)があり、3x + 2が定義され、それの2乗があるとしましょう。

外側の関数は2乗関数です。なぜなら2乗関数が3x + 2を保持しているからです。それは3x + 2に適用されています。

外側の関数は2乗関数で、内側の関数は3x + 2になります。

f(x)をu²として表現できます。ここでuは単に3x + 2です。

f'(x)、つまりf(x)の導関数を取ると、先ほど学んだべき乗則を使用します。xのn乗は単純にn × xのn-1乗です。

u²を微分すると、2 × uの2-1乗 = 1乗を得るので、単純に2uを得ます。

次に、連鎖律の2番目の規則に従って、内側の関数の導関数を掛けます。単純にdu/dxを掛けます。

それは何でしょうか。uをxで微分し始めます。

導関数の代数の最初の規則、つまり定数とある関数の積は、その関数だけです。その関数の導関数への定数の積です。

3は定数で、関数Xと掛けられています。その導関数を取り始めると、それは単に3 × Xの導関数です。

XはXの1乗として書けるので、それは単に1 × Xの1-1乗 = 0乗を意味します。何でも0乗は1です。

Xの導関数は1なので、3 × 1 = 3です。この全体の導関数として3を得ます。2はどうなったのかと思うかもしれません。

ずっと最初のスライドに戻ると、標準関数の導関数で、任意の定数の導関数は単に0です。2の導関数は0になりました。

uの導関数全体は3になりました。それをこの関数に戻して代入し、uの値も入れます。2 × u × 3を得ます。それを簡略化すると、18x + 12を得ます。

これについて質問はありますか。

はい、どうぞ。

標準関数の規則を覚えていますか。xのn乗の導関数は単純にn × xのn-1乗です。

はい。

よし、もっと質問はありますか。

完璧、先に進みましょう。

偏微分

覚えておいてください、先ほど導関数には2つのタイプがあると言いました。今探索したのが全導関数でした。今度は、それ自体が本当に強力なツールである偏微分に進みましょう。

2つの違いは何でしょうか。

全導関数は実際にすべての変数を同時に変更する効果を測定します。

一方、偏導関数は、他のすべての変数を定数に保ちながら1つの変数を変更する効果を与えてくれます。単一の式でX、Y、Z変数がある場合、YとZは単に定数になり、Xについてのみ関心を持ち、Xがどのように値を変更するかについて関心を持ちます。

全導関数は、マシンがあってそのマシンのすべてのノブと設定をいじって出力がどのように変わるかを見ることと考えてください。一方、偏導関数は、そのマシンで1つの設定だけを変更してその出力がどのように変わるかを見ることを意味します。

これら2つはMLでどのように適用されるのでしょうか。全導関数は実際にはMLで適用されません。なぜなら、モデルを構築するのに使用される各パラメータや側面の効果を分離しないからです。

モデルにエラーがある場合、エラーの正確な原因を特定することが非常に困難になり、モデルが最適化されていない理由を決定することも非常に困難になります。再び、これはすべての変数の変更の効果を測定しているからです。何が正確に問題なのかを特定することは非常に困難です。

そのため、偏微分を使用します。

これはエラー関数の傾きを計算するからです。

それが何かは次のクラスで学びます。そこで実際にMLモデルの動作と最適化と訓練を始めることになります。

これは基本的にMLモデルから得ているエラー、つまりMLモデルが犯している間違いを測定し、その間違いがなぜ正確に起こっているかを特定します。

そのため偏微分は素晴らしいツールです。正確に何が問題なのかを教えてくれるので、先に進んで修正できます。

これは、全導関数では行えない最適化への明確で実行可能な道筋を提供します。

偏導関数をどのように計算するのでしょうか。

導関数を計算するのと同じですが、他のすべての変数を定数として取るだけです。

Yを見るたびに、Yの導関数は0になります。なぜならYは定数だからです。

Xに関してここで定義されるある関数fの偏導関数を計算しようとしているとしましょう。

この変数は実際の変数が何であるかを教えてくれ、この、すべての変数は定数になります。

この場合、Xを変数として取り、Yは定数になります。微分を始めると、べき乗則により3に2を掛けて6xになります。

Yは定数ですよね。ここで積の法則を適用し、結果は単に2Yになります。

それがどのように来たかは積の法則からです。PPTを皆さんと共有するときに、前のスライドを参照してこれを計算し、2Yがどのように来たかを見つけることができます。

Y²がなぜ0になったのでしょうか。Y自体が定数であるため、Y²は定数であり、定数の導関数は0になるからです。これがXに関するXの偏導関数の取得方法です。

質問はありますか。どうぞ。

すべての変数のethic関数にあります。彼らがそれらの間を補間できるように、それは正しいですか。

正確にはそうではありません。将来それを見るときに非常に混乱するので、それについて考えるのは良い方法ではないかもしれません。

しようとしていることは、各変数がその関数の出力に何を貢献しているかを分離することです。

この関数fで、Xの値の貢献は何でしょうか。fの計算でxが1に等しいと言ったら、それは正確に何を意味するのでしょうか。

f(x)を1の代わりに2にしたら、その1の差により出力はどれだけ変わるでしょうか。

それが偏微分を使用して見つけようとしていることです。質問に答えましたか。

素晴らしい。他に質問はありますか。

よし。Yについても同様です。その場合、Xを定数として扱うだけです。

まったく同じ計算、同じ公式です。Yを定数として扱う代わりに、Xを定数として扱うだけです。

先に進みましょう。

fの偏導関数の解は、両方を加えた場合です。

これは全導関数での解です。

これは関数Fの全変化を表します。

これは、Xによって引き起こされた変化とYによって引き起こされた変化と考えることができます。

XとYの両方を変更し始めたら、関数全体がどれだけ変わるかを言おうとしている場合、それは単純にXによって引き起こされた変化で、Yによって引き起こされた変化を加えたものです。それが関数の全変化を与えてくれます。

それがどのように有用かは、線形回帰を学び始める次のクラスで見ることになります。

なぜMLが正確に偏微分を必要とするのでしょうか。なぜこれらの関数を最適化する必要があるのでしょうか。何を達成しようとしているのでしょうか。

機械学習システムは、単に数学的関数の連鎖に他ならず、時間をかけて集約して、あなたにとって何らかの意味を持つ最終出力を与えてくれます。

その最終出力は、あなたにとって何らかの意味があります。それ自体では意味がないかもしれませんが、あなたにとっては意味があります。家の価格かもしれません。モデルの出力は$23,000かもしれません。

$23,000自体には何の意味もありませんが、あなたにとって23,000は、その与えられた月の家の家賃が$23,000であることを意味します。与えられた時間でのサンプル内の細菌の人口が23,000であることを意味するかもしれません。

MLモデルは、それが何を表現しようとしているかを自分自身では知りません。単に数値を計算するだけです。入力を取って数値を吐き出す数学的関数です。その数値をどのように解釈するかはあなた次第です。

この画像を理解してみましょう。これは、多くの山と多くの谷を持つ3次元の本当に奇妙な曲線を示しているだけです。

これは、その出力を与えている関数です。これは基本的にモデルが犯している間違いです。

ML技術者としての私たちの目標は、モデルが犯している間違いを最小化することです。

ここのこの関数がモデルが犯している間違いを教えてくれており、モデルがそこの黒い点で始まったとしましょう。多くの間違いを犯しています。

そして、私たちは何とかしてこの青い点に到達する必要があります。そこで最も少ない間違いを犯しています。

単純に下り坂に行き始めると、ここのこの点に到達するかもしれません。下り坂に行きましたが、今度はモデルが戻って上がってこなければなりません。これをあなたが丘を歩いて下りることと考えてください。モデルをあなたとして想像してください。この点に到達しようとしています。

この点まで下がってから、戻って出てこなければなりません。それはより多くのエネルギーです。

全導関数を使用して最適化している場合、モデルにより多くの計算を与え、モデルの訓練により多くの時間を費やす必要があります。

しかし、偏微分を使用すると、正確にどこに問題があるかを見つけることができ、まっすぐ下に行かないと言うことができます。

代わりに、この方向に下って行きます。

それがあなたのためにすることは、全体の道のりが下り坂のままであることを確実にします。

それが偏微分を使用して従おうとしている同じイデオロギーです。正確にどのようにそれを行っているのか、どのようにそれを達成しているのか、それは次の講義で見ることになります。そこで線形回帰モデルを訓練することになります。

しかし、線形回帰モデルは基本的にこれを行っています。この損失…失い平面とでも言いましょう、を下って行っています。

エラーを最小化しようとしています。

最も少ないエラー数を持つとき、モデルは正確な予測を行っているため、非常に良いものになります。

今度は、コードで微積分の一部を見てみましょう。

コードでの微積分

コードでの微積分は、PyTorchライブラリを使用して実装できます。

PyTorchは、非常に有用で非常に便利な関数を提供してくれます。autogradと呼ばれる関数です。

Autogradは、基本的に勾配を計算してくれます。勾配とは何でしょうか。それは単に導関数です。

基本的に、導関数を自動的に計算してくれます。実際に座って、ああ、私の関数の導関数は何だろうかと計算する必要がありません。

それは完全にPyTorchによって処理されます。

簡単な関数をPyTorchを使用して定義してみましょう。

入力を定義しましょう。Xは与えられた入力値だとしましょう。

入力値は1です。

このrequires_gradは何かと思うかもしれません。requires_grad引数は、実際にPyTorchに、ヘイ、将来これの導関数を計算したいと伝えるものです。

この入力に何が起こっても、それを追跡し続けてください。将来導関数を計算するためにそれを使用できるようにです。どのようにそれを行うかは、すぐに見てみましょう。

先ほど連鎖律で見た古い例を参照して、3x + 2の全2乗の導関数を計算しようとしていると言いました。その関数Yを定義しましょう。

それは正確にそれです。Y = 3 × X + 2で、この二重の掛け算はPythonの指数演算子です。単に冪を意味します。この全体の式を取っています。

そして、それを2乗しています。この式を取って、2乗しています。

さて、これは通常の式ではありません。XがPyTorchテンソルだからです。

これが何かをこれに追跡し続けていることです。

それがどのように見えるかの簡単な画像を見せましょう。時間をかけてXに正確に何が起こっているかを示す画像です。

この画像をここで見せましょう。

これが時間をかけてXに起こっていることです。

どうぞ。素晴らしい。

見てのとおり、先ほどXを定義し、requires_gradをtrueに設定しました。

次にそれを3で掛けました。PyTorchは私たちがXに何をしているかを追跡し続けています。まず3で掛け、次に2を加え、次に全体を2乗しました。

PyTorchはrequires_gradをtrueと言ったので、その事実を覚えています。そして、これがf(x)であることを追跡し続けています。

実際のコードに戻りましょう。

今度に行うことは、PyTorchの内蔵関数を使用することです。これは非常に便利な関数で、backward と呼ばれます。これが実際にYのXに関する導関数を計算してくれます。これがYのXに関する導関数を実際に構築している関数です。

残念ながら、PyTorchは計算した実際の導関数を見ることを許可しないので、実際に関数を印刷することはできません。

しかし、できることは、関数の値を実際に見て、それが正しいことを確認することです。

いくつかのprint文を自分たちで追加しましょう。

Xはある値です。Xは値1を持つテンソルです。

XをYに入れると、出力は25です。ここの例に戻りましょう。

連鎖律のスライドを見ると、そこに1を入れると、3 × 1 + 2の全2乗になり、5になります。5の全2乗は25になります。

コードで再び25を得ました。Yについてコードが実際に正しいことを確認できます。

X = 1でのYの値は、今見たように25です。

X = 1でのdy/dx、つまりX = 1でのXに関するYの導関数は30です。それがコードが教えてくれることです。関数も確認してみましょう。

X = 1をここのf'(x)に入れると、それは18になり、18 + 12です。18 + 12は30ですよね。コードの前の結果が再び確認されました。

これがコードが実際に動作していることと、PyTorchによって導関数が計算されていることを確認できる方法です。

Yを非常に複雑な関数に変更したとしても、その導関数を自分で計算する必要がありません。PyTorchがあなたのためにそれを行ってくれます。

これはPyTorchの非常に便利な方法です。

それがそのようなユーティリティやモジュールを使用する利点です。

よし、これで微積分については以上です。今度は、AIの次の柱である確率と統計に進みましょう。

確率と統計

これらは密接に関連しているので、一緒にカバーしましょう。

確率とは何でしょうか。

再び、まず数学的定義を見てみましょう。

確率は、イベントが発生する可能性の数値的測定です。

これは単に、何らかのXYZが発生する可能性がどれくらいかを確認しているということです。

これは0と1の間の値です。0は、そのことが決して起こりえないことを意味します。太陽が西から昇ることを考えてください。

決して起こりえませんよね。そのようなイベントの確率は0でしょう。

1は確実な値です。皆さんがこのセッションを愛している確率は1です。

皆さんがこのセッションを愛するでしょう。冗談です。しかし、要点は理解できますよね。

イベントの発生は、連続的または離散的でありえます。

離散的なイベントの場合、それは有利な結果の総可能な結果数に対する比率として計算されます。

ここで質問はありますか。

よし、先に進みましょう。

例を見て、確率の理解と直感を構築してみましょう。あなたがこの本当に大きなソフトウェア会社の一部で、広告キャンペーンを実行しているとしましょう。

分析チームは、広告が表示された過去100回で、20人のユーザーがクリックしたと教えてくれます。

このデータに基づいて、ML技術者として、広告を見る次の人がそれをクリックする確率は何かを予測する必要があります。

この場合、私たちのイベントは、その広告をクリックする人です。

私たちが持った試行の総数は100です。

成功した試行の総数、つまり広告をクリックした人の総数は20です。

次の人が広告をクリックする確率、または可能性は、単純にクリック数を広告が表示された総数で割ったものです。

それは20/100、または0.2、または20%になります。

P(click)は、ユーザーがクリックする確率を計算していることを言う表記です。

ここで質問はありますか。

よし、先に進みましょう。

なぜ確率が実際にMLで重要なのでしょうか。

今日コードで実際に実装することになる、電子メールをスパムかスパムでないかに分類するこの例を見てみましょう。

そこで広範囲に使用されています。

次のトピックである条件付き確率に進みましょう。

条件付き確率

条件付き確率は、あるイベントが既に発生したことを前提とした、イベントが発生する可能性に他なりません。これはP(A|B)として表されます。これは、過去に1つのイベントが既に発生したという事実に基づいて確率を再計算します。

古い問題を拡張して、広告を送った100人のユーザーのうち50人が実際にモバイルフォンを使用していたことがわかっているとしましょう。

次に入ってくるユーザーがモバイルフォンを使用していることを既に知っている場合、彼らがその広告をクリックする確率は再び変わるかどうかを決定しようとしています。

見てみましょう。クリックの総数は20です。モバイルユーザーの総数は50です。

チームから、モバイルユーザーからのクリック数は15だったと言われています。以前に広告をクリックした20人のユーザーのうち、15人がモバイルユーザーでした。

モバイルフォンを使用していることを前提として、ユーザーがクリックする確率を見つける必要があります。

それは単純にモバイルフォンからのクリック数を総モバイルユーザー数で割ったものです。

それは15/50、または0.3になります。見てのとおり、確率が変わりました。

これは、イベントの条件付き確率がそのイベント自体の確率と同じでない可能性があることを意味します。

なぜ条件付き確率がMLで重要なのでしょうか。

デバイスタイプのような特徴は、私たちが扱っているデータの種類についてモデルにより多くの詳細を伝えることによって、予測を洗練するのに役立つからです。

今見たように、ユーザーがモバイルフォンを使用しているという事実を知ったとき、確率は実際に増加しました。

モデルもその事実を知っている場合、より良い予測を与えることができます。

そのため、条件付き確率は非常に有用です。

全確率の法則

全確率の法則を見てみましょう。

これは単に、与えられたイベントの確率が、可能な各ケースでの発生確率の加重平均であることを述べています。

これは全確率の本当に怖い公式です。あまり役に立ちません。例に移って実際に理解できるようにしましょう。

再び声明を拡張して、その人がラップトップを使用していることを前提として、広告をクリックする確率を見つけることができますかと言いましょう。

以前から、クリックの総数は20であることを知っています。

モバイルフォンから広告をクリックするユーザーの確率は、先ほど計算したように0.3です。

人が広告をクリックする確率自体は0.2です。

ユーザーがモバイルフォンを使用している確率は0.5です。なぜなら、100人のうち50人のユーザーがモバイルフォンを使用しているからです。

ユーザーがラップトップを使用している確率は、モバイルフォンの確率を差し引いたものになります。なぜなら、ユーザーはモバイルフォンまたはラップトップのいずれかを使用するからです。

それは再び0.5になります。

全確率の法則によると、ユーザーがクリックする確率は、モバイルからユーザーがクリックする確率にユーザーがモバイルを使用している確率を掛けたもの、プラス、ラップトップからユーザーがクリックする確率にユーザーがラップトップを使用している確率を掛けたものです。

ここでいくつかの数学を行い、ラップトップからクリックする確率を見つけなければならないと言います。それをXとしましょう。

数学を行い、Xの値を計算すると、0.1になります。

それは10%です。

ユーザーがラップトップを使用していることを前提として、広告をクリックする10%の確率があることに注意してください。これは、電話を使用していた場合にクリックする確率の1から引いたものではないことに注意してください。

ベイズの定理

これが、ベイズの定理と呼ばれるものに私たちを導きます。

ベイズの定理は、他のイベントが既に発生したことを前提として、イベントが発生する確率がある場合、実際に逆の確率を計算できると述べています。広告を既にクリックしたことを前提として、ユーザーがモバイルを使用している確率を計算できます。

これはどのように役立つのでしょうか。ユーザーのデバイスタイプを知らないとしましょう。パイプラインで何らかの障害が発生し、ユーザーのデバイスタイプにアクセスできなくなりました。

ユーザーのデバイスタイプをバックフィルできます。

先に進みましょう。

これについてはすでに議論しました。なぜベイズの定理が実際にMLで重要なのでしょうか。欠損データをバックフィルできるからです。

視覚化による理解

すべてはどういう意味だったのでしょうか。数値と公式がすべて進行していて、少し混乱していましたよね。視覚化してみましょう。この長方形全体が100人のユーザー全員を表すとしましょう。

50人のユーザーがモバイルで50人がラップトップだったので、それを半分に分けると、モバイルユーザーは50%、ラップトップユーザーは50%と単純に言えます。

次に持っていたデータは、ユーザーの20%がクリックし、80%がクリックしなかったということでした。

これらがクリックしたユーザーです。これらがクリックしなかったユーザーです。

今度は、これら両方のグラフを1つに重ねてみましょう。

モバイルフォンユーザーの中で、クリックした人が15人いました。50人のラップトップユーザーの中で、クリックしたのはわずか5人でした。

確率がどのように関連しているかがわかりますか。これが0.3になるのは、モバイルフォンユーザーの中でクリックした人の数がより多いからです。

サンプル空間全体がモバイルフォンユーザーだけだった場合、それは0.3、30%になります。

しかし、サンプル空間全体がラップトップユーザーだけだった場合、それは10%になります。

しかし、クリックした人全員を足すと、それは20%になります。

これにより、非常によく視覚化できます。

期待値と分散

期待値とは何でしょうか。

期待値は、単純にランダム変数の期待される値です。

それは、変数の各可能な値とその対応する確率の積を合計することによって計算されます。

期待値は、何も知らずにその実験を行うだけで、平均的にどのような値を期待できるかを教えてくれます。

コインを投げているとしましょう。表が出る確率または裏が出る確率を正確に知っています。

それが期待値でできることです。

分散とは何でしょうか。分散は、値が期待値からどれくらい離れているかを教えてくれます。

たとえば、MLモデルが来月のこの与えられた家の住宅価格は$23,000であると予測したとしましょう。

分散は、それがどれくらい増加するか、またはどれくらい減少する可能性があるかを教えてくれます。

分散は、単純にモデルのエラー率を測定できるようにしてくれます。

先に進んで、例についてはすでにカバーしました。

なぜ分散がMLで重要なのでしょうか。

非常に高い分散を持つモデルは、実際に不正確な予測を与えるからです。

モデルが持つべき実際の期待値から非常に外れた予測をしているからです。

確率のコード実装

確率についてより多くの実用性を学ぶために、確率のコードに入りましょう。

問題に取り組んでいるとしましょう。この問題について、自分たちをGoogleのエンジニアと想像してみましょう。

Googleにいて、Gmailアプリケーションを開発しており、ユーザーは受信箱に多くのスパムが来るという問題に直面しています。そこで、何らかの方法でスパムメールを正当な本物のメールからフィルタリングできるプログラムを構築する必要があります。

データ分析チームから、スパムメールでは、特定の単語が特定の与えられた確率で発生すると言われているとしましょう。

また、メールがスパムである回数もX回であることが知られているという事実も与えられています。

チームから持っているデータを理解してみましょう。

スパムメールに頻繁に現れるいくつかの単語があるので、それらの各単語と、それらの単語が発生する確率があります。

また、メールがスパムである確率も持っています。

P(スパム)、つまりメールがスパムである確率が与えられ、特定の単語が存在することを前提として、メールがスパムである確率も与えられています。

また、その単語が存在することを前提として、メールがスパムでない確率も知っています。これが与えられたデータです。

計算する必要があるのは、特定の数の単語を持つメールが与えられたとき、それがスパムである確率は何かということです。

簡単にするために、1つの単語の発生が他の単語に依存しないと仮定しましょう。メールに「free」が存在する場合、「winner」の存在は「free」という単語に依存しないということです。これは公式を簡素化するために行う単純な仮定です。

全確率の法則によると、メールがスパムであることを前提として、これらすべての単語の発生確率は、単純にこれらの単語がスパムメールで発生するすべての確率の積です。

計算しようとしているのは、ここにあるこのものです。

これはベイズの定理です。

コードでそれをどのように行うかを見てみましょう。コードを入力することを心配しないでください。このコードを皆さんと共有するので、後で各項目で正確に何が起こっているかを見ることができます。

これは、先ほど言ったように、メールがスパムである確率です。

メールがスパムでない確率があり、これは単純にスパムである確率の1から引いたものです。また、特定の数の単語と、その単語が存在することを前提としてメールがスパムである確率もあります。また、同じ単語と、その単語が存在することを前提としてメールがスパムでない確率もあります。

確率を使用して簡単なPython関数を書けます。

それを計算するために。

はい、はい。

自分たちのためにそれをすぐに定義しましょう。

それを実行すると、この簡単な関数は与えられたメールをスパムかスパムでないかに分類するだけです。

計算が簡単になり、数値が大きくなってより良く見えるように、これらすべての確率のlogを取っているだけなので、それについて心配しないでください。

受け取るメール内のすべての単語に対して、その単語が存在することを前提として、メールがスパムである確率を計算しているだけです。

次に、その単語が存在することを前提として、メールがスパムでない確率も計算します。

次に、値を正規化し、それらをより良く処理できるようにするためにlogを再び取ります。

次に、ベイズの定理の公式を適用します。そこで、すべてのそれらの単語がその中に存在することを前提として、メールがスパムである確率を計算しています。

行っていることは、メールがスパムである確率とスパムでない確率を返すことです。

これら2つのメール、メールと言っているこれら2つのランダムな単語の集合があるとしましょう。

この関数をすぐに定義しましょう。

これが持っている2つのメールです。

「free winner money」と「hello money」です。訓練データから、これがスパムで、これがスパムでないことをすでに知っています。これは単に私たちが知るためです。これは実際の予測ではありません。

これらのメールに何が起こるかを見てみましょう。私たちのために結果を実際に印刷できる簡単な関数を定義しましょう。

このfor loopが行っているのは、両方のメールについて結果を印刷することです。実行すると、

メール「free winner money」について、関数が予測したのは、与えられたメールがスパムである確率は.998でした。

正しく思えますよね。「あなたは無料でお金を獲得します」と言うメールを見たら、おそらくそれはスパムだと思うでしょう。

しかし、「hello money」と言うメールがあった場合、それはスパムほどではないかもしれません。

このメールがスパムである確率は0.2、つまり21%で、スパムでない確率は78%です。

純粋な数学と確率を使用するだけで、メールをスパムかスパムでないかに分類できる分類器を実装しました。

おめでとうございます、あなたたちはGoogleの開発者です。

もちろん、実際の現実世界のシステムでは、これははるかに洗練されたものになりますが、根本的な概念はまったく同じままです。単語の確率を使用して、メールがスパムかスパムでないかを決定しています。

しかし、前回の講義から、これはどのような種類のアルゴリズムでしょうか。

前回の講義に参加した人はいますか。

はい。分類は正しく、今度はそれがどのような種類の分類かを考えてください。

それは正しいです。

なぜ正確にそれが教師ありアルゴリズムなのかは、教師あり機械学習を深く掘り下げ始める将来の講義で学ぶことになります。

今日はここまでです。Kostovが皆さんと共有するいくつかの追加リソースがあります。

簡単なメモですが、今日カバーしたものは、機械学習で使用される数学の概念の広範囲なスペクトラムでした。

コメント

タイトルとURLをコピーしました