rendered paste bodyimport pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport torchimport torch.nn as nnimport torch.optim as optimfrom sklearn.metrics import r2_score# ---------------------- 全局设置 中文+随机种子 ----------------------plt.rcParams['font.sans-serif'] = ['SimHei']plt.rcParams['axes.unicode_minus'] = Falsetorch.manual_seed(42)np.random.seed(42)# 读取数据df = pd.read_csv("data.csv")x_raw = df[['x']].values.astype(np.float32)y_raw = df[['y']].values.astype(np.float32)x_tensor = torch.from_numpy(x_raw)y_tensor = torch.from_numpy(y_raw)# 神经网络定义:单层隐藏层,GELU激活class MLP(nn.Module): def __init__(self, hidden_n): super().__init__() self.net = nn.Sequential( nn.Linear(1, hidden_n), nn.GELU(), nn.Linear(hidden_n, 1) ) def forward(self, x): return self.net(x)# ---------------------- 任务2:不同隐藏节点n,cosine decay,lr=0.01,epoch=10000 ----------------------n_list = [2,4,6,8,16,32] # 6个n,正好6张子图epoch_total = 10000lr0 = 0.01criterion = nn.MSELoss()res_fit = [] # 保存预测结果res_loss = [] # 保存loss曲线res_r2 = [] # 保存R2lr_record = [] # 保存学习率变化(取n=8为例)for n in n_list: model = MLP(n) opt = optim.Adam(model.parameters(), lr=lr0) scheduler = optim.lr_scheduler.CosineAnnealingLR(opt, T_max=epoch_total, eta_min=0) loss_hist = [] for ep in range(epoch_total): opt.zero_grad() pred = model(x_tensor) loss = criterion(pred, y_tensor) loss.backward() opt.step() scheduler.step() loss_hist.append(loss.item()) if n == 8: lr_record.append(opt.param_groups[0]['lr']) # 预测 & R2 with torch.no_grad(): y_pred = model(x_tensor).numpy() r2 = r2_score(y_raw, y_pred) res_fit.append(y_pred) res_loss.append(loss_hist) res_r2.append(r2)# 图1:6个子图,不同n拟合效果fig1, axes = plt.subplots(2,3,figsize=(14,9))axes = axes.flatten()for i, ax in enumerate(axes): ax.scatter(x_raw, y_raw, s=10, label="真实数据") ax.plot(x_raw, res_fit[i], c='red', lw=2, label=f"n={n_list[i]}, R2={res_r2[i]:.4f}") ax.set_title(f"隐藏层节点数 n={n_list[i]}") ax.legend() ax.grid(alpha=0.3)fig1.suptitle("不同隐藏层节点数的拟合效果", fontsize=15)plt.tight_layout()plt.savefig("fit_compare.jpg", dpi=300)# 图2:不同n训练损失曲线plt.figure(figsize=(10,6))colors = ["#e74c3c","#3498db","#2ecc71","#9b59b6","#f39c12","#1abc9c"]for i, n in enumerate(n_list): plt.plot(res_loss[i], label=f"n={n}", color=colors[i])plt.xlabel("Epoch")plt.ylabel("MSE损失")plt.yscale("log")plt.title("不同隐藏层节点数的训练损失曲线")plt.legend()plt.grid(alpha=0.3)plt.tight_layout()plt.savefig("loss_n_curve.jpg", dpi=300)# 图3:cosine decay学习率变化曲线(n=8)plt.figure(figsize=(8,5))plt.plot(lr_record)plt.xlabel("Epoch")plt.ylabel("学习率")plt.title("Cosine Decay学习率变化曲线")plt.grid(alpha=0.3)plt.tight_layout()plt.savefig("lr_cosine_curve.jpg", dpi=300)# 图4:柱状图 R2对比plt.figure(figsize=(8,5))plt.bar([str(i) for i in n_list], res_r2, color=colors)plt.xlabel("隐藏层节点数 n")plt.ylabel("决定系数 R²")plt.title("不同隐藏层节点数的决定系数对比")plt.ylim(0, 1.05)for idx,val in enumerate(res_r2): plt.text(idx, val+0.01, f"{val:.4f}", ha="center")plt.tight_layout()plt.savefig("r2_bar.jpg", dpi=300)# ---------------------- 任务3:固定n=8,关闭cosine decay,lr=[0.001,0.01,0.1,1] ----------------------lr_test_list = [0.001, 0.01, 0.1, 1.0]loss_lr_all = []for lr in lr_test_list: model = MLP(hidden_n=8) opt = optim.Adam(model.parameters(), lr=lr) # 不设置scheduler,lr固定不变 loss_hist = [] for ep in range(epoch_total): opt.zero_grad() pred = model(x_tensor) loss = criterion(pred, y_tensor) loss.backward() opt.step() loss_hist.append(loss.item()) loss_lr_all.append(loss_hist)# 图5:不同学习率损失曲线fig2, axes = plt.subplots(2,2,figsize=(12,9))axes = axes.flatten()for i, ax in enumerate(axes): ax.plot(loss_lr_all[i]) ax.set_title(f"学习率 lr={lr_test_list[i]}") ax.set_xlabel("Epoch") ax.set_ylabel("MSE Loss") ax.grid(alpha=0.3)fig2.suptitle("不同学习率下的训练损失曲线(关闭cosine decay)", fontsize=15)plt.tight_layout()plt.savefig("lr_loss_compare.jpg", dpi=300)plt.show()print("===== 任务2结果R2 =====")for n,r2 in zip(n_list, res_r2): print(f"n={n}, R2={r2:.4f}")print("===== 全部绘图完成 =====")