Python 不收敛的批量梯度下降
Batch Gradient Descent with Python not converging
这是我用于此练习的 Jupyter Notebook:https://drive.google.com/file/d/18-OXyvXSit5x0ftiW9bhcqJrO_SE22_S/view?usp=sharing
我正在用 this 数据集练习简单的线性回归,这里是我的参数:
sat = np.array(data['SAT'])
gpa = np.array(data['GPA'])
theta_0 = 0.01
theta_1 = 0.01
alpha = 0.003
cost = 0
m = len(gpa)
我试图通过将成本函数转换为矩阵并执行元素明智的操作来优化成本函数计算。这是我得出的结果公式:
成本函数优化:
成本函数
def calculateCost(matrix_x,matrix_y,m):
global theta_0,theta_1
cost = (1 / (2 * m)) * ((theta_0 + (theta_1 * matrix_x) - matrix_y) ** 2).sum()
return cost
我也尝试对梯度下降做同样的事情。
梯度下降
def gradDescent(alpha,matrix_x,matrix_y):
global theta_0,theta_1,m,cost
cost = calculateCost(sat,gpa,m)
while cost > 1
temp_0 = theta_0 - alpha * (1 / m) * (theta_0 + theta_1 * matrix_x - matrix_y).sum()
temp_1 = theta_1 - alpha * (1 / m) * (matrix_x.transpose() * (theta_0 + theta_1 * matrix_x - matrix_y)).sum()
theta_0 = temp_0
theta_1 = temp_1
我不完全确定这两种实现是否正确。该实现返回了 114.89379821428574 的成本,这就是我绘制成本时 "descent" 的样子:
梯度下降图:
如果我正确实现了成本函数和梯度下降,请指正,并尽可能提供解释,因为我仍然多变量微积分的初学者。谢谢。
该代码有很多问题。
首先,漏洞背后的两个主要问题:
1) 行
temp_1 = theta_1 - alpha * (1 / m) * (matrix_x.transpose() * (theta_0 + theta_1 * matrix_x - matrix_y)).sum()
特别是矩阵乘法matrix_x.transpose() * (theta_0 + ...)
。 *
运算符进行逐元素乘法,因此,结果的大小为 20x20
,其中您期望的梯度大小为 1x1
(当您更新单个实数变量 theta_1
.
2) 梯度计算中的 while cost>1:
条件。您永远不会在循环中更新成本...
这是您的代码的一个有效版本:
import numpy as np
import matplotlib.pyplot as plt
sat=np.random.rand(40,1)
rand_a=np.random.randint(500)
rand_b=np.random.randint(400)
gpa=rand_a*sat+rand_b
theta_0 = 0.01
theta_1 = 0.01
alpha = 0.1
cost = 0
m = len(gpa)
def calculateCost(matrix_x,matrix_y,m):
global theta_0,theta_1
cost = (1 / 2 * m) * ((theta_0 + (theta_1 * matrix_x) - matrix_y) ** 2).sum()
return cost
def gradDescent(alpha,matrix_x,matrix_y,num_iter=10000,eps=0.5):
global theta_0,theta_1,m,cost
cost = calculateCost(sat,gpa,m)
cost_hist=[cost]
for i in range(num_iter):
theta_0 -= alpha * (1 / m) * (theta_0 + theta_1 * matrix_x - matrix_y).sum()
theta_1 -= alpha * (1 / m) * (matrix_x.transpose().dot(theta_0 + theta_1 * matrix_x - matrix_y)).sum()
cost = calculateCost(sat,gpa,m)
cost_hist.append(cost)
if cost<eps:
return cost_hist
if __name__=="__main__":
print("init_cost==",cost)
cost_hist=gradDescent(alpha,sat,gpa)
print("final_cost,num_iters",cost,len(cost_hist))
print(rand_b,theta_0,rand_a,theta_1)
plt.plot(cost_hist,linewidth=5,color="r");plt.show()
最后,编码风格本身虽然不对错误负责,但绝对是这里的一个问题。通常,全局变量只是不好的做法。它们只会导致容易出错、无法维护的代码。最好将它们存储在小型数据结构中并将它们传递给函数。在你的情况下,你可以将初始参数放在一个列表中,将它们传递给你的梯度计算函数,最后 return 优化的参数。
您对成本函数的实现有误:
1 / 2 * m
被解释为m/2
,你应该写成1/2/m
.
这是我用于此练习的 Jupyter Notebook:https://drive.google.com/file/d/18-OXyvXSit5x0ftiW9bhcqJrO_SE22_S/view?usp=sharing
我正在用 this 数据集练习简单的线性回归,这里是我的参数:
sat = np.array(data['SAT'])
gpa = np.array(data['GPA'])
theta_0 = 0.01
theta_1 = 0.01
alpha = 0.003
cost = 0
m = len(gpa)
我试图通过将成本函数转换为矩阵并执行元素明智的操作来优化成本函数计算。这是我得出的结果公式:
成本函数优化:
成本函数
def calculateCost(matrix_x,matrix_y,m):
global theta_0,theta_1
cost = (1 / (2 * m)) * ((theta_0 + (theta_1 * matrix_x) - matrix_y) ** 2).sum()
return cost
我也尝试对梯度下降做同样的事情。
梯度下降
def gradDescent(alpha,matrix_x,matrix_y):
global theta_0,theta_1,m,cost
cost = calculateCost(sat,gpa,m)
while cost > 1
temp_0 = theta_0 - alpha * (1 / m) * (theta_0 + theta_1 * matrix_x - matrix_y).sum()
temp_1 = theta_1 - alpha * (1 / m) * (matrix_x.transpose() * (theta_0 + theta_1 * matrix_x - matrix_y)).sum()
theta_0 = temp_0
theta_1 = temp_1
我不完全确定这两种实现是否正确。该实现返回了 114.89379821428574 的成本,这就是我绘制成本时 "descent" 的样子:
梯度下降图:
如果我正确实现了成本函数和梯度下降,请指正,并尽可能提供解释,因为我仍然多变量微积分的初学者。谢谢。
该代码有很多问题。
首先,漏洞背后的两个主要问题:
1) 行
temp_1 = theta_1 - alpha * (1 / m) * (matrix_x.transpose() * (theta_0 + theta_1 * matrix_x - matrix_y)).sum()
特别是矩阵乘法matrix_x.transpose() * (theta_0 + ...)
。 *
运算符进行逐元素乘法,因此,结果的大小为 20x20
,其中您期望的梯度大小为 1x1
(当您更新单个实数变量 theta_1
.
2) 梯度计算中的 while cost>1:
条件。您永远不会在循环中更新成本...
这是您的代码的一个有效版本:
import numpy as np
import matplotlib.pyplot as plt
sat=np.random.rand(40,1)
rand_a=np.random.randint(500)
rand_b=np.random.randint(400)
gpa=rand_a*sat+rand_b
theta_0 = 0.01
theta_1 = 0.01
alpha = 0.1
cost = 0
m = len(gpa)
def calculateCost(matrix_x,matrix_y,m):
global theta_0,theta_1
cost = (1 / 2 * m) * ((theta_0 + (theta_1 * matrix_x) - matrix_y) ** 2).sum()
return cost
def gradDescent(alpha,matrix_x,matrix_y,num_iter=10000,eps=0.5):
global theta_0,theta_1,m,cost
cost = calculateCost(sat,gpa,m)
cost_hist=[cost]
for i in range(num_iter):
theta_0 -= alpha * (1 / m) * (theta_0 + theta_1 * matrix_x - matrix_y).sum()
theta_1 -= alpha * (1 / m) * (matrix_x.transpose().dot(theta_0 + theta_1 * matrix_x - matrix_y)).sum()
cost = calculateCost(sat,gpa,m)
cost_hist.append(cost)
if cost<eps:
return cost_hist
if __name__=="__main__":
print("init_cost==",cost)
cost_hist=gradDescent(alpha,sat,gpa)
print("final_cost,num_iters",cost,len(cost_hist))
print(rand_b,theta_0,rand_a,theta_1)
plt.plot(cost_hist,linewidth=5,color="r");plt.show()
最后,编码风格本身虽然不对错误负责,但绝对是这里的一个问题。通常,全局变量只是不好的做法。它们只会导致容易出错、无法维护的代码。最好将它们存储在小型数据结构中并将它们传递给函数。在你的情况下,你可以将初始参数放在一个列表中,将它们传递给你的梯度计算函数,最后 return 优化的参数。
您对成本函数的实现有误:
1 / 2 * m
被解释为m/2
,你应该写成1/2/m
.