web-dev-qa-db-ja.com

ロジスティック回帰の最急降下法

タイトル通りにやろうとしていますが、どうしたらいいのかよくわかりません。

何が悪いのかを理解するのを手伝っていただければ、とても助かります。バッチ勾配降下法を使用してロジスティック回帰を実行する必要があります。

import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline

X = np.asarray([
[0.50],[0.75],[1.00],[1.25],[1.50],[1.75],[1.75],
[2.00],[2.25],[2.50],[2.75],[3.00],[3.25],[3.50],
[4.00],[4.25],[4.50],[4.75],[5.00],[5.50]])

y = np.asarray([0,0,0,0,0,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1])

m = len(X)

def sigmoid(a):
    return 1.0 / (1 + np.exp(-a))

def gradient_Descent(theta, alpha, X , y):
    for i in range(0,m):
        cost = ((-y) * np.log(sigmoid(X[i]))) - ((1 - y) * np.log(1 - sigmoid(X[i])))
    grad = theta - alpha * (1.0/m) * (np.dot(cost,X[i]))
    theta = theta - alpha * grad
return 

gradient_Descent(0.1,0.005,X,y)   

私のやり方はこんな感じですが、どうやって動かすのかわからないようです。

Method

6
Sean

ここでいくつかのものが混同されているようです。これを行うときは、ベクトルの形状を追跡し、適切な結果が得られるようにすることが重要です。たとえば、次のようにコストを計算しています。

_cost = ((-y) * np.log(sigmoid(X[i]))) - ((1 - y) * np.log(1 - sigmoid(X[i])))
_

あなたの場合、yは20項目のベクトルであり、X [i]は単一の値です。これにより、コスト計算は20項目のベクトルになりますが意味がありません。コストは単一の値である必要があります。 (勾配降下関数では、理由もなく、このコストを何回も計算しています)。

また、これをデータに適合させたい場合は、Xにバイアス項を追加する必要があります。それでは、そこから始めましょう。

_X = np.asarray([
    [0.50],[0.75],[1.00],[1.25],[1.50],[1.75],[1.75],
    [2.00],[2.25],[2.50],[2.75],[3.00],[3.25],[3.50],
    [4.00],[4.25],[4.50],[4.75],[5.00],[5.50]])

ones = np.ones(X.shape)
X = np.hstack([ones, X])
# X.shape is now (20, 2)
_

シータでは、Xごとに2つの値が必要になります。したがって、それとYを初期化します。

_Y = np.array([0,0,0,0,0,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1]).reshape([-1, 1])
# reshape Y so it's column vector so matrix multiplication is easier
Theta = np.array([[0], [0]])
_

あなたのシグモイド関数は良いです。ベクトル化されたコスト関数も作成しましょう。

_def sigmoid(a):
    return 1.0 / (1 + np.exp(-a))

def cost(x, y, theta):
    m = x.shape[0]
    h = sigmoid(np.matmul(x, theta))
    cost = (np.matmul(-y.T, np.log(h)) - np.matmul((1 -y.T), np.log(1 - h)))/m
    return cost
_

Thetaの形状は(2、1)であり、Xの形状は(20、2)であるため、コスト関数は機能します。したがって、matmul(X, Theta)の形状は(20、 1)。 then行列は、Yの転置を乗算し(_y.T_形状は(1、20))、単一の値になります。コストは、シータの特定の値が与えられます。

次に、バッチ勾配降下の単一ステップを実行する関数を記述できます。

_def gradient_Descent(theta, alpha, x , y):
    m = x.shape[0]
    h = sigmoid(np.matmul(x, theta))
    grad = np.matmul(X.T, (h - y)) / m;
    theta = theta - alpha * grad
    return theta
_

np.matmul(X.T, (h - y))が形状(2、20)と(20、1)を乗算していることに注意してください。これにより、(2、1)の形状になります。これはThetaと同じ形状です。あなたの勾配から。これにより、学習率を乗算し、それを最初のシータから減算することができます。これは、最急降下法が行うことになっていることです。

したがって、ここで、いくつかの反復のループを作成し、収束するように見えるまでThetaを更新します。

_n_iterations = 500
learning_rate = 0.5

for i in range(n_iterations):
    Theta = gradient_Descent(Theta, learning_rate, X, Y)
    if i % 50 == 0:
        print(cost(X, Y, Theta))
_

これにより、50回の反復ごとにコストが出力され、コストが着実に減少します。これは、次のことを望んでいます。

[[0.6410409]] [[0.44766253]] [[0.41593581]] [[0.40697167]] [[0.40377785]] [[0.4024982]] [[0.40195]] [[0.40170533]] [[0.40159325]] [[0.40154101]]

Thetaのさまざまな初期値を試すことができ、常に同じものに収束することがわかります。

これで、新しく見つかったThetaの値を使用して予測を行うことができます。

_h = sigmoid(np.matmul(X, Theta))
print((h > .5).astype(int) )
_

これにより、データへの線形フィットに期待されるものが出力されます。

[[0] [0] [0] [0] [0] [0] [0] [0] [0] [0] [1] [1] [1] [1] [1] [1] [ 1] [1] [1] [1]]

7
Mark Meyer