逻辑回归梯度下降

Logistic Regression Gradient Descent

我必须使用批量梯度下降法进行逻辑回归。

import numpy as np

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)   

我必须这样做的方式是这样的,但我似乎无法理解如何让它工作。

看起来你在这里混了一些东西。执行此操作时,务必要跟踪矢量的形状并确保获得合理的结果。例如,您正在计算费用:

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)

Theta 现在需要每个 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]])

你的 sigmoid 函数很好。让我们也做一个矢量化成本函数:

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).然后矩阵乘以 Y 的转置(y.T 形状为 (1, 20)),结果为单个值,我们的成本给定了特定的 Theta 值。

然后我们可以编写一个函数来执行单步批量梯度下降:

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 相同的形状你想从你的梯度。这允许您将 is 乘以您的学习率并从初始 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]]