#matplotlib #machine-learning #linear-regression
#matplotlib #машинное обучение #линейная регрессия
Вопрос:
Я пытаюсь создать график поверхности функции ошибки в линейной регрессии. Я делаю это так:
class LinearRegression:
def __init__(self):
self.data = pd.read_csv("data.csv")
def computeCost(self):
j = 0.5 * (
(self.data.hypothesis - self.data.y)**2).sum() / self.data.y.size
return j
def regress(self, theta0, theta1):
self.data["hypothesis"] = theta1 * self.data.x theta0
def plotCostFunction3D(self):
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
theta0_vals = np.linspace(-100, 100, 200)
theta1_vals = np.linspace(-100, 100, 200)
costs = []
for theta0 in theta0_vals:
for theta1 in theta1_vals:
self.regress(theta0, theta1)
costs.append(self.computeCost())
ax.plot_surface(
theta0_vals,
theta1_vals,
np.array(costs),
)
if __name__ == "__main__":
regression = LinearRegression()
regression.plotCostFunction3D()
plt.show()
Я получаю следующую ошибку:
ValueError: Argument Z must be 2-dimensional.
Я знаю, что мне нужно использовать np.meshgrid
для theta0_vals
и theta1_vals
, но я не уверен, как вычислить затраты на основе этих результатов. Как бы я это сделал?
Комментарии:
1. Вы уже вычислили затраты для всей сетки внутри вложенных
for
циклов, верно? Итак, я думаю, вы могли бы просто использоватьcosts_2d = np.reshape(costs, (200, 200))
, или я что-то упустил?2. вам нужно изменить Z
3. И каковы будут аргументы для изменения формы? @Arne почему 200. 200?
4. Неважно. Я понял. Это потому, что у меня есть 200 значений как для theta0, так и для theta1. Спасибо.
5. Это сработало! Хотел бы кто-нибудь из вас, джентльмены, отправить ответ, который я могу принять?
Ответ №1:
Ошибка вызвана вызовом метода ax.plot_surface(theta0_vals, theta1_vals, np.array(costs))
, поскольку Axes3D.plot_surface(X, Y, Z)
ожидается, что его аргументы будут двумерными массивами.
Итак, как вы заметили, np.meshgrid()
следует использовать для вычисления сетки, охватываемой theta0_vals
и theta1_vals
. Что касается Z
, вы уже вычислили стоимость в каждой точке сетки, используя вложенные for
циклы, поэтому вам просто нужно превратить одномерный costs
список в двумерный массив, соответствующий сетке Xy. Это можно сделать с np.reshape()
помощью .
def plotCostFunction3D(self):
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
theta0_vals = np.linspace(-100, 100, 200)
theta1_vals = np.linspace(-100, 100, 200)
costs = []
for theta0 in theta0_vals:
for theta1 in theta1_vals:
self.regress(theta0, theta1)
costs.append(self.computeCost())
X, Y = np.meshgrid(theta0_vals, theta1_vals)
Z = np.reshape(costs, (200, 200))
ax.plot_surface(X, Y, Z)
Для повышения производительности было бы неплохо избежать вложенных for
циклов. Вы можете сохранить точки сетки X-Y в фрейме данных, а затем вычислить столбец Z с df.apply()
помощью .