From 350ecc39e9367e3e352c5702878beef0c3edd967 Mon Sep 17 00:00:00 2001 From: yukun-hh Date: Sun, 22 Mar 2026 16:28:55 +0800 Subject: [PATCH] chapter5 to 6 over change environment manager and package mannager from virtualenv to miniconda --- chapter1-4.ipynb | 1659 +++++++++++++++++++++++++++++++++++++++------- chapter5.ipynb | 1313 ++++++++++++++++++++++++++++++++++++ 2 files changed, 2732 insertions(+), 240 deletions(-) create mode 100644 chapter5.ipynb diff --git a/chapter1-4.ipynb b/chapter1-4.ipynb index f27c542..dcaef41 100644 --- a/chapter1-4.ipynb +++ b/chapter1-4.ipynb @@ -6,8 +6,8 @@ "metadata": { "collapsed": true, "ExecuteTime": { - "end_time": "2026-03-19T05:45:23.532371843Z", - "start_time": "2026-03-19T05:45:23.227305138Z" + "end_time": "2026-03-19T06:08:49.521494353Z", + "start_time": "2026-03-19T06:08:47.762419340Z" } }, "source": [ @@ -15,31 +15,53 @@ "import numpy\n", "import pandas" ], - "outputs": [ - { - "ename": "ModuleNotFoundError", - "evalue": "No module named 'torch'", - "output_type": "error", - "traceback": [ - "\u001B[31m---------------------------------------------------------------------------\u001B[39m", - "\u001B[31mModuleNotFoundError\u001B[39m Traceback (most recent call last)", - "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[1]\u001B[39m\u001B[32m, line 1\u001B[39m\n\u001B[32m----> \u001B[39m\u001B[32m1\u001B[39m \u001B[38;5;28;01mimport\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34;01mtorch\u001B[39;00m\n\u001B[32m 2\u001B[39m \u001B[38;5;28;01mimport\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34;01mnumpy\u001B[39;00m\n\u001B[32m 3\u001B[39m \u001B[38;5;28;01mimport\u001B[39;00m\u001B[38;5;250m \u001B[39m\u001B[34;01mpandas\u001B[39;00m\n", - "\u001B[31mModuleNotFoundError\u001B[39m: No module named 'torch'" - ] - } - ], + "outputs": [], "execution_count": 1 }, { - "metadata": {}, + "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": [], - "execution_count": null + "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": {}, + "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", @@ -47,11 +69,35 @@ "torch.cat((X, Y), dim=0), torch.cat((X, Y), dim=1)" ], "id": "8ae20ae68abbf32f", - "outputs": [], - "execution_count": null + "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": {}, + "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", @@ -60,19 +106,55 @@ "a+b" ], "id": "2960a1ded2cdd5a4", - "outputs": [], - "execution_count": null + "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": {}, + "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": [], - "execution_count": null + "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": {}, + "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", @@ -80,11 +162,27 @@ "type(A), type(B)" ], "id": "b8d779a1bc7e4b1a", - "outputs": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "(numpy.ndarray, torch.Tensor)" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 6 }, { - "metadata": {}, + "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", @@ -100,10 +198,15 @@ ], "id": "82be028b0f1dd1e3", "outputs": [], - "execution_count": null + "execution_count": 7 }, { - "metadata": {}, + "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", @@ -111,11 +214,28 @@ "print(data)\n" ], "id": "ddd789a2656899d1", - "outputs": [], - "execution_count": null + "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": {}, + "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", @@ -127,11 +247,33 @@ "print(inputs)\n" ], "id": "e98fcc3bd4f067cf", - "outputs": [], - "execution_count": null + "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": {}, + "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", @@ -139,41 +281,119 @@ "X, y\n" ], "id": "8ff0f7b40f0e4996", - "outputs": [], - "execution_count": null + "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": {}, + "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": [], - "execution_count": null + "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": {}, + "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": [], - "execution_count": null + "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": {}, + "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": [], - "execution_count": null + "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": {}, + "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", @@ -184,8 +404,19 @@ "id(A),id(B)" ], "id": "ee0905479b1dbc2b", - "outputs": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "(140069082123952, 140069083998928)" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 14 }, { "metadata": {}, @@ -194,15 +425,40 @@ "id": "136459f5efe765cf" }, { - "metadata": {}, + "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": [], - "execution_count": null + "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": {}, + "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", @@ -210,11 +466,34 @@ "a+X,(a*X).shape" ], "id": "b2373af1d7f2a45", - "outputs": [], - "execution_count": null + "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": {}, + "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", @@ -223,22 +502,65 @@ "A_sum_axis0,A_sum_axis1" ], "id": "2b50246e1ca8a3bc", - "outputs": [], - "execution_count": null + "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": {}, + "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": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([ 14., 38., 62., 86., 110.])" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 18 }, { - "metadata": {}, + "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", @@ -259,19 +581,49 @@ "fun()\n" ], "id": "ebda8c74ead3e42b", - "outputs": [], - "execution_count": null + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "I am silly\n", + "执行时间: 0.000109秒\n" + ] + } + ], + "execution_count": 19 }, { - "metadata": {}, + "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": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "tensor(6.)" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 20 }, { - "metadata": {}, + "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", @@ -279,32 +631,69 @@ ], "id": "674e2416e9417cfe", "outputs": [], - "execution_count": null + "execution_count": 21 }, { - "metadata": {}, + "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": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "tensor(28., grad_fn=)" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 22 }, { - "metadata": {}, + "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": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([ 0., 4., 8., 12.])" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 23 }, { - "metadata": {}, + "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", @@ -313,11 +702,27 @@ "x.grad\n" ], "id": "df399463515e9d3c", - "outputs": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([1., 1., 1., 1.])" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 24 }, { - "metadata": {}, + "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", @@ -330,19 +735,58 @@ "x.grad" ], "id": "f9207619bd4b3de8", - "outputs": [], - "execution_count": null + "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": {}, + "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": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([1., 1., 1., 1.])" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 26 }, { - "metadata": {}, + "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", @@ -353,11 +797,27 @@ "x.grad==u" ], "id": "521b948fe0683b12", - "outputs": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([True, True, True, True])" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 27 }, { - "metadata": {}, + "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", @@ -365,11 +825,27 @@ "x.grad==2*x" ], "id": "b040beecf0632315", - "outputs": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([True, True, True, True])" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 28 }, { - "metadata": {}, + "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", @@ -377,19 +853,51 @@ "fair_probs" ], "id": "4e6ec763dbea5aa3", - "outputs": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([1., 1., 1., 1., 1., 1.])" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 29 }, { - "metadata": {}, + "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": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([0., 0., 0., 1., 0., 0.])" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 30 }, { - "metadata": {}, + "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", @@ -398,11 +906,27 @@ "cum_counts.size()" ], "id": "b02f43376fd6f1fe", - "outputs": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "torch.Size([500, 6])" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 31 }, { - "metadata": {}, + "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", @@ -433,11 +957,30 @@ "#plt.savefig('dice_probability.png', bbox_inches='tight')" ], "id": "8b80daa4edd0b066", - "outputs": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data", + "jetTransient": { + "display_id": null + } + } + ], + "execution_count": 32 }, { - "metadata": {}, + "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", @@ -465,10 +1008,15 @@ ], "id": "4bdbb4999907154a", "outputs": [], - "execution_count": null + "execution_count": 33 }, { - "metadata": {}, + "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", @@ -481,11 +1029,27 @@ "f'{timer.stop():.5f} sec'" ], "id": "c6f71622e2cc578a", - "outputs": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "'0.11861 sec'" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 34 }, { - "metadata": {}, + "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", @@ -493,11 +1057,27 @@ "f'{timer.stop():.5f} sec'" ], "id": "2578c79b1214a79f", - "outputs": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "'0.00074 sec'" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 35 }, { - "metadata": {}, + "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", @@ -507,10 +1087,15 @@ ], "id": "fd17fdbe38a5f79", "outputs": [], - "execution_count": null + "execution_count": 36 }, { - "metadata": {}, + "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", @@ -562,10 +1147,15 @@ ], "id": "82158a69cba14da0", "outputs": [], - "execution_count": null + "execution_count": 37 }, { - "metadata": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-19T06:08:58.000767154Z", + "start_time": "2026-03-19T06:08:57.732355844Z" + } + }, "cell_type": "code", "source": [ "# 再次使用numpy进行可视化\n", @@ -577,11 +1167,30 @@ "legend=[f'mean {mu}, std {sigma}' for mu, sigma in params])" ], "id": "f69ac10ebc3d13d8", - "outputs": [], - "execution_count": null + "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": {}, + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-19T06:08:58.045153274Z", + "start_time": "2026-03-19T06:08:58.022867228Z" + } + }, "cell_type": "code", "source": [ "#注意一下matmul做向量乘上矩阵的时候不用考虑转置的情况\n", @@ -594,10 +1203,15 @@ ], "id": "7ed837bdd2b3a26d", "outputs": [], - "execution_count": null + "execution_count": 39 }, { - "metadata": {}, + "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", @@ -606,21 +1220,55 @@ ], "id": "5ec2e204a6fd5cb2", "outputs": [], - "execution_count": null + "execution_count": 40 }, { - "metadata": {}, + "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": [], - "execution_count": null + "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": {}, + "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", @@ -641,10 +1289,15 @@ ], "id": "12166e1bc3ddd695", "outputs": [], - "execution_count": null + "execution_count": 42 }, { - "metadata": {}, + "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", @@ -660,10 +1313,15 @@ ], "id": "f3b7ee9f326bc687", "outputs": [], - "execution_count": null + "execution_count": 43 }, { - "metadata": {}, + "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", @@ -672,11 +1330,43 @@ " break" ], "id": "f386e12d65afff2e", - "outputs": [], - "execution_count": null + "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": {}, + "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", @@ -689,22 +1379,68 @@ " print(f'epoch {epoch+1}, train loss: {float(train_l.mean()):3f}')" ], "id": "8888ab6adcec36f1", - "outputs": [], - "execution_count": null + "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": {}, + "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": [], - "execution_count": null + "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": {}, + "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", @@ -719,10 +1455,15 @@ ], "id": "560d537dcbb5a335", "outputs": [], - "execution_count": null + "execution_count": 47 }, { - "metadata": {}, + "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", @@ -731,11 +1472,27 @@ "net[0].bias.data.fill_(0)" ], "id": "c54fe059d6fd20de", - "outputs": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([0.])" + ] + }, + "execution_count": 48, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 48 }, { - "metadata": {}, + "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", @@ -751,11 +1508,26 @@ " print(f'epoch {epoch + 1}, loss {l:f}')\n" ], "id": "e8a44851125b7cc6", - "outputs": [], - "execution_count": null + "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": {}, + "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", @@ -766,29 +1538,66 @@ ], "id": "bd4e8a65ccd03177", "outputs": [], - "execution_count": null + "execution_count": 50 }, { - "metadata": {}, + "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": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "(60000, 10000)" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 51 }, { - "metadata": {}, + "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": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "torch.Size([1, 28, 28])" + ] + }, + "execution_count": 52, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 52 }, { - "metadata": {}, + "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", @@ -798,10 +1607,15 @@ ], "id": "332f3d6da0bafbe8", "outputs": [], - "execution_count": null + "execution_count": 53 }, { - "metadata": {}, + "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", @@ -824,10 +1638,15 @@ ], "id": "c83202fe9b0ab487", "outputs": [], - "execution_count": null + "execution_count": 54 }, { - "metadata": {}, + "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", @@ -835,11 +1654,37 @@ "show_images(X.reshape(18, 28, 28), 2, 9, titles=get_fashion_mnist_labels(y));" ], "id": "cf4abd8370d55416", - "outputs": [], - "execution_count": null + "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": {}, + "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", @@ -855,11 +1700,27 @@ "f'{timer.stop():.2f} sec'" ], "id": "552769fbffc16142", - "outputs": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "'1.59 sec'" + ] + }, + "execution_count": 56, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 56 }, { - "metadata": {}, + "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", @@ -879,10 +1740,15 @@ ], "id": "aa81880abd86cae6", "outputs": [], - "execution_count": null + "execution_count": 57 }, { - "metadata": {}, + "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", @@ -891,11 +1757,24 @@ " break" ], "id": "4248a103f745154", - "outputs": [], - "execution_count": null + "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": {}, + "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", @@ -909,11 +1788,29 @@ "X.sum(0, keepdim=True), X.sum(1, keepdim=True)\n" ], "id": "94c52f0cca88ef48", - "outputs": [], - "execution_count": null + "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": {}, + "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", @@ -925,11 +1822,29 @@ "X_prob, X_prob.sum(1)" ], "id": "c4ab34373c5a664e", - "outputs": [], - "execution_count": null + "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": {}, + "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", @@ -937,10 +1852,15 @@ ], "id": "6eacc53b2b9738af", "outputs": [], - "execution_count": null + "execution_count": 61 }, { - "metadata": {}, + "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", @@ -948,11 +1868,27 @@ "y_hat[[0, 1], y]" ], "id": "698449b4dafb545c", - "outputs": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([0.1000, 0.5000])" + ] + }, + "execution_count": 62, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 62 }, { - "metadata": {}, + "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", @@ -960,11 +1896,27 @@ "cross_entropy(y_hat, y)" ], "id": "1720369fc8568c8c", - "outputs": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([2.3026, 0.6931])" + ] + }, + "execution_count": 63, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 63 }, { - "metadata": {}, + "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", @@ -977,11 +1929,27 @@ "accuracy(y_hat, y)/len(y)" ], "id": "e65719500a64ed87", - "outputs": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "0.5" + ] + }, + "execution_count": 64, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 64 }, { - "metadata": {}, + "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", @@ -997,10 +1965,15 @@ ], "id": "f1eebb35ff2e9fea", "outputs": [], - "execution_count": null + "execution_count": 65 }, { - "metadata": {}, + "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", @@ -1015,18 +1988,39 @@ ], "id": "bc2beb5f2d6afe7e", "outputs": [], - "execution_count": null + "execution_count": 66 }, { - "metadata": {}, + "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": [], - "execution_count": null + "outputs": [ + { + "data": { + "text/plain": [ + "0.1045" + ] + }, + "execution_count": 67, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 67 }, { - "metadata": {}, + "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", @@ -1055,10 +2049,15 @@ ], "id": "2faf1dcc6c023a53", "outputs": [], - "execution_count": null + "execution_count": 68 }, { - "metadata": {}, + "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", @@ -1102,10 +2101,15 @@ ], "id": "7cd5367ab43c5e5f", "outputs": [], - "execution_count": null + "execution_count": 69 }, { - "metadata": {}, + "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", @@ -1123,10 +2127,15 @@ ], "id": "b02a143c75fad40", "outputs": [], - "execution_count": null + "execution_count": 70 }, { - "metadata": {}, + "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", @@ -1135,10 +2144,15 @@ ], "id": "6a97b70779276b61", "outputs": [], - "execution_count": null + "execution_count": 71 }, { - "metadata": {}, + "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", @@ -1146,10 +2160,15 @@ ], "id": "df3cceb72faee402", "outputs": [], - "execution_count": null + "execution_count": 72 }, { - "metadata": {}, + "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", @@ -1164,11 +2183,30 @@ "predict_ch3(net, test_iter)\n" ], "id": "94f6177bfb40eece", - "outputs": [], - "execution_count": null + "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": {}, + "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", @@ -1176,10 +2214,15 @@ ], "id": "4a0bfd0479ec7386", "outputs": [], - "execution_count": null + "execution_count": 74 }, { - "metadata": {}, + "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", @@ -1191,14 +2234,19 @@ "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)" + "#train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)" ], "id": "b9808d88f5e6827b", "outputs": [], - "execution_count": null + "execution_count": 76 }, { - "metadata": {}, + "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", @@ -1206,33 +2254,90 @@ "plot(x.detach(), y.detach(), 'x', 'relu(x)', figsize=(5, 2.5))" ], "id": "c25dd146307f58e0", - "outputs": [], - "execution_count": null + "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": {}, + "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": [], - "execution_count": null + "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": {}, + "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": [], - "execution_count": null + "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": {}, + "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", @@ -1240,11 +2345,30 @@ "plot(x.detach(), x.grad, 'x', 'grad of sigmoid', figsize=(5, 2.5))" ], "id": "6a0b4f529bf9cc5c", - "outputs": [], - "execution_count": null + "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": {}, + "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", @@ -1252,10 +2376,15 @@ ], "id": "f1de998439b1b9f", "outputs": [], - "execution_count": null + "execution_count": 81 }, { - "metadata": {}, + "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", @@ -1267,10 +2396,15 @@ ], "id": "adcea8cd4ee792a8", "outputs": [], - "execution_count": null + "execution_count": 82 }, { - "metadata": {}, + "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", @@ -1287,18 +2421,42 @@ ], "id": "cfd81a0f16d0c573", "outputs": [], - "execution_count": null + "execution_count": 83 }, { - "metadata": {}, + "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": [], - "execution_count": null + "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": {}, + "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", @@ -1312,11 +2470,32 @@ "net.apply(init_weights)\n" ], "id": "9e4ed6d103380bc7", - "outputs": [], - "execution_count": null + "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": {}, + "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", @@ -1327,7 +2506,7 @@ ], "id": "52d71c77c4f51e90", "outputs": [], - "execution_count": null + "execution_count": 86 }, { "metadata": {}, diff --git a/chapter5.ipynb b/chapter5.ipynb new file mode 100644 index 0000000..cdb9a03 --- /dev/null +++ b/chapter5.ipynb @@ -0,0 +1,1313 @@ +{ + "cells": [ + { + "cell_type": "code", + "id": "initial_id", + "metadata": { + "collapsed": true, + "ExecuteTime": { + "end_time": "2026-03-22T08:08:29.467878519Z", + "start_time": "2026-03-22T08:08:28.169276694Z" + } + }, + "source": [ + "import d2l\n", + "import torch\n", + "import d2l\n", + "import numpy\n", + "import torch.nn as nn\n", + "import torch.nn.functional as F" + ], + "outputs": [], + "execution_count": 1 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:29.562521238Z", + "start_time": "2026-03-22T08:08:29.470022979Z" + } + }, + "cell_type": "code", + "source": [ + "net = nn.Sequential(nn.Linear(20, 256), nn.ReLU(), nn.Linear(256, 10))\n", + "X = torch.rand(2, 20)\n", + "net(X)" + ], + "id": "dcd5590e7795eec1", + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[ 0.0362, 0.0737, -0.0211, 0.0666, -0.1115, 0.0158, -0.1162, 0.0884,\n", + " 0.1486, -0.1063],\n", + " [ 0.1796, -0.0009, 0.1236, -0.0783, -0.0937, -0.0560, 0.0441, 0.0812,\n", + " 0.2236, -0.0597]], grad_fn=)" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 2 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:29.719824050Z", + "start_time": "2026-03-22T08:08:29.644546772Z" + } + }, + "cell_type": "code", + "source": [ + "class MLP(nn.Module):\n", + " def __init__(self):\n", + " super().__init__()\n", + " self.hidden=nn.Linear(20,256)\n", + " self.out=nn.Linear(256,10)\n", + " def forward(self,X):\n", + " return self.out(F.relu(self.hidden(X)))\n" + ], + "id": "4ae330604b643cb4", + "outputs": [], + "execution_count": 3 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:29.957480273Z", + "start_time": "2026-03-22T08:08:29.789396471Z" + } + }, + "cell_type": "code", + "source": [ + "net=MLP()\n", + "net(X)" + ], + "id": "cca55c6c0c7da12f", + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[ 0.0376, -0.2522, -0.0243, -0.0838, 0.1215, 0.0258, -0.2358, 0.0799,\n", + " 0.0756, 0.0520],\n", + " [ 0.0098, -0.2070, 0.0638, 0.1173, 0.0275, 0.0116, -0.0448, -0.0448,\n", + " -0.0309, -0.0976]], grad_fn=)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 4 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:30.177898340Z", + "start_time": "2026-03-22T08:08:30.069505281Z" + } + }, + "cell_type": "code", + "source": [ + "class FixedHiddenMLP(nn.Module):\n", + " def __init__(self):\n", + " super().__init__()\n", + " # 不计算梯度的随机权重参数。因此其在训练期间保持不变\n", + " self.rand_weight = torch.rand((20, 20), requires_grad=False)\n", + " self.linear = nn.Linear(20, 20)\n", + " def forward(self, X):\n", + " X = self.linear(X)\n", + " # 使用创建的常量参数以及relu和mm函数\n", + " X = F.relu(torch.mm(X, self.rand_weight) + 1)\n", + " # 复用全连接层。这相当于两个全连接层共享参数\n", + " X = self.linear(X)\n", + " # 控制流\n", + " while X.abs().sum() > 1:\n", + " X /= 2\n", + " return X.sum()" + ], + "id": "4518d62611d5e749", + "outputs": [], + "execution_count": 5 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:30.414648562Z", + "start_time": "2026-03-22T08:08:30.251182946Z" + } + }, + "cell_type": "code", + "source": [ + "net = FixedHiddenMLP()\n", + "net(X)" + ], + "id": "fae0187ece4ed5c6", + "outputs": [ + { + "data": { + "text/plain": [ + "tensor(0.1704, grad_fn=)" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 6 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:30.514145240Z", + "start_time": "2026-03-22T08:08:30.426612891Z" + } + }, + "cell_type": "code", + "source": [ + "class NestMLP(nn.Module):\n", + " def __init__(self):\n", + " super().__init__()\n", + " self.net = nn.Sequential(nn.Linear(20, 64), nn.ReLU(),\n", + " nn.Linear(64, 32), nn.ReLU())\n", + " self.linear = nn.Linear(32, 16)\n", + " def forward(self, X):\n", + " return self.linear(self.net(X))\n", + " chimera = nn.Sequential(NestMLP(), nn.Linear(16, 20), FixedHiddenMLP())\n", + " chimera(X)" + ], + "id": "407ef13a86453aae", + "outputs": [], + "execution_count": 7 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:30.617747011Z", + "start_time": "2026-03-22T08:08:30.517586238Z" + } + }, + "cell_type": "code", + "source": [ + "net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 1))\n", + "X = torch.rand(size=(2, 4))\n", + "net(X)" + ], + "id": "9f3526f263c7a249", + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[-0.2445],\n", + " [-0.2901]], grad_fn=)" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 8 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:30.825671299Z", + "start_time": "2026-03-22T08:08:30.691388202Z" + } + }, + "cell_type": "code", + "source": "print(net[2].state_dict())", + "id": "8c73f8daa02ba28b", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "OrderedDict([('weight', tensor([[-0.2116, 0.3448, 0.0726, -0.0626, -0.2922, 0.3172, 0.3025, -0.3025]])), ('bias', tensor([-0.3315]))])\n" + ] + } + ], + "execution_count": 9 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:31.020445691Z", + "start_time": "2026-03-22T08:08:30.902305394Z" + } + }, + "cell_type": "code", + "source": "net[2].state_dict()", + "id": "b6fee6b64fb96e3c", + "outputs": [ + { + "data": { + "text/plain": [ + "OrderedDict([('weight',\n", + " tensor([[-0.2116, 0.3448, 0.0726, -0.0626, -0.2922, 0.3172, 0.3025, -0.3025]])),\n", + " ('bias', tensor([-0.3315]))])" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 10 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:31.127350738Z", + "start_time": "2026-03-22T08:08:31.055037575Z" + } + }, + "cell_type": "code", + "source": "print(type(net[2].bias))", + "id": "b38e8dc384e038c5", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "execution_count": 11 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:31.206008645Z", + "start_time": "2026-03-22T08:08:31.139239226Z" + } + }, + "cell_type": "code", + "source": [ + "print(net[2].bias)\n", + "print(net[2].bias.data)\n" + ], + "id": "73f12ca3669d9ede", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Parameter containing:\n", + "tensor([-0.3315], requires_grad=True)\n", + "tensor([-0.3315])\n" + ] + } + ], + "execution_count": 12 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:31.286245677Z", + "start_time": "2026-03-22T08:08:31.230728228Z" + } + }, + "cell_type": "code", + "source": "net[2].weight.grad==None", + "id": "db0fe33018c16fac", + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 13 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:31.385905750Z", + "start_time": "2026-03-22T08:08:31.307506282Z" + } + }, + "cell_type": "code", + "source": [ + "print(*[(name, param.shape) for name, param in net[0].named_parameters()])\n", + "print(*[(name, param.shape) for name, param in net.named_parameters()])" + ], + "id": "75847a1c608ee5c7", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "('weight', torch.Size([8, 4])) ('bias', torch.Size([8]))\n", + "('0.weight', torch.Size([8, 4])) ('0.bias', torch.Size([8])) ('2.weight', torch.Size([1, 8])) ('2.bias', torch.Size([1]))\n" + ] + } + ], + "execution_count": 14 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:31.470489659Z", + "start_time": "2026-03-22T08:08:31.391689979Z" + } + }, + "cell_type": "code", + "source": "net.state_dict()['2.bias'].data", + "id": "cc74913e8742da7d", + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([-0.3315])" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 15 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:31.522581812Z", + "start_time": "2026-03-22T08:08:31.482437170Z" + } + }, + "cell_type": "code", + "source": [ + "def block1():\n", + " return nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 4),nn.ReLU())\n", + "def block2():\n", + " net = nn.Sequential()\n", + " for i in range(4):\n", + " net.add_module(f'block{i}', block1())\n", + " return net" + ], + "id": "53c39c5e61fa7bf5", + "outputs": [], + "execution_count": 16 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:31.643076590Z", + "start_time": "2026-03-22T08:08:31.558403449Z" + } + }, + "cell_type": "code", + "source": [ + "rgnet = nn.Sequential(block2(),nn.Linear(4,1))\n", + "rgnet(X)" + ], + "id": "d3ac7759b619aca", + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[-0.3640],\n", + " [-0.3640]], grad_fn=)" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 17 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:31.860114658Z", + "start_time": "2026-03-22T08:08:31.722546330Z" + } + }, + "cell_type": "code", + "source": "print(rgnet)", + "id": "8fc60f64b07781e6", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Sequential(\n", + " (0): Sequential(\n", + " (block0): Sequential(\n", + " (0): Linear(in_features=4, out_features=8, bias=True)\n", + " (1): ReLU()\n", + " (2): Linear(in_features=8, out_features=4, bias=True)\n", + " (3): ReLU()\n", + " )\n", + " (block1): Sequential(\n", + " (0): Linear(in_features=4, out_features=8, bias=True)\n", + " (1): ReLU()\n", + " (2): Linear(in_features=8, out_features=4, bias=True)\n", + " (3): ReLU()\n", + " )\n", + " (block2): Sequential(\n", + " (0): Linear(in_features=4, out_features=8, bias=True)\n", + " (1): ReLU()\n", + " (2): Linear(in_features=8, out_features=4, bias=True)\n", + " (3): ReLU()\n", + " )\n", + " (block3): Sequential(\n", + " (0): Linear(in_features=4, out_features=8, bias=True)\n", + " (1): ReLU()\n", + " (2): Linear(in_features=8, out_features=4, bias=True)\n", + " (3): ReLU()\n", + " )\n", + " )\n", + " (1): Linear(in_features=4, out_features=1, bias=True)\n", + ")\n" + ] + } + ], + "execution_count": 18 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:32.103301882Z", + "start_time": "2026-03-22T08:08:31.980555778Z" + } + }, + "cell_type": "code", + "source": "rgnet[0][1][0].bias.data", + "id": "e590aaafca787b50", + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([ 0.3672, -0.3124, -0.3113, -0.3251, -0.4771, -0.3622, 0.1464, -0.4632])" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 19 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:32.231455211Z", + "start_time": "2026-03-22T08:08:32.137730392Z" + } + }, + "cell_type": "code", + "source": [ + "def init_normal(m):\n", + " if type(m) == nn.Linear:\n", + " nn.init.normal_(m.weight, mean=0, std=0.01)\n", + " nn.init.zeros_(m.bias)\n", + "net.apply(init_normal)\n", + "net[0].weight.data[0], net[0].bias.data[0]" + ], + "id": "925ca33221d0a87e", + "outputs": [ + { + "data": { + "text/plain": [ + "(tensor([-0.0004, 0.0166, -0.0085, -0.0099]), tensor(0.))" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 20 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:32.322842445Z", + "start_time": "2026-03-22T08:08:32.234982576Z" + } + }, + "cell_type": "code", + "source": [ + "def init_xavier(m):\n", + " if type(m) == nn.Linear:\n", + " nn.init.xavier_uniform_(m.weight)\n", + "def init_42(m):\n", + " if type(m) == nn.Linear:\n", + " nn.init.constant_(m.weight, 42)\n", + "\n", + "net[0].apply(init_xavier)\n", + "net[2].apply(init_42)\n", + "print(net[0].weight.data[0])\n", + "print(net[2].weight.data)" + ], + "id": "81e2de84a8c4ef32", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "tensor([-0.3265, -0.5057, -0.5062, -0.2116])\n", + "tensor([[42., 42., 42., 42., 42., 42., 42., 42.]])\n" + ] + } + ], + "execution_count": 21 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:32.377993392Z", + "start_time": "2026-03-22T08:08:32.324885649Z" + } + }, + "cell_type": "code", + "source": [ + "x = torch.arange(4)\n", + "torch.save(x, 'x-file')" + ], + "id": "f05bb378bb60ab9e", + "outputs": [], + "execution_count": 22 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:32.474581135Z", + "start_time": "2026-03-22T08:08:32.386815096Z" + } + }, + "cell_type": "code", + "source": [ + "x2 = torch.load('x-file')\n", + "x2" + ], + "id": "a74ecaaac0d826c6", + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([0, 1, 2, 3])" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 23 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:32.492632663Z", + "start_time": "2026-03-22T08:08:32.476644136Z" + } + }, + "cell_type": "code", + "source": [ + "class MLP(nn.Module):\n", + " def __init__(self):\n", + " super().__init__()\n", + " self.hidden = nn.Linear(20, 256)\n", + " self.output = nn.Linear(256, 10)\n", + " def forward(self, x):\n", + " return self.output(F.relu(self.hidden(x)))\n", + "\n", + "net = MLP()\n", + "X = torch.randn(size=(2, 20))\n", + "Y = net(X)" + ], + "id": "b42598f0c4a8e801", + "outputs": [], + "execution_count": 24 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:32.600312816Z", + "start_time": "2026-03-22T08:08:32.528496997Z" + } + }, + "cell_type": "code", + "source": "torch.save(net.state_dict(), 'mlp.params')", + "id": "aaa22eef549caa6f", + "outputs": [], + "execution_count": 25 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:32.697771732Z", + "start_time": "2026-03-22T08:08:32.616231856Z" + } + }, + "cell_type": "code", + "source": [ + "clone = MLP()\n", + "clone.load_state_dict(torch.load('mlp.params'))\n", + "clone.eval()" + ], + "id": "b92f920229abeeae", + "outputs": [ + { + "data": { + "text/plain": [ + "MLP(\n", + " (hidden): Linear(in_features=20, out_features=256, bias=True)\n", + " (output): Linear(in_features=256, out_features=10, bias=True)\n", + ")" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 26 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:32.782119612Z", + "start_time": "2026-03-22T08:08:32.715175504Z" + } + }, + "cell_type": "code", + "source": [ + "Y_clone = clone(X)\n", + "Y_clone == Y" + ], + "id": "646c9eb6d7cc81c2", + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[True, True, True, True, True, True, True, True, True, True],\n", + " [True, True, True, True, True, True, True, True, True, True]])" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 27 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:32.908809253Z", + "start_time": "2026-03-22T08:08:32.843784246Z" + } + }, + "cell_type": "code", + "source": [ + "def corr2d(X,K):\n", + " h,w=K.shape\n", + " Y=torch.ones((X.shape[0]-h+1,X.shape[1]-w+1))\n", + " for i in range(Y.shape[0]):\n", + " for j in range(Y.shape[1]):\n", + " Y[i,j]=(X[i:i+h,j:j+w]*K).sum()\n", + " return Y\n" + ], + "id": "d45f9adfe47fce20", + "outputs": [], + "execution_count": 28 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:33.174646764Z", + "start_time": "2026-03-22T08:08:33.092115317Z" + } + }, + "cell_type": "code", + "source": [ + "X = torch.tensor([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]])\n", + "K = torch.tensor([[0.0, 1.0], [2.0, 3.0]])\n", + "corr2d(X,K)" + ], + "id": "db7279e13647c315", + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[19., 25.],\n", + " [37., 43.]])" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 29 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:33.292523218Z", + "start_time": "2026-03-22T08:08:33.234892901Z" + } + }, + "cell_type": "code", + "source": [ + "class Conv2D(nn.Module):\n", + " def __init__(self, kernel_size):\n", + " super().__init__()\n", + " self.weight = nn.Parameter(torch.rand(kernel_size))\n", + " self.bias = nn.Parameter(torch.zeros(1))\n", + " def forward(self, x):\n", + " return corr2d(x, self.weight) + self.bias\n" + ], + "id": "d60be1bd12a1f37e", + "outputs": [], + "execution_count": 30 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:33.497922435Z", + "start_time": "2026-03-22T08:08:33.387838879Z" + } + }, + "cell_type": "code", + "source": [ + "X = torch.ones((6, 8))\n", + "X[:, 2:6] = 0\n", + "X" + ], + "id": "5083789b7a728442", + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[1., 1., 0., 0., 0., 0., 1., 1.],\n", + " [1., 1., 0., 0., 0., 0., 1., 1.],\n", + " [1., 1., 0., 0., 0., 0., 1., 1.],\n", + " [1., 1., 0., 0., 0., 0., 1., 1.],\n", + " [1., 1., 0., 0., 0., 0., 1., 1.],\n", + " [1., 1., 0., 0., 0., 0., 1., 1.]])" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 31 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:33.751910360Z", + "start_time": "2026-03-22T08:08:33.561038017Z" + } + }, + "cell_type": "code", + "source": [ + "K = torch.tensor([[1.0, -1.0]])\n", + "Y = corr2d(X, K)\n", + "Y" + ], + "id": "ee8d6bedbde886ad", + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[ 0., 1., 0., 0., 0., -1., 0.],\n", + " [ 0., 1., 0., 0., 0., -1., 0.],\n", + " [ 0., 1., 0., 0., 0., -1., 0.],\n", + " [ 0., 1., 0., 0., 0., -1., 0.],\n", + " [ 0., 1., 0., 0., 0., -1., 0.],\n", + " [ 0., 1., 0., 0., 0., -1., 0.]])" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 32 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:34.156019672Z", + "start_time": "2026-03-22T08:08:33.891686033Z" + } + }, + "cell_type": "code", + "source": "corr2d(X.t(), K)", + "id": "a8278c3837fa9a1c", + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0.]])" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 33 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:34.438245033Z", + "start_time": "2026-03-22T08:08:34.313636464Z" + } + }, + "cell_type": "code", + "source": "conv2d = nn.Conv2d(1,1, kernel_size=(1, 2), bias=False)", + "id": "ec61cdb61a8cabff", + "outputs": [], + "execution_count": 34 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:34.619825611Z", + "start_time": "2026-03-22T08:08:34.507329239Z" + } + }, + "cell_type": "code", + "source": [ + "X = X.reshape((1, 1, 6, 8))\n", + "Y = Y.reshape((1, 1, 6, 7))\n", + "lr = 3e-2" + ], + "id": "d2fc19d84c79a10", + "outputs": [], + "execution_count": 35 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:35.980584379Z", + "start_time": "2026-03-22T08:08:34.640606389Z" + } + }, + "cell_type": "code", + "source": [ + "for i in range(100):\n", + " Y_hat = conv2d(X)\n", + " l = (Y_hat - Y) ** 2\n", + " conv2d.zero_grad()\n", + " l.sum().backward()\n", + " # 迭代卷积核\n", + " conv2d.weight.data[:] -= lr * conv2d.weight.grad\n", + " if (i + 1) % 20 == 0:\n", + " print(f'epoch {i+1}, loss {l.sum():.3f}')" + ], + "id": "51fbb2e6398a9bd5", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "epoch 20, loss 0.000\n", + "epoch 40, loss 0.000\n", + "epoch 60, loss 0.000\n", + "epoch 80, loss 0.000\n", + "epoch 100, loss 0.000\n" + ] + } + ], + "execution_count": 36 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:36.147166039Z", + "start_time": "2026-03-22T08:08:36.070619821Z" + } + }, + "cell_type": "code", + "source": "conv2d.weight.data.reshape((1, 2))\n", + "id": "bf53a423f429dfe4", + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[ 1.0000, -1.0000]])" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 37 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:36.349805416Z", + "start_time": "2026-03-22T08:08:36.243749022Z" + } + }, + "cell_type": "code", + "source": [ + "\n", + "# 为了方便起见,我们定义了一个计算卷积层的函数。\n", + "# 此函数初始化卷积层权重,并对输入和输出提高和缩减相应的维数\n", + "def comp_conv2d(conv2d, X):\n", + "# 这里的(1,1)表示批量大小和通道数都是1\n", + " X = X.reshape((1, 1) + X.shape)\n", + " Y = conv2d(X)\n", + " # 省略前两个维度:批量大小和通道\n", + " return Y.reshape(Y.shape[2:])\n", + "# 请注意,这里每边都填充了1行或1列,因此总共添加了2行或2列\n", + "conv2d = nn.Conv2d(1, 1, kernel_size=3, padding=1)" + ], + "id": "77b61d8c9a2363cc", + "outputs": [], + "execution_count": 38 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:36.565573176Z", + "start_time": "2026-03-22T08:08:36.473905736Z" + } + }, + "cell_type": "code", + "source": [ + "X = torch.rand(size=(8, 8))\n", + "comp_conv2d(conv2d, X).shape" + ], + "id": "beda6ffa67ec2677", + "outputs": [ + { + "data": { + "text/plain": [ + "torch.Size([8, 8])" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 39 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:36.629064391Z", + "start_time": "2026-03-22T08:08:36.577410135Z" + } + }, + "cell_type": "code", + "source": [ + "conv2d = nn.Conv2d(1, 1, kernel_size=(5, 3), padding=(2, 1))\n", + "comp_conv2d(conv2d, X).shape" + ], + "id": "8c51095daea1432d", + "outputs": [ + { + "data": { + "text/plain": [ + "torch.Size([8, 8])" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 40 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:36.778747354Z", + "start_time": "2026-03-22T08:08:36.631642133Z" + } + }, + "cell_type": "code", + "source": [ + "conv2d = nn.Conv2d(1, 1, kernel_size=3, padding=1, stride=2)\n", + "comp_conv2d(conv2d, X).shape" + ], + "id": "581bf1b15162cbf6", + "outputs": [ + { + "data": { + "text/plain": [ + "torch.Size([4, 4])" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 41 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:08:36.912486341Z", + "start_time": "2026-03-22T08:08:36.816037554Z" + } + }, + "cell_type": "code", + "source": [ + "conv2d = nn.Conv2d(1, 1, kernel_size=(3, 5), padding=(0, 1), stride=(3, 4))\n", + "comp_conv2d(conv2d, X).shape" + ], + "id": "6f7a2411247baff0", + "outputs": [ + { + "data": { + "text/plain": [ + "torch.Size([2, 2])" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 42 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:09:37.230541174Z", + "start_time": "2026-03-22T08:09:37.139260256Z" + } + }, + "cell_type": "code", + "source": [ + "def corr2d_multi_in(X,K):\n", + " return sum(corr2d(x,k) for x,k in zip(X,K))\n", + "X = torch.tensor([[[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]],\n", + "[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]])\n", + "K = torch.tensor([[[0.0, 1.0], [2.0, 3.0]], [[1.0, 2.0], [3.0, 4.0]]])\n", + "corr2d_multi_in(X, K)" + ], + "id": "7ac0f17f97b2daa8", + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[ 56., 72.],\n", + " [104., 120.]])" + ] + }, + "execution_count": 50, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 50 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:09:01.390798830Z", + "start_time": "2026-03-22T08:09:01.334900206Z" + } + }, + "cell_type": "code", + "source": [ + "def corr2d_multi_in_out(X,K) ->torch.Tensor :\n", + " return torch.stack([corr2d_multi_in(X,k) for k in K],0)\n" + ], + "id": "d409110d0d6b4b49", + "outputs": [], + "execution_count": 47 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:09:39.731392821Z", + "start_time": "2026-03-22T08:09:39.608604541Z" + } + }, + "cell_type": "code", + "source": [ + "K = torch.stack((K, K + 1, K + 2), 0)\n", + "K.shape" + ], + "id": "4114cd871a627075", + "outputs": [ + { + "data": { + "text/plain": [ + "torch.Size([3, 2, 2, 2])" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 51 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:09:43.297502870Z", + "start_time": "2026-03-22T08:09:43.186648920Z" + } + }, + "cell_type": "code", + "source": "corr2d_multi_in_out(X, K)", + "id": "ce52f41dc9585f8c", + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[[ 56., 72.],\n", + " [104., 120.]],\n", + "\n", + " [[ 76., 100.],\n", + " [148., 172.]],\n", + "\n", + " [[ 96., 128.],\n", + " [192., 224.]]])" + ] + }, + "execution_count": 52, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 52 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:23:20.460754568Z", + "start_time": "2026-03-22T08:23:20.424813665Z" + } + }, + "cell_type": "code", + "source": [ + "def corr2d_multi_in_out_1x1(X, K):\n", + " h_i,h,w=X.shape\n", + " h_o=K.shape[0]\n", + " X=X.reshape((h_i,h*w))\n", + " print(X.shape)\n", + " K=K.reshape((h_o,h_i))\n", + " print(K.shape)\n", + " Y=torch.matmul(K,X)\n", + " return Y.reshape((h_o,h,w))" + ], + "id": "362d8c692b3c1d75", + "outputs": [], + "execution_count": 56 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:23:21.690978973Z", + "start_time": "2026-03-22T08:23:21.638506037Z" + } + }, + "cell_type": "code", + "source": [ + "X = torch.normal(0, 1, (3, 3, 3))\n", + "K = torch.normal(0, 1, (2, 3, 1, 1))" + ], + "id": "28e761f677df8b16", + "outputs": [], + "execution_count": 57 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:23:22.844449890Z", + "start_time": "2026-03-22T08:23:22.694694019Z" + } + }, + "cell_type": "code", + "source": "Y1 = corr2d_multi_in_out_1x1(X, K)", + "id": "8eb276fed751a6b9", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "torch.Size([3, 9])\n", + "torch.Size([2, 3])\n" + ] + } + ], + "execution_count": 58 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-03-22T08:24:53.417955565Z", + "start_time": "2026-03-22T08:24:53.297421833Z" + } + }, + "cell_type": "code", + "source": [ + "Y2 = corr2d_multi_in_out(X, K)\n", + "assert float(torch.abs(Y1 - Y2).sum()) < 1e-6" + ], + "id": "be28e27d30f36e2c", + "outputs": [], + "execution_count": 59 + }, + { + "metadata": {}, + "cell_type": "code", + "outputs": [], + "execution_count": null, + "source": "", + "id": "3c3f71349a2e54c0" + } + ], + "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 +}