目录
Task01 - 初识深度学习
1.安装anaconda(之前装过)
2.安装git
3.下载课程jupyter notebook资料
4.安装pytorch(昨天跟直播回放做的)
练习前先激活conda才能使用之前装的torch包等 conda activate d2l
Task02:预备知识
1.数据操作
1.1 n维数组概念
批量batch
1.2 数组的创建与访问
冒号表示到最后, 子区域是左闭右开区间
最后一种表示跳选,跳3行2列
1.3数据操作代码实现
生成等差数组
张量(tensor)
arange创建等差数组
改变数组形状
生成全0或全1张量
torch.zeros((2, 3, 4)) 创建一个形状为 (2,3,4) 的张量,其中每个元素均为0. 这个张量具有 2 个秩/维度(rank/dimension),最外层维度长度为2,中间为3,最内层为4。可以将这个张量看作一个由两个 $3\times4$ 的矩阵组成的张量。在PyTorch中,通常用torch.zeros创建一个全0的张量作为初始化的起点,在后续的操作中不断更新张量中的数值。
随机生成数组
torch.rand()生成一个[0,1)之间的均匀分布随机张量
torch.randn()生成正态分布的随机张量
在功能上,torch.rand(2, 3, 4) 和 torch.rand((2, 3, 4)) 是等价的,它们都会产生一个形状为 (2, 3, 4) 的随机数张量。唯一的区别是它们的输入参数形式不同:
- torch.rand(2, 3, 4) 将整个张量的形状以多个参数的形式进行传递,逐一指定每个维度的大小。
- torch.rand((2,3,4))则将整个张量的形状包装在单个元组中进行传递。
生成指定数组
对张量size的解释
第一个维度大小为 1,这个维度通常表示 batch size。batch size 为 1 表示当前张量中只有一组数据,通常用于单个数据的处理场景。
第二个维度大小为 3,可能代表了张量中的特征数量。例如,如果这是一个图像相关的张量,那么第二个维度的大小可以代表图像的通道数量(如RGB图像中通常有三个通道)。
第三个维度大小为 4,其含义可以根据实际问题确定。例如,如果这是一个图像相关的张量,那么第三维可以代表图像的宽度,或者其他与图像相关的信息。同样地,对于其他类型的数据,这个维度的大小也可以代表不同的含义。
在一个形状为 (1, 3, 4) 的张量中,如果我们将其当做一个矩阵来处理,其实是不太准确的,因为这个张量实际上有三个维度。通常,我们将它展开成一个2D的矩阵后再进行矩阵运算,可以使用reshape方法实现此操作,例如:
import torch
x = torch.randn(1, 3, 4)
matrix = x.reshape(3, 4)
print(matrix)
以上代码将x张量形状变为 [3, 4] 的矩阵,并在控制台输出。
如果使用矩阵的观点,可以将第一个维度当作行数,第二个维度当作列数,因此可以将这个张量视为一个一行三列四元素的矩阵(当然,如果不使用展平操作,它也可以同时被视为一列三行四元素的矩阵或四行三列一元素的张量)。
但需要注意,在深度学习领域中,通常不这样处理三维张量。这是因为三维张量在深度学习中一般代表的含义比较特殊,例如在卷积神经网络(Convolutional Neural Network,CNN)中,一个输入图像通常被表示成一个更高维度的张量。
通过选择下标的方式修改矩阵元素将X的第一行第二列的元素值修改为17
矩阵赋值 指数运算 加减乘除求幂
x**y 求幂运算 x的y次方
连接多个张量
dimension
通过逻辑运算符构建二元张量张量元素求和
广播机制
把a拓展成2列,再与b相加
内存问题
id 指针
与numpy之间的转化
2.数据预处理
2.1创建csv文件
os.path.join('..', 'data') 将创建一个路径为'../data'的文件夹,其中'..'代表上一级目录。如果该文件夹已经存在,则不会创建该文件夹。
open(),它打开一个文件并返回文件对象,'w' 表示写入方式打开该文件。
使用 with as 语句块来自动进行文件的关闭操作,并且将文件对象绑定到 f 变量上。代码中的字符串是要写入文件的内容,使用 f.write() 方法将字符串写入打开的文件中。代码中的三个单引号用于表示一个多行字符串。
2.2通过插值和分类的方法填补数据![](https://img-blog.csdnimg.cn/c330a80f4f674b6589a8b8d7477dda06.png)
把NaN当作一个类别(not a number) iloc index location
Pandas 库的 get_dummies() 函数将分类变量转换为二进制哑变量,dummy_na 参数指定是否为缺失值创建一个额外的哑变量列。
函数的输入参数 inputs 是一个 Pandas DataFrame 对象,其中包含了需要进行哑变量编码的分类变量以及其他的特征变量。函数处理分类变量并创建对应的二进制哑变量列,并将其与原始数据集中的其他变量合并,最终返回一个 DataFrame 对象。
2.3简单处理完成
3.线性代数
3.1标量
3.2向量
3.3矩阵
矩阵乘法 是对空间的扭曲
不是每一个矩阵都有特征向量
这个对特征向量的解释比较好
3.4代码实现
指定求和汇总张量的轴
axis=0表示对数组的第一个轴进行求和,即按列对数组进行求和。
对于一个二维数组A,假设A的shape为(m, n),则对A进行 A.sum(axis=0) 操作会得到一个一维数组,长度为n,表示按列对A进行求和,返回的结果中第i个元素为第i列的所有元素的和。
降维
例如,对于以下二维数组A:
A = [[1, 2, 3],
[4, 5, 6]]
执行 A.sum(axis=0) 的结果为:
array([5, 7, 9])
求均值
计算总和或均值时保持轴数不变 / 广播
点积
向量积
矩阵乘法
范数
补充解释 0,1,2....axis=谁,shape里把谁消掉
4.矩阵计算
梯度
梯度(gradient)指的是一个向量操作,用于计算函数在某一点处的斜率或者导数。在向量微积分中,梯度是一个向量,表示在某一点处函数的变化率最快的方向。梯度的方向指向函数值增加最快的方向,函数值减少最快的方向为梯度的反方向。
在机器学习中,梯度常常被用来表示模型对于训练数据的误差函数的导数。通过计算误差函数对于模型参数的梯度,可以使用梯度下降算法来调整模型参数,从而最小化误差函数,达到优化模型的目的。
梯度下降算法是一个迭代的优化算法,初始时需要指定一个参数向量,通过计算误差函数对于参数的梯度方向,不断调整参数的值来达到最小化误差函数的目的。在每一次迭代中,算法会根据梯度的方向更新参数,直到误差函数收敛或达到一个预定的迭代次数为止。梯度下降算法是一种基本的优化算法,在深度学习中被广泛应用。
最后一个是内积符号
x,y都为向量
5.自动求导
5.1链式法则
5.2自动求导
计算图
5.3代码实现
定义储存梯度的位置
求导
Task03 - 线性神经网络
1.线性回归+基础优化算法
1.1线性回归
线性模型
1.2 基础优化算法
计算梯度很贵!
1.3 线性回归的从零开始
构造数据集
x=torch.normal(0,1,(num_examples,len(w)))
这行代码使用PyTorch生成一个均值为0,标准差为1,维度为(num_examples,len(w))的正态分布随机数张量。其中,num_examples是示例数量,len(w)是权重向量的长度。这行代码通常用于在训练神经网络之前初始化权重。
y=torch.matmul(x,w)+b
这行代码使用 PyTorch 中的矩阵乘法函数 matmul(),将生成的随机数张量 x 与权重向量 w 相乘,并加上偏置 b,得到输出张量 y。其中,x 的维度为(num_examples,len(w)),w 的维度为(len(w),num_outputs),b 的维度为(num_outputs,),y 的维度为(num_examples,num_outputs)。这行代码通常用于神经网络前向传播的计算过程。
return x,y.reshape((-1,1))
这行代码使用 PyTorch 中的 reshape() 函数,将张量 y 的形状从 (num_examples, num_outputs) 调整为 (num_examples, 1),同时返回张量 x 和调整后的张量 y。这行代码通常用于在神经网络训练过程中返回输入特征值 x 和标签值 y,以供后续计算梯度和监测模型性能。
features,labels=d2l.synthetic_data(true_w,true_b,1000)
这行代码调用了名为 synthetic_data() 的函数,用于生成 1000 个样本数据集。其中 true_w 表示真实权重向量,true_b 表示真实偏差。函数生成的 features 张量形状为 (1000, 2),表示有 1000 个样本,每个样本有 2 个特征;labels 张量形状为 (1000, 1),表示对于这 1000 个样本而言,每个样本有一个标签值。可以将 features 和 labels 看作是对应的输入和输出数据。这行代码生成的数据集通常用于机器学习的训练和测试。
d2l.set_figsize()
:设置图形的尺寸大小。
d2l.plt.scatter()
:使用matplotlib库中的scatter()函数绘制散点图。它的第一个参数表示x轴的数据,第二个参数表示y轴的数据,第三个参数表示点的大小。
features[:,1].detach().numpy()
:将features变量(一个张量)的所有行和第1列的数据提取出来,并将其转化为numpy数组。类似于Python中的切片操作。
labels.detach().numpy()
:将labels变量(一个张量)的所有元素提取出来,并将其转化为numpy数组。
综合起来,这段代码的作用是将features的第1列作为x轴数据,labels作为y轴数据,将它们绘制成散点图。其中1表示点的大小。
def data_iter(batch_size,features,labels):
num_examples=len(features)
indices=list(range(num_examples))
random.shuffle(indices)
for i in range(0,num_examples,batch_size):
batch_indices=torch.tensor(
indices[i:min(i+batch_size,num_examples)])
yield features[batch_indices],labels[batch_indices]
这段代码是一个迭代器函数,用于生成小批量的数据集。具体解释如下:
data_iter(batch_size,features,labels)
:该函数有三个参数,分别是batch_size(每个小批量的大小)、features(输入特征)和labels(标签)。
num_examples=len(features)
:将features张量的长度(即数据集的大小)赋值给num_examples。
indices=list(range(num_examples))
:生成num_examples个数字的列表[0,1,2,...,num_examples-1],并将其存储在indices列表中。
random.shuffle(indices)
:将indices列表的元素打乱顺序。
for i in range(0,num_examples,batch_size):
:循环,每次迭代生成一个小批量的数据。其中i表示该批量的起始下标。
batch_indices=torch.tensor(indices[i:min(i+batch_size,num_examples)])
:生成一个张量batch_indices,包含indices列表中从下标i到下标min(i+batch_size,num_examples)-1的所有元素。如果batch_size等于1,则取单个数,否则取多个数。
yield features[batch_indices],labels[batch_indices]
:使用Python中的yield关键字将features张量和labels张量中在batch_indices张量中指定的元素提取出来,并将它们组合成一个元组,作为本次循环中的返回值。这样生成器函数就可以迭代地返回多个小批量的数据了。
综合起来,该函数的作用是将输入的features特征和labels标签随机打乱后,将它们分成多个小批量,并且每次迭代一个小批量,数据的顺序是随机的。
将大型数据集分批次处理可以带来多方面的好处:
1.减少内存开销:在深度学习中,通常需要处理大量数据,将整个数据集一次性加载到内存中可能会导致内存溢出。小批量数据可以将数据集分批次加载,避免了内存的不足和浪费,使得计算机可以更好地处理数据。
2.增加模型的泛化能力:小批量数据训练集合在每个迭代周期内都是随机的,这使得模型不会过拟合,提高了模型的泛化能力。在对测试数据进行预测时,需要将其分批次送入模型,因此在训练阶段使用小批量数据可以更好地模拟实际预测情况。
3.加速训练过程:小批量数据使得梯度下降算法可以更加高效地更新模型参数,因为在每个迭代周期内只需要计算小批量数据的梯度,提高了计算效率和训练速度。
综上所述,生成小批量的数据集不仅可以提高训练效率和模型的泛化能力,而且有助于减少内存开销,提高训练速度,使模型能够更快地达到收敛。
squared_loss(y_hat,y)
:该函数有两个参数,分别是y_hat(预测值)和y(真实值)。
return (y_hat-y.reshape(y_hat.shape))**2/2
:平方损失函数的公式为(��−��^)2。该函数对应了所有的样本点的平均误差,因此返回的是平方误差的平均值,即(��−��^)2/2。其中,y和y_hat的形状可能不相同,因此首先使用y.reshape(y_hat.shape)
将y的形状调整为y_hat的形状,然后计算两个张量之间的平方差。该函数返回一个张量,其形状与y_hat相同,表示所有样本点的平均误差。
在深度学习中,损失函数的作用是衡量模型预测结果和真实标签之间的误差。平方损失函数是一种常用的损失函数,它将模型预测值与真实值之间的差异平方后求平均。将平方损失函数作为模型的损失函数,可以在训练的同时优化模型参数,从而提高模型的预测能力和泛化性能。
sgd(parama,lr,batch_size)
:该函数有三个参数,分别是params(需要更新的参数)、lr(学习率)和batch_size(批量大小)。
with torch.no_grad():
:使用PyTorch中的上下文管理器,即在上下文环境中不自动计算梯度。也就是说,在该代码块中,param.grad不会被自动计算。这么做主要是为了节约计算资源,因为在更新参数的过程中只需要使用已经计算过的梯度。对于代码块中的更新操作,PyTorch不会对其进行跟踪或记录历史,而是直接执行。
for param in params:
:遍历所有需要更新的参数。
param-=lr*param.grad/batch_size
:通过梯度下降法更新参数,其中lr*param.grad/batch_size
表示学习率与参数梯度的乘积除以批量大小,即参数每次更新的量。使用减法是因为梯度下降的目标是最小化损失函数,而梯度的方向是函数在当前点下降最快的方向,因此减去一个梯度更新参数是合理的。
param.grad.zero_()
:清除参数的梯度,以便下一次计算。这个操作不能省略,因为PyTorch默认会对从backward()
方法中计算出来的梯度做累加,如果不清零的话,那么在下次计算梯度时,就会在原来的梯度值的基础上做累加,导致结果错误。
综上所述,该函数的作用是对给定参数进行梯度下降优化,并更新参数的值,以便让参数最优地拟合训练数据。在深度学习中,SGD是最常用的优化算法之一,其作用是通过不断地调整参数的值,以使得损失函数的值最小化。
该段代码是一个标准的模型训练流程,主要包括模型训练和模型测试两个阶段。具体解释如下:
for epoch in range(num_epochs):
:表示模型训练的轮数为num_epochs。
for x,y in data_iter(batch_size,features,labels):
:对数据集进行迭代,每个迭代周期训练一个小批量的数据。
l=loss(net(x,w,b),y)
:计算当前模型的预测值与真实标签的误差,得到损失值,用于衡量模型的预测能力。
l.sum().backward()
:通过反向传播计算参数的梯度,反向传播是求解梯度下降优化算法中的偏导数。
sgd([w,b],lr,batch_size)
:利用优化算法(随机梯度下降)更新参数,使得参数值更贴近于真实标签。
with torch.no_grad():
:使用PyTorch中的上下文管理器,即在上下文环境中不自动计算梯度。
train_l=loss(net(features,w,b),labels)
:计算训练集中所有样本的损失函数值,也就是衡量训练误差的大小。
print(f'epoch {epoch + 1},loss {float(train_l.mean()):f}')
:在每个训练周期结束后打印训练误差,{epoch+1}
表示当前的训练轮数,{float(train_l.mean()):f}
表示每个批次的平均损失函数值,并使用f字符串格式化输出。最终输出结果为当前训练轮数和该轮训练中的平均训练误差。
综上所述,该段代码的作用是对一个线性回归模型进行训练,不断地利用优化算法调整模型的参数,以使得损失函数的值最小化,从而让模型在训练数据上表现得更好。同时,也对模型在训练集上的表现进行评估,以了解模型的训练效果和性能。
1.4 线性回归的简洁实现