跟李沐学AI B站链接:https://space.bilibili.com/1567748478/channel/seriesdetail?sid=358497 
课程官网:https://courses.d2l.ai/zh-v2/ 
环境配置 在一台新的Ubuntu机器上:
首先更新软件包:sudo apt update
安装gcc之类的东西:sudo apt install build-essential
安装Python:sudo apt install python3.8
安装Miniconda:
先进入miniconda的官方文档:https://docs.conda.io/en/latest/miniconda.html#linux-installerswget 刚刚复制的地址 (例如https://repo.anaconda.com/miniconda/Miniconda3-py38_23.1.0-1-Linux-x86_64.sh)bash 刚刚下载下来的.sh文件(例如bash Miniconda3-py38_23.1.0-1-Linux-x86_64.sh)bash命令就进入conda环境了
 
安装所需要的Python包:pip install jupyter d2l torch torchvision(torchvision是pytorch的一个图形库)
下载d2l官网 的jupyter记事本 :wget https://zh-v2.d2l.ai/d2l-zh.zip
安装解压用的zip:sudo apt install zip
解压刚刚的zip:unzip d2l-zh.zip
解压出来有三个文件夹(mxnet版本、pytorch版本、transformer版本)
本课程主要使用Pytorch版本。此外,本课程还将使用幻灯片版本的“记事本”:git clone https://github.com/d2l-ai/d2l-zh-pytorch-slides  并进入:cd .\d2l-zh-pytorch-slides\
打开jupyter:jupyter notebook。这样将会在机器上开辟一个8888端口。
如果是在服务器上进行的上述操作,也可以将远端的端口映射到本地ssh -L8888:localhost:8888 [email protected] 
可以安装一个插件,pip install rise来以幻灯片格式显示。
Pytorch基础 张量(数组)的创建与基本操作 从0到11的数组: 
1 2 x = torch.arange(12 )print (x)
运行结果:
1 tensor ([ 0 ,  1 ,  2 ,  3 ,  4 ,  5 ,  6 ,  7 ,  8 ,  9 , 10 , 11 ])
使用列表初始化数组: 
1 torch.tensor([[1 , 2 ], [3 , 1 ]])
运行结果:
1 2 tensor([[1, 2],         [3, 1]] )
数组形状更改reshape: 
注意x自身并不会发生改变,这个函数只是返回一个改变后的副本
1 2 x2 = x.reshape(3 , 4 )print (x2)
运行结果:
1 2 3 tensor([[ 0,  1,  2,  3],         [ 4,  5,  6,  7],         [ 8,  9, 10, 11]] )
注意虽然b和a不同,但修改b中的元素可能会导致a中元素的改变(可以理解为b是a的另一个视图)
1 2 3 4 5 a = torch.arange(12 )3 , 4 )print (id (a) == id (b))2 print (a)
运行结果:
1 2 False tensor ([2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ])
获取数组形状shape: 
注意.shape是一个“成员”但不是一个“方法”
运行结果:
获取数组中元素总个数: 
运行结果:
生成全是1的数组: 
1 2 x = torch.ones(2 , 3 )print (x)
运行结果:
1 2 tensor([[1., 1., 1.],         [1., 1., 1.]] )
指定数据类型:
1 2 x = torch.ones(2 , 3 , dtype=int )print (x)
运行结果:
1 2 tensor([[1, 1, 1],         [1, 1, 1]] )
张量间的+-乘除等运算: 
1 2 3 4 5 6 7 8 9 x = torch.tensor([1. , 2 , 4 , 8 ])2 , 2 , 2 , 2 ])print (x + y)print (x - y)print (x * y)print (x / y)print (x ** y)print (torch.exp(x))  print (x == y)
运行结果:
1 2 3 4 5 6 7 tensor ([ 3 .,  4 .,  6 ., 10 .])tensor ([-1 .,  0 .,  2 .,  6 .])tensor ([ 2 .,  4 .,  8 ., 16 .])tensor ([0 .5000 , 1 .0000 , 2 .0000 , 4 .0000 ])tensor ([ 1 .,  4 ., 16 ., 64 .])tensor ([2 .7183 e+00 , 7 .3891 e+00 , 5 .4598 e+01 , 2 .9810 e+03 ])tensor ([False,  True, False, False])
向量连接(concatenate):torch.cat 
1 2 3 X = torch.arange(12 , dtype=torch.float32).reshape((3 , 4 ))2.0 , 1 , 4 , 3 ], [1 , 2 , 3 , 4 ], [4 , 3 , 2 , 1 ]])0 ), torch.cat((X, Y), dim=1 )
运行结果:
1 2 3 4 5 6 7 8 9 (tensor ([[ 0 .,  1 .,  2 .,  3 .],4 .,  5 .,  6 .,  7 .],8 .,  9 ., 10 ., 11 .],2 .,  1 .,  4 .,  3 .],1 .,  2 .,  3 .,  4 .],4 .,  3 .,  2 .,  1 .]]),0 .,  1 .,  2 .,  3 .,  2 .,  1 .,  4 .,  3 .],4 .,  5 .,  6 .,  7 .,  1 .,  2 .,  3 .,  4 .],8 .,  9 ., 10 ., 11 .,  4 .,  3 .,  2 .,  1 .]]))
默认dim = 0
1 2 3 x = torch.tensor([[1 , 2 ], [3 , 4 ]])5 , 6 ]])print (torch.cat((x, y)))
运行结果:
1 2 3 tensor([[1, 2],         [3, 4],         [5, 6]] )
只有拼接的那一维度的长度可以不同,其他维度必须相同(By Let,未完全验证)。例如下面代码会报错:
1 2 3 x = torch.tensor([[1 , 2 ], [3 , 4 ]])5 , 6 ]])1 )
运行结果:
1 2 3 4 5 6 15 ], line 3 1  x = torch.tensor([[1, 2], [3, 4]] )2  y = torch.tensor([[5, 6]] )
求和:x.sum() 
产生一个只有一个元素的张量:
运行结果:
1 2 3 tensor ([[1, 2] ,[3, 4] ])tensor (10 ) 
广播机制:形状不同的向量进行运算 
1 2 3 4 5 6 7 8 9 a = torch.arange(3 ).reshape((3 , 1 ))2 ).reshape((1 , 2 ))print (a)print (b)print (a + b)print (a - b)print (a * b)print (a / b)print (a == b)
相当于是把a复制成了3 x 2,把b也复制成了3 x 2。
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 tensor([[0],         [1],         [2]] )[[0, 1]] )[[0, 1],         [1, 2],         [2, 3]] )[[ 0, -1],         [ 1,  0],         [ 2,  1]] )[[0, 0],         [0, 1],         [0, 2]] )[[nan, 0.],         [inf, 1.],         [inf, 2.]] )[[ True, False],         [False,  True],         [False, False]] )
同理
取元素/改元素:[第一维列表操作, 第二维列表操作, 第三维] 
1 2 3 4 5 6 7 8 x = torch.arange(12 ).reshape(3 , 4 )print (x)print (x[0 :2 , 1 :3 ])1 ] = 0 print (x)0 ] = -1 print (x)print (x[1 , 2 ] == x[1 ][2 ])
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 tensor([[ 0,  1,  2,  3],         [ 4,  5,  6,  7],         [ 8,  9, 10, 11]] )[[1, 2],         [5, 6]] )[[ 0,  1,  2,  0],         [ 4,  5,  6,  0],         [ 8,  9, 10,  0]] )[[-1, -1, -1, -1],         [ 4,  5,  6,  0],         [ 8,  9, 10,  0]] )
一些操作可能导致为结果重新分配内存: 
1 2 3 4 5 6 before = id (Y)print (before)id (Y)print (after)print (before == after)
运行结果:
1 2 3 139769251739696 139769252745984 False 
那是当然的,X + Y肯定要新赋值给一个元素,不能把X或Y的值给修改掉。
原地执行操作:
1 2 3 4 before = id (Y)id (Y)print (before == after)
运行结果:
原地执行:
1 2 3 4 5 Z = torch.zeros_like(Y)id (Z)id (Z)print (before == after)
运行结果:
转为Numpy张量 
1 2 A = x.numpy()print (type (A), type (x))
运行结果:
1 <class  'numpy.ndarray' > <class  'torch.Tensor' >
将大小为1的张量转为Python的标量: 
1 2 3 4 x = torch.tensor([1 ])print (x, x.item(), float (x), int (x))1. ])print (y, y.item(), float (y), int (y))
运行结果:
1 2 tensor ([1 ]) 1  1 .0  1 tensor ([1 .]) 1 .0  1 .0  1 
数据预处理 新建一个数据集
1 2 3 4 5 6 7 dataFile = "data.csv" with  open (dataFile, 'w' ) as  f:'NumRooms,Alley,Price\n' )'NA,Pave,127500\n' )'2,NA,106000\n' )'4,NA,178100\n' )'NA,NA,140000\n' )
读取到pandas中
1 2 3 4 import  pandas as  pd  print (data)
运行结果:
1 2 3 4 5    NumRooms  Alley   Price0        NaN  Pave  127500 1        2 .0    NaN  106000 2        4 .0    NaN  178100 3        NaN   NaN  140000 
获取输入和输出 
1 2 0 :2 ], data.iloc[:, 2 ]
处理缺失值 
使用平均值填补NaN:
1 2 inputs = inputs.fillna(inputs.mean())print (inputs)
运行结果:
1 2 3 4 5 6 7    NumRooms Alley0        3.0   Pave1        2.0    NaN 2        4.0    NaN 3        3.0    NaN 2420151946. py:1 : FutureWarning: The default  value  of  numeric_only in  DataFrame.mean is  deprecated. In  a future version , it will default  to  False . In  addition, specifying 'numeric_only=None'  is  deprecated. Select  only  valid  columns  or  specify the value  of  numeric_only to  silence this warning .
警告的意思是说在未来的版本中,numeric_only将不设置默认值。因此手动添加numeric_only=True以消除警告:
1 inputs = inputs.fillna(inputs.mean(numeric_only=True ))
将pandas中的Nan视为一个类别 
1 2 inputs = pd.get_dummies(inputs, dummy_na=True )print (inputs)
运行结果(结果中的1和0也有可能被标记为True和False):
1 2 3 4 5    NumRooms   Alley_Pave  Alley_nan0        3 .0            1           0 1        2 .0            0           1 2        4 .0            0           1 3        3 .0            0           1 
将数据转为torch的张量 
1 2 3 4 5 6 7 print (inputs.values)import  torchprint (X)print (y)
运行结果:
1 2 3 4 5 6 7 8 9 [[3. 1. 0.] [2. 0. 1.] [4. 0. 1.] [3. 0. 1.] ]tensor ([[3., 1., 0.] ,[2., 0., 1.] ,[4., 0., 1.] ,[3., 0., 1.] ], dtype=torch.float64)tensor ([127500 , 106000 , 178100 , 140000 ]) 
注意这里X的dtype是64位浮点数。但其实64位运行较慢,实际使用时经常使用32位浮点数。
1 2 3 X = X.to(dtype=torch.float32)print (X)print (X.dtype)
运行结果:
1 2 3 X = X.to (dtype =torch.float32)print (X)print (X.dtype)
线性代数基础 矩阵转置x.T: 
1 2 3 x = torch.arange(12 ).reshape(3 , 4 )print (x)print (x.T)
运行结果:
1 2 3 4 5 6 7 tensor([[ 0,  1,  2,  3],         [ 4,  5,  6,  7],         [ 8,  9, 10, 11]] )[[ 0,  4,  8],         [ 1,  5,  9],         [ 2,  6, 10],         [ 3,  7, 11]] )
简单操作: 
$c = a + b$ where $c_i=a_i+b_i$ 
$c=\alpha\cdot b$ where $c_i=\alpha b_i$ 
$c=\sin a$ where $c_i=\sin a_i$ 
 
