Tiiktak's

Pytorch中的激活函数

介绍神经网络的时候已经说到,神经元会对化学物质的刺激进行,当达到一定程度的时候,神经元才会兴奋,并向其他神经元发送信息。神经网络中的激活函数就是用来判断我们所计算的信息是否达到了往后面传输的条件。 为什么激活函数都是非线性的 因为如果使用线性的激活函数,那么input跟output之间的关系始终为线性的,这样完全可以不使用网络结构,直接使用线性组合即可。 所以需要激活函数来引入非线性因素,使得神经网络可以任意逼近任何非线性函数,这样神经网络就可以应用到众多的非线性模型中,增加了神经网络模型泛化的特性。 一般只有在输出层有极小的可能性使用线性激活函数,在隐含层都使用非线性激活函数. 常见的激活函数 # 初始化一些信息 import torch import torch.nn.functional as F import matplotlib.pyplot as plt import numpy as np x= torch.linspace(-10,10,60) Sigmoid 函数 g(z) = a = 1 / (1 + e^(-z)) g'(z) = a' = a (1 - a) 在sigmod函数中我们可以看到,其输出是在(0,1)这个开区间,它能够把输入的连续实值变换为0和1之间的输出,如果是非常大的负数,那么输出就是0;如果是非常大的正数输出就是1,起到了抑制的作用。 ax = plt.gca() ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') ax.xaxis.set_ticks_position('bottom') ax.spines['bottom'].set_position(('data', 0)) ax.yaxis.set_ticks_position('left') ax.spines['left'].set_position(('data', 0)) plt.ylim((0, 1)) sigmod=torch.sigmoid(x) plt.plot(x.numpy(),sigmod.numpy()) 但是sigmod由于需要进行指数运算(这个对于计算机来说是比较慢,相比relu),再加上函数输出*不是以0为中心*的(这样会使权重更新效率降低),当输入稍微远离了坐标原点,函数的梯度就变得很小了(几乎为零)。 在神经网络反向传播的过程中不利于权重的优化,这个问题叫做梯度饱和,也可以叫梯度弥散。这些不足,所以现在使用到sigmod基本很少了,基本上只有在做二元分类(0,1)时的输出层才会使用。 Tanh 函数 tanh是双曲正切函数,输出区间是在(-1,1)之间,而且整个函数是*以0为中心*的 ax = plt....

Pytorch中的梯度下降及优化

在PyTorch中使用Mini-batch这种方法进行训练 Mini-batch的梯度下降法 对整个训练集进行梯度下降法的时候,我们必须处理整个训练数据集,然后才能进行一步梯度下降,即每一步梯度下降法需要对整个训练集进行一次处理,如果训练数据集很大的时候处理速度会很慢,而且也不可能一次的载入到内存或者显存中 所以我们会把大数据集分成小数据集,一部分一部分的训练,这个训练子集即称为Mini-batch。 对于普通的梯度下降法,一个epoch只能进行一次梯度下降;而对于Mini-batch梯度下降法,一个epoch可以进行Mini-batch的个数次梯度下降。 普通的batch梯度下降法和Mini-batch梯度下降法代价函数的变化趋势,如下图所示: 如果训练样本的大小比较小时,能够一次性的读取到内存中,那我们就不需要使用Mini-batch 如果训练样本的大小比较大时,一次读入不到内存或者现存中,那我们必须要使用 Mini-batch来分批的计算 Mini-batch size的计算规则如下,在内存允许的最大情况下使用2的N次方个size torch.optim torch.optim是一个实现了各种优化算法的库。大部分常用优化算法都有实现 torch.optim.SGD Stochastic Gradient Descent 随机梯度下降算法,带有动量(momentum)的算法作为一个可选参数可以进行设置 可以把动量看作惯性:当你跑起来,由于惯性的存在你跑起来会比刚起步加速的时候更轻松,当你跑过头,想调头往回跑,惯性会让你拖着你。 在普通的梯度下降法的方向相同,则会加速。反之,则会减速。 加了动量的优势: 1. 加速收敛 2. 提高精度(减少收敛过程中的振荡) SGD(params, lr=<required parameter>, momentum=0, dampening=0, weight_decay=0, nesterov=False) torch.optim.RMSprop Root Mean Square Prop 均方根传递。也是一种可以*加快梯度下降*的算法,利用RMSprop算法,可以减小某些维度梯度更新波动较大的情况,使其梯度下降的速度变得更快 相较于gradient descent with momentum,RMSprop的思想是: * 对于梯度震动较大的项,在下降时,减小其下降速度; * 对于震动幅度小的项,在下降时,加速其下降速度。 torch.optim.Adam Adam 优化算法的基本思想就是将 Momentum 和 RMSprop 结合起来形成的一种适用于不同深度学习结构的优化算法 它能基于训练数据迭代地更新神经网络权重 详细介绍 e.d. # 这里的lr,betas,还有eps都是用默认值即可,所以Adam是一个使用起来最简单的优化方法 optimizer = torch....

