パーセプトロンからアダラインまで – From the Perceptron to Adaline

「パーセプトロンからアダリンまで - パーセプトロンからアダリンまで」

基礎を正しく設定する

写真はUnsplashのEinar Storsulによるものです

はじめに

以前の記事では、おそらく存在していたであろう最も基本的なバイナリ分類器であるローゼンブラットのパーセプトロンについて説明しました。このアルゴリズムを理解することは教育的な価値があり、初等機械学習コースの良い導入として役立ちます。このアルゴリズムは、たった1つの午後でゼロからコーディングできるだけでなく、興味や達成感、さらにはより複雑なトピックへの探求意欲を引き起こすことができます。しかし、アルゴリズムとしては、線形分離可能な場合にのみ収束が保証されるため、望ましい結果にはなりません。

本記事では、分類の概念をマスターするための旅を続けます。ローゼンブラットのパーセプトロンからの自然な進化は、adaptive linear neuron クラシファイア、またはコロキアルにはadalineとして知られるものです。パーセプトロンからadalineに移行することは大きな飛躍ではありません。単にステップ活性化関数を線形に変更する必要があります。この小さな変更により、堅牢に最小化できる連続的な損失関数が生じます。これにより、ベクトル化や最適化手法など、機械学習における多くの有用な概念を導入することができます。

また、将来の記事では、adalineからロジスティック回帰への活性化関数や損失関数の微妙な変更も取り上げ、既に日常の実践で役立つアルゴリズムになるであろうロジスティック回帰まで取り扱います。これらすべてのアルゴリズムは基本的には単層ニューラルネットワークであり、それらは簡単に多層ニューラルネットワークに拡張することができます。この意味で、本記事は読者をこの進化の次のステップに進め、より高度な概念に取り組むための基盤を築きます。

いくつかの数式が必要です。私はオンラインのLaTeX数式エディターを使用して数式のLaTeXコードを作成し、その後、LaTeX数式エディターのChromeプラグインであるMaths Equations Anywhereを使用して数式を画像にレンダリングしました。この方法の唯一の欠点は、LaTeXコードが再度レンダリングする必要がある場合には保存されないということです。そのため、本記事の最後に数式のリストを提供します。LaTeXに慣れていない方には、それ自体が教育的な価値があるかもしれません。正しい記法を身につけることは、機械学習の旅の一部です。

アダプティブ線形ニューロンクラシファイア (adaline)

では、adalineアルゴリズムとは何でしょうか? Adalineはパーセプトロンと同様のバイナリ分類器です。予測は、特徴の入力値のセット [x₁, .. , xₘ](ここでmは特徴の数)を使用して行われます。入力値は重み [w₁, .. , wₘ] とバイアスが掛け合わされ、ネット入力 z = w₁x₁ + .. + wₘxₘ + b を得ます。ネット入力は線形活性化関数 σ(z) に渡され、パーセプトロンと同様のステップ関数を使用して予測が行われます:

パーセプトロンとの主な違いは、線形活性化関数が重みの学習に使用される点です。ステップ関数は予測の最後にのみ使用されます。これは小さなことのように聞こえますが、重要なことです。線形活性化関数は微分可能であり、ステップ関数はそうではありません!上記の閾値0.5は固定されたものではありません。閾値を調整することで、偽陽性と偽陰性のコストに応じて適合率と再現率を調整することができます。

adalineの場合、線形活性化関数は単に恒等関数であり、すなわち σ(z) = z です。トレーニングプロセスで最小化する必要のある目的関数(または損失関数)は以下のようなものです

重み w の例です

そして、 b はバイアスです。 Σ はトレーニングセット内のすべての例についての合計です。実装によっては、損失関数に便利な 1/2 の係数も含まれます。これは、重みとバイアスに対する損失関数の勾配を取るときに無効化されること、および後述するように、学習率を 2 の倍率でスケーリングする以外の影響がないことを意味します。この記事では 1/2 の係数は使用しません。

各例について、計算されたアウトプット

と真のクラスラベルの二乗差を計算します。入力ベクトルは行列(1、m)の形状を持つということに注意してください。後で見るように、それは特徴行列 x の1行としてわかります(形状は(n、m))。

