ラグランジュの未定乗数法

準備

長方形の面積最大化

たとえば2変数の問題として、長方形の周囲長Lを一定として、その面積が最大となる長方形の形状と面積はどのようになるかを考える。この場合、長方形の辺の長さをx, yとすると、問題は以下のように表せる。

(1)    \begin{equation*} \max S(x, y) = xy \quad {\rm s.t.} \: x+y = \frac{L}{2} \end{equation*}

これは以下のように代数的に簡単に解けて、答えは正方形とわかる。

(2)    \begin{gather*} S = x \left( \frac{L}{2} - x \right) = -x^2 + \frac{L}{2} x = - \left( x - \frac{L}{4} \right)^2 + \frac{L^2}{16} \\ \max S = \frac{L^2}{16} \quad {\rm for} \: x = y = \frac{L}{4} \end{gather*}

ただし変数の数が増えたり、目的関数や制約条件が複雑になると、解析的に解くのが面倒になる。

Lgrangeの未定乗数法による解

解法から先に示す。Lagrangeの未定乗数法では、目的関数L(x, y)に対して以下の問題となる。

(3)    \begin{gather*} \max \quad L(x, y, \lambda) = S(x, y) - \lambda f(x, y) = xy - \lambda \left( x + y - \frac{L}{2} \right) \\ {\rm where} \quad S(x, y) = xy, \quad f(x, y) = x + y - \frac{L}{2} \end{gather*}

L(x, y)を最大化するために、x, y, \lambdaで偏微分した以下の方程式を設定する。

(4)    \begin{gather*} \frac{\partial L}{\partial x} = 0, \quad \frac{\partial L}{\partial y} = 0, \quad \frac{\partial L}{\partial \lambda} = 0 \end{gather*}

これを計算すると

(5)    \begin{gather*} y - \lambda = 0, \quad x - \lambda = 0, \quad x + y - \frac{L}{2}= 0 \\ \therefore x = \frac{L}{4} \end{gather*}

Lagrangeの未定乗数法の一般形

一般には、変数\boldsymbol{x} = (x_1, \ldots, x_n)について、目的関数f(\boldsymbol{x})を制約条件g(\boldsymbol{x})=0の下で最大化/最小化する問題として与えられる。

(6)    \begin{align*} & \max \quad f(\boldsymbol{x}) \\ & {\rm s.t.} \quad g(\boldsymbol{x}) = 0 \end{align*}

この等式制約条件付き最大化/最小化問題は、以下のようにL(\boldsymbol{x}, \lambda)を導入して、連立方程式として表現される。

(7)    \begin{align*} & L(\boldsymbol{x}, \lambda) = f(\boldsymbol{x}) - \lambda g(\boldsymbol{x}) \\ & \frac{L(\boldsymbol{x}, \lambda)}{\boldsymbol{x}} = \frac{L(\boldsymbol{x}, \lambda)}{\lambda} = 0 \end{align*}

例題

例題1:凸関数と直線

下に凸な関数f(x, y) = x^2 + y^2について、直線x + y = 1の制約条件下での最小値を求める。

(8)    \begin{align*} & \min \quad f(x, y) = x^2 + y^2 \\ & {\rm s.t.} \quad x + y - 1 = 0 \end{align*}

ここでlagrangeの未定乗数を導入して問題を定式化すると以下のようになる。

(9)    \begin{equation*} L(x, y, \lambda) = x^2 + y^2 - \lambda (x + y - 1) \end{equation*}

(10)    \begin{align*} &\dfrac{\partial L}{\partial x} = 2x - \lambda = 0 \\ &\dfrac{\partial L}{\partial y} = 2y - \lambda = 0 \\ &\dfrac{\partial L}{\partial \lambda} = - x - y + 1 = 0 \end{align*}

この連立方程式を解くと以下のようになり、解は最小値1つとなる。

