王海鱼 发表于 2024-12-9 05:23:17

深度学习之预备知识

深度学习是关于优化的学习。对一个带有参数的模型,找到其中能拟合数据最好的模型。
一、数据操作

  张量:表示一个由数值构成的数组,这个数组大概有多个维度。具有一个轴的张量对应数学上的向量,具有两个轴的张量对应数学上的矩阵,具有两个以上轴的张量没有特定的数学名称。
  深度学习的张量与Numpy雷同,但深度学习框架比Numpy的ndarray多一些重要功能:起首,GPU很好支持加速盘算,而Numpy仅支持CPU盘算;其次,张量类支持自动微分。这类功能使得张量类更适合深度学习。
  导入torch,虽然它被称为Pytorch。但代码中利用torch而不是pytorch。
import torch
x=torch.arange(12)
x.shape    #访问张量形状
x.numel()#计算张量中总数,即形状的所有元素乘积
X=x.reshape(3,4) #通过reshape函数,改变张量的形状而不改变元素数量和元素值。
x.reshape(-1,4)或者reshape(3,-1) #通过-1来调用此自动计算出形状
#创建全为0或者1的张量
torch.zeros((2,3,4))
torch.ones((2,3,4))
##通过某个特定概率分布中随机采样来得到张量中每个元素的值
torch.randn(3,4) #均值0,标准差为1的正态分布中随机采样
##通过提供办好数值的python列表来为张量的每个元素赋值
torch.tensor(,,]) #外层列表对应轴0,内层列表对应轴1
1.1 运算符

import torch
x=torch.tensor()
y=torch.tensor()
x+y,x-y,x*y,x/y
torch.exp(x)#求幂
x.sum()#对张量中的所有元素求和,会产生一个单元素张量


[*]多个张量毗连cat
x=torch.arange(12,dtype=torch.float32).reshape(3,4)
y=torch.tensor([,,])
torch.cat((x,y),dim=0),torch.cat((x,y),dim=1)
https://i-blog.csdnimg.cn/direct/2c3be5e0a6fd4951983077accca88704.png
1.2 广播机制

  1.1中看到如何在雷同形状的两个张量上实行按元素操作,在某些情况下,即使形状不同,我们仍然可以通过调用广播机制来实行按元素操作。这种机制的工作方式如下:
(1)通过得当复制元素来扩展一个或两个数组,以便在转换之后,两个张量具有雷同的形状;
(2)对生成的数组实行按元素操作
  在大多数情况下,我们将沿着数组中长度为1的轴进行广播,如下:
import torch
x=torch.arange(3).reshape(3,1)
y=torch.arange(2).reshape(1,2)
x,y
x+y
https://i-blog.csdnimg.cn/direct/8351584ba4cb406aaf6770d1b5fdcbde.png
  由于x和y分别是3x1矩阵和1x2矩阵,它们的形状不匹配,如果相加,矩阵x将复制列,矩阵y将复制行,实现两个矩阵广播为一个更大的3x2矩阵。
1.3 索引和切片

  与python数组一样,张量中的元素可以通过索引访问,第一个元素的索引是0,最后一个元素的索引是-1。
x=torch.arange(12,dtype=torch.float32).reshape(3,4)
x[-1],x
https://i-blog.csdnimg.cn/direct/bb6b12fe744b4d0a95c8d16b087dccdb.png


[*]可以通过指定索引来将元素写入矩阵
x=9
x
https://i-blog.csdnimg.cn/direct/2e22a5e1d6934e58bc1618b306d23cc3.png


[*]想为多个元素赋予雷同的值,只须要索引所有元素,然后为它们赋值。
x=12
x
https://i-blog.csdnimg.cn/direct/cba88a474e224233892643fc4bab429d.png
1.4 转换为其他python对象

  将深度学习框架界说的张量转换为numpy张量很轻易,反之也同样轻易。torch张量和numpy数组将共享它们的底层内存,就地操作更改一个张量也会同时更改另一个张量。
import torch
a=x.numpy()
b=torch.tensor(a)
type(a),type(b)
https://i-blog.csdnimg.cn/direct/d13f0bd82be649ca983fc4816434f14a.png


[*]要将大小为1的张量转换为python标量,可以调用item函数或python的内置函数。
import torch
a=torch.tensor()
a,a.item(),float(a),int(a)
https://i-blog.csdnimg.cn/direct/904571b5b5de48588bdf005ca4f54981.png
二、数据预处理

  在python常用的数据分析中,通常利用pandas包,与庞大的python生态系统中的许多其他扩展包一样,pandas可以与张量兼容。接下来先容pandas预处理原始数据,并将原始数据转换为张量格式的步骤。
2.1 读取数据集

import pandas as pd
data =pd.read_excel('data.xlsx')
print(data)
https://i-blog.csdnimg.cn/direct/92aefdde617d4850a167f19bc4e6cf96.png
2.2 处理缺失值

  通过位置索引 iloc,将data分成 inputs 和 outputs,其中前者为data的前两列,后者为data的最后一列,对于inputs 中的缺失值,用一列的均值替换NaN项。