Pytorch中的损失函数Loss Function

由于Pytorch中使用mini-batch进行计算,因此其损失函数的计算结果会对mini-batch取平均 常见的Pytorch中内置的损失函数有: nn.L1Loss 计算input与output的差的绝对值,input与output应该是同一维度,得到的loss也是相应维度 nn.NLLLoss Negative Log Likelihood class torch.nn.NLLLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='mean') 常用于多分类任务。在NLLLoss输入input之前,我们需要对input进行log_softmax处理(即将input转换成概率分布的形式,并且取对数,底数为e) 计算公式 loss(input, class) = -input[class] NLLLoss中如果传递了weight参数,会对损失进行加权,公式就变成了 loss(input, class) = -weight[class] * input[class] nn.MSELoss Mean Square Error 计算input与ouput之间的均方差 nn.CrossEntropyLoss 多分类用的交叉熵损失合函数,将LogSoftMax和nn.NLLLoss集成到一个类中,nn.CrossEntropyLoss可以自动对input进行logSoftMax操作,可以理解为CrossEntropyLoss()=log_softmax() + NLLLoss() 传入weight参数后 一般多分类的情况会使用这个损失函数 nn.BCELoss Binary Cross Entropy 计算input与output之间的二进制交叉熵 添加weight后 用的时候需要在该层前面加上 Sigmoid 函数...

Pytorch_数据集的创建和加载

PyTorch通过torch.utils.data对一般常用的数据加载进行了封装,可以很容易地实现多线程数据预读和批量加载。 可以通过dataset定义数据集,并使用Datalorder载入和遍历数据集 Dataset Dataset是一个抽象类,为了能够方便的读取,需要将要使用的数据包装为Dataset类。 自定义的Dataset需要继承它并且实现两个成员方法: __getitem__() 该方法定义用索引(0 到 len(self))获取一条数据或一个样本 __len__() 该方法返回数据集的总长度 下面使用kaggle上的一个竞赛bluebook for bulldozers自定义一个数据集,用里面的数据字典来做说明(因为条数少) 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) # 返回df的长度 def __len__(self): return len(self.df) # 根据 idx 返回一行数据 def __getitem__(self, idx): return self.df.iloc[idx].SalePrice 至此,我们的数据集已经定义完成了,我们可以实例话一个对象访问他 ds_demo = BulldozerDataset('median_benchhmark.csv') print(len(ds_demo)) # 11573 print(ds_demo[0]) # 24000.0 Dataloader DataLoader为我们提供了对Dataset的读取操作,常用参数有:batch_size(每个batch的大小)、 shuffle(是否进行shuffle操作)、 num_workers(加载数据的时候使用几个子进程)。下面做一个简单的操作 dl = torch.utils.data.DataLoader(ds_demo, batch_size=10, shuffle=True, num_workers=0) DataLoader返回的是一个可迭代对象,我们可以使用迭代器分次获取数据...

Pytorch_torchvision

