拟合的曲面与相同数据生成的热图不相似
我有一些 z 值,这些值分布在一个 8 x 10 的网格上。可以把这些 z 值画成一个热图,显示在 x-y 平面上(左边的子图)。现在我想给这些数据拟合一个表面,和热图上显示的内容一样。然而,拟合出来的表面(右边的子图)看起来和热图完全不一样。我哪里做错了呢?另外,如果我把 .T
从 contour1 = ...
这一行去掉(有些人建议这样做),我会遇到类型错误,因为形状不匹配。
这是代码:
import matplotlib.pyplot as plt
import numpy as np
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
x_values = np.linspace(1, 8, 8)
y_values = np.linspace(1, 10, 10)
z_values = [[0.0128, 0.0029, 0.0009, 0.0006, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
[0.0049, 0.0157, 0.0067, 0.0003, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
[0.0203, 0.0096, 0.0055, 0.0096, 0.0012, 0.0023, 0.0000, 0.0000, 0.0000, 0.0000],
[0.0229, 0.0191, 0.0020, 0.0073, 0.0055, 0.0026, 0.0022, 0.0000, 0.0000, 0.0000],
[0.0218, 0.0357, 0.0035, 0.0133, 0.0073, 0.0145, 0.0000, 0.0029, 0.0000, 0.0000],
[0.0261, 0.0232, 0.0365, 0.0200, 0.0212, 0.0107, 0.0036, 0.0007, 0.0022, 0.0007],
[0.0305, 0.0244, 0.0284, 0.0786, 0.0226, 0.0160, 0.0000, 0.0196, 0.0007, 0.0007],
[0.0171, 0.0189, 0.0598, 0.0215, 0.0218, 0.0464, 0.0399, 0.0051, 0.0000, 0.0000]]
z_values = np.array(z_values)
x_grid, y_grid = np.meshgrid(x_values, y_values)
fig = plt.figure(figsize=(12, 5))
ax1 = fig.add_subplot(121)
contour1 = ax1.contourf(x_grid, y_grid, np.log(z_values.T + 1))
fig.colorbar(contour1, ax=ax1)
ax1.set_xlabel('x values')
ax1.set_ylabel('y values')
x_flat = x_grid.flatten()
y_flat = y_grid.flatten()
z_flat = z_values.flatten()
degree = 4
poly_features = PolynomialFeatures(degree=degree)
X_poly = poly_features.fit_transform(np.column_stack((x_flat, y_flat)))
model = LinearRegression()
model.fit(X_poly, z_flat)
z_pred = model.predict(X_poly)
z_pred_grid = z_pred.reshape(x_grid.shape)
ax2 = fig.add_subplot(122, projection='3d')
ax2.plot_surface(x_grid, y_grid, np.log(z_pred_grid + 1), cmap='viridis')
ax2.set_xlabel('x values')
ax2.set_ylabel('y values')
ax2.set_zlabel('z values')
plt.show()
这是图形:
1 个回答
0
根据评论进行了编辑
如果你使用默认的 numpy.meshgrid 调用,那么你的 x 和 y 值与依赖变量数组的布局是这样的:(如果你想看,可以打印 x_grid
、y_grid
和 z_values
):
x ------->
y
| [dependent-]
| [variable ]
\|/ [ array ]
你的多项式拟合图是这样的,但你的热图就不是。我觉得这是因为你在热图中转置了 z,但在多项式拟合中没有转置 z。
无论你怎么做,你都需要在两个图中使用相同的依赖变量数组。
你有两个选择:要么 (1) 在绘图之前转置依赖变量数组,保持 meshgrid 调用不变;要么 (2) 保持依赖变量数组不变,但改变 meshgrid 中的索引顺序。
下面是完整的代码。请注意这两个选项(通过容易更改的变量 option
给出)。
在这两种情况下,输出图是一样的。两个子图的峰值现在对应在一起。它们位于高-x/低-y 的位置。
import matplotlib.pyplot as plt
import numpy as np
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
x_values = np.linspace(1, 8, 8)
y_values = np.linspace(1, 10, 10)
z_values = [[0.0128, 0.0029, 0.0009, 0.0006, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
[0.0049, 0.0157, 0.0067, 0.0003, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000],
[0.0203, 0.0096, 0.0055, 0.0096, 0.0012, 0.0023, 0.0000, 0.0000, 0.0000, 0.0000],
[0.0229, 0.0191, 0.0020, 0.0073, 0.0055, 0.0026, 0.0022, 0.0000, 0.0000, 0.0000],
[0.0218, 0.0357, 0.0035, 0.0133, 0.0073, 0.0145, 0.0000, 0.0029, 0.0000, 0.0000],
[0.0261, 0.0232, 0.0365, 0.0200, 0.0212, 0.0107, 0.0036, 0.0007, 0.0022, 0.0007],
[0.0305, 0.0244, 0.0284, 0.0786, 0.0226, 0.0160, 0.0000, 0.0196, 0.0007, 0.0007],
[0.0171, 0.0189, 0.0598, 0.0215, 0.0218, 0.0464, 0.0399, 0.0051, 0.0000, 0.0000]]
#### If you want x to vary with ROW rather than the default COLUMN then choose ONE of these two approaches
option = 2
if ( option == 1 ): # Default meshgrid, but transpose the dependent variables
z_values = np.array(z_values).T
x_grid, y_grid = np.meshgrid(x_values, y_values)
else: # Leave the dependent variable, but use non-default meshgrid arrangement: indexing='ij'
z_values = np.array(z_values)
x_grid, y_grid = np.meshgrid(x_values, y_values,indexing='ij')
fig = plt.figure(figsize=(12, 5))
ax1 = fig.add_subplot(121)
contour1 = ax1.contourf(x_grid, y_grid, np.log(z_values + 1))
fig.colorbar(contour1, ax=ax1)
ax1.set_xlabel('x values')
ax1.set_ylabel('y values')
x_flat = x_grid.flatten()
y_flat = y_grid.flatten()
z_flat = z_values.flatten()
degree = 4
poly_features = PolynomialFeatures(degree=degree)
X_poly = poly_features.fit_transform(np.column_stack((x_flat, y_flat)))
model = LinearRegression()
model.fit(X_poly, z_flat)
z_pred = model.predict(X_poly)
z_pred_grid = z_pred.reshape(x_grid.shape)
ax2 = fig.add_subplot(122, projection='3d')
ax2.plot_surface(x_grid, y_grid, np.log(z_pred_grid + 1), cmap='viridis')
ax2.set_xlabel('x values')
ax2.set_ylabel('y values')
ax2.set_zlabel('z values')
plt.show()