代码如下:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.patches import Patch# 生成二维输入数据
np.random.seed(0)
X1 = 2 * np.random.rand(100, 1) # 第一个特征
X2 = 3 * np.random.rand(100, 1) # 第二个特征
X = np.hstack((X1, X2)) # 将两个特征合并为二维输入# 生成目标值 y(线性关系 + 噪声)
y = 4 + 3 * X1 + 5 * X2 + np.random.randn(100, 1)# 添加偏置项(全为1的列)
X_b = np.c_[np.ones((100, 1)), X]# 初始化参数 theta (theta0, theta1, theta2)
theta = np.random.randn(3, 1)# 学习率
eta = 0.1# 迭代次数
n_iterations = 100# 用于存储每次迭代的损失值
loss_history = []# 用于存储每次迭代的 theta 值
theta_history = [theta]# 梯度下降
for iteration in range(n_iterations):gradients = 2 / 100 * X_b.T.dot(X_b.dot(theta) - y) # 计算梯度theta = theta - eta * gradients # 更新参数theta_history.append(theta)# 计算损失(均方误差)loss = np.mean((X_b.dot(theta) - y) ** 2)loss_history.append(loss)# 可视化每次拟合的平面
def plot_fitted_plane(X1, X2, y, theta, iteration):fig = plt.figure(figsize=(10, 6))ax = fig.add_subplot(111, projection='3d')scatter = ax.scatter(X1, X2, y, color='blue', label='Data points') # 绘制数据点# 生成网格点用于绘制平面X1_grid, X2_grid = np.meshgrid(np.linspace(X1.min(), X1.max(), 10), np.linspace(X2.min(), X2.max(), 10))y_grid = theta[0] + theta[1] * X1_grid + theta[2] * X2_grid # 计算平面surface = ax.plot_surface(X1_grid, X2_grid, y_grid, alpha=0.5, facecolor='red') # 绘制平面# 手动创建图例legend_elements = [Patch(facecolor='blue', label='Data points'),Patch(facecolor='red', label=f'Fitted plane (Iteration {iteration})')]ax.legend(handles=legend_elements)ax.set_xlabel('X1')ax.set_ylabel('X2')ax.set_zlabel('y')ax.set_title(f'Linear Regression with Gradient Descent (Iteration {iteration})')plt.show()# 每隔 20 次迭代绘制一次拟合平面
for i in range(0, n_iterations, 20):plot_fitted_plane(X1, X2, y, theta_history[i].flatten(), i)# 绘制损失函数的变化
plt.figure(figsize=(10, 6))
plt.plot(range(n_iterations), loss_history, color='red')
plt.xlabel('Iterations')
plt.ylabel('Loss')
plt.title('Loss Function over Iterations')
plt.show()
输入 X 为2维度 , XY 一共三维, 所以可以可视化在一个 3d 图形中。
X1 = 2 * np.random.rand(100, 1) # 第一个特征
X2 = 3 * np.random.rand(100, 1) # 第二个特征
X = np.hstack((X1, X2)) # 将两个特征合并为二维输入# 生成目标值 y(线性关系 + 噪声)
y = 4 + 3 * X1 + 5 * X2 + np.random.randn(100, 1)
这是随机生成 x1 和x2 , 然后 根据 y = 4 + 3*x1 + 5*x2 + 随机噪音来生成 y
最后会拟合为一个平面。 为啥会这样?
可以理解为 起点 和 两个垂直方向的向量 可以 张开一个 平面。
也可以理解为 ,
-
如果方程中只有一个自变量(例如
y = 4 + 3 * X1
),那么它是一条 直线。 -
如果有两个自变量(例如
y = 4 + 3 * X1 + 5 * X2
),那么它是一个 平面。 -
如果有更多自变量(例如
y = 4 + 3 * X1 + 5 * X2 + 2 * X3
),那么它是一个 超平面(在更高维空间中)。
梯度下降: