diff --git a/大作业代码.py b/大作业代码.py new file mode 100644 index 0000000..9efc974 --- /dev/null +++ b/大作业代码.py @@ -0,0 +1,117 @@ +import numpy as np +import matplotlib.pyplot as plt + +# 设置中文显示 +plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"] +plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 + +# 生成数据集 +def gen(): + m = 20 + X0 = np.ones((m, 1)) + X1 = np.arange(1, m+1).reshape(m, 1) + X = np.hstack((X0, X1)) + true_params = np.array([[1], [1.5]]) + y = np.dot(X, true_params) + np.random.normal(0, 2, size=(m, 1)) + return X, X1, y, m + +# 定义代价函数 (均方误差) +def cos(theta, X, y, m): + error = np.dot(X, theta) - y + return (1 / (2 * m)) * np.dot(error.T, error)[0, 0] + +# 定义梯度函数 +def gra(theta, X, y, m): + error = np.dot(X, theta) - y + return (1 / m) * np.dot(X.T, error) + +# 梯度下降迭代 +def des(X, y, m, al=0.01, max=10000, t=1e-5): + """ + 使用梯度下降算法求解最优参数 + + 参数: + X: 特征矩阵 + y: 目标值向量 + m: 样本数量 + al: 学习率 + max: 最大迭代次数 + t: 收敛阈值 + + 返回: + theta: 最优参数 + costs: 每次迭代的代价函数值 + """ + theta = np.array([[1], [1]]) # 初始化参数 [b, w] + costs = [] # 记录每次迭代的代价函数值 + + for iteration in range(max): + gradient = gra(theta, X, y, m) + theta = theta - al * gradient + cost = cos(theta, X, y, m) + costs.append(cost) + + # 检查收敛条件 + if np.max(np.abs(gradient)) < t: + print(f"在第 {iteration+1} 次迭代后收敛") + break + + # 每100次迭代打印一次信息 + if (iteration + 1) % 100 == 0: + print(f"迭代 {iteration+1}/{max}, 代价: {cost:.6f}") + + return theta, costs + +# 绘制结果 +def res(X1, y, theta, costs=None): + plt.figure(figsize=(14, 5)) + + # 绘制数据点和拟合直线 + plt.subplot(1, 2, 1) + plt.scatter(X1, y, s=30, c="red", marker="s", label="数据点") + plt.xlabel("X") + plt.ylabel("Y") + plt.title("数据点与拟合直线") + + x_range = np.arange(0, 21, 0.2) + y_pred = theta[0] + theta[1] * x_range + plt.plot(x_range, y_pred, 'b-', label=f'拟合直线: y = {theta[0][0]:.4f} + {theta[1][0]:.4f}x') + plt.legend() + + # 如果提供了代价函数值,绘制代价函数变化曲线 + if costs is not None: + plt.subplot(1, 2, 2) + plt.plot(range(1, len(costs) + 1), costs, 'g-') + plt.xlabel("迭代次数") + plt.ylabel("代价函数值") + plt.title("代价函数收敛过程") + plt.grid(True) + + plt.tight_layout() + plt.show() + +# 主函数 +def main(): + # 生成数据集 + X, X1, y, m = gen() + + # 设置超参数 + al = 0.01 # 学习率 + max = 10000 # 最大迭代次数 + t = 1e-5 # 收敛阈值 + + # 执行梯度下降 + print("开始执行梯度下降算法...") + theta, costs = des(X, y, m, al, max, t) + + # 输出结果 + print("\n优化结果:") + print(f"截距项 b = {theta[0][0]:.6f}") + print(f"斜率项 w = {theta[1][0]:.6f}") + print(f"最终代价函数值 = {cos(theta, X, y, m):.6f}") + + # 绘制结果 + res(X1, y, theta, costs) + +if __name__ == "__main__": + main() \ No newline at end of file