我需要使用批量梯度下降法进行逻辑回归。
import numpy as npX = 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 * gradgradient_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 现在是 (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])# 重塑Y,使其成为列向量,以便矩阵乘法更容易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
的形状相同,这是你从梯度中想要的。这允许你将它乘以学习率并从初始Theta中减去,这是梯度下降应该做的。
所以现在你只需编写一个循环,进行一定数量的迭代,并更新Theta,直到它看起来收敛:
n_iterations = 500learning_rate = 0.5for 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]]