inputs,outputs=data.iloc[:,0:2],data.iloc[:,2]
inputs=inputs.fillna(inputs.mean())
print(inputs)
https://i-blog.csdnimg.cn/direct/f320315c873542d0830353d14b0af010.png
  将NaN视为一个种别,由于Alley列只接受两种类型值Pave和NaN,pandas可以自动将此列转换为两列Alley_pave和Alley_nan。Alley列为pave的行会将Alley_pave的值设置为1,Alley_nan的值设置为0。
inputs=pd.get_dummies(inputs,dummy_na=True)
print(inputs)
https://i-blog.csdnimg.cn/direct/8cc0f312410341038a769425e18b7c30.png
2.3 转换为张量格式



[*]如今inputs和outputs中的所有条目都是数值类型,它们可以转换为张量格式。
X,y=torch.tensor(inputs.values),torch.tensor(outputs.values)
X,y
https://i-blog.csdnimg.cn/direct/52e472f0a2a44f61982260785e008ad6.png
三、线性代数

3.1 标量

标量由只有一个元素的张量表示。
x=torch.tensor(3.0)
y=torch.tensor(2.0)
x+y,x*y,x/y,x**y
https://i-blog.csdnimg.cn/direct/470d7ec0ad0c4d1aa46fabd876355933.png
3.2 向量

  向量可以被视为标量值构成的列表,这些标量值被称为向量的元素。当向量表示数据会合的样本时,它们的值具有肯定的实际意义。在数学上,具有一个轴的张量表示向量。
x=torch.arange(4)
x
https://i-blog.csdnimg.cn/direct/ab2adbf40ef74714bfe67930c092be4d.png
与普通的python数组一样,可以通过调用python的内置函数len来访问张量的长度,shape属性访问向量的长度。
X=torch.arange(12,dtype=torch.float32).reshape(3,4)
len(X),X.shape
https://i-blog.csdnimg.cn/direct/d00a587d04544a17b44290bd09fd6ba9.png
3.3 矩阵

正如向量将标量从零阶推广到一维,矩阵将向量从一维推广到二维。在代码中表示为具有两个轴的张量。
X=torch.arange(16).reshape(4,4)
X,X.T
https://i-blog.csdnimg.cn/direct/1a2b6f436e484ef79bf9ca8e28adf84a.png
3.4 张量算法的基本性子

标量、向量、矩阵和任意数量轴的张量由一些利用的属性。
X=torch.arange(16).reshape(4,4)
y=X.clone()#通过分配新的内存,将X的一个副本分配给y
X,X+y,X*y
https://i-blog.csdnimg.cn/direct/991196d648e14281b0423cd0385619b2.png
将张量加上或乘以一个标量不会改变张量的形状,其中张量的每个元素都将与标量相加或相乘。
a=2
X=torch.arange(24).reshape(2,3,4)
a+X,(a*X).shape
https://i-blog.csdnimg.cn/direct/d7f192a5d98149baa6153b67e79a8958.png
3.5 降维

我们可以对任意张量进行的一个有用的操作是盘算其元素的和。
X=torch.arange(24).reshape(2,3,4)
X,X.sum()
X.sum(axis=0)#对所有的行元素求和
X.sum(axis=1)#对所有的列元素求和
https://i-blog.csdnimg.cn/direct/a5f936fe616c4807afd34f969758c35c.png


[*]非降维求和
有时在调用函数来盘算总和或均匀值时保持轴数不变会很有用。keepdims=True
A=torch.arange(20).reshape(5,4)
sum_a=A.sum(axis=1)
sum_A=A.sum(axis=1,keepdims=True)
A,sum_a,sum_A,A/sum_A,A.cumsum(axis=0)#按行累计求和
https://i-blog.csdnimg.cn/direct/c3c747b967da4a2ebc34ffda1c67ca37.png
3.6 点积

点积:雷同位置的按元素乘积的和。
x=torch.arange(4,dtype=torch.float32)
y=torch.ones(4,dtype=torch.float32)
x,y,torch.dot(x,y)


[*]矩阵-向量积
利用mv函数表示矩阵-向量积,矩阵A和向量x调用torch.mv(A,x)时,实行矩阵-向量积。
A=torch.arange(20).reshape(5,4)
x=torch.arange(4)
A,x,torch.mv(A,x)
https://i-blog.csdnimg.cn/direct/e7a27b7281d34b1f8e86bae62ab885ad.png


[*]矩阵-矩阵乘法(矩阵乘法)
A=torch.arange(20,dtype=torch.float32).reshape(5,4)
B=torch.ones(4,3)
torch.mm(A,B)
https://i-blog.csdnimg.cn/direct/469a2ea4c3574fce9e0d3459b423dd37.png
3.7 范数

  线性代数中最有用的一些运算符是范数,向量的范数表示一个向量有多大。这里思量的大小概念不涉及维度,而是分量的大小。在线性代数中,向量范数是将向量映射到标量的函数 f 。给定任意向量 x ,向量范数具有如下性子:
(1)如果按常数因子 ɑ 缩放向量的所有元素,其范数也会按雷同常熟因子的绝对值缩放:f(ɑx)=|ɑ|f(x)
(2)f(x+y)≤f(x)+f(y)
(3)非负性f(x)≥0
  范数很像间隔的度量,欧几里得间隔是一个L2范数:假设 n 维向量 x 中的元素是x1,…,xn,其L2范数是向量元素平方和的平方根。
https://i-blog.csdnimg.cn/direct/e333b4af4997496f815f0c662aea75b3.png
import torch
u=torch.tensor()
torch.norm(u)
https://i-blog.csdnimg.cn/direct/b89d0b5f1d6e48e2984b7760370fb399.png
深度学习中经常利用L2范数的平方,也会经常遇到L1范数,它表示为向量元素的绝对值之和:
https://i-blog.csdnimg.cn/direct/25b34f95bcf84727bee492a6a088c8ba.png
与L2范数相比,L1范数受异常值的影响较小。为了盘算L1范数,我们将绝对值函数和按元素求和组合起来。
torch.abs(u).sum()
https://i-blog.csdnimg.cn/direct/bb0d469f3c42438b800ce921e02e264b.png
L2范数和L1范数都是更一般的LP范数的特例:
https://i-blog.csdnimg.cn/direct/2ee6712b8aa7438d94413393e41a7520.png
四、自动微分

  在深度学习中,我们“训练”模型,不停更新它们,使它们在见到越来越多的数据时变得越来越好。通常情况下,变得更盛情味着最小化一个损失函数,即一个衡量“模型有多糟糕”这个题目标分数。最终我们真正关心的是生成一个模型,它可以或许在从未见到过数据上表现良好。但“训练”模型只能将模型与我们实际见到的数据相拟合。因此,我们可以将拟合模型的使命分解为两个关键题目。


[*]优化:用模型拟合观察数据的过程。
[*]泛化:模型不仅在训练集表现良好,在未知的数据(测试集)也表现良好,即具有良好的泛化能力。
  求导是险些所有深度学习优化算法的关键步骤,虽然求导的盘算简单,但对于复杂的模型,手动进行更新是一件痛苦的事情,深度学习框架通过自动盘算导数,即自动微分来加快求导。实践中,根据计划好的模型,系统会构建一个盘算图,来跟踪盘算是哪些数据通过哪些操作组合起来产生输出。自动微分使系统可以或许随后反向传播梯度。这里,反向传播意味着跟踪整个盘算图,填充关于每个参数的偏导数。
import torch
x = torch.arange(4.0, requires_grad=True)# 设置 requires_grad=True 使得 x 被标记为需要计算梯度的张量。
y = 2 * torch.dot(x, x)
y.backward()#调用 y.backward() 后,x.grad 会保存 x 关于 y 的梯度。
print(x.grad)# 输出 x 的梯度
https://i-blog.csdnimg.cn/direct/9554c0db14ed478e8bb52686dd669882.png
函数y=2*x^2关于x的梯度应为4x,验证梯度是否正确:
x.grad==4*x
https://i-blog.csdnimg.cn/direct/c46a1131fc9d4df9a2b9b64e36034f01.png
盘算x的另一个函数:
x.grad.zero_() #将x的梯度清零的操作。通常在反向传播 (backward) 之前或之后调用它,目的是防止梯度的累积。
y=x.sum()
y.backward()
x.grad
https://i-blog.csdnimg.cn/direct/3a20d66d7dae45bdb73d70a6846f249d.png
4.1 分离盘算

  有时,我们盼望将某些盘算移到记载的盘算图之外。例如,假设y是作为x的函数盘算的,而z则是作为y和x的函数盘算的。想盘算z关于x的梯度,但由于某种缘故原由,盼望将y视为一个常数,并且只思量x在y被盘算后发挥的作用。
  这里可以分离y来返回一个新变量u,该变量与y具有雷同的值,但丢弃盘算图中如何盘算y的任何信息,换句话说,梯度不会向后流经u到x。因此,下面的反向传播函数盘算z=ux关于x的偏导数,同时将u作为常数处理,而不是盘算z=xx*x关于x的偏导数。
x.grad.zero_()
y=x*x
u=y.detach() #创建一个新的张量 u,它是 y 的一个 detach 副本。detach() 是 PyTorch 中的一个方法,用于返回一个新的张量,该张量与原始张量 y 共享相同的数据,但不会参与梯度计算,也就是说,它与计算图分离了。
z=u*x# u 是通过 y.detach() 得到的,所以 u 不再跟踪梯度,而 x 仍然是需要梯度的。因此,这条语句不会改变 x 的梯度计算行为,但会产生一个新的张量 z。
z.sum().backward() #计算 z 的所有元素的和,然后对其进行反向传播,计算 x 的梯度。
x.grad==u #x.grad 会被更新,存储关于 x 的梯度值。
https://i-blog.csdnimg.cn/direct/6f8477a8f47f49e09a09f301ecfa0241.png

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 深度学习之预备知识