トレーニングは最適化問題の一種です。重みとバイアスを調整し、損失関数を最小化する必要があります。最小化問題では、目的関数の独立変数(今回は重みとバイアス)に対する勾配を計算する必要があります。損失関数の重み wⱼ に対する偏微分は

最後の行は重要な行列表記を導入します。特徴行列 x は形状(n、m)を持ち、その列 j の転置を取る(形状は(1、n))ということです。真のクラスラベル y は形状(n、1)の行列です。すべてのサンプルのネット出力 z も形状(n、1)の行列であり、アクティベーション後に各要素に適用されると理解されます。上記の式の最終結果はスカラーです。行列表記を使ってすべての重みに関する勾配をどのように表現できるか推測できますか?

ここで特徴行列の転置は(m、n)の形状を持ちます。この操作の結果は(m、1)の形状を持つ行列です。この表記は重要です。ループを使用せずに、numpy を使ってまさにこの行列の乗算を行います。ニューラルネットワークとGPUの時代では、ベクトル化を適用する能力が不可欠です!

バイアスに対する損失関数の勾配はどうなるでしょうか?

ここで、上線はその下のベクトルの平均を示しています。再度、numpy を使用して平均を計算すると、ベクトル化された操作になり、ループを使用して実装する必要はありません。

勾配を持っている場合、損失を最小化するために勾配降下最適化法を使用できます。重みとバイアスは、次の手順で反復的に更新されます

ここで、η は適切に選ばれた学習率です。小さすぎる値は収束を遅らせる可能性があり、値が高すぎると収束そのものを防ぐ可能性があります。いくつかの実験が必要です。これは機械学習アルゴリズムのパラメータとして一般的なケースです。

上記の実装では、重みとバイアスが一度にすべての例に基づいて更新されると仮定しています。これはフルバッチ勾配降下法として知られ、一つの極端な方法です。もう一つの極端な方法は、各トレーニング例の後に重みとバイアスを更新することであり、これは確率的勾配降下法(SGD)として知られています。実際には、重みとバイアスをサブセットの例に基づいて更新するミニバッチ勾配降下法という中間地点もあります。この方法では収束が通常よりも早く達成されます。つまり、全体のトレーニングセットを実行する必要はありませんが、ベクトル化は(少なくとも部分的に)可能です。トレーニングセットが非常に大きい場合(またはNLPの変換器の場合のようにモデルが非常に複雑な場合)、フルバッチ勾配降下法を単純に選択できない場合もあります。

代替定式化と閉じた形式の解

Pythonでadalineを実装する前に、ちょっとした逸脱をします。重みベクトル内のバイアスbを以下のように吸収することができます。

この場合、トレーニングセットのすべてのサンプルのネットの出力は以下のようになります。

これにより、フィーチャーマトリックスは列が1で埋められたカラムが先頭に追加され、形状は(n, m+1)になります。結合重みセットに関する勾配は以下のようになります。

原理的には、すべての勾配がゼロになるため、閉じた形式の解を導出することができます。

しかし、実際には、上記の式での行列の逆が存在しない場合や、十分に正確に計算できない場合など、特異点のために逆行列を計算できない場合があります。したがって、このような閉じた形式の解は、機械学習や一般的な数値メソッドのどちらにおいても実際には使用されません。それでも、adalineが線形回帰に似ていることや、閉じた形式の解を持つことを理解するのに役立ちます。

Pythonでadalineを実装する

私たちの実装では、ミニバッチ勾配降下法を使用します。ただし、実装は柔軟で、損失関数を最適化するためにストキャスティック勾配降下法とフルバッチ勾配降下法の両極端を使用することができます。バッチサイズを変化させることで収束の振る舞いを検証します。

adalineを使用するためのクラスを実装し、通常のscikit-learnスタイルのfitとpredict関数を公開します。

