这是我用于此练习的Jupyter Notebook:https://drive.google.com/file/d/18-OXyvXSit5x0ftiW9bhcqJrO_SE22_S/view?usp=sharing
我在练习使用这个数据集进行简单的线性回归,以下是我的参数设置:
sat = np.array(data['SAT'])gpa = np.array(data['GPA'])theta_0 = 0.01theta_1 = 0.01alpha = 0.003cost = 0m = len(gpa)
我尝试通过将成本函数计算转换为矩阵并进行元素 wise 操作来优化成本函数计算。这是最终得出的公式:
成本函数优化:
成本函数
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,当我绘制成本图时,“下降”的情况看起来是这样的:
梯度下降图表:
如果我对成本函数和梯度下降的实现有误,请纠正我,并尽可能提供解释,因为我在多变量微积分方面还是初学者。谢谢你。
回答:
这段代码存在许多问题。
首先,导致错误的两个主要问题是:
1)这一行
temp_1 = theta_1 - alpha * (1 / m) * (matrix_x.transpose() * (theta_0 + ...)
特别是矩阵乘法matrix_x.transpose() * (theta_0 + ...)
。这里的*
运算符执行的是元素 wise 乘法,结果是20x20
的大小,而你期望的是一个1x1
的梯度(因为你更新的是单个实数变量theta_1
)。
2)你在梯度计算中的while cost>1:
条件。你在循环中从未更新成本…
以下是工作版本的代码:
import numpy as npimport matplotlib.pyplot as pltsat=np.random.rand(40,1)rand_a=np.random.randint(500)rand_b=np.random.randint(400)gpa=rand_a*sat+rand_btheta_0 = 0.01theta_1 = 0.01alpha = 0.1cost = 0m = 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 costdef 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_histif __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()
最后,编码风格本身虽然不是导致错误的原因,但确实是一个问题。通常,全局变量是一种不好的做法。它们会导致容易出错且难以维护的代码。最好是将它们存储在小型数据结构中,并在函数之间传递。在你的情况下,你可以将初始参数放入一个列表中,传递给你的梯度计算函数,并在最后返回优化的参数。