{"id":"6w5kCatWxG","url":"https://pastebin.ca/6w5kCatWxG","raw_url":"https://raw.anybin.ca/6w5kCatWxG","visibility":"public","access":"public","created_at":1793949842046,"expires_at":1794554642046,"fetch_limit":null,"fetches_used":0,"reads_remaining":null,"size_bytes":4798,"syntax_hint":null,"title":null,"filename":null,"change_note":null,"cipher":null,"cipher_meta":null,"parent_id":null,"root_id":"6w5kCatWxG","version":1,"owner_id":null,"recipient_id":null,"body":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom sklearn.metrics import r2_score\n\n# ---------------------- 全局设置 中文+随机种子 ----------------------\nplt.rcParams['font.sans-serif'] = ['SimHei']\nplt.rcParams['axes.unicode_minus'] = False\ntorch.manual_seed(42)\nnp.random.seed(42)\n\n# 读取数据\ndf = pd.read_csv(\"data.csv\")\nx_raw = df[['x']].values.astype(np.float32)\ny_raw = df[['y']].values.astype(np.float32)\nx_tensor = torch.from_numpy(x_raw)\ny_tensor = torch.from_numpy(y_raw)\n\n# 神经网络定义：单层隐藏层，GELU激活\nclass MLP(nn.Module):\n    def __init__(self, hidden_n):\n        super().__init__()\n        self.net = nn.Sequential(\n            nn.Linear(1, hidden_n),\n            nn.GELU(),\n            nn.Linear(hidden_n, 1)\n        )\n    def forward(self, x):\n        return self.net(x)\n\n# ---------------------- 任务2：不同隐藏节点n，cosine decay，lr=0.01，epoch=10000 ----------------------\nn_list = [2,4,6,8,16,32]  # 6个n，正好6张子图\nepoch_total = 10000\nlr0 = 0.01\ncriterion = nn.MSELoss()\n\nres_fit = []   # 保存预测结果\nres_loss = []  # 保存loss曲线\nres_r2 = []    # 保存R2\nlr_record = [] # 保存学习率变化（取n=8为例）\n\nfor n in n_list:\n    model = MLP(n)\n    opt = optim.Adam(model.parameters(), lr=lr0)\n    scheduler = optim.lr_scheduler.CosineAnnealingLR(opt, T_max=epoch_total, eta_min=0)\n    loss_hist = []\n    for ep in range(epoch_total):\n        opt.zero_grad()\n        pred = model(x_tensor)\n        loss = criterion(pred, y_tensor)\n        loss.backward()\n        opt.step()\n        scheduler.step()\n        loss_hist.append(loss.item())\n        if n == 8:\n            lr_record.append(opt.param_groups[0]['lr'])\n    # 预测 & R2\n    with torch.no_grad():\n        y_pred = model(x_tensor).numpy()\n    r2 = r2_score(y_raw, y_pred)\n    res_fit.append(y_pred)\n    res_loss.append(loss_hist)\n    res_r2.append(r2)\n\n# 图1：6个子图，不同n拟合效果\nfig1, axes = plt.subplots(2,3,figsize=(14,9))\naxes = axes.flatten()\nfor i, ax in enumerate(axes):\n    ax.scatter(x_raw, y_raw, s=10, label=\"真实数据\")\n    ax.plot(x_raw, res_fit[i], c='red', lw=2, label=f\"n={n_list[i]}, R2={res_r2[i]:.4f}\")\n    ax.set_title(f\"隐藏层节点数 n={n_list[i]}\")\n    ax.legend()\n    ax.grid(alpha=0.3)\nfig1.suptitle(\"不同隐藏层节点数的拟合效果\", fontsize=15)\nplt.tight_layout()\nplt.savefig(\"fit_compare.jpg\", dpi=300)\n\n# 图2：不同n训练损失曲线\nplt.figure(figsize=(10,6))\ncolors = [\"#e74c3c\",\"#3498db\",\"#2ecc71\",\"#9b59b6\",\"#f39c12\",\"#1abc9c\"]\nfor i, n in enumerate(n_list):\n    plt.plot(res_loss[i], label=f\"n={n}\", color=colors[i])\nplt.xlabel(\"Epoch\")\nplt.ylabel(\"MSE损失\")\nplt.yscale(\"log\")\nplt.title(\"不同隐藏层节点数的训练损失曲线\")\nplt.legend()\nplt.grid(alpha=0.3)\nplt.tight_layout()\nplt.savefig(\"loss_n_curve.jpg\", dpi=300)\n\n# 图3：cosine decay学习率变化曲线（n=8）\nplt.figure(figsize=(8,5))\nplt.plot(lr_record)\nplt.xlabel(\"Epoch\")\nplt.ylabel(\"学习率\")\nplt.title(\"Cosine Decay学习率变化曲线\")\nplt.grid(alpha=0.3)\nplt.tight_layout()\nplt.savefig(\"lr_cosine_curve.jpg\", dpi=300)\n\n# 图4：柱状图 R2对比\nplt.figure(figsize=(8,5))\nplt.bar([str(i) for i in n_list], res_r2, color=colors)\nplt.xlabel(\"隐藏层节点数 n\")\nplt.ylabel(\"决定系数 R²\")\nplt.title(\"不同隐藏层节点数的决定系数对比\")\nplt.ylim(0, 1.05)\nfor idx,val in enumerate(res_r2):\n    plt.text(idx, val+0.01, f\"{val:.4f}\", ha=\"center\")\nplt.tight_layout()\nplt.savefig(\"r2_bar.jpg\", dpi=300)\n\n# ---------------------- 任务3：固定n=8，关闭cosine decay，lr=[0.001,0.01,0.1,1] ----------------------\nlr_test_list = [0.001, 0.01, 0.1, 1.0]\nloss_lr_all = []\nfor lr in lr_test_list:\n    model = MLP(hidden_n=8)\n    opt = optim.Adam(model.parameters(), lr=lr)\n    # 不设置scheduler，lr固定不变\n    loss_hist = []\n    for ep in range(epoch_total):\n        opt.zero_grad()\n        pred = model(x_tensor)\n        loss = criterion(pred, y_tensor)\n        loss.backward()\n        opt.step()\n        loss_hist.append(loss.item())\n    loss_lr_all.append(loss_hist)\n\n# 图5：不同学习率损失曲线\nfig2, axes = plt.subplots(2,2,figsize=(12,9))\naxes = axes.flatten()\nfor i, ax in enumerate(axes):\n    ax.plot(loss_lr_all[i])\n    ax.set_title(f\"学习率 lr={lr_test_list[i]}\")\n    ax.set_xlabel(\"Epoch\")\n    ax.set_ylabel(\"MSE Loss\")\n    ax.grid(alpha=0.3)\nfig2.suptitle(\"不同学习率下的训练损失曲线（关闭cosine decay）\", fontsize=15)\nplt.tight_layout()\nplt.savefig(\"lr_loss_compare.jpg\", dpi=300)\n\nplt.show()\nprint(\"===== 任务2结果R2 =====\")\nfor n,r2 in zip(n_list, res_r2):\n    print(f\"n={n}, R2={r2:.4f}\")\nprint(\"===== 全部绘图完成 =====\")\n\n"}