(11)    \begin{gather*} x = y = \frac{\lambda}{2} \quad \Rightarrow \quad \frac{\lambda}{2} + \frac{\lambda}{2} = 1 \quad \Rightarrow \quad \lambda = 1\\ \therefore \; x = y = \frac{1}{2} \quad , \quad \min f(x, y) = \frac{1}{2} \end{gather*}

これを目的関数のコンターと制約条件の線で表すと以下の通り。

例題2:平面と円

平面x + y - 1について、制約条件f(x, y) = x^2 + y^2の下での極値を求める。

(12)    \begin{align*} & \min \quad f(x, y) = x + y - 1 \\ & {\rm s.t.} \quad x^2 + y^2 = 1 \end{align*}

lagrangeの未定乗数を導入して問題を定式化すると以下のようになる。

(13)    \begin{equation*} L(x, y, \lambda) = x + y - 1 - \lambda (x^2 + y^2 - 1) \end{equation*}

(14)    \begin{align*} &\dfrac{\partial L}{\partial x} = 1 - 2 \lambda x = 0 \\ &\dfrac{\partial L}{\partial y} = 1 - 2 \lambda y = 0 \\ &\dfrac{\partial L}{\partial \lambda} = - x^2 - y^2 + 1 = 0 \end{align*}

この連立方程式を解くと以下のようになり、解として2つの極値を得るが、それらは最大値と最小値に相当する。

(15)    \begin{gather*} x = y = \frac{1}{2 \lambda} \quad \Rightarrow \quad \frac{1}{4 \lambda ^2} + \frac{1}{4 \lambda ^2} = 1 \quad \Rightarrow \quad \lambda = \pm \frac{1}{\sqrt{2}}\\ \therefore \; x = y = \pm \frac{1}{\sqrt{2}} \approx \pm 0.7071\\ \max f(x, y) = \sqrt{2} - 1 \approx 0.414\\ \min f(x, y) = -\sqrt{2} - 1 \approx -2.414 \end{gather*}

これを目的関数のコンターと制約条件の線で表すと以下の通り。

matplotlib.pyplot~quiver~ベクトル場

概要

matplotlib.pyplot.quiver()はベクトル場を可視化する。基本的なパラメーターは以下の通り。

quiver(X, Y, U, V, [C])
X, Yはベクトルの開始点、U, Vはベクトルの成分、Cはベクトルの大きさに応じたカラーマップ上の色をつけるための配列。

単一のベクトルの描画例

以下の例では、視点の位置と成分を1つずつ指定してベクトルを描画している。デフォルトではベクトルのスケールは描画領域に対して自動的に調節されるが、ここでは描画領域のスケールと同じになるようパラメーターを設定している。

matplotlibのドキュメントでは、scale_unitsのところに以下のように書かれている。

“To plot vectors in the x-y plane, with u and v having the same units as x and y, use angles='xy', scale_units='xy', scale=1

ベクトル場の描画例

以下の例では、xy平面上の位置に応じた成分を持つベクトルを描画している。関数のgradientのイメージ。

描画にあたって、開始点の座標とベクトルの成分をmeshgridで生成している。

1つ目の図は単に開始点と成分を与えただけで、単一の色で、ベクトルのスケールは自動調節されている。

2つ目の図はスケールと色付けのための配列を指定し、ベクトルの大きさに応じてcolormapで色を付けている。

Axes.spines~軸の設定

概要

グラフのx軸、y軸の位置や表示の有無については、Axesオブジェクトのspinesプロパティーで制御する。

spinesは辞書型でbottomtopleftrightのキーで対象を指定し、表示位置はset_position()メソッド、表示の有無はset_visible()で操作する。

軸の指定

spines['bottom']spines['left']は下と左の軸で、軸の値が表示される。

spines['top']spines['right']は上と右の軸で、ただ線が引かれるだけ。

各軸に対して、set_positon()set_visible()の各メソッドを実行して、位置や可視/不可視を設定する。

軸の表示・非表示

set_visible(False)で軸を非表示にする。

以下の例では、上の軸と右の軸を非表示にしている。

ゼロ位置/中央に軸位置を設定

