错误计算线性回归模型的成本函数
Miscalculating the cost function for a linear regression model
我正在尝试渲染成本函数的 3D 图。给定一个数据集和两个不同的参数(theta0 和 theta1),我想渲染一个我们都在经典文学中看到的 bowl-like 图。我的假设函数只是一个简单的h(x) = theta_0 + theta_1 * x
。但是,我的成本函数呈现如下:
这个剧情能搞定吗?万一是这样的“碗”怎么画呢?
import matplotlib.pyplot as plt
import numpy as np
training_set = np.array([
[20, 400],
[30, 460],
[10, 300],
[50, 780],
[15, 350],
[60, 800],
[19, 360],
[31, 410],
[5, 50],
[46, 650],
[37, 400],
[39, 900]])
cost_factor = (1.0 / (len(training_set) * 2))
hypothesis = lambda theta0, theta1, x: theta0 + theta1 * x
cost = lambda theta0, theta1: cost_factor * sum(map(
lambda entry: (hypothesis(theta0, theta1, entry[0]) - entry[1]) ** 2, training_set))
theta1 = np.arange(0, 10, 1)
theta2 = np.arange(0, 10, 1)
X, Y = np.meshgrid(theta1, theta1)
Z = cost(X, Y)
ax = plt.axes(projection='3d')
ax.plot_surface(X, Y, Z, cmap='viridis', edgecolor='none')
ax.set_xlabel(r'$\theta_0$')
ax.set_ylabel(r'$\theta_1$')
ax.set_zlabel(r'$J(\theta_0, \theta_1)$')
ax.set_title('Cost function')
plt.show()
旁注:
- 我已在您的代码中将
theta1
重命名为 theta0
并将 theta2
重命名为 theta1
以避免代码与绘图标签之间的混淆
- 您的代码包含错字:
X, Y = np.meshgrid(theta1, theta1)
应该是 X, Y = np.meshgrid(theta0, theta1)
您的 Z
表面可能有一个 absolute/relative minimum/maximum 的点位于您选择的域之外:0 < theta0 < 10
和 0 < theta1 < 10
。你可以尝试扩大这个区间,看看是否真的有一个驻点:
theta0 = np.arange(-100, 100, 5)
theta1 = np.arange(-100, 100, 5)
所以有一个 -50 < theta1 < 50
的最小区域。您的 2D 表面似乎没有沿 theta0
方向的最小值;但是您也可以尝试扩展此域:
theta0 = np.arange(-1000, 1000, 100)
theta1 = np.arange(-50, 50, 1)
所以你可以看到你的 Z
表面没有最小点,但有一个不与 theta0
或 theta1
对齐的最小区域。
由于我不知道 theta0
和 theta1
实际上代表什么,我可能给它们赋了没有意义的值:例如,如果它们分别是纬度和经度,那么它们的域应该是 -90 < theta0 < 90
和 0 < theta1 < 180
。这取决于theta0
和theta1
的物理意义。
但是,您始终可以使用 np.gradient
计算曲面的梯度并绘制它们:
g1, g2 = np.gradient(Z)
fig = plt.figure()
ax1 = fig.add_subplot(1, 3, 1, projection = '3d')
ax2 = fig.add_subplot(1, 3, 2, projection = '3d')
ax3 = fig.add_subplot(1, 3, 3, projection = '3d')
ax1.plot_surface(X, Y, Z, cmap='viridis', edgecolor='none')
ax2.plot_surface(X, Y, g1, cmap='viridis', edgecolor='none')
ax3.plot_surface(X, Y, g2, cmap='viridis', edgecolor='none')
ax1.set_xlabel(r'$\theta_0$')
ax1.set_ylabel(r'$\theta_1$')
ax1.set_zlabel(r'$J(\theta_0, \theta_1)$')
ax1.set_title('Cost function')
ax2.set_xlabel(r'$\theta_0$')
ax2.set_ylabel(r'$\theta_1$')
ax3.set_xlabel(r'$\theta_0$')
ax3.set_ylabel(r'$\theta_1$')
plt.show()
可以看到梯度为空的区域是一条线,不是一个点
如果您的 Z
表面会有不同的表达式,例如:
Z = np.exp(-X**2 - Y**2)
你会:
在这种情况下,您可以看到在表面具有最大值的点 (0, 0)
中两个梯度都为空。
我正在尝试渲染成本函数的 3D 图。给定一个数据集和两个不同的参数(theta0 和 theta1),我想渲染一个我们都在经典文学中看到的 bowl-like 图。我的假设函数只是一个简单的h(x) = theta_0 + theta_1 * x
。但是,我的成本函数呈现如下:
这个剧情能搞定吗?万一是这样的“碗”怎么画呢?
import matplotlib.pyplot as plt
import numpy as np
training_set = np.array([
[20, 400],
[30, 460],
[10, 300],
[50, 780],
[15, 350],
[60, 800],
[19, 360],
[31, 410],
[5, 50],
[46, 650],
[37, 400],
[39, 900]])
cost_factor = (1.0 / (len(training_set) * 2))
hypothesis = lambda theta0, theta1, x: theta0 + theta1 * x
cost = lambda theta0, theta1: cost_factor * sum(map(
lambda entry: (hypothesis(theta0, theta1, entry[0]) - entry[1]) ** 2, training_set))
theta1 = np.arange(0, 10, 1)
theta2 = np.arange(0, 10, 1)
X, Y = np.meshgrid(theta1, theta1)
Z = cost(X, Y)
ax = plt.axes(projection='3d')
ax.plot_surface(X, Y, Z, cmap='viridis', edgecolor='none')
ax.set_xlabel(r'$\theta_0$')
ax.set_ylabel(r'$\theta_1$')
ax.set_zlabel(r'$J(\theta_0, \theta_1)$')
ax.set_title('Cost function')
plt.show()
旁注:
- 我已在您的代码中将
theta1
重命名为theta0
并将theta2
重命名为theta1
以避免代码与绘图标签之间的混淆 - 您的代码包含错字:
X, Y = np.meshgrid(theta1, theta1)
应该是X, Y = np.meshgrid(theta0, theta1)
您的 Z
表面可能有一个 absolute/relative minimum/maximum 的点位于您选择的域之外:0 < theta0 < 10
和 0 < theta1 < 10
。你可以尝试扩大这个区间,看看是否真的有一个驻点:
theta0 = np.arange(-100, 100, 5)
theta1 = np.arange(-100, 100, 5)
所以有一个 -50 < theta1 < 50
的最小区域。您的 2D 表面似乎没有沿 theta0
方向的最小值;但是您也可以尝试扩展此域:
theta0 = np.arange(-1000, 1000, 100)
theta1 = np.arange(-50, 50, 1)
所以你可以看到你的 Z
表面没有最小点,但有一个不与 theta0
或 theta1
对齐的最小区域。
由于我不知道 theta0
和 theta1
实际上代表什么,我可能给它们赋了没有意义的值:例如,如果它们分别是纬度和经度,那么它们的域应该是 -90 < theta0 < 90
和 0 < theta1 < 180
。这取决于theta0
和theta1
的物理意义。
但是,您始终可以使用 np.gradient
计算曲面的梯度并绘制它们:
g1, g2 = np.gradient(Z)
fig = plt.figure()
ax1 = fig.add_subplot(1, 3, 1, projection = '3d')
ax2 = fig.add_subplot(1, 3, 2, projection = '3d')
ax3 = fig.add_subplot(1, 3, 3, projection = '3d')
ax1.plot_surface(X, Y, Z, cmap='viridis', edgecolor='none')
ax2.plot_surface(X, Y, g1, cmap='viridis', edgecolor='none')
ax3.plot_surface(X, Y, g2, cmap='viridis', edgecolor='none')
ax1.set_xlabel(r'$\theta_0$')
ax1.set_ylabel(r'$\theta_1$')
ax1.set_zlabel(r'$J(\theta_0, \theta_1)$')
ax1.set_title('Cost function')
ax2.set_xlabel(r'$\theta_0$')
ax2.set_ylabel(r'$\theta_1$')
ax3.set_xlabel(r'$\theta_0$')
ax3.set_ylabel(r'$\theta_1$')
plt.show()
可以看到梯度为空的区域是一条线,不是一个点
如果您的 Z
表面会有不同的表达式,例如:
Z = np.exp(-X**2 - Y**2)
你会:
在这种情况下,您可以看到在表面具有最大值的点 (0, 0)
中两个梯度都为空。