{ "cells": [ { "cell_type": "code", "id": "initial_id", "metadata": { "collapsed": true, "ExecuteTime": { "end_time": "2026-03-19T06:08:49.521494353Z", "start_time": "2026-03-19T06:08:47.762419340Z" } }, "source": [ "import torch\n", "import numpy\n", "import pandas" ], "outputs": [], "execution_count": 1 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:49.830469193Z", "start_time": "2026-03-19T06:08:49.585762895Z" } }, "cell_type": "code", "source": "torch.randn(3,4,2)", "id": "3e141a42d342fa96", "outputs": [ { "data": { "text/plain": [ "tensor([[[-1.0244, -0.4164],\n", " [ 1.5765, -0.9106],\n", " [-1.6388, -0.7727],\n", " [-1.8594, -1.6634]],\n", "\n", " [[-0.3226, 0.6604],\n", " [ 0.4341, -0.9600],\n", " [ 0.2575, 2.0599],\n", " [ 0.6960, 0.7095]],\n", "\n", " [[-0.0242, -0.5866],\n", " [-0.8018, -0.3080],\n", " [-1.3225, -0.0591],\n", " [ 0.0322, 0.8251]]])" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 2 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:49.974163555Z", "start_time": "2026-03-19T06:08:49.860972205Z" } }, "cell_type": "code", "source": [ "X = torch.arange(12, dtype=torch.float32).reshape((3,4))\n", "Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])\n", "torch.cat((X, Y), dim=0), torch.cat((X, Y), dim=1)" ], "id": "8ae20ae68abbf32f", "outputs": [ { "data": { "text/plain": [ "(tensor([[ 0., 1., 2., 3.],\n", " [ 4., 5., 6., 7.],\n", " [ 8., 9., 10., 11.],\n", " [ 2., 1., 4., 3.],\n", " [ 1., 2., 3., 4.],\n", " [ 4., 3., 2., 1.]]),\n", " tensor([[ 0., 1., 2., 3., 2., 1., 4., 3.],\n", " [ 4., 5., 6., 7., 1., 2., 3., 4.],\n", " [ 8., 9., 10., 11., 4., 3., 2., 1.]]))" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 3 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:50.119655002Z", "start_time": "2026-03-19T06:08:50.007109478Z" } }, "cell_type": "code", "source": [ "a = torch.arange(3).reshape((3, 1))\n", "b = torch.arange(2).reshape((1, 2))\n", "a, b\n", "a+b" ], "id": "2960a1ded2cdd5a4", "outputs": [ { "data": { "text/plain": [ "tensor([[0, 1],\n", " [1, 2],\n", " [2, 3]])" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 4 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:50.341778101Z", "start_time": "2026-03-19T06:08:50.149819865Z" } }, "cell_type": "code", "source": "X[-1], X[1:3]\n", "id": "69c2ec23ab6ae97c", "outputs": [ { "data": { "text/plain": [ "(tensor([ 8., 9., 10., 11.]),\n", " tensor([[ 4., 5., 6., 7.],\n", " [ 8., 9., 10., 11.]]))" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 5 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:51.169775176Z", "start_time": "2026-03-19T06:08:50.471288979Z" } }, "cell_type": "code", "source": [ "A = X.numpy()\n", "B = torch.tensor(A)\n", "type(A), type(B)" ], "id": "b8d779a1bc7e4b1a", "outputs": [ { "data": { "text/plain": [ "(numpy.ndarray, torch.Tensor)" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 6 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:51.804601549Z", "start_time": "2026-03-19T06:08:51.491609008Z" } }, "cell_type": "code", "source": [ "import os\n", "os.makedirs(os.path.join(\"..\",\"data\"),exist_ok=True)\n", "data_file = os.path.join(os.path.join(\"..\",\"data\",\"data.csv\"))\n", "with open(data_file, \"w\") as f:\n", " f.write('NumRooms,Alley,Price\\n') # 列名\n", " f.write('NA,Pave,127500\\n') # 每行表示一个数据样本\n", " f.write('2,NA,106000\\n')\n", " f.write('4,NA,178100\\n')\n", " f.write('NA,NA,140000\\n')\n", "\n" ], "id": "82be028b0f1dd1e3", "outputs": [], "execution_count": 7 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:51.995470564Z", "start_time": "2026-03-19T06:08:51.819209475Z" } }, "cell_type": "code", "source": [ "import pandas as pd\n", "data = pd.read_csv(data_file)\n", "print(data)\n" ], "id": "ddd789a2656899d1", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " NumRooms Alley Price\n", "0 NaN Pave 127500\n", "1 2.0 NaN 106000\n", "2 4.0 NaN 178100\n", "3 NaN NaN 140000\n" ] } ], "execution_count": 8 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:52.239162983Z", "start_time": "2026-03-19T06:08:52.016744354Z" } }, "cell_type": "code", "source": [ "inputs, outputs = data.iloc[:, 0:2], data.iloc[:, 2]\n", "\n", "\n", "inputs = pd.get_dummies(inputs, dummy_na=True)\n", "print(inputs)\n", "inputs = inputs.fillna(inputs.mean())\n", "print(inputs)\n" ], "id": "e98fcc3bd4f067cf", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " NumRooms Alley_Pave Alley_nan\n", "0 NaN True False\n", "1 2.0 False True\n", "2 4.0 False True\n", "3 NaN False True\n", " NumRooms Alley_Pave Alley_nan\n", "0 3.0 True False\n", "1 2.0 False True\n", "2 4.0 False True\n", "3 3.0 False True\n" ] } ], "execution_count": 9 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:52.439862351Z", "start_time": "2026-03-19T06:08:52.252020096Z" } }, "cell_type": "code", "source": [ "X = torch.tensor(inputs.to_numpy(dtype=float))\n", "y = torch.tensor(outputs.to_numpy(dtype=float))\n", "X, y\n" ], "id": "8ff0f7b40f0e4996", "outputs": [ { "data": { "text/plain": [ "(tensor([[3., 1., 0.],\n", " [2., 0., 1.],\n", " [4., 0., 1.],\n", " [3., 0., 1.]], dtype=torch.float64),\n", " tensor([127500., 106000., 178100., 140000.], dtype=torch.float64))" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 10 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:52.613938268Z", "start_time": "2026-03-19T06:08:52.458366888Z" } }, "cell_type": "code", "source": [ "B=torch.tensor([[1,2,3],[2,0,4],[3,4,5]])\n", "B" ], "id": "91a6e0da442b95a0", "outputs": [ { "data": { "text/plain": [ "tensor([[1, 2, 3],\n", " [2, 0, 4],\n", " [3, 4, 5]])" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 11 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:52.927117918Z", "start_time": "2026-03-19T06:08:52.661665190Z" } }, "cell_type": "code", "source": "B==B.T", "id": "297e6a678fb19be7", "outputs": [ { "data": { "text/plain": [ "tensor([[True, True, True],\n", " [True, True, True],\n", " [True, True, True]])" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 12 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:53.355336655Z", "start_time": "2026-03-19T06:08:53.046923921Z" } }, "cell_type": "code", "source": [ "X=torch.arange(24).reshape(2,3,4)\n", "X" ], "id": "24e864b336beb58b", "outputs": [ { "data": { "text/plain": [ "tensor([[[ 0, 1, 2, 3],\n", " [ 4, 5, 6, 7],\n", " [ 8, 9, 10, 11]],\n", "\n", " [[12, 13, 14, 15],\n", " [16, 17, 18, 19],\n", " [20, 21, 22, 23]]])" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 13 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:53.538512227Z", "start_time": "2026-03-19T06:08:53.424545812Z" } }, "cell_type": "code", "source": [ "A = torch.arange(20, dtype=torch.float32).reshape(5, 4)\n", "B = A.clone() # 通过分配新内存,将A的一个副本分配给B\n", "A, A + B\n", "#A = torch.arange(20, dtype=torch.float32).reshape(5, 4)\n", "#B = A # 通过分配新内存,将A的一个副本分配给B\n", "id(A),id(B)" ], "id": "ee0905479b1dbc2b", "outputs": [ { "data": { "text/plain": [ "(140069082123952, 140069083998928)" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 14 }, { "metadata": {}, "cell_type": "markdown", "source": "Hadamard乘积", "id": "136459f5efe765cf" }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:53.817503675Z", "start_time": "2026-03-19T06:08:53.581674028Z" } }, "cell_type": "code", "source": "A*B", "id": "f576b0df17cc0e98", "outputs": [ { "data": { "text/plain": [ "tensor([[ 0., 1., 4., 9.],\n", " [ 16., 25., 36., 49.],\n", " [ 64., 81., 100., 121.],\n", " [144., 169., 196., 225.],\n", " [256., 289., 324., 361.]])" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 15 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:54.105858002Z", "start_time": "2026-03-19T06:08:53.885857754Z" } }, "cell_type": "code", "source": [ "a=2\n", "X=torch.arange(24).reshape(2,3,4)\n", "a+X,(a*X).shape" ], "id": "b2373af1d7f2a45", "outputs": [ { "data": { "text/plain": [ "(tensor([[[ 2, 3, 4, 5],\n", " [ 6, 7, 8, 9],\n", " [10, 11, 12, 13]],\n", " \n", " [[14, 15, 16, 17],\n", " [18, 19, 20, 21],\n", " [22, 23, 24, 25]]]),\n", " torch.Size([2, 3, 4]))" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 16 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:54.282899541Z", "start_time": "2026-03-19T06:08:54.174420931Z" } }, "cell_type": "code", "source": [ "print(A)\n", "A_sum_axis0=A.sum(axis=0)\n", "A_sum_axis1=A.sum(axis=1)\n", "A_sum_axis0,A_sum_axis1" ], "id": "2b50246e1ca8a3bc", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tensor([[ 0., 1., 2., 3.],\n", " [ 4., 5., 6., 7.],\n", " [ 8., 9., 10., 11.],\n", " [12., 13., 14., 15.],\n", " [16., 17., 18., 19.]])\n" ] }, { "data": { "text/plain": [ "(tensor([40., 45., 50., 55.]), tensor([ 6., 22., 38., 54., 70.]))" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 17 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:54.345533969Z", "start_time": "2026-03-19T06:08:54.290459990Z" } }, "cell_type": "code", "source": [ "x=torch.arange(4,dtype=torch.float32)\n", "torch.mv(A,x)" ], "id": "3195464dfeb554ed", "outputs": [ { "data": { "text/plain": [ "tensor([ 14., 38., 62., 86., 110.])" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 18 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:54.432702369Z", "start_time": "2026-03-19T06:08:54.361198167Z" } }, "cell_type": "code", "source": [ "import time\n", "\n", "def showtime(func):\n", " def wrapper():\n", " start = time.time()\n", " result = func() # 执行原始函数\n", " end = time.time()\n", " print(f\"执行时间: {end - start:.6f}秒\")\n", " return result\n", " return wrapper # 返回包装函数\n", "\n", "@showtime\n", "def fun():\n", " print(\"I am silly\")\n", "\n", "fun()\n" ], "id": "ebda8c74ead3e42b", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I am silly\n", "执行时间: 0.000109秒\n" ] } ], "execution_count": 19 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:54.696923466Z", "start_time": "2026-03-19T06:08:54.436724383Z" } }, "cell_type": "code", "source": "torch.norm(torch.ones((4, 9)))", "id": "3343cc0c01d0161c", "outputs": [ { "data": { "text/plain": [ "tensor(6.)" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 20 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:54.768902496Z", "start_time": "2026-03-19T06:08:54.719453919Z" } }, "cell_type": "code", "source": [ "x =torch.arange(4.0,requires_grad=True)\n", "x.grad" ], "id": "674e2416e9417cfe", "outputs": [], "execution_count": 21 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:54.891549085Z", "start_time": "2026-03-19T06:08:54.804248422Z" } }, "cell_type": "code", "source": [ "y=2*torch.dot(x,x)\n", "y" ], "id": "66c0febebcf98cde", "outputs": [ { "data": { "text/plain": [ "tensor(28., grad_fn=)" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 22 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:54.993310716Z", "start_time": "2026-03-19T06:08:54.914195086Z" } }, "cell_type": "code", "source": [ "y.backward()\n", "x.grad" ], "id": "825f2ce6c46ca4a8", "outputs": [ { "data": { "text/plain": [ "tensor([ 0., 4., 8., 12.])" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 23 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:55.184135089Z", "start_time": "2026-03-19T06:08:54.995848170Z" } }, "cell_type": "code", "source": [ "x.grad.zero_()\n", "y = x.sum()\n", "y.backward()\n", "x.grad\n" ], "id": "df399463515e9d3c", "outputs": [ { "data": { "text/plain": [ "tensor([1., 1., 1., 1.])" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 24 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:55.569785595Z", "start_time": "2026-03-19T06:08:55.211139587Z" } }, "cell_type": "code", "source": [ "# 对非标量调用backward需要传入一个gradient参数,该参数指定微分函数关于self的梯度。\n", "# 本例只想求偏导数的和,所以传递一个1的梯度是合适的\n", "x.grad.zero_()\n", "y = x * x\n", "# 等价于y.backward(torch.ones(len(x)))\n", "print(y)\n", "y.sum().backward()\n", "x.grad" ], "id": "f9207619bd4b3de8", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tensor([0., 1., 4., 9.], grad_fn=)\n" ] }, { "data": { "text/plain": [ "tensor([0., 2., 4., 6.])" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 25 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:55.706654768Z", "start_time": "2026-03-19T06:08:55.573574038Z" } }, "cell_type": "code", "source": "torch.ones(len(x))", "id": "409c14c230570859", "outputs": [ { "data": { "text/plain": [ "tensor([1., 1., 1., 1.])" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 26 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:55.928404498Z", "start_time": "2026-03-19T06:08:55.717433023Z" } }, "cell_type": "code", "source": [ "x.grad.zero_()\n", "y=x*x\n", "u=y.detach()\n", "z=u*x\n", "z.sum().backward()\n", "x.grad==u" ], "id": "521b948fe0683b12", "outputs": [ { "data": { "text/plain": [ "tensor([True, True, True, True])" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 27 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:56.100782679Z", "start_time": "2026-03-19T06:08:55.980278337Z" } }, "cell_type": "code", "source": [ "x.grad.zero_()\n", "y.sum().backward()\n", "x.grad==2*x" ], "id": "b040beecf0632315", "outputs": [ { "data": { "text/plain": [ "tensor([True, True, True, True])" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 28 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:56.391506058Z", "start_time": "2026-03-19T06:08:56.102643728Z" } }, "cell_type": "code", "source": [ "from torch.distributions import multinomial\n", "fair_probs=torch.ones([6])\n", "fair_probs" ], "id": "4e6ec763dbea5aa3", "outputs": [ { "data": { "text/plain": [ "tensor([1., 1., 1., 1., 1., 1.])" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 29 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:56.646489725Z", "start_time": "2026-03-19T06:08:56.454875071Z" } }, "cell_type": "code", "source": "multinomial.Multinomial(1, fair_probs).sample()", "id": "f12d5e85bc6ab595", "outputs": [ { "data": { "text/plain": [ "tensor([0., 0., 0., 1., 0., 0.])" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 30 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:56.713816600Z", "start_time": "2026-03-19T06:08:56.653507072Z" } }, "cell_type": "code", "source": [ "counts = multinomial.Multinomial(10, fair_probs).sample((500,))\n", "\n", "cum_counts = counts.cumsum(dim=0)\n", "cum_counts.size()" ], "id": "b02f43376fd6f1fe", "outputs": [ { "data": { "text/plain": [ "torch.Size([500, 6])" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 31 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:57.183010802Z", "start_time": "2026-03-19T06:08:56.761045787Z" } }, "cell_type": "code", "source": [ "import matplotlib.pyplot as plt\n", "\n", "# 假设 estimates 是你的数据张量\n", "estimates = cum_counts / cum_counts.sum(dim=1, keepdims=True)\n", "\n", "# 设置图形大小 (等效于 d2l.set_figsize)\n", "plt.figure(figsize=(6, 4.5))\n", "\n", "# 绘制每条概率曲线\n", "for i in range(6):\n", " plt.plot(estimates[:, i].numpy(),\n", " label=f\"P(die={i + 1})\") # 使用 f-string 更简洁\n", "\n", "# 添加理论概率水平线\n", "plt.axhline(y=0.167, color='black', linestyle='dashed', label='Theoretical probability')\n", "\n", "# 设置坐标轴标签\n", "plt.xlabel('Groups of experiments')\n", "plt.ylabel('Estimated probability')\n", "\n", "# 添加图例\n", "plt.legend()\n", "\n", "# 显示图形\n", "plt.show()\n", "#plt.savefig('dice_probability.png', bbox_inches='tight')" ], "id": "8b80daa4edd0b066", "outputs": [ { "data": { "text/plain": [ "
" ], "image/png": "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" }, "metadata": {}, "output_type": "display_data", "jetTransient": { "display_id": null } } ], "execution_count": 32 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:57.312713568Z", "start_time": "2026-03-19T06:08:57.273001160Z" } }, "cell_type": "code", "source": [ "import numpy as np\n", "class Timer:\n", " \"\"\"记录多次运行时间\"\"\"\n", " def __init__(self):\n", " self.times = []\n", " self.start()\n", " def start(self):\n", " \"\"\"启动计时器\"\"\"\n", " self.tik = time.time()\n", " def stop(self):\n", " \"\"\"停止计时器并将时间记录在列表中\"\"\"\n", " self.times.append(time.time() - self.tik)\n", " return self.times[-1]\n", " def avg(self):\n", " \"\"\"返回平均时间\"\"\"\n", " return sum(self.times) / len(self.times)\n", " def sum(self):\n", " \"\"\"返回时间总和\"\"\"\n", " return sum(self.times)\n", " def cumsum(self):\n", " \"\"\"返回累计时间\"\"\"\n", " return np.array(self.times).cumsum().tolist()" ], "id": "4bdbb4999907154a", "outputs": [], "execution_count": 33 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:57.504357761Z", "start_time": "2026-03-19T06:08:57.314864132Z" } }, "cell_type": "code", "source": [ "n = 10000\n", "a = torch.ones([n])\n", "b = torch.ones([n])\n", "c=torch.zeros(n)\n", "timer = Timer()\n", "for i in range(n):\n", " c[i]=a[i]+b[i]\n", "f'{timer.stop():.5f} sec'" ], "id": "c6f71622e2cc578a", "outputs": [ { "data": { "text/plain": [ "'0.11861 sec'" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 34 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:57.608980105Z", "start_time": "2026-03-19T06:08:57.525327Z" } }, "cell_type": "code", "source": [ "timer.start()\n", "d=a+b\n", "f'{timer.stop():.5f} sec'" ], "id": "2578c79b1214a79f", "outputs": [ { "data": { "text/plain": [ "'0.00074 sec'" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 35 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:57.665429699Z", "start_time": "2026-03-19T06:08:57.610507099Z" } }, "cell_type": "code", "source": [ "import math\n", "def normal(x, mu, sigma):\n", " p = 1 / math.sqrt(2 * math.pi * sigma**2)\n", " return p * np.exp(-0.5 / sigma**2 * (x - mu)**2)" ], "id": "fd17fdbe38a5f79", "outputs": [], "execution_count": 36 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:57.729971931Z", "start_time": "2026-03-19T06:08:57.669321828Z" } }, "cell_type": "code", "source": [ "from matplotlib_inline import backend_inline\n", "def use_svg_display(): #@save\n", " \"\"\"使用svg格式在Jupyter中显示绘图\"\"\"\n", " backend_inline.set_matplotlib_formats('svg')\n", "def set_figsize(figsize=(3.5, 2.5)): #@save\n", " \"\"\"设置matplotlib的图表大小\"\"\"\n", " use_svg_display()\n", " plt.rcParams['figure.figsize'] = figsize\n", "def set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend):\n", " \"\"\"设置matplotlib的轴\"\"\"\n", " axes.set_xlabel(xlabel)\n", " axes.set_ylabel(ylabel)\n", " axes.set_xscale(xscale)\n", " axes.set_yscale(yscale)\n", " axes.set_xlim(xlim)\n", " axes.set_ylim(ylim)\n", " if legend:\n", " axes.legend(legend)\n", " axes.grid()\n", "def plot(X, Y=None, xlabel=None, ylabel=None, legend=None, xlim=None,\n", "ylim=None, xscale='linear', yscale='linear',\n", "fmts=('-', 'm--', 'g-.', 'r:'), figsize=(3.5, 2.5), axes=None):\n", " \"\"\"绘制数据点\"\"\"\n", " if legend is None:\n", " legend = []\n", " set_figsize(figsize)\n", " axes = axes if axes else plt.gca()\n", " # 如果X有一个轴,输出True\n", " def has_one_axis(X):\n", " return (hasattr(X, \"ndim\") and X.ndim == 1 or isinstance(X, list)\n", "and not hasattr(X[0], \"__len__\"))\n", " if has_one_axis(X):\n", " X = [X]\n", " if Y is None:\n", " X, Y = [[]] * len(X), X\n", " elif has_one_axis(Y):\n", " Y = [Y]\n", " if len(X) != len(Y):\n", " X = X * len(Y)\n", " axes.cla()\n", " for x, y, fmt in zip(X, Y, fmts):\n", " if len(x):\n", " axes.plot(x, y, fmt)\n", " else:\n", " axes.plot(y, fmt)\n", " set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend)" ], "id": "82158a69cba14da0", "outputs": [], "execution_count": 37 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:58.000767154Z", "start_time": "2026-03-19T06:08:57.732355844Z" } }, "cell_type": "code", "source": [ "# 再次使用numpy进行可视化\n", "x = np.arange(-7, 7, 0.01)\n", "# 均值和标准差对\n", "params = [(0, 1), (0, 2), (3, 1)]\n", "plot(x, [normal(x, mu, sigma) for mu, sigma in params], xlabel='x',\n", "ylabel='p(x)', figsize=(4.5, 2.5),\n", "legend=[f'mean {mu}, std {sigma}' for mu, sigma in params])" ], "id": "f69ac10ebc3d13d8", "outputs": [ { "data": { "text/plain": [ "
" ], "image/svg+xml": "\n\n\n \n \n \n \n 2026-03-19T14:08:57.923771\n image/svg+xml\n \n \n Matplotlib v3.7.2, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" }, "metadata": {}, "output_type": "display_data", "jetTransient": { "display_id": null } } ], "execution_count": 38 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:58.045153274Z", "start_time": "2026-03-19T06:08:58.022867228Z" } }, "cell_type": "code", "source": [ "#注意一下matmul做向量乘上矩阵的时候不用考虑转置的情况\n", "def synthetic_data(w, b, num_examples): #@save\n", " \"\"\"生成y=Xw+b+噪声\"\"\"\n", " X = torch.normal(0, 1, (num_examples, len(w)))\n", " y = torch.matmul(X, w) + b\n", " y += torch.normal(0, 0.01, y.shape)\n", " return X, y.reshape((-1, 1))\n" ], "id": "7ed837bdd2b3a26d", "outputs": [], "execution_count": 39 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:58.199486802Z", "start_time": "2026-03-19T06:08:58.048763885Z" } }, "cell_type": "code", "source": [ "true_w = torch.tensor([2, -3.4])\n", "true_b = 4.2\n", "features, labels = synthetic_data(true_w, true_b, 1000)" ], "id": "5ec2e204a6fd5cb2", "outputs": [], "execution_count": 40 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:58.497612094Z", "start_time": "2026-03-19T06:08:58.215279467Z" } }, "cell_type": "code", "source": [ "set_figsize()\n", "plt.scatter(features[:, (1)].detach().numpy(), labels.detach().numpy(), 1)" ], "id": "38213d46b3d9900d", "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "
" ], "image/svg+xml": "\n\n\n \n \n \n \n 2026-03-19T14:08:58.330374\n image/svg+xml\n \n \n Matplotlib v3.7.2, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" }, "metadata": {}, "output_type": "display_data", "jetTransient": { "display_id": null } } ], "execution_count": 41 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:58.613128054Z", "start_time": "2026-03-19T06:08:58.566128920Z" } }, "cell_type": "code", "source": [ "w=torch.normal(0,0.01,size=(2,1),requires_grad=True)\n", "b=torch.zeros(1,requires_grad=True)\n", "def linreg(X, w, b):\n", " return torch.matmul(X,w)+b\n", "def squared_loss(y_hat,y):\n", " return (y_hat-y.reshape(y_hat.shape))**2/2\n", "def sgd(params,lr,batch_size):\n", " with torch.no_grad():\n", " for param in params:\n", " param-=lr*param.grad/batch_size\n", " param.grad.zero_()\n", "lr = 0.03\n", "num_epochs =20\n", "net = linreg\n", "loss = squared_loss" ], "id": "12166e1bc3ddd695", "outputs": [], "execution_count": 42 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:58.733166644Z", "start_time": "2026-03-19T06:08:58.676875700Z" } }, "cell_type": "code", "source": [ "import random\n", "def data_iter(batch_size, features, labels):\n", " num_examples = len(features)\n", " indices = list(range(num_examples))\n", " # 这些样本是随机读取的,没有特定的顺序\n", " random.shuffle(indices)\n", " for i in range(0, num_examples, batch_size):\n", " batch_indices = torch.tensor(\n", " indices[i: min(i + batch_size, num_examples)])\n", " yield features[batch_indices], labels[batch_indices]" ], "id": "f3b7ee9f326bc687", "outputs": [], "execution_count": 43 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:58.810488693Z", "start_time": "2026-03-19T06:08:58.736278875Z" } }, "cell_type": "code", "source": [ "batch_size =10\n", "for X,y in data_iter(batch_size, features, labels):\n", " print(X,'\\n',y)\n", " break" ], "id": "f386e12d65afff2e", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tensor([[ 0.0169, -0.3729],\n", " [ 0.2105, -1.0088],\n", " [-1.3548, 0.9556],\n", " [-0.0298, 0.4827],\n", " [ 1.5137, -2.4433],\n", " [ 0.0029, 0.6444],\n", " [ 0.5705, 1.1589],\n", " [ 0.3421, -0.5686],\n", " [-0.8094, -0.8650],\n", " [ 0.3897, -1.3542]]) \n", " tensor([[ 5.5058],\n", " [ 8.0436],\n", " [-1.7624],\n", " [ 2.4937],\n", " [15.5411],\n", " [ 2.0171],\n", " [ 1.3941],\n", " [ 6.8340],\n", " [ 5.5124],\n", " [ 9.5840]])\n" ] } ], "execution_count": 44 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:59.082220079Z", "start_time": "2026-03-19T06:08:58.813592858Z" } }, "cell_type": "code", "source": [ "for epoch in range(num_epochs):\n", " for X, y in data_iter(batch_size, features, labels):\n", " l=loss(net(X, w, b), y)\n", " l.sum().backward()\n", " sgd([w,b],lr,batch_size)\n", " with torch.no_grad():\n", " train_l =loss(net(features, w, b), labels)\n", " print(f'epoch {epoch+1}, train loss: {float(train_l.mean()):3f}')" ], "id": "8888ab6adcec36f1", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "epoch 1, train loss: 0.040479\n", "epoch 2, train loss: 0.000158\n", "epoch 3, train loss: 0.000052\n", "epoch 4, train loss: 0.000052\n", "epoch 5, train loss: 0.000052\n", "epoch 6, train loss: 0.000052\n", "epoch 7, train loss: 0.000052\n", "epoch 8, train loss: 0.000052\n", "epoch 9, train loss: 0.000052\n", "epoch 10, train loss: 0.000052\n", "epoch 11, train loss: 0.000052\n", "epoch 12, train loss: 0.000052\n", "epoch 13, train loss: 0.000052\n", "epoch 14, train loss: 0.000052\n", "epoch 15, train loss: 0.000052\n", "epoch 16, train loss: 0.000052\n", "epoch 17, train loss: 0.000052\n", "epoch 18, train loss: 0.000052\n", "epoch 19, train loss: 0.000052\n", "epoch 20, train loss: 0.000052\n" ] } ], "execution_count": 45 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:59.178712680Z", "start_time": "2026-03-19T06:08:59.105484540Z" } }, "cell_type": "code", "source": [ "print(f'w的估计误差: {true_w - w.reshape(true_w.shape)}')\n", "print(f'b的估计误差: {true_b - b}')" ], "id": "8199439fa7f26309", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "w的估计误差: tensor([ 0.0010, -0.0003], grad_fn=)\n", "b的估计误差: tensor([0.0002], grad_fn=)\n" ] } ], "execution_count": 46 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:59.278946646Z", "start_time": "2026-03-19T06:08:59.180914818Z" } }, "cell_type": "code", "source": [ "from torch.utils import data\n", "true_w = torch.tensor([2,-3.4])\n", "true_b = 4.2\n", "features,labels=synthetic_data(true_w, true_b, 1000)\n", "def load_array(data_arrays,batch_size,is_train=True):\n", " dataset = data.TensorDataset(*data_arrays)\n", " return data.DataLoader(dataset,batch_size,shuffle=is_train)\n", "batch_size = 10\n", "data_iter = load_array((features,labels),batch_size)" ], "id": "560d537dcbb5a335", "outputs": [], "execution_count": 47 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:08:59.328289201Z", "start_time": "2026-03-19T06:08:59.284666591Z" } }, "cell_type": "code", "source": [ "from torch import nn\n", "net = nn.Sequential(nn.Linear(2, 1))\n", "net[0].weight.data.normal_(0,0.001)\n", "net[0].bias.data.fill_(0)" ], "id": "c54fe059d6fd20de", "outputs": [ { "data": { "text/plain": [ "tensor([0.])" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 48 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:00.631251025Z", "start_time": "2026-03-19T06:08:59.342163794Z" } }, "cell_type": "code", "source": [ "loss = nn.MSELoss()\n", "trainer = torch.optim.SGD(net.parameters(), lr=0.01)\n", "num_epochs = 3\n", "for epoch in range(num_epochs):\n", " for X, y in data_iter:\n", " l = loss(net(X) ,y)\n", " trainer.zero_grad()\n", " l.backward()\n", " trainer.step()\n", " l = loss(net(features), labels)\n", " print(f'epoch {epoch + 1}, loss {l:f}')\n" ], "id": "e8a44851125b7cc6", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "epoch 1, loss 0.546318\n", "epoch 2, loss 0.009022\n", "epoch 3, loss 0.000254\n" ] } ], "execution_count": 49 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:00.829165029Z", "start_time": "2026-03-19T06:09:00.673423450Z" } }, "cell_type": "code", "source": [ "import torchvision\n", "from torchvision import transforms\n", "trans =transforms.ToTensor()\n", "mnist_train = torchvision.datasets.FashionMNIST(root=\"./data\",train=True,transform=trans,download=False)\n", "mnist_test = torchvision.datasets.FashionMNIST(root=\"./data\",train=False,transform=trans,download=False)\n" ], "id": "bd4e8a65ccd03177", "outputs": [], "execution_count": 50 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:00.996874134Z", "start_time": "2026-03-19T06:09:00.830172776Z" } }, "cell_type": "code", "source": [ "use_svg_display()\n", "len(mnist_train),len(mnist_test)" ], "id": "ed2c915af7f6a76a", "outputs": [ { "data": { "text/plain": [ "(60000, 10000)" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 51 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:01.048577861Z", "start_time": "2026-03-19T06:09:01.002950237Z" } }, "cell_type": "code", "source": "mnist_train[0][0].shape", "id": "4df1cbc292aa5981", "outputs": [ { "data": { "text/plain": [ "torch.Size([1, 28, 28])" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 52 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:01.146967321Z", "start_time": "2026-03-19T06:09:01.075154216Z" } }, "cell_type": "code", "source": [ "def get_fashion_mnist_labels(labels):\n", " text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',\n", "'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']\n", " return [text_labels[int(i)] for i in labels]\n" ], "id": "332f3d6da0bafbe8", "outputs": [], "execution_count": 53 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:01.203692216Z", "start_time": "2026-03-19T06:09:01.148474439Z" } }, "cell_type": "code", "source": [ "def show_images(imgs, num_rows, num_cols, titles=None, scale=1): #@save\n", " \"\"\"绘制图像列表\"\"\"\n", " figsize = (num_cols * scale, num_rows * scale)\n", " _, axes = plt.subplots(num_rows, num_cols, figsize=figsize)\n", " axes = axes.flatten()\n", " for i, (ax, img) in enumerate(zip(axes, imgs)):\n", " if torch.is_tensor(img):\n", " # 图片张量\n", " ax.imshow(img.numpy())\n", " else:\n", " # PIL图片\n", " ax.imshow(img)\n", " ax.axes.get_xaxis().set_visible(False)\n", " ax.axes.get_yaxis().set_visible(False)\n", " if titles:\n", " ax.set_title(titles[i])\n", " return axes" ], "id": "c83202fe9b0ab487", "outputs": [], "execution_count": 54 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:01.696988026Z", "start_time": "2026-03-19T06:09:01.208873844Z" } }, "cell_type": "code", "source": [ "X, y = next(iter(data.DataLoader(mnist_train, batch_size=18)))\n", "print(X.shape)\n", "show_images(X.reshape(18, 28, 28), 2, 9, titles=get_fashion_mnist_labels(y));" ], "id": "cf4abd8370d55416", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "torch.Size([18, 1, 28, 28])\n" ] }, { "data": { "text/plain": [ "
" ], "image/svg+xml": "\n\n\n \n \n \n \n 2026-03-19T14:09:01.564207\n image/svg+xml\n \n \n Matplotlib v3.7.2, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" }, "metadata": {}, "output_type": "display_data", "jetTransient": { "display_id": null } } ], "execution_count": 55 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:03.457306914Z", "start_time": "2026-03-19T06:09:01.729639427Z" } }, "cell_type": "code", "source": [ "batch_size = 256\n", "def get_dataloader_workers():\n", " \"\"\"使用4个进程来读取数据\"\"\"\n", " return 4\n", "\n", "train_iter = data.DataLoader(mnist_train, batch_size, shuffle=True,\n", "num_workers=get_dataloader_workers())\n", "timer = Timer()\n", "for X, y in train_iter:\n", " continue\n", "f'{timer.stop():.2f} sec'" ], "id": "552769fbffc16142", "outputs": [ { "data": { "text/plain": [ "'1.59 sec'" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 56 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:03.736459982Z", "start_time": "2026-03-19T06:09:03.597245687Z" } }, "cell_type": "code", "source": [ "def load_data_fashion_mnist(batch_size, resize=None):\n", " \"\"\"下载Fashion-MNIST数据集,然后将其加载到内存中\"\"\"\n", " trans = [transforms.ToTensor()]\n", " if resize:\n", " trans.insert(0, transforms.Resize(resize))\n", " trans = transforms.Compose(trans)\n", " mnist_train = torchvision.datasets.FashionMNIST(\n", " root=\"./data\", train=True, transform=trans, download=False)\n", " mnist_test = torchvision.datasets.FashionMNIST(\n", " root=\"./data\", train=False, transform=trans, download=False)\n", " return (data.DataLoader(mnist_train, batch_size, shuffle=True,\n", " num_workers=get_dataloader_workers()),\n", " data.DataLoader(mnist_test, batch_size, shuffle=False,\n", " num_workers=get_dataloader_workers()))" ], "id": "aa81880abd86cae6", "outputs": [], "execution_count": 57 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:04.172516352Z", "start_time": "2026-03-19T06:09:03.782776079Z" } }, "cell_type": "code", "source": [ "train_iter, test_iter = load_data_fashion_mnist(32, resize=64)\n", "for X, y in train_iter:\n", " print(X.shape, X.dtype, y.shape, y.dtype)\n", " break" ], "id": "4248a103f745154", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "torch.Size([32, 1, 64, 64]) torch.float32 torch.Size([32]) torch.int64\n" ] } ], "execution_count": 58 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:04.306546718Z", "start_time": "2026-03-19T06:09:04.202047232Z" } }, "cell_type": "code", "source": [ "from IPython import display\n", "batch_size = 256\n", "train_iter, test_iter = load_data_fashion_mnist(32)\n", "num_inputs = 784\n", "num_outputs = 10\n", "W = torch.normal(0, 0.01, size=(num_inputs, num_outputs), requires_grad=True)\n", "b = torch.zeros(num_outputs, requires_grad=True)\n", "X = torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])\n", "X.sum(0, keepdim=True), X.sum(1, keepdim=True)\n" ], "id": "94c52f0cca88ef48", "outputs": [ { "data": { "text/plain": [ "(tensor([[5., 7., 9.]]),\n", " tensor([[ 6.],\n", " [15.]]))" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 59 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:04.394766349Z", "start_time": "2026-03-19T06:09:04.309113610Z" } }, "cell_type": "code", "source": [ "def softmax(X):\n", " X_exp = torch.exp(X)\n", " partition = X_exp.sum(1, keepdim=True)\n", " return X_exp / partition # 这里应用了广播机制\n", "X = torch.normal(0, 1, (2, 5))\n", "X_prob = softmax(X)\n", "X_prob, X_prob.sum(1)" ], "id": "c4ab34373c5a664e", "outputs": [ { "data": { "text/plain": [ "(tensor([[0.1969, 0.2421, 0.2949, 0.1017, 0.1645],\n", " [0.2729, 0.1267, 0.0365, 0.2715, 0.2924]]),\n", " tensor([1., 1.]))" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 60 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:04.445839278Z", "start_time": "2026-03-19T06:09:04.430535547Z" } }, "cell_type": "code", "source": [ "def net(X):\n", " return softmax(torch.matmul(X.reshape((-1, W.shape[0])), W) + b)" ], "id": "6eacc53b2b9738af", "outputs": [], "execution_count": 61 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:04.567489691Z", "start_time": "2026-03-19T06:09:04.449587260Z" } }, "cell_type": "code", "source": [ "y = torch.tensor([0, 2])\n", "y_hat = torch.tensor([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])\n", "y_hat[[0, 1], y]" ], "id": "698449b4dafb545c", "outputs": [ { "data": { "text/plain": [ "tensor([0.1000, 0.5000])" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 62 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:04.745616835Z", "start_time": "2026-03-19T06:09:04.613175566Z" } }, "cell_type": "code", "source": [ "def cross_entropy(y_hat, y):\n", " return - torch.log(y_hat[range(len(y_hat)), y])\n", "cross_entropy(y_hat, y)" ], "id": "1720369fc8568c8c", "outputs": [ { "data": { "text/plain": [ "tensor([2.3026, 0.6931])" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 63 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:04.855442356Z", "start_time": "2026-03-19T06:09:04.774151992Z" } }, "cell_type": "code", "source": [ "def accuracy(y_hat, y): #@save\n", " \"\"\"计算预测正确的数量\"\"\"\n", " if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:\n", " y_hat = y_hat.argmax(axis=1)\n", " cmp = y_hat.type(y.dtype) == y\n", " return float(cmp.type(y.dtype).sum())\n", "\n", "accuracy(y_hat, y)/len(y)" ], "id": "e65719500a64ed87", "outputs": [ { "data": { "text/plain": [ "0.5" ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 64 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:04.919559483Z", "start_time": "2026-03-19T06:09:04.858709428Z" } }, "cell_type": "code", "source": [ "class Accumulator: #@save\n", " \"\"\"在n个变量上累加\"\"\"\n", " def __init__(self, n):\n", " self.data = [0.0] * n\n", " def add(self, *args):\n", " self.data = [a + float(b) for a, b in zip(self.data, args)]\n", " def reset(self):\n", " self.data = [0.0] * len(self.data)\n", " def __getitem__(self, idx):\n", " return self.data[idx]\n" ], "id": "f1eebb35ff2e9fea", "outputs": [], "execution_count": 65 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:04.987417283Z", "start_time": "2026-03-19T06:09:04.924473660Z" } }, "cell_type": "code", "source": [ "def evaluate_accuracy(net, data_iter): #@save\n", " \"\"\"计算在指定数据集上模型的精度\"\"\"\n", " if isinstance(net, torch.nn.Module):\n", " net.eval() # 将模型设置为评估模式\n", " metric = Accumulator(2) # 正确预测数、预测总数\n", " with torch.no_grad():\n", " for X, y in data_iter:\n", " metric.add(accuracy(net(X), y), y.numel())\n", " return metric[0] / metric[1]\n" ], "id": "bc2beb5f2d6afe7e", "outputs": [], "execution_count": 66 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:09.640811163Z", "start_time": "2026-03-19T06:09:04.992201693Z" } }, "cell_type": "code", "source": "evaluate_accuracy(net, test_iter)", "id": "65bcfb7e40c1a98b", "outputs": [ { "data": { "text/plain": [ "0.1045" ] }, "execution_count": 67, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 67 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:10.226880910Z", "start_time": "2026-03-19T06:09:09.774018681Z" } }, "cell_type": "code", "source": [ "def train_epoch_ch3(net, train_iter, loss, updater): #@save\n", " \"\"\"训练模型一个迭代周期(定义见第3章)\"\"\"\n", " # 将模型设置为训练模式\n", " if isinstance(net, torch.nn.Module):\n", " net.train()\n", " # 训练损失总和、训练准确度总和、样本数\n", " metric = Accumulator(3)\n", " for X, y in train_iter:\n", " # 计算梯度并更新参数\n", " y_hat = net(X)\n", " l = loss(y_hat, y)\n", " if isinstance(updater, torch.optim.Optimizer):\n", " # 使用PyTorch内置的优化器和损失函数\n", " updater.zero_grad()\n", " l.mean().backward()\n", " updater.step()\n", " else:\n", " # 使用定制的优化器和损失函数\n", " l.sum().backward()\n", " updater(X.shape[0])\n", " metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())\n", "# 返回训练损失和训练精度\n", " return metric[0] / metric[2], metric[1] / metric[2]" ], "id": "2faf1dcc6c023a53", "outputs": [], "execution_count": 68 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:10.673837338Z", "start_time": "2026-03-19T06:09:10.455642059Z" } }, "cell_type": "code", "source": [ "class Animator: #@save\n", " \"\"\"在动画中绘制数据\"\"\"\n", " def __init__(self, xlabel=None, ylabel=None, legend=None, xlim=None,\n", " ylim=None, xscale='linear', yscale='linear',\n", " fmts=('-', 'm--', 'g-.', 'r:'), nrows=1, ncols=1,\n", " figsize=(3.5, 2.5)):\n", " # 增量地绘制多条线\n", " if legend is None:\n", " legend = []\n", " use_svg_display()\n", " self.fig, self.axes = plt.subplots(nrows, ncols, figsize=figsize)\n", " if nrows * ncols == 1:\n", " self.axes = [self.axes, ]\n", " # 使用lambda函数捕获参数\n", " self.config_axes = lambda: set_axes(\n", " self.axes[0], xlabel, ylabel, xlim, ylim, xscale, yscale, legend)\n", " self.X, self.Y, self.fmts = None, None, fmts\n", " def add(self, x, y):\n", " # 向图表中添加多个数据点\n", " if not hasattr(y, \"__len__\"):\n", " y = [y]\n", " n = len(y)\n", " if not hasattr(x, \"__len__\"):\n", " x = [x] * n\n", " if not self.X:\n", " self.X = [[] for _ in range(n)]\n", " if not self.Y:\n", " self.Y = [[] for _ in range(n)]\n", " for i, (a, b) in enumerate(zip(x, y)):\n", " if a is not None and b is not None:\n", " self.X[i].append(a)\n", " self.Y[i].append(b)\n", " self.axes[0].cla()\n", " for x, y, fmt in zip(self.X, self.Y, self.fmts):\n", " self.axes[0].plot(x, y, fmt)\n", " self.config_axes()\n", " display.display(self.fig)\n", " display.clear_output(wait=True)\n" ], "id": "7cd5367ab43c5e5f", "outputs": [], "execution_count": 69 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:10.768738929Z", "start_time": "2026-03-19T06:09:10.687413593Z" } }, "cell_type": "code", "source": [ "def train_ch3(net, train_iter, test_iter, loss, num_epochs, updater): #@save\n", " \"\"\"训练模型(定义见第3章)\"\"\"\n", " animator = Animator(xlabel='epoch', xlim=[1, num_epochs], ylim=[0.3, 0.9],\n", " legend=['train loss', 'train acc', 'test acc'])\n", " for epoch in range(num_epochs):\n", " train_metrics = train_epoch_ch3(net, train_iter, loss, updater)\n", " test_acc = evaluate_accuracy(net, test_iter)\n", " animator.add(epoch + 1, train_metrics + (test_acc,))\n", " train_loss, train_acc = train_metrics\n", " assert train_loss < 0.5, train_loss\n", " assert train_acc <= 1 and train_acc > 0.7, train_acc\n", " assert test_acc <= 1 and test_acc > 0.7, test_acc" ], "id": "b02a143c75fad40", "outputs": [], "execution_count": 70 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:10.914319299Z", "start_time": "2026-03-19T06:09:10.840221929Z" } }, "cell_type": "code", "source": [ "lr = 0.1\n", "def updater(batch_size):\n", " return sgd([W, b], lr, batch_size)" ], "id": "6a97b70779276b61", "outputs": [], "execution_count": 71 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:11.044553254Z", "start_time": "2026-03-19T06:09:10.940821708Z" } }, "cell_type": "code", "source": [ "num_epochs = 10\n", "#train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater)" ], "id": "df3cceb72faee402", "outputs": [], "execution_count": 72 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:11.628097076Z", "start_time": "2026-03-19T06:09:11.067755016Z" } }, "cell_type": "code", "source": [ "def predict_ch3(net, test_iter, n=6): #@save\n", " \"\"\"预测标签(定义见第3章)\"\"\"\n", " for (X, y),i in zip(test_iter,range(1)):\n", " trues = get_fashion_mnist_labels(y)\n", " preds = get_fashion_mnist_labels(net(X).argmax(axis=1))\n", " titles = [true +'\\n' + pred for true, pred in zip(trues, preds)]\n", " show_images(\n", " X[0:n].reshape((n, 28, 28)), 1, n, titles=titles[0:n])\n", "\n", "predict_ch3(net, test_iter)\n" ], "id": "94f6177bfb40eece", "outputs": [ { "data": { "text/plain": [ "
" ], "image/svg+xml": "\n\n\n \n \n \n \n 2026-03-19T14:09:11.541460\n image/svg+xml\n \n \n Matplotlib v3.7.2, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" }, "metadata": {}, "output_type": "display_data", "jetTransient": { "display_id": null } } ], "execution_count": 73 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:11.756853549Z", "start_time": "2026-03-19T06:09:11.685653252Z" } }, "cell_type": "code", "source": [ "batch_size = 256\n", "train_iter, test_iter = load_data_fashion_mnist(batch_size)" ], "id": "4a0bfd0479ec7386", "outputs": [], "execution_count": 74 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:42.908237720Z", "start_time": "2026-03-19T06:09:42.860595602Z" } }, "cell_type": "code", "source": [ "net = nn.Sequential(nn.Flatten(), nn.Linear(784, 10))\n", "def init_weights(m):\n", " if type(m) == nn.Linear:\n", " nn.init.normal_(m.weight, std=0.01)\n", "\n", "net.apply(init_weights);\n", "loss = nn.CrossEntropyLoss(reduction='none')\n", "trainer = torch.optim.SGD(net.parameters(), lr=0.1)\n", "num_epochs = 10\n", "#train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)" ], "id": "b9808d88f5e6827b", "outputs": [], "execution_count": 76 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:46.372721439Z", "start_time": "2026-03-19T06:09:46.108696173Z" } }, "cell_type": "code", "source": [ "x = torch.arange(-8.0, 8.0, 0.1, requires_grad=True)\n", "y = torch.relu(x)\n", "plot(x.detach(), y.detach(), 'x', 'relu(x)', figsize=(5, 2.5))" ], "id": "c25dd146307f58e0", "outputs": [ { "data": { "text/plain": [ "
" ], "image/svg+xml": "\n\n\n \n \n \n \n 2026-03-19T14:09:46.256394\n image/svg+xml\n \n \n Matplotlib v3.7.2, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" }, "metadata": {}, "output_type": "display_data", "jetTransient": { "display_id": null } } ], "execution_count": 77 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:46.713437268Z", "start_time": "2026-03-19T06:09:46.494861144Z" } }, "cell_type": "code", "source": [ "y.backward(torch.ones_like(x), retain_graph=True)\n", "plot(x.detach(), x.grad, 'x', 'grad of relu', figsize=(5, 2.5))" ], "id": "f96acd2015dccb38", "outputs": [ { "data": { "text/plain": [ "
" ], "image/svg+xml": "\n\n\n \n \n \n \n 2026-03-19T14:09:46.640099\n image/svg+xml\n \n \n Matplotlib v3.7.2, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" }, "metadata": {}, "output_type": "display_data", "jetTransient": { "display_id": null } } ], "execution_count": 78 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:47.267818729Z", "start_time": "2026-03-19T06:09:47.018071215Z" } }, "cell_type": "code", "source": [ "y = torch.sigmoid(x)\n", "plot(x.detach(), y.detach(), 'x', 'sigmoid(x)', figsize=(5, 2.5))" ], "id": "74013cea59cd8be3", "outputs": [ { "data": { "text/plain": [ "
" ], "image/svg+xml": "\n\n\n \n \n \n \n 2026-03-19T14:09:47.185521\n image/svg+xml\n \n \n Matplotlib v3.7.2, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" }, "metadata": {}, "output_type": "display_data", "jetTransient": { "display_id": null } } ], "execution_count": 79 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:47.710436882Z", "start_time": "2026-03-19T06:09:47.473515430Z" } }, "cell_type": "code", "source": [ "x.grad.data.zero_()\n", "y.backward(torch.ones_like(x),retain_graph=True)\n", "plot(x.detach(), x.grad, 'x', 'grad of sigmoid', figsize=(5, 2.5))" ], "id": "6a0b4f529bf9cc5c", "outputs": [ { "data": { "text/plain": [ "
" ], "image/svg+xml": "\n\n\n \n \n \n \n 2026-03-19T14:09:47.635692\n image/svg+xml\n \n \n Matplotlib v3.7.2, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" }, "metadata": {}, "output_type": "display_data", "jetTransient": { "display_id": null } } ], "execution_count": 80 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:48.096574814Z", "start_time": "2026-03-19T06:09:48.002692660Z" } }, "cell_type": "code", "source": [ "batch_size = 256\n", "train_iter, test_iter = load_data_fashion_mnist(batch_size)" ], "id": "f1de998439b1b9f", "outputs": [], "execution_count": 81 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:51.282745933Z", "start_time": "2026-03-19T06:09:51.217670982Z" } }, "cell_type": "code", "source": [ "num_inputs,num_outputs,num_hiddens = 784, 10, 256\n", "W1=nn.Parameter(torch.randn(num_inputs,num_hiddens,requires_grad=True)*0.01)\n", "b1=nn.Parameter(torch.zeros(num_hiddens,requires_grad=True))\n", "W2 = nn.Parameter(torch.randn(num_hiddens,num_outputs,requires_grad=True)*0.01)\n", "b2=nn.Parameter(torch.zeros(num_outputs,requires_grad=True))\n", "params=[W1,b1,W2,b2]\n" ], "id": "adcea8cd4ee792a8", "outputs": [], "execution_count": 82 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:53.068840701Z", "start_time": "2026-03-19T06:09:52.988897182Z" } }, "cell_type": "code", "source": [ "def relu(X):\n", " a = torch.zeros_like(X)\n", " return torch.max(X,a)\n", "def net(X):\n", " X = X.reshape((-1,num_inputs))\n", " H = relu(X@W1+b1)\n", " return (H@W2+b2)\n", "loss = nn.CrossEntropyLoss(reduction='none')\n", "num_epochs,lr=10,0.05\n", "updater=torch.optim.SGD(params,lr=lr)\n", "#train_ch3(net,train_iter,test_iter,loss,num_epochs,updater)\n" ], "id": "cfd81a0f16d0c573", "outputs": [], "execution_count": 83 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:54.454079900Z", "start_time": "2026-03-19T06:09:53.918996975Z" } }, "cell_type": "code", "source": "predict_ch3(net, test_iter)", "id": "f2ed2e9cee14c28a", "outputs": [ { "data": { "text/plain": [ "
" ], "image/svg+xml": "\n\n\n \n \n \n \n 2026-03-19T14:09:54.360205\n image/svg+xml\n \n \n Matplotlib v3.7.2, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" }, "metadata": {}, "output_type": "display_data", "jetTransient": { "display_id": null } } ], "execution_count": 84 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:55.272193107Z", "start_time": "2026-03-19T06:09:55.113735528Z" } }, "cell_type": "code", "source": [ "net = nn.Sequential(nn.Flatten(),\n", " nn.Linear(784,256),\n", " nn.ReLU(),\n", " nn.Linear(256,10))\n", "def init_weights(m):\n", " if type(m) == nn.Linear:\n", " nn.init.normal_(m.weight,std=0.01)\n", "\n", "net.apply(init_weights)\n" ], "id": "9e4ed6d103380bc7", "outputs": [ { "data": { "text/plain": [ "Sequential(\n", " (0): Flatten(start_dim=1, end_dim=-1)\n", " (1): Linear(in_features=784, out_features=256, bias=True)\n", " (2): ReLU()\n", " (3): Linear(in_features=256, out_features=10, bias=True)\n", ")" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 85 }, { "metadata": { "ExecuteTime": { "end_time": "2026-03-19T06:09:56.028892806Z", "start_time": "2026-03-19T06:09:55.915661103Z" } }, "cell_type": "code", "source": [ "batch_size,lr, num_epochs=256,0.1,10\n", "loss = nn.CrossEntropyLoss(reduction='none')\n", "trainer = torch.optim.SGD(net.parameters(),lr=lr)\n", "train_iter, test_iter = load_data_fashion_mnist(batch_size)\n", "#train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)" ], "id": "52d71c77c4f51e90", "outputs": [], "execution_count": 86 }, { "metadata": {}, "cell_type": "code", "source": "", "id": "94706c936b4be3e1", "outputs": [], "execution_count": null } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.6" } }, "nbformat": 4, "nbformat_minor": 5 }