set_position(‘zero’)でゼロの位置に、set_position(‘center’)で描画位置の中央に軸をセットできる。set_visible()と組み合わせて使うケースが多そう。

軸の位置の数値指定

set_position()の引数として、タプルで('指定方法', 値)の形で与える。

指定方法
data 各軸を配置するx、yの値。
outward 単位はポイントで、正なら描画領域の内側、負なら外側に配置。
axes 描画領域の高さ・幅に対する割合。

ヘッセの標準形~点と平面の距離

2次元の場合

直線l、点Qの距離を考える。直線と各点の記号、座標を以下のように定義する。

(1)    \begin{equation*} l:ax + by + c = 0 \end{equation*}

Step-1:直線に直行するベクトル

まず、ベクトル(a, b)が直線lに直行することを示す。直線は以下のように媒介変数表示できて、ベクトル(u_x , u_y)は直線に平行なベクトル。

(2)    \begin{equation*} \left\{ \begin{array}{lll} x &=& u_x + x_0 \\ y &=& u_y + y_0 \end{array} \right. \end{equation*}

これを直線の式に代入して、

(3)    \begin{gather*} a (u_x t + x_0) + b (u_y t + y_0) + c = 0 \\ (a u_x + b u_y) t + (a x_0 + b y_0 + c) = 0 \end{gather*}

ここで任意のtに対して上式が成り立つことから、a u_x + b u_y = 0となり、ベクトル(a, b)は直線に垂直であることが示された。

Step-2:法線ベクトルとの平行条件による導出

与えられた点Pから直線lへの垂線の足をHとすると、\overrightarrow{PH} \parallel (a, b)なので、以下が成り立つ

(4)    \begin{equation*} \left| \overrightarrow{PH} \cdot (a, b) \right| = \left| \overrightarrow{PH} \right| \cdot | (a, b) | \end{equation*}

ここで(x_h, y_h)は直線l上にあることを考慮し、上式の左辺を以下のように変形できる。

(5)    \begin{equation*} \begin{array}{lll} \left| \overrightarrow{PH} \cdot (a, b) \right| &=& | (x_p - x_h ) a + (y_p - y_h) b | \\ &=& | a x_p + b y_p  - (a x_h + b y_h) | \\ &=& | a x_p + b y_p + c | \end{equation*}

これより

(6)    \begin{equation*} \left| \overrightarrow{PH} \right| = \frac{\left| a x_p + b y_p + c \right|}{\sqrt{a^2 + b^2}} \end{equation*}

3次元の場合

3次元平面の式

3次元平面は、たとえば以下のように表すことができる。

(7)    \begin{equation*} \pi : w_x x + w_y y + w_z z + w_0 = 0 \end{equation*}

一方、3次元平面上の点と法線ベクトル{\boldsymbol n} = (x_x, n_y, n_z)との直行条件から、以下のようにも表現できる。

(8)    \begin{gather*} {\boldsymbol n} ({\boldsymbol x} - {\boldsymbol x_0} ) = 0 \\ (n_x, n_y, n_z) \cdot (x - x_0, y - y_0, z - z0) = 0 \\ n_x x + n_y y + n_z z + (-n_x x_0 -n_y y_0 -n_z z_0) = 0 \end{gather*}

上記2つの式より、ベクトル{\boldsymbol w} = (w_x, w_y, w_z)は平面に対する法線ベクトルであることがわかる。

法線ベクトルとの平行条件

この法線ベクトルがベクトル\left| \overrightarrow{PH} \right|と平行であることから、

(9)    \begin{equation*} \left| \overrightarrow{PH} \cdot {\boldsymbol w} \right| = \left| \overrightarrow{PH} \right| \cdot \left| {\boldsymbol w} \right| \end{equation*}

上式の左辺は以下のように変形できる。

 \begin{array}{lll} \left| \overrightarrow{PH} \cdot {\boldsymbol w} \right| &=& \left| (x_p - x_h, y_p - y_h, z_p - z_h) \cdot (w_x, w_y, w_z) \right| \\ &=& \left| w_x x_p + w_y y_p + w_z z_p - (w_x x_h +w_y y_h + w_z z_h) \right| \\ &=& \left| w_x x_p + w_y y_p + w_z z_p + w_0 \right| \end{array}

以上のことから、点{\boldsymbol x}_pから三次元平面\piへの距離については、以下で表される。

(10)    \begin{equation*} \left| \overrightarrow{PH} \right| = \frac{\left| w_x x_p + w_y y_p + w_z z_p + w_0 \right|}{| {\boldsymbol w} |} \end{equation*}

多次元の場合

n次元の超平面を以下の式で与える。

(11)   } \begin{equation*} {\boldsymbol w} \cdot {\boldsymbol x} + w_0 = 0 \; \Leftrightarrow \; w_0 + w_1 x_1 + \cdots + w_n x_n = 0 \end{equation*}

