torch.rand(col, row) # 使用(0~1)均匀分布随机初始化二维数组
torch.ones(col, row) # 填充1初始化
torch.zero(col, row) # 填充0初始化
torch.eye(col, row) # 对角线为一,其它为0初始化
tensor = torch.tensor([3.1433223])
torch.DoubleTensor(col, row) # 64位浮点
torch.FloatTensor(col, row) # 32位浮点
torch.HalfTensor(col, row) # 16位浮点
torch.LongTensor(col, row) # 64位整数
torch.IntTensor(col, row) # 32位整数
torch.ShortTensor(col, row) # 16位整数
torch.CharTensor(col, row) # 8位整数(带符号)
torch.ByteTensor(col, row) # 8位整数(无符号)
#转换
tensor.long() # 64位整数
tensor.int() # 32位整数
tensor.short() # 16位整数
tensor.double() # 64位浮点
tensor.float() # 32位浮点
tensor.half() # 16位浮点
tensor.cahr() # 8位整数(带符号)
tensor.byte() # 8位整数(无符号)
torch.XXX(col, row).numpy() # tensor转换为numpy
torch.from_numpy(numpy.XXX((col, row))) # numpy转换为tensor
gpu_a=cpu_a.cuda() # cup转gpu
cpu_a=gpu_a.cpu() # gpu转cpu
max_value, max_idx = torch.max(input, dim=0) # max_value最大值,max_idx最大值索引,dim 1为行、0为列
sum_x = torch.sum(input, dim=1) # sum_x求和,dim 1为行、0为列
x.add_(y) # 将y加到a中
在张量创建时,通过设置 requires_grad 标识为Ture来告诉Pytorch需要对该张量进行自动求导。
当计算完成后调用.backward()方法自动计算梯度并且将计算结果保存到grad属性中。
使用with torch.no_grad()上下文管理器临时禁止对已设置requires_grad=True的张量进行自动求导
x = torch.rand(5, 5, requires_grad=True)
y = torch.rand(5, 5, requires_grad=True)
z=torch.sum(x+y)
z.backward()
print(x.grad,y.grad)
with torch.no_grad()
print((x +y*2).requires_grad) # False
class Net(nn.Module):
def __init__(self):
# nn.Module子类的函数必须在构造函数中执行父类的构造函数
super(Net, self).__init__()
# 卷积层 '1'表示输入图片为单通道, '6'表示输出通道数,'3'表示卷积核为3*3
self.conv1 = nn.Conv2d(1, 6, 3)
#线性层,输入1350个特征,输出10个特征
self.fc1 = nn.Linear(1350, 10) #这里的1350是如何计算的呢?这就要看后面的forward函数
#正向传播
def forward(self, x):
print(x.size()) # 结果:[1, 1, 32, 32]
# 卷积 -> 激活 -> 池化
x = self.conv1(x) #根据卷积的尺寸计算公式,计算结果是30,具体计算公式后面第二章第四节 卷积神经网络 有详细介绍。
x = F.relu(x)
print(x.size()) # 结果:[1, 6, 30, 30]
x = F.max_pool2d(x, (2, 2)) #我们使用池化层,计算结果是15
x = F.relu(x)
print(x.size()) # 结果:[1, 6, 15, 15]
# reshape,‘-1’表示自适应
#这里做的就是压扁的操作 就是把后面的[1, 6, 15, 15]压扁,变为 [1, 1350]
x = x.view(x.size()[0], -1)
print(x.size()) # 这里就是fc1层的的输入1350
x = self.fc1(x)
return x
net = Net()
print(net)
input = torch.randn(1, 1, 32, 32) # 这里的对应前面forward的输入是32
out = net(input)
# 在反向传播前,先要将所有参数的梯度清零
net.zero_grad()
out.backward(torch.ones(1,10)) # 反向传播的实现是PyTorch自动实现的,我们只要调用这个函数即可
在nn中PyTorch还预制了常用的损失函数
nn.L1Loss L1损失函数 l o s s ( x i , y i ) = v m a t r i x x i − y i ∣ loss(x_i,y_i) = vmatrixx_i-y_i| loss(xi,yi)=vmatrixxi−yi∣
nn.MSELoss L2损失函数 l o s s ( x i , y i ) = ( x i − y i ) 2 loss(x_i,y_i) = (x_i-y_i)^2 loss(xi,yi)=(xi−yi)2
nn.SmoothL1Loss Huber Loss损失函数 l o s s ( x i , y i ) = { 1 2 ( x i − y i ) 2 i f ∣ x i − y i ∣ < 1 ∣ x i − y i ∣ − 1 2 otherwise loss(x_i,y_i) = \begin{cases} \frac{1}{2}(x_i-y_i)^2& {if|x_i-y_i|<1}\\ |x_i-y_i| - \frac{1}{2}& \text{otherwise} \end{cases} loss(xi,yi)={ 21(xi−yi)2∣xi−yi∣−21if∣xi−yi∣<1otherwise
nn.BCELoss 二分类交叉熵损失函数 l o s s ( x i , y i ) = − ω i [ y i l o g x i + ( 1 − y i ) l o g ( 1 − x i ) ] loss(x_i,y_i)=-\omega_i[y_ilogx_i+(1-y_i)log(1-x_i)] loss(xi,yi)=−ωi[yilogxi+(1−yi)log(1−xi)]
y = torch.arange(0,10).view(1,10).float()
criterion = nn.MSELoss()
loss = criterion(out, y)
#loss是个scalar,我们可以直接用item获取到他的python类型的数值
在反向传播计算完所有参数的梯度后,还需要使用优化方法来更新网络的权重和参数
SGD
torch.optim.SGD(params, lr=<required parameter>, momentum=0, dampening=0, weight_decay=0, nesterov=False)
AdaGrad
torch.optim.Adagrad(params, lr=0.01, lr_decay=0, weight_decay=0, initial_accumulator_value=0)
RMSProp
torch.optim.RMSprop(params, lr=0.01, alpha=0.99, eps=1e-08, weight_decay=0, momentum=0, centered=False)
Adam
torch.optim.Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0, amsgrad=False)
import torch.optim
out = net(input) # 这里调用的时候会打印出我们在forword函数中打印的x的大小
criterion = nn.MSELoss()
loss = criterion(out, y)
# 新建一个优化器,SGD只需要要调整的参数和学习率
optimizer = torch.optim.SGD(net.parameters(), lr = 0.01)
# 先梯度清零(与net.zero_grad()效果一样)
optimizer.zero_grad()
loss.backward()
# 更新参数
optimizer.step()
Dataset是一个抽象类,为了能够方便的读取,需要将要使用的数据包装为Dataset类。
from torch.utils.data import Dataset
import pandas as pd
#定义一个数据集
class BulldozerDataset(Dataset):
""" 数据集演示 """
def __init__(self, csv_file):
"""实现初始化方法,在初始化的时候将数据读载入"""
self.df=pd.read_csv(csv_file)
def __len__(self):
'''
返回df的长度
'''
return len(self.df)
def __getitem__(self, idx):
'''
根据 idx 返回一行数据
'''
return self.df.iloc[idx].SalePrice
ds_demo= BulldozerDataset('median_benchmark.csv')
#实现了 __len__ 方法所以可以直接使用len获取数据总数
len(ds_demo)
#用索引可以直接访问对应的数据,对应 __getitem__ 方法
ds_demo[0]
对Dataset的读取操作,常用参数有:batch_size(每个batch的大小)、 shuffle(是否进行shuffle操作)、 num_workers(加载数据的时候使用几个子进程)。
dl = torch.utils.data.DataLoader(ds_demo, batch_size=10, shuffle=True, num_workers=0)
idata=iter(dl) # 获得dl一批数据
PyTorch中专门用来处理图像的库
PyTorch团队自定义的dataset,这些dataset帮我们提前处理好了很多的图片数据集
MNIST,COCO,Captions,Detection,LSUN,ImageFolder,Imagenet-12,CIFAR,STL10,SVHN,PhotoTour
import torchvision.datasets as datasets
trainset = datasets.MNIST(root='./data', # 表示 MNIST 数据的加载的目录
train=True, # 表示是否加载数据库的训练集,false的时候加载测试集
download=True, # 表示是否自动下载 MNIST 数据集
transform=None) # 表示是否需要对数据进行预处理,none为不进行预处理
不仅提供了常用图片数据集,还提供了训练好的模型
AlexNet,VGG,ResNet,SqueezeNet,DenseNet
import torchvision.models as models
resnet18 = models.resnet18(pretrained=True)
提供了一般的图像转换操作类,用作数据处理和数据增强
性回归分析:自变量与因变量关系可用一条线近似表示
l o s s ( x , y ) = 1 / n ∑ ∣ x i − y i ∣ loss(x,y)=1/n\sum|x_i-y_i| loss(x,y)=1/n∑∣xi−yi∣
用于多分类的负对数似然损失函数
l o s s ( x , c l a s s ) = − x [ c l a s s ] loss(x, class) = -x[class] loss(x,class)=−x[class]
如果传递了weights参数,会对损失进行加权
l o s s ( x , c l a s s ) = − w e i g h t s [ c l a s s ] ∗ x [ c l a s s ] loss(x, class) = -weights[class] * x[class] loss(x,class)=−weights[class]∗x[class]
l o s s ( x , y ) = 1 / n ∑ ( x i − y i ) 2 loss(x,y)=1/n\sum(x_i-y_i)^2 loss(x,y)=1/n∑(xi−yi)2
多分类用的交叉熵损失函数,LogSoftMax和NLLLoss集成到一个类中,会调用nn.NLLLoss函数,我们可以理解为CrossEntropyLoss()=log_softmax() + NLLLoss()
l o s s ( x , c l a s s ) = − log e x p ( x [ c l a s s ] ) ∑ j e x p ( x [ j ] ) ) = − x [ c l a s s ] + l o g ( ∑ j e x p ( x [ j ] ) ) \begin{aligned} loss(x, class) &= -\text{log}\frac{exp(x[class])}{\sum_j exp(x[j]))}\ &= -x[class] + log(\sum_j exp(x[j])) \end{aligned} loss(x,class)=−log∑jexp(x[j]))exp(x[class]) =−x[class]+log(j∑exp(x[j]))
计算 x 与 y 之间的二进制交叉熵。
l o s s ( o , t ) = − 1 n ∑ i ( t [ i ] ∗ l o g ( o [ i ] ) + ( 1 − t [ i ] ) ∗ l o g ( 1 − o [ i ] ) ) loss(o,t)=-\frac{1}{n}\sum_i(t[i]* log(o[i])+(1-t[i])* log(1-o[i])) loss(o,t)=−n1i∑(t[i]∗log(o[i])+(1−t[i])∗log(1−o[i]))
与NLLLoss类似,也可以添加权重参数
l o s s ( o , t ) = − 1 n ∑ i w e i g h t s [ i ] ∗ ( t [ i ] ∗ l o g ( o [ i ] ) + ( 1 − t [ i ] ) ∗ l o g ( 1 − o [ i ] ) ) loss(o,t)=-\frac{1}{n}\sum_iweights[i]* (t[i]* log(o[i])+(1-t[i])* log(1-o[i])) loss(o,t)=−n1i∑weights[i]∗(t[i]∗log(o[i])+(1−t[i])∗log(1−o[i]))
几何上讲,梯度就是函数变化增加最快的地方,沿着梯度向量的方向,更加容易找到函数的最大值。反过来说,沿着梯度向量相反的方向梯度减少最快,也就是更加容易找到函数的最小值。
如果训练数据集很大的时候处理速度会很慢,而且也不可能一次的载入到内存或者显存中,所以我们会把大数据集分成小数据集,一部分一部分的训练,这个训练子集即称为Mini-batch。
一个实现了各种优化算法的库。
不推荐
torch.optim.SGD(params,lr=<requiredparameter>,momentum=0,dampening=0,weight_decay=0,nesterov=False)
很少见
torch.optim.ASGD(params, lr=0.01, lambd=0.0001, alpha=0.75, t0=1000000.0, weight_decay=0)
优点:它可以自动调节学习率,不需要人为调节
缺点:仍依赖于人工设置一个全局学习率,随着迭代次数增多,学习率会越来越小,最终会趋近于0
不推荐
torch.optim.Adagrad(params, lr=0.01, lr_decay=0, weight_decay=0)
是Adagard的改进版,对学习率进行自适应约束,但是进行了计算上的简化,加速效果不错,训练速度快
优点:避免在训练后期,学习率过小;初期和中期,加速效果不错,训练速度快
缺点:还是需要自己手动指定初始学习率,初始梯度很大的话,会导致整个训练过程的学习率一直很小,在模型训练的后期,模型会反复地在局部最小值附近抖动,从而导致学习时间变长
可以试一试更好的
torch.optim.Adadelta(params, lr=1.0, rho=0.9, eps=1e-06, weight_decay=0)
不推荐优化方法适用于full-batch,不适用于mini-batch,因此基本上没什么用
torch.optim.Rprop(params, lr=0.01, etas=(0.5, 1.2), step_sizes=(1e-06, 50))
RProp的改进版,也是Adagard的改进版
优点:可缓解Adagrad学习率下降较快的问题,并且引入均方根,可以减少摆动,适合处理非平稳目标,对于RNN效果很好
缺点:依然依赖于全局学习率
推荐
torch.optim.RMSprop(params, lr=0.01, alpha=0.99, eps=1e-08, weight_decay=0, momentum=0, centered=False)
将Momentum算法和RMSProp算法结合起来使用的一种算法
基本上是最最常用的优化方法
torch.optim.Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0)
Adam的改进版,对Adam增加了一个学习率上限的概念
是Adam的一个变种,差不了多少
torch.optim.Adamax(params, lr=0.002, betas=(0.9, 0.999), eps=1e-08, weight_decay=0)
针对稀疏张量的一种“阉割版”Adam优化方法
推荐,在处理稀疏张量的时候尤其推荐
torch.optim.SparseAdam(params,lr=0.001,betas=(0.9,0.999),eps=1e-08)
Adam的进化版,是目前训练神经网络最快的方式
优点:比Adam收敛得更快
缺点:只有fastai使用,缺乏广泛的框架,而且也具有很大的争议性
torch.optim.AdamW(params,lr=0.001,betas=(0.9,0.999),eps=1e-08,weight_decay=0.01,amsgrad=False)
torch.optim.LBFGS(params, lr=1, max_iter=20, max_eval=None, tolerance_grad=1e-05, tolerance_change=1e-09, history_size=100,line_search_fn=None)
高偏差:(错误值过多)欠拟合。
增加网络结构,如增加隐藏层数目。
训练更长时间。
寻找合适的网络架构,使用更大的NN结构。
高方差:(将偏离过多的量拟合)过拟合。
使用更多的数据。
正则化( regularization)。
寻找合适的网络结构。
减小方差的策略。
torch.optim集成的`优化器只有L2正则化方法
将神经元拼接起来,两层神经元,即输入层+输出层(M-P神经元),构成感知机。输入层与输出层之间的所有层神经元,称为隐藏层
激活函数都是非线性的
a = 1 1 + e − z a=\frac{1}{1+e^{-z}} a=1+e−z1 导数 : a ′ = a ( 1 − a ) a^\prime =a(1 - a) a′=a(1−a)