torchvision.models torchvision不仅提供了常用图片数据集,还提供了训练好的模型,可以加载之后,直接使用,或者在进行迁移学习 torchvision.models模块的 子模块中包含以下模型结构。 - AlexNet - VGG - ResNet - SqueezeNet - DenseNet torchvision.datasets 这其中所有的数据集都是torch.utils.data.Dataset的子类,它们都具有__getitem__和__len__实现的方法。因此,它们都可以传递给torch.utils.data.DataLoader,它使用torch.multiprocessing并行加载多个样本。 torchvision.transforms 提供了一般的图像转换操作类,用作数据处理和数据增强 其中都是常见的图像转换,可以通过Compose将他们链接在一起 from torchvision import transforms as transforms transform = transforms.Compose([ transforms.RandomCrop(32, padding=4), #先四周填充0,在把图像随机裁剪成32*32 transforms.RandomHorizontalFlip(), #图像一半的概率翻转,一半的概率不翻转 transforms.RandomRotation((-45,45)), #随机旋转 transforms.ToTensor(), transforms.Normalize((0.4914, 0.4822, 0.4465), (0.229, 0.224, 0.225)), #R,G,B每层的归一化用到的均值和方差 ]) 此外还有torchvision.transforms.functional模块,可对转换进行细粒度控制,这对于要构建一个更复杂的 transformation pipeline(例如在segmentation tasks分段任务中)很有帮助 torchvision.transforms.Normalize(mean, std, inplace=False) 用均值和标准差对张量图像进行归一化。 给定n个通道的均值: (M1,...,Mn) 和标准差:(S1,..,Sn), 这个转换将归一化输入torch.*Tensor的每个通道。例如: input[channel] = (input[channel] - mean[channel]) / std[channel] Note: 这种变换的作用不适当,即它不会改变输入张量 torchvision.utils torchvision....

Pytorch学习笔记_4_训练一个分类器

关于数据 一般来说,对于图像、文本、音频或视频数据,可以使用标准的Python包来将这些数据加载为numpy array,之后可以将这些array转换为torch.*Tensor 对于图像,Pillow、OpenCV包 音频,scipy、librosa包 文本,可以使用原始Python和Cython加载,或NLKT和SpaCy 特别的,对于视觉任务,有一个包torchvision,其中包含了处理类似Imagnet, CIFAR10, MNIST等常见数据集的方法,以及图像转换器,如torchvision.datasets和torch.utils.data.DataLoader torchvision包不仅提供了巨大的便利,也避免了代码的重复。 在这里使用CIFAR10数据集,它有如下10个类别 :‘airplane’, ‘automobile’, ‘bird’, ‘cat’, ‘deer’, ‘dog’, ‘frog’, ‘horse’, ‘ship’, ‘truck’。 CIFAR-10的图像都是 3x32x32 大小的,即,3颜色通道,32x32像素。 训练一个图像分类器 使用torchvision加载和归一化CIFAR10训练集和测试集 定义一个卷积神经网络 定义损失函数 用训练集训练网络 用测试集测试网络 1.读取和归一化 CIFAR10 使用torchvision可以非常容易得加载CIFAR10 import torch import torchvision import torchvision.transforms as transforms torchvision的输出是 [0,1]的PILImage图像,把它转化为归一化范围为[-1, 1]的张量 transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) # 下载数据并加载到loader中 trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform) trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2) testset = torchvision....

Pytorch_linear

Linear 对输入数据应用线性变换:y = xA^T + b torch.nn.Linear(in_features, out_features, bias=True) 参数 in_features 每个输入样本的大小 out_features 每个输出样本的大小 bias 若为False,layer不会学习附加偏差b shape 输入: (N, ∗, H_in),其中 ∗ 代表任意数量的附加维度,H_in = in_features 输出: (N, *, H_out),除了最后一个维度,其余都与输入相同,H_out = out_features ...

Pytorch_nn.Conv2d

Conv2d torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros') in_channels 输入数据通道数 out_channels 输出数据通道数 kennel_size 卷积核大小,int或tuple stride 步长 padding 每个维度零填充的数量 dilation 内核点之间的距离,也称à trous algorithm groups 控制inputs与outputs间的连接 > * groups=1,所有输入都卷积到输出 > * groups=2,并排设置两个conv层,每个层查看一半的输入通道,并生成一半的输出通道,然后将两者连接起来 > * groups=in_channels,每个输入通道都有它自己的filter,size为[out_channels/in_channels] ...

Python面向对象_super()函数

super() super()是用于调用父类(超类)的一个方法 用于解决多重继承问题:直接用类名调用父类方法在使用单继承时没有问题,但若使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等问题 MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。 语法 super(type[, object-or-type]) 参数 type 类 object-or-type 类,一般是self 在 Python3 中:super().xxx 在 Python2 中:super(Class, self).xxx 两者等价 示例 class Bird: def __init__(self): self.hungry = True def eat(self): if self.hungry: print('Ahahahah') else: print('No thanks!') class SongBird(Bird): def __init__(self): self.sound = 'Squawk' def sing(self): print(self.sound) sb = SongBird() sb.sing() # 能正常输出'Squawk' sb.eat() # 报错,因为 SongBird 中没有 hungry 特性 使用super解决:...

Pytorch学习笔记_3_构建一个神经网络

Neural Networks 神经网络可以通过使用torch.nn包来创建 nn依赖于autograd来定义模型并求导。 一个nn.Module类包含各个层和一个forward(input)前向传播方法,该方法返回output 例如这个分类数字图像的网络: 这是个简单的前馈神经网络,它接受一个输入,然后一层接一层的传递,最后输出计算结果 一个神经网络的典型训练过程: 定义包含一些可学习的参数(或权重)的神经网络 在数据集上迭代 通过神经网络处理输入 计算损失函数(预测值与实际值的差值大小) 将梯度反向传播回网络的参数 更新网络参数,主要使用一个简单的更新法则:weight = weight - learning_rate * gradient 另参见:konosuba.xyz/blog/%E8%AE%AD%E7%BB%83%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C%E7%9A%84%E5%9F%BA%E6%9C%AC%E6%AD%A5%E9%AA%A4 定义网络 import torch import torch.nn as nn import torch.nn.functional as F class Net(nn.Module): def __init__(self): # 构造方法 super().__init__() # 复制并使用Net的父类的初始化方法,即先运行nn.Module的初始化函数 # 卷积层 self.conv1 = nn.Conv2d(1, 6, 5) self.conv2 = nn.Conv2d(6, 16, 5) # fc(full_connect)全连接函数,均为线性函数 y = Wx + b self....