このとき、これまでと同様の考え方により、点{\boldsymbol x}_p (x_{p1}, \ldots , x_{pn})と上記の超平面との距離は以下で表される。

(12)    \begin{equation*} \left| \overrightarrow{PH} \right| = \frac{ {\boldsymbol w} \cdot {\boldsymbol x} + w_0 }{ \| {\boldsymbol w} \|} \end{equation*}

 

 

Python3 – コレクションのソート

リストのソート

sort()メソッドは破壊的処理

sort()はリストのメソッドで、元のリストの内容を変更する(破壊的処理)。メソッドの実行結果はNone

降順にソートしたいときは、引数reverseTrueで指定。

sorted()関数は非破壊的処理

sorted()関数は引数のリストのソート結果を返す。元のリストの内容は変更されない(非破壊的処理)。

降順ソートの指定はsort()メソッドと同じ。

文字列は辞書順でソートされる

ndarrayの場合の注意

sorted()はそのままではndarrayにならない

ndarrayをsorted()関数の引数にすると、エラーにはならないが結果はリストで返されるため、配列への変換が必要。

numpy.sort()は非破壊的にndarrayをソートできる

numpy.sort()関数は、引数のndarrayのソート結果を返し、元のndarrayは変更しない。リストの場合のsorted()関数と同じ動作。

ndarraysort()メソッドは破壊的

ndarraysort()メソッドは、元の配列の内容を書き換える。リストのsort()メソッドと同じ挙動で、実行結果の戻り値はNone

辞書のソート

今後

 

Python3 – zipによる複数リストの並行ループ

2つのリストの要素を並行して取得しつつ処理したい場合、zip()関数を用いる。

zip()関数は、引数で与えた複数のコレクションの要素が対になったタプルのイテレーターを返す。各コレクションの長さが異なる場合、イテレーターの長さは最も短いコレクションの長さとなり、それ以降の各コレクションの要素は無視される。

 

 

contour/contourf~等高線

contour~コンターライン

matplotlib.pyplot.contour()は2次元平面上のコンター(等値線)を描く。x, yの値から計算されたzの値が等しい点を曲線で結ぶ。

x, y, zの指定方法

引数がzのみの場合

以下のコードでは、zの値のみを2次元配列で与えている。この場合は、配列zのインデックスの値が座標値となる(行番号0~20がy座標、列番号0~16がx座標)。

引数に1次元のx, yを指定

以下のコードでは、x, yを1次元配列で引数として渡している。この場合は、x, yの値が座標値として用いられる(x座標が-1~1、y座標が-1.2~1.2)。

meshgridを使う方法

最も一般的な方法。x, yの1次元配列からnumpy.meshgrid()メソッドでそれぞれの2次元配列を生成し、それらを使ってzを計算するとともに、contour()の引数に与える。結果は上と同じになる。

ラベル

コンターの値をラベル表示させる。手順としては、contour()で描画した際の戻り値のオブジェクトを保存しておき、それをclabel()の引数として与える。

コンターレベル