长度: 
$||a||2=[\sum^m {i=1}a_i^2]^{\frac12}$ 
$||a||\geq 0$ for all $a$ 
$||a + b||\leq ||a|| + ||b||$ 
$||a\cdot b||=|a|\cdot||b||$ 
 
自动求导 自动求导:requires_grad 
1 2 3 4 5 6 7 8 x = torch.arange(4. )True )  print (x)2  * torch.dot(x, x)  print (y)print (x.grad == 4  * x)  
运行结果:
1 2 3 tensor([0., 1., 2., 3.], requires_grad =True )grad_fn =<MulBackward0>)True , True , True , True ])
清除梯度:x.grad.zero_ 
默认情况torch会把梯度累积起来,因此计算下一个梯度是时候记得清除掉之前的梯度
1 2 3 4 5 6 7 8 9 10 11 x = torch.arange(4. , requires_grad=True )2  * torch.dot(x, x)print (x.grad)print (x.grad)  print (x.grad)  
运行结果:
1 2 3 tensor ([ 0 .,  4 .,  8 ., 12 .])tensor ([ 0 .,  6 ., 12 ., 18 .])tensor ([0 ., 2 ., 4 ., 6 .])
将某些计算结果移动到记录的计算图之外:y.detach() 
1 2 3 4 5 6 7 8 x = torch.arange(4. , requires_grad=True )print (y)print (u)sum ().backward()print (x.grad == u)
运行结果:
1 2 3 tensor ([0 ., 1 ., 4 ., 9 .], grad_fn=<MulBackward0>) tensor ([0 ., 1 ., 4 ., 9 .]) tensor ([True, True, True, True]) 
但注意y.detach()不改变y,y仍是关于x的函数
1 2 3 x.grad.zero_()sum ().backward()print (x.grad == 2  * x)
运行结果:
1 tensor([True , True , True , True ])
线性回归 线性回归手动实现 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 import  randomimport  torchfrom  d2l import  torch as  d2ldef  synthetic_data (w, b, num_examples ):"""生成y = Xw + b + 噪声""" 0 , 1 , (num_examples, len (w)))  0 , 0.01 , y.shape)return  X, y.reshape((-1 , 1 ))2 , -3.4 ])4.2 1000 )  def  data_iter (batch_size, features, labels ):len (features)list (range (num_examples))for  i in  range (0 , num_examples, batch_size):min (i + batch_size, num_examples)])  yield  features[batch_indices], labels[batch_indices]10 0 , 0.01 , size=(2 , 1 ), requires_grad=True )1 , requires_grad=True )def  linreg (X, w, b ):"""线性回归模型""" return  torch.matmul(X, w) + bdef  squared_loss (y_hat, y ):"""均方损失""" return  (y_hat - y.reshape(y_hat.shape)) ** 2  / 2 def  sgd (params, lr, batch_size ):"""小批量梯度下降算法""" with  torch.no_grad():for  param in  params:0.03 3 for  epoch in  range (num_epochs):for  X, y in  data_iter(batch_size, features, labels):sum ().backward()with  torch.no_grad():print (f'epoch {epoch + 1 } , loss {float (train_l.mean()):f} ' )print (f'w的估计误差: {true_w - w.reshape(true_w.shape)} ' )print (f'b的估计误差: {true_b - b} ' )
运行结果:
1 2 3 4 5 epoch  1 , loss 0 .038151 epoch  2 , loss 0 .000152 epoch  3 , loss 0 .000048 w 的估计误差: tensor([-0 .0003 , -0 .0008 ], grad_fn=<SubBackward0>)b 的估计误差: tensor([0 .0008 ], grad_fn=<RsubBackward1>)
借助Pytorch实现 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 import  numpy as  npimport  torchfrom  torch.utils import  datadef  synthetic_data (w, b, num_examples ):"""生成y = Xw + b + 噪声""" 0 , 1 , (num_examples, len (w)))  0 , 0.01 , y.shape)return  X, y.reshape((-1 , 1 ))2 , -3.4 ])4.2 1000 )def  load_array (data_arrays, batch_size, is_train=True  ):"""构造一个PyTorch数据迭代器""" return  data.DataLoader(dataset, batch_size, shuffle=is_train)10 from  torch import  nn2 , 1 ))0 ].weight.data.normal_(0 , 0.01 )0 ].bias.data.fill_(0 )0.03 )3 for  epoch in  range (num_epochs):for  X, y in  data_iter:print (f'epoch {epoch + 1 } , loss {l:f} ' )0 ].weight.dataprint ('w的估计误差:' , true_w - w.reshape(true_w.shape))0 ].bias.dataprint ('b的估计误差:' , true_b - b)
运行结果:
1 2 3 4 5 epoch  1 , loss 0 .000258 epoch  2 , loss 0 .000101 epoch  3 , loss 0 .000100 w 的估计误差: tensor([-0 .0003 ,  0 .0005 ])b 的估计误差: tensor([0 .0012 ])
: 
运行结果:
: 
运行结果:
: 
运行结果:
TODO: 等完成地差不多了发布至CSDN 
原创不易,转载请附上原文链接 哦~https://blog.letmefly.xyz/2023/03/15/Other-AI-LearnAIWithLiMu/