错误计算线性回归模型的成本函数

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 < 100 < 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 表面没有最小点,但有一个不与 theta0theta1 对齐的最小区域。
由于我不知道 theta0theta1 实际上代表什么,我可能给它们赋了没有意义的值:例如,如果它们分别是纬度和经度,那么它们的域应该是 -90 < theta0 < 900 < theta1 < 180。这取决于theta0theta1的物理意义。


但是,您始终可以使用 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) 中两个梯度都为空。