コンターの数をlevelsで指定する。数値で指定する方法と、配列等で指定する方法があるが、数値で指定する方法は条件によって期待した結果にならないことがある。

数値による指定

1つの整数値で指定する場合、ドキュメンテーションでは以下のように書かれている。

“If an int n, use n data intervals; i.e. draw n+1 contour lines. The level heights are automatically chosen.”

すなわち、n個の間隔に対してn+1本のコンターが描かれることになっている。

以下のコードを実行してみる。

範囲と関数の関係によって、同じlevels=5を指定しているのにコンターの本数が異なる。ドキュメント通りなら、5つの間隔に対して6本のコンターが描かれるはずだが、左は6つの間隔に対して5本、右は5つの間隔に対して4本。

右の図の場合は左下でz2 = 0、右上でz2 = 4となり、コーナーの点がコンターに含まれているとすると勘定は合う。左はこれが合わないが、桁落ちなのかゼロが含まれるときに挙動が違うのか、よくわからない。

以下のようにlevels=1とした場合も、挙動が一定しない。

配列等による指定

levelsをリストなどで指定すると、その要素で指定された値のコンターを描く。要素は昇順でなければならない(昇順でない場合は実行時エラー)。

線のデザイン

linewidths~線の太さ

線の太さはlinewidthsで指定する。1つの数値で指定した場合は全てのコンターラインに適用、配列等で指定した場合は、サイクリックにその太さが適用される。赤字で示したように、引数名の最後に”s”が着く点に注意。

linestyles~線のスタイル

linestilesで、線のスタイルをスタイル名で指定する。複数指定した場合はサイクリックに適用される。

なお、線の色に単色を用いた場合は、負の値のコンターラインが破線('dashed')で描かれるが、この例は次のcolorsのところで示す。

colors~線の色

コンターラインの色はcolorsで指定する。配列等で指定するのが標準だが、単色の場合は配列化せず色名のみで指定可能。ただしその場合は、red, blue等の色名による指定方法のみ。

単色指定の場合、負の値に対するコンターは破線となる。

If linestyles is None, the default is ‘solid’ unless the lines are monochrome. In that case, negative contours will take their linestyle  fromrcParams["contour.negative_linestyle"] = 'dashed' setting.

cmap~カラーマップ

線の色にcolormapを適用できる。

alpha~透過度

線によるコンターではあまり意味がないが、線の透過度を0 ~1の実数で指定できる。

contourf~色付きのコンターエリア

contourfはコンターラインで区切られた各エリアを色付けする。

ラベル

contourfでラベルを付けることはあまり想定されないが、contourと同じようにすると図が崩れてしまう。contourcontourfの合わせ技がよい。

デザイン

cmap~カラーマップ

コンターエリアの色分けにカラーマップを指定できる。

 

alpha~透過度

透過度を1未満に設定して、透過させることができる。

 

ndarray – 条件式による要素の取り出し

基本形

ndarrayの要素に以下のような条件式を指定すると、条件に適合した要素を取り出せる。

これは次のような仕組みになっている。

まず配列の要素として、要素数と同数の論理値(True/False)を格納した配列を指定すると、Trueに対応した要素のみを要素とする配列が返される。

一方、配列全体を条件式とすると、各要素について条件判定を行った結果(True/False)を要素とする配列が返される。

したがって、配列の要素に配列全体の条件式を適用すると、その条件判定がTrueとなる要素からなる配列が返される。

別配列の条件による取り出し

条件に合う行の取り出し

上記の応用で、以下のように配列aの要素を配列bの条件により取り出すことができる。

この方法は、元データからクラス分類に応じたデータのみを取り出すときなどに使える。

たとえば以下は、5組の座標値のセットXから、クラスyが1となる座標値のサブセットを取り出すイメージ。

条件に合う列の取り出し

条件に適合した列のみ取り出す場合には、少し工夫が必要で、内包表記と条件指定を組み合わせる。

以下の例では、配列yで抽出したい列を1としていて、内包表記で配列を取り出す際にこれを利用している。