拟合的曲面与相同数据生成的热图不相似

0 投票
1 回答
60 浏览
提问于 2025-04-12 18:21

我有一些 z 值,这些值分布在一个 8 x 10 的网格上。可以把这些 z 值画成一个热图,显示在 x-y 平面上(左边的子图)。现在我想给这些数据拟合一个表面,和热图上显示的内容一样。然而,拟合出来的表面(右边的子图)看起来和热图完全不一样。我哪里做错了呢?另外,如果我把 .Tcontour1 = ... 这一行去掉(有些人建议这样做),我会遇到类型错误,因为形状不匹配。

这是代码:

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()

这是图形:

enter image description here

1 个回答

0

根据评论进行了编辑

如果你使用默认的 numpy.meshgrid 调用,那么你的 x 和 y 值与依赖变量数组的布局是这样的:(如果你想看,可以打印 x_gridy_gridz_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()

输出: 在这里输入图片描述

撰写回答