From 84f523f559fea3b7336ac568c6df7076ff892a8f Mon Sep 17 00:00:00 2001 From: yukun-hh Date: Sat, 14 Mar 2026 19:51:56 +0800 Subject: [PATCH] nn learning (d2l chapter 3.3) --- test.ipynb | 1510 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1489 insertions(+), 21 deletions(-) diff --git a/test.ipynb b/test.ipynb index 7bde084..3e0e16e 100644 --- a/test.ipynb +++ b/test.ipynb @@ -6,24 +6,26 @@ "metadata": { "collapsed": true, "ExecuteTime": { - "end_time": "2026-03-12T07:47:43.647984080Z", - "start_time": "2026-03-12T07:47:42.201741749Z" + "end_time": "2026-03-14T11:37:46.716891442Z", + "start_time": "2026-03-14T11:37:45.891202979Z" } }, "source": [ "import torch\n", "import numpy\n", "import pandas\n", + "from sympy.physics.control.control_plots import matplotlib\n", + "from torch.distributed.algorithms.ddp_comm_hooks.powerSGD_hook import batched_powerSGD_hook\n", "\n" ], "outputs": [], - "execution_count": 4 + "execution_count": 1 }, { "metadata": { "ExecuteTime": { - "end_time": "2026-03-12T07:48:05.008880758Z", - "start_time": "2026-03-12T07:48:04.943146770Z" + "end_time": "2026-03-14T11:37:46.748820470Z", + "start_time": "2026-03-14T11:37:46.717673396Z" } }, "cell_type": "code", @@ -33,20 +35,141 @@ { "data": { "text/plain": [ - "tensor([[[ 0.2132, 0.9767],\n", - " [-1.0454, 0.1760],\n", - " [ 1.1094, -1.8272],\n", - " [ 0.3191, 0.6993]],\n", + "tensor([[[ 1.1696, -0.5395],\n", + " [-1.2794, -1.0168],\n", + " [ 3.2351, 0.6066],\n", + " [ 1.5116, -0.1253]],\n", "\n", - " [[ 0.1007, 2.2675],\n", - " [-0.3900, 0.5697],\n", - " [ 0.8869, 0.9942],\n", - " [ 0.5918, -0.1472]],\n", + " [[-0.1823, 0.1887],\n", + " [ 0.0186, -1.5205],\n", + " [-0.3032, 0.1184],\n", + " [-0.1708, 1.2866]],\n", "\n", - " [[-0.8392, 0.5961],\n", - " [ 0.7128, -0.3702],\n", - " [-0.8278, 0.6045],\n", - " [ 0.2568, -0.2580]]])" + " [[ 0.1142, 0.0435],\n", + " [-0.4102, -0.4663],\n", + " [ 0.2203, 0.3123],\n", + " [ 1.9645, 1.8992]]])" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 2 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-14T11:37:46.795608911Z", + "start_time": "2026-03-14T11:37:46.749770547Z" + } + }, + "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-14T11:37:46.812288160Z", + "start_time": "2026-03-14T11:37:46.803470930Z" + } + }, + "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-14T11:37:46.908394350Z", + "start_time": "2026-03-14T11:37:46.858309741Z" + } + }, + "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-14T11:37:46.990018992Z", + "start_time": "2026-03-14T11:37:46.944214131Z" + } + }, + "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, @@ -59,15 +182,1360 @@ { "metadata": { "ExecuteTime": { - "end_time": "2026-03-12T07:47:43.874354756Z", - "start_time": "2026-03-12T07:47:43.725800097Z" + "end_time": "2026-03-14T11:37:47.097040164Z", + "start_time": "2026-03-14T11:37:46.993944041Z" + } + }, + "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-14T11:37:47.138922799Z", + "start_time": "2026-03-14T11:37:47.109432980Z" + } + }, + "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-14T11:37:47.162491839Z", + "start_time": "2026-03-14T11:37:47.139968456Z" + } + }, + "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-14T11:37:47.186754928Z", + "start_time": "2026-03-14T11:37:47.168374155Z" + } + }, + "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-14T11:37:47.214268957Z", + "start_time": "2026-03-14T11:37:47.192209367Z" + } + }, + "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-14T11:37:47.309990671Z", + "start_time": "2026-03-14T11:37:47.241157425Z" + } + }, + "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-14T11:37:47.535195222Z", + "start_time": "2026-03-14T11:37:47.409682869Z" + } + }, + "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-14T11:37:47.648470258Z", + "start_time": "2026-03-14T11:37:47.558566189Z" + } + }, + "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": [ + "(140539332541136, 140539333492432)" + ] + }, + "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-14T11:37:47.690032963Z", + "start_time": "2026-03-14T11:37:47.651693108Z" + } + }, + "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-14T11:37:47.778795013Z", + "start_time": "2026-03-14T11:37:47.722390317Z" + } + }, + "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-14T11:37:47.852744522Z", + "start_time": "2026-03-14T11:37:47.810917322Z" + } + }, + "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-14T11:37:48.039859489Z", + "start_time": "2026-03-14T11:37:47.861768656Z" + } + }, + "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-14T11:37:48.070161220Z", + "start_time": "2026-03-14T11:37:48.042514455Z" + } + }, + "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.000630秒\n" + ] + } + ], + "execution_count": 19 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-14T11:37:48.092871646Z", + "start_time": "2026-03-14T11:37:48.071687740Z" + } + }, + "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-14T11:37:48.100506481Z", + "start_time": "2026-03-14T11:37:48.094144409Z" + } + }, + "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-14T11:37:48.121524857Z", + "start_time": "2026-03-14T11:37:48.101329494Z" + } + }, + "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-14T11:37:48.148136131Z", + "start_time": "2026-03-14T11:37:48.129950999Z" + } + }, + "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-14T11:37:48.175519287Z", + "start_time": "2026-03-14T11:37:48.153141505Z" + } + }, + "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-14T11:37:48.190165115Z", + "start_time": "2026-03-14T11:37:48.176741284Z" + } + }, + "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-14T11:37:48.210632850Z", + "start_time": "2026-03-14T11:37:48.200923142Z" + } + }, + "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-14T11:37:48.229459200Z", + "start_time": "2026-03-14T11:37:48.218856646Z" + } + }, + "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-14T11:37:48.269115256Z", + "start_time": "2026-03-14T11:37:48.244909724Z" + } + }, + "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-14T11:37:48.300440123Z", + "start_time": "2026-03-14T11:37:48.279382427Z" + } + }, + "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-14T11:37:48.318972768Z", + "start_time": "2026-03-14T11:37:48.301409242Z" + } + }, + "cell_type": "code", + "source": "multinomial.Multinomial(1, fair_probs).sample()", + "id": "f12d5e85bc6ab595", + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([0., 0., 1., 0., 0., 0.])" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 30 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-14T11:37:48.337802576Z", + "start_time": "2026-03-14T11:37:48.320185416Z" + } + }, + "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-14T11:37:48.463214605Z", + "start_time": "2026-03-14T11:37:48.358849572Z" + } + }, + "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-14T11:37:48.474923890Z", + "start_time": "2026-03-14T11:37:48.467148045Z" + } + }, + "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-14T11:37:48.638326094Z", + "start_time": "2026-03-14T11:37:48.475453591Z" + } + }, + "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.05042 sec'" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 34 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-14T11:37:48.678544906Z", + "start_time": "2026-03-14T11:37:48.640377978Z" + } + }, + "cell_type": "code", + "source": [ + "timer.start()\n", + "d=a+b\n", + "f'{timer.stop():.5f} sec'" + ], + "id": "2578c79b1214a79f", + "outputs": [ + { + "data": { + "text/plain": [ + "'0.00046 sec'" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 35 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-14T11:37:48.687129040Z", + "start_time": "2026-03-14T11:37:48.680082631Z" + } + }, + "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-14T11:37:48.705878968Z", + "start_time": "2026-03-14T11:37:48.687875003Z" + } + }, + "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-14T11:37:48.820167717Z", + "start_time": "2026-03-14T11:37:48.707125239Z" + } + }, + "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-14T19:37:48.782465\n image/svg+xml\n \n \n Matplotlib v3.10.8, 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-14T11:37:48.849464685Z", + "start_time": "2026-03-14T11:37:48.839470354Z" + } + }, + "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-14T11:37:49.046153840Z", + "start_time": "2026-03-14T11:37:48.850521592Z" + } + }, + "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-14T11:37:49.114421568Z", + "start_time": "2026-03-14T11:37:49.049220234Z" + } + }, + "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-14T19:37:49.085396\n image/svg+xml\n \n \n Matplotlib v3.10.8, 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 \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-14T11:37:49.133683224Z", + "start_time": "2026-03-14T11:37:49.125021829Z" + } + }, + "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-14T11:37:49.152287703Z", + "start_time": "2026-03-14T11:37:49.134387652Z" + } + }, + "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-14T11:37:49.183095346Z", + "start_time": "2026-03-14T11:37:49.153518090Z" + } + }, + "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.3577, 0.6754],\n", + " [-0.1904, -0.6314],\n", + " [-1.5305, -0.2903],\n", + " [ 2.0532, -0.3528],\n", + " [ 0.4056, -0.7645],\n", + " [-0.7985, 1.3492],\n", + " [-0.4550, 0.1608],\n", + " [ 1.1672, -0.5057],\n", + " [ 0.3912, -2.4489],\n", + " [ 1.9930, 1.6857]]) \n", + " tensor([[ 1.1766],\n", + " [ 5.9634],\n", + " [ 2.1265],\n", + " [ 9.5015],\n", + " [ 7.6220],\n", + " [-1.9910],\n", + " [ 2.7378],\n", + " [ 8.2718],\n", + " [13.2983],\n", + " [ 2.4553]])\n" + ] + } + ], + "execution_count": 44 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-14T11:37:49.350363398Z", + "start_time": "2026-03-14T11:37:49.184018282Z" + } + }, + "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.052015\n", + "epoch 2, train loss: 0.000228\n", + "epoch 3, train loss: 0.000049\n", + "epoch 4, train loss: 0.000048\n", + "epoch 5, train loss: 0.000048\n", + "epoch 6, train loss: 0.000048\n", + "epoch 7, train loss: 0.000048\n", + "epoch 8, train loss: 0.000048\n", + "epoch 9, train loss: 0.000048\n", + "epoch 10, train loss: 0.000048\n", + "epoch 11, train loss: 0.000048\n", + "epoch 12, train loss: 0.000048\n", + "epoch 13, train loss: 0.000048\n", + "epoch 14, train loss: 0.000048\n", + "epoch 15, train loss: 0.000048\n", + "epoch 16, train loss: 0.000048\n", + "epoch 17, train loss: 0.000048\n", + "epoch 18, train loss: 0.000048\n", + "epoch 19, train loss: 0.000048\n", + "epoch 20, train loss: 0.000048\n" + ] + } + ], + "execution_count": 45 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-14T11:37:49.378897333Z", + "start_time": "2026-03-14T11:37:49.353047845Z" + } + }, + "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.0004, 0.0002], grad_fn=)\n", + "b的估计误差: tensor([-0.0005], grad_fn=)\n" + ] + } + ], + "execution_count": 46 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-14T11:40:57.656654704Z", + "start_time": "2026-03-14T11:40:57.637331612Z" + } + }, + "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": 51 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-14T11:40:58.976005043Z", + "start_time": "2026-03-14T11:40:58.927183259Z" + } + }, + "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": 52, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 52 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-14T11:41:52.186040634Z", + "start_time": "2026-03-14T11:41:52.126046372Z" + } + }, + "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.000091\n", + "epoch 2, loss 0.000091\n", + "epoch 3, loss 0.000091\n" + ] + } + ], + "execution_count": 63 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-14T11:37:49.859894220Z", + "start_time": "2026-03-14T11:37:49.844955750Z" } }, "cell_type": "code", "source": "", - "id": "8ae20ae68abbf32f", + "id": "bd4e8a65ccd03177", "outputs": [], - "execution_count": 5 + "execution_count": 49 } ], "metadata": {