adaline分類器を初期化すると、ミニバッチ勾配降下法のバッチサイズが設定されます。バッチサイズがNoneに設定されている場合、トレーニングセット全体が使用されます(フルバッチ勾配降下法)。それ以外の場合、トレーニングセットはバッチ単位で使用されます(ミニバッチ勾配降下法)。バッチサイズが1の場合、実質的には確率的勾配降下法に戻ります。トレーニングセットは、反復的なサイクルを避けるために、各トレーニングセットの通過の前にシャッフルされますが、これはミニバッチ勾配降下法を使用する場合にのみ効果があります。アルゴリズムの本質は、トレーニングセットを完全に通過し、対応する損失を返す_update_weights_bias関数にあります。この関数では、前のセクションと同様に導出された勾配を使用して、解析的に勾配降下法を適用します。明示的なループの使用を避けるために、numpyのmatmuldot関数を使用しています。バッチサイズがNoneに設定されている場合、ループは一切なく、実装は完全にベクトル化されています。

実践でのadalineの使用方法

必要なインポートを行い、以前のパーセプトロンの記事と同様に合成データセットを作成します。記事で行ったように

以下を生成する

Syntheticデータセット内の2つのクラスの散布図。著者による画像。

以前の記事との唯一の違いは、ガウス平均と共分散を微調整して、クラスが線形分離可能ではないようにしたことです。さらに、2つの独立変数のスケールをわざと異なるものにして、特徴のスケーリングの重要性について議論します。

最初のモデルをフィットして収束を可視化してみましょう。フィットする前に、特徴量を正規化して、両方の特徴量が平均ゼロ、単位標準偏差を持つようにします。

これは収束グラフを生成します

収束するアダリン. 画像: 著者提供

アダリンはゆっくりと収束しますが、損失関数はゼロになりません。成功したトレーニングを検証するために、以前の記事と同様の手法を用いて決定境界を視覚化します。

以下を生成します

適合したアダリンモデルの決定境界. 画像: 著者提供

トレーニングセット内の2つのクラスが線形に分離できなかったため、いくつかの誤分類ポイントがありますが、アルゴリズムはうまく収束しました。解は確定的です。トレーニングセットを十分な回数パスすると、初期値に関係なく数値上等な重みとバイアスが得られます。

ミニバッチ vs. フルバッチ勾配降下法

上記の数値実験ではフルバッチ勾配降下法を使用し、これが収束を遅くする一因です。同じデータセットとランダム状態を使用し、今度は20から400までのバッチサイズ(トレーニングセットの例数)でアダリン分類器を適合させます。

以下を生成します

収束に与えるバッチサイズの影響 (学習率: 0.001). 画像: 著者提供

バッチサイズが小さいほど収束が速くなることが明確にわかりますが、いくつかの振動もあります。これらの振動は、より大きな学習率では収束を不安定にする可能性があります。学習率を0.002倍に増やすと、これが明らかになります

収束に与えるバッチサイズの影響 (学習率: 0.002). 画像: 著者提供

学習率をさらに上げると、小さなバッチサイズでは収束が妨げられるようになります。さらに大きな学習率では、フルバッチ勾配降下法でもグローバルミニマムを超えるため収束しなくなります。

結論

アダリンはパーセプトロンに比べて重要な改善です。重みとバイアスは連続的な損失関数の最小化によって得られますが、この関数は凸であるため(したがって局所的な最小値は存在しません)、線形に分離できないクラスでもアルゴリズムは収束します。さまざまな変数で勾配降下法を使用する場合、収束率は特徴のスケーリングに影響を受けます。本記事では、特徴の平均をゼロにシフトし、分散を単位分散に調整する単純な標準化を使用しました。この方法では、すべての重みとバイアスに適した学習率を選択することができます。つまり、より少ないエポックでグローバルミニマムを得ることができます。

ベクトル化を使用したバイナリ分類器の構築方法を理解することは、サポートベクターマシンやマルチレイヤーニューラルネットワークなどのより複雑なトピックに踏み込む前に重要です。実際の業務では、scikit-learnを使用することが多く、非線形な決定境界を可能にし、効率的で体系的なハイパーパラメータのチューニングや交差検証をサポートしています。ただし、ゼロからシンプルなバイナリ分類器を構築することで、深い理解を得ることができ、自信を持つことができます。すべてをゼロから構築することは現実的ではありませんが、よりシンプルなアルゴリズムを深く理解することで、既製のライブラリに含まれるより高度なアルゴリズムがより理解しやすくなります。

記事で使用された方程式のLaTeXコード

記事で使用された方程式は、以下のgistに記載されており、再度レンダリングする場合に使用することができます。

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more