深度学习之PyTorch实战计算机视觉2

自动梯度torch.autograd和Variable

torch.autograd包的主要功能是完成神经网络后向传播中的链式求导,实现自动梯度功能的过程大致为:先通过输入的Tensor数据类型的变量在神经网络的前向传播过程中生成一张计算图,然后根据这个计算图和输出结果准确计算出每个参数需要更新的梯度,并通过完成后向传播完成对参数的梯度更新。
在实践中完成自动梯度需要用到torch.autograd包中的Variable类对我们定义的Tensor数据类型变量进行封装,在封装后,计算图中的各个节点就是一个Variable对象,这样才能应用自动梯度的功能。
那么X.data代表Tensor数据类型的变量,X.grad也是一个Variable对象,不过它表示的是X的梯度,在想访问梯度值时需要使用X.grad.data。
“Variable(torch.randn(batch_n, input_data), requires_grad = False)”这段代码就是之前讲到的用 Variable类对 Tensor数据类型变量进行封装的操作。在以上代码中还使用了一个requires_grad参数,这个参数的赋值类型是布尔型,如果requires_grad的值是False,那么表示该变量在进行自动梯度计算的过程中不会保留梯度值。我们将输入的数据x和输出的数据y的requires_grad参数均设置为False,这是因为这两个变量并不是我们的模型需要优化的参数,而两个权重w1和w2的requires_grad参数的值为True。
loss.backward(),这个函数的功能在于让模型根据计算图自动计算每个节点的梯度值并根据需求进行保留,有了这一步,我们的权重参数w1.data和 w2.data就可以直接使用在自动梯度过程中求得的梯度值w1.data.grad和w2.data.grad,并结合学习速率来对现有的参数进行更新、优化了。在代码的最后还要将本次计算得到的各个参数节点的梯度值通过grad.data.zero_()全部置零,如果不置零,则计算的梯度值会被一直累加,这样就会影响到后续的计算。同样,在整个模型的训练和优化过程中,每个循环都加入了打印loss值的操作

自定义传播函数



import torch
from torch.autograd import Variable
batch_n = 64
hidden_layer = 100
input_data = 1000
output_data = 10
#通过class Model(torch.nn.Module)完成了类继承的操作
class Model(torch.nn.Module):
    def __init__(self):
        super(Model,self).__init__()
    #forward函数实现了模型的前向传播中的矩阵运算
    def forward(self,input,w1,w2):
        x = torch.mm(input,w1)
        x = torch.clamp(x,min=0)
        x= torch.mm(x,w2)
        return x
    #backward实现了模型的后向传播中的自动梯度计算
    def backward(self):
        pass
#调用
model = Model()
x = Variable(torch.randn(batch_n,input_data),requires_grad=False)
y = Variable(torch.randn(batch_n,output_data),requires_grad=False)
w1 = Variable(torch.randn(input_data,hidden_layer),requires_grad=True)
w2 = Variable(torch.randn(hidden_layer,output_data),requires_grad=True)

epoch_n = 30
learning_rate = 1e-6
for epoch in range(epoch_n):
    y_pred = model(x,w1,w2)
    loss = (y_pred-y).pow(2).sum()
    print("Epoch:{},Loss:{:.4f}".format(epoch,loss.data))
    loss.backward()
    w1.data -= learning_rate * w1.grad.data
    w2.data -= learning_rate * w2.grad.data
    w1.grad.data.zero_()
    w2.grad.data.zero_()

输出结果

Epoch:0,Loss:26221274.0000
Epoch:1,Loss:20603464.0000
Epoch:2,Loss:18612060.0000
Epoch:3,Loss:17337622.0000
Epoch:4,Loss:15648332.0000
Epoch:5,Loss:13005498.0000
Epoch:6,Loss:9988581.0000
Epoch:7,Loss:7071273.5000
Epoch:8,Loss:4782064.5000
Epoch:9,Loss:3150822.5000
Epoch:10,Loss:2094325.3750
Epoch:11,Loss:1424698.5000
Epoch:12,Loss:1008405.1875
Epoch:13,Loss:744257.1250
Epoch:14,Loss:572528.4375
Epoch:15,Loss:456056.8750
Epoch:16,Loss:373789.3125
Epoch:17,Loss:313048.3750
Epoch:18,Loss:266437.3750
Epoch:19,Loss:229543.7812
Epoch:20,Loss:199547.0938
Epoch:21,Loss:174697.8281
Epoch:22,Loss:153759.8438
Epoch:23,Loss:135922.7656
Epoch:24,Loss:120608.9844
Epoch:25,Loss:107367.8672
Epoch:26,Loss:95839.7656
Epoch:27,Loss:85756.5469
Epoch:28,Loss:76903.7969
Epoch:29,Loss:69101.1797

模型搭建和参数优化

PyTorch之torch.nn

(1)torch.nn.Sequential:torch.nn.Sequential类是torch.nn中的一种
序列容器,通过在容器中嵌套各种实现神经网络中具体功能相关的类,
来完成对神经网络模型的搭建,最主要的是,参数会按照我们定义好的
序列自动传递下去。我们可以将嵌套在容器中的各个部分看作各种不同
的模块,这些模块可以自由组合。模块的加入一般有两种方式,一种是
在以上代码中使用的直接嵌套,另一种是以orderdict有序字典的方式进
行传入,这两种方式的唯一区别是,使用后者搭建的模型的每个模块都
有我们自定义的名字,而前者默认使用从零开始的数字序列作为每个模
块的名字。下面通过示例来直观地看一下使用这两种方式搭建的模型之
间的区别。
使用直接嵌套搭建的模型代码如下:

import torch
from torch.autograd import Variable

batch_n=100
hidden_layer = 100
input_data = 1000
output_data = 10

x = Variable(torch.randn(batch_n,input_data),requires_grad=False)
y = Variable(torch.randn(batch_n,output_data),requires_grad=False)

#torch.nn.Sequential括号内的内容就是我们搭建的神经网络模型的具体结构
models = torch.nn.Sequential(
    #首先通过torch.nn.Linear(input_data, hidden_layer)完成从输入层到隐藏层的线性变换
    torch.nn.Linear(input_data,hidden_layer),
    #然后经过激活函数及torch.nn.Linear(hidden_layer, output_data)
    # 完成从隐藏层到输出层的线性变换
    torch.nn.ReLU(),
    torch.nn.Linear(hidden_layer,output_data)
)
print(models)

结果:

Sequential(
  (0): Linear(in_features=1000, out_features=100, bias=True)
  (1): ReLU()
  (2): Linear(in_features=100, out_features=10, bias=True)
)

使用orderdict有序字典进行传入来搭建的模型代码:

import torch
from torch.autograd import Variable
from collections import OrderedDict
batch_n=100
hidden_layer = 100
input_data = 1000
output_data = 10

x = Variable(torch.randn(batch_n,input_data),requires_grad=False)
y = Variable(torch.randn(batch_n,output_data),requires_grad=False)

#torch.nn.Sequential括号内的内容就是我们搭建的神经网络模型的具体结构
models = torch.nn.Sequential(OrderedDict([
#首先通过torch.nn.Linear(input_data, hidden_layer)完成从输入层到隐藏层的线性变换
    ("Line1",torch.nn.Linear(input_data,hidden_layer)),
    #然后经过激活函数及torch.nn.Linear(hidden_layer, output_data)
    # 完成从隐藏层到输出层的线性变换
    ("Relu1",torch.nn.ReLU()),
    ("line2",torch.nn.Linear(hidden_layer,output_data))
])

)
print(models)

结果:

Sequential(
  (Line1): Linear(in_features=1000, out_features=100, bias=True)
  (Relu1): ReLU()
  (line2): Linear(in_features=100, out_features=10, bias=True)
)

(2)torch.nn.Linear:torch.nn.Linear类用于定义模型的线性层,
即完成前面提到的不同的层之间的线性变换。torch.nn.Linear类接收的参
数有三个,分别是输入特征数、输出特征数和是否使用偏置,设置是否
使用偏置的参数是一个布尔值,默认为True,即使用偏置。在实际使用
的过程中,我们只需将输入的特征数和输出的特征数传递给
torch.nn.Linear类,就会自动生成对应维度的权重参数和偏置,对于生成
的权重参数和偏置,我们的模型默认使用了一种比之前的简单随机方式
更好的参数初始化方法。
根据我们搭建模型的输入、输出和层次结构需求,它的输入是在一
个批次中包含100个特征数为1000的数据,最后得到100个特征数为10的
输出数据,中间需要经过两次线性变换,所以要使用两个线性层,两个
线性层的代码分别是torch.nn.Linear(input_data,hidden_layer)和
torch.nn.Linear(hidden_layer, output_data)。可看到,其代替了之前使用
矩阵乘法方式的实现,代码更精炼、简洁。
(3)torch.nn.ReLU:torch.nn.ReLU类属于非线性激活分类,在定
义时默认不需要传入参数。当然,在 torch.nn包中还有许多非线性激活
函数类可供选择,比如之前讲到的PReLU、LeakyReLU、Tanh、
Sigmoid、Softmax等。

损失函数

(1)torch.nn.MSELoss:torch.nn.MSELoss类使用均方误差函数对
损失值进行计算,在定义类的对象时不用传入任何参数,但在使用实例
时需要输入两个维度一样的参数方可进行计算
(2)torch.nn.L1Loss:torch.nn.L1Loss类使用平均绝对误差函数对
损失值进行计算,同样,在定义类的对象时不用传入任何参数,但在使
用实例时需要输入两个维度一样的参数进行计算
(3)torch.nn.CrossEntropyLoss:torch.nn.CrossEntropyLoss类用
于计算交叉熵,在定义类的对象时不用传入任何参数,在使用实例时需
要输入两个满足交叉熵的计算条件的参数

import torch
from torch.autograd import Variable
from collections import OrderedDict
batch_n=100
hidden_layer = 100
input_data = 1000
output_data = 10

x = Variable(torch.randn(batch_n,input_data),requires_grad=False)
y = Variable(torch.randn(batch_n,output_data),requires_grad=False)

#torch.nn.Sequential括号内的内容就是我们搭建的神经网络模型的具体结构
models = torch.nn.Sequential(OrderedDict([
#首先通过torch.nn.Linear(input_data, hidden_layer)完成从输入层到隐藏层的线性变换
    ("Line1",torch.nn.Linear(input_data,hidden_layer)),
    #然后经过激活函数及torch.nn.Linear(hidden_layer, output_data)
    # 完成从隐藏层到输出层的线性变换
    ("Relu1",torch.nn.ReLU()),
    ("line2",torch.nn.Linear(hidden_layer,output_data))
])

)
epoch_n = 10000
learning_rate = 1e-4
loss_fn = torch.nn.MSELoss()

for epoch in range(epoch_n):
    y_pred = models(x)
    loss = loss_fn(y_pred,y)
    if epoch%1000==0:
        print("Epoch:{},Loss:{:.4f}".format(epoch,loss.data))
    models.zero_grad()
    loss.backward()
    for param in models.parameters():
        param.data -= param.grad.data*learning_rate


结果:

Epoch:0,Loss:1.0735
Epoch:1000,Loss:0.9964
Epoch:2000,Loss:0.9298
Epoch:3000,Loss:0.8706
Epoch:4000,Loss:0.8175
Epoch:5000,Loss:0.7695
Epoch:6000,Loss:0.7255
Epoch:7000,Loss:0.6851
Epoch:8000,Loss:0.6474
Epoch:9000,Loss:0.6120

PyTorch之torch.optim

在PyTorch的torch.optim包中提供了非常多的
可实现参数自动优化的类,比如SGD、AdaGrad、RMSProp、Adam等,
这些类都可以被直接调用,使用起来也非常方便

import torch
from torch.autograd import Variable
from collections import OrderedDict
batch_n=100
hidden_layer = 100
input_data = 1000
output_data = 10

x = Variable(torch.randn(batch_n,input_data),requires_grad=False)
y = Variable(torch.randn(batch_n,output_data),requires_grad=False)

#torch.nn.Sequential括号内的内容就是我们搭建的神经网络模型的具体结构
models = torch.nn.Sequential(OrderedDict([
#首先通过torch.nn.Linear(input_data, hidden_layer)完成从输入层到隐藏层的线性变换
    ("Line1",torch.nn.Linear(input_data,hidden_layer)),
    #然后经过激活函数及torch.nn.Linear(hidden_layer, output_data)
    # 完成从隐藏层到输出层的线性变换
    ("Relu1",torch.nn.ReLU()),
    ("line2",torch.nn.Linear(hidden_layer,output_data))
])

)
epoch_n = 100
learning_rate = 1e-4
loss_fn = torch.nn.MSELoss()
optimzer = torch.optim.Adam(models.parameters(),lr = learning_rate)
for epoch in range(epoch_n):
    y_pred = models(x)
    loss = loss_fn(y_pred,y)
    print("Epoch:{},Loss:{:.4f}".format(epoch,loss.data))
    optimzer.zero_grad()
    loss.backward()
    optimzer.step()

这里使用了torch.optim包中的torch.optim.Adam类作为我们的模型参
数的优化函数,在torch.optim.Adam类中输入的是被优化的参数和学习
速率的初始值,如果没有输入学习速率的初始值,那么默认使用0.001
这个值。因为我们需要优化的是模型中的全部参数,所以传递给
torch.optim.Adam类的参数是models.parameters。另外,Adam优化函数
还有一个强大的功能,就是可以对梯度更新使用到的学习速率进行自适
应调节,所以最后得到的结果自然会比之前的代码更理想。
结果:

Epoch:0,Loss:1.0281
Epoch:1,Loss:1.0067
Epoch:2,Loss:0.9858
Epoch:3,Loss:0.9653
Epoch:4,Loss:0.9453
Epoch:5,Loss:0.9259
Epoch:6,Loss:0.9068
Epoch:7,Loss:0.8881
Epoch:8,Loss:0.8698
Epoch:9,Loss:0.8520
Epoch:10,Loss:0.8346
Epoch:11,Loss:0.8177
Epoch:12,Loss:0.8012
Epoch:13,Loss:0.7850
Epoch:14,Loss:0.7693
Epoch:15,Loss:0.7539
Epoch:16,Loss:0.7389
Epoch:17,Loss:0.7242
Epoch:18,Loss:0.7098
Epoch:19,Loss:0.6957
Epoch:20,Loss:0.6818
Epoch:21,Loss:0.6683
Epoch:22,Loss:0.6551
Epoch:23,Loss:0.6422
Epoch:24,Loss:0.6295
Epoch:25,Loss:0.6171
Epoch:26,Loss:0.6049
Epoch:27,Loss:0.5931
Epoch:28,Loss:0.5814
Epoch:29,Loss:0.5700
Epoch:30,Loss:0.5588
Epoch:31,Loss:0.5478
Epoch:32,Loss:0.5370
Epoch:33,Loss:0.5264
Epoch:34,Loss:0.5161
Epoch:35,Loss:0.5059
Epoch:36,Loss:0.4959
Epoch:37,Loss:0.4861
Epoch:38,Loss:0.4765
Epoch:39,Loss:0.4671
Epoch:40,Loss:0.4578
Epoch:41,Loss:0.4487
Epoch:42,Loss:0.4397
Epoch:43,Loss:0.4309
Epoch:44,Loss:0.4222
Epoch:45,Loss:0.4137
Epoch:46,Loss:0.4053
Epoch:47,Loss:0.3971
Epoch:48,Loss:0.3890
Epoch:49,Loss:0.3811
Epoch:50,Loss:0.3733
Epoch:51,Loss:0.3656
Epoch:52,Loss:0.3580
Epoch:53,Loss:0.3506
Epoch:54,Loss:0.3433
Epoch:55,Loss:0.3361
Epoch:56,Loss:0.3290
Epoch:57,Loss:0.3221
Epoch:58,Loss:0.3153
Epoch:59,Loss:0.3085
Epoch:60,Loss:0.3019
Epoch:61,Loss:0.2955
Epoch:62,Loss:0.2891
Epoch:63,Loss:0.2828
Epoch:64,Loss:0.2767
Epoch:65,Loss:0.2706
Epoch:66,Loss:0.2647
Epoch:67,Loss:0.2589
Epoch:68,Loss:0.2531
Epoch:69,Loss:0.2475
Epoch:70,Loss:0.2420
Epoch:71,Loss:0.2365
Epoch:72,Loss:0.2312
Epoch:73,Loss:0.2260
Epoch:74,Loss:0.2209
Epoch:75,Loss:0.2158
Epoch:76,Loss:0.2109
Epoch:77,Loss:0.2060
Epoch:78,Loss:0.2012
Epoch:79,Loss:0.1965
Epoch:80,Loss:0.1919
Epoch:81,Loss:0.1874
Epoch:82,Loss:0.1830
Epoch:83,Loss:0.1786
Epoch:84,Loss:0.1743
Epoch:85,Loss:0.1701
Epoch:86,Loss:0.1660
Epoch:87,Loss:0.1620
Epoch:88,Loss:0.1580
Epoch:89,Loss:0.1541
Epoch:90,Loss:0.1503
Epoch:91,Loss:0.1466
Epoch:92,Loss:0.1430
Epoch:93,Loss:0.1394
Epoch:94,Loss:0.1359
Epoch:95,Loss:0.1324
Epoch:96,Loss:0.1291
Epoch:97,Loss:0.1258
Epoch:98,Loss:0.1225
Epoch:99,Loss:0.1194

在以上代码中有几处代码和之前的训练代码不同,这是因为我们引
入了优化算法,所以通过直接调用optimzer.zero_grad来完成对模型参数
梯度的归零;并且在以上代码中增加了optimzer.step,它的主要功能是
使用计算得到的梯度值对各个节点的参数进行梯度更新。

实战手写数字识别

先使用已经提供的训练数据对搭建好的神经网络模
型进行训练并完成参数优化;然后使用优化好的模型对测试数据进行预
测,对比预测值和真实值之间的损失值,同时计算出结果预测的准确
率。在将要搭建的模型中会用到卷积神经网络模型

torch.transforms

在PyTorch中实际进行计
算的是Tensor数据类型的变量,所以我们首先需要解决的是数据类型转
换的问题,如果获取的数据是格式或者大小不一的图片,则还需要进行
归一化和大小缩放等操作,庆幸的是,这些方法在torch.transforms中都
能找到。
在torch.transforms中有大量的数据变换类,其中有很大一部分可以
用于实现数据增强(Data Argumentation)。若在我们需要解决的问题上
能够参与到模型训练中的图片数据非常有限,则这时就要通过对有限的
图片数据进行各种变换,来生成新的训练集了,这些变换可以是缩小或
者放大图片的大小、对图片进行水平或者垂直翻转等,都是数据增强的
方法。不过在手写数字识别的问题上可以不使用数据增强的方法,因为
可用于模型训练的数据已经足够了
(1)torchvision.transforms.Resize:用于对载入的图片数据按我
们需求的大小进行缩放。传递给这个类的参数可以是一个整型数据,也
可以是一个类似于(h,w)的序列,其中,h代表高度,w代表宽度,但
是如果使用的是一个整型数据,那么表示缩放的宽度和高度都是这个整
型数据的值。
(2)torchvision.transforms.Scale:用于对载入的图片数据按我们
需求的大小进行缩放,用法和torchvision.transforms.Resize类似。
(3)torchvision.transforms.CenterCrop:用于对载入的图片以图
片中心为参考点,按我们需要的大小进行裁剪。传递给这个类的参数可
以是一个整型数据,也可以是一个类似于(h,w)的序列。
(4)torchvision.transforms.RandomCrop:用于对载入的图片按
我们需要的大小进行随机裁剪。传递给这个类的参数可以是一个整型数
据,也可以是一个类似于(h,w)的序列。
(5)torchvision.transforms.RandomHorizontalFlip:用于对载入
的图片按随机概率进行水平翻转。我们可以通过传递给这个类的参数自
定义随机概率,如果没有定义,则使用默认的概率值0.5。
(6)torchvision.transforms.RandomVerticalFlip:用于对载入的
图片按随机概率进行垂直翻转。我们可以通过传递给这个类的参数自定
义随机概率,如果没有定义,则使用默认的概率值0.5。
(7)torchvision.transforms.ToTensor:用于对载入的图片数据进
行类型转换,将之前构成PIL图片的数据转换成Tensor数据类型的变
量,让PyTorch能够对其进行计算和处理。
(8)torchvision.transforms.ToPILImage:用于将Tensor变量的数
据转换成PIL图片数据,主要是为了方便图片内容的显示

数据预览和数据装载

我们可以将数据的载入理解为对图片的处理,在处理完成后,我们就需要将这
些图片打包好送给我们的模型进行训练了,而装载就是这个打包的过
程。在装载时通过batch_size的值来确认每个包的大小,通过shuffle的值
来确认是否在装载的过程中打乱图片的顺序。
对数据的装载使用的是torch.utils.data.DataLoader类,类中的dataset
参数用于指定我们载入的数据集名称,batch_size参数设置了每个包中
的图片数据个数,代码中的值是64,所以在每个包中会包含64张图片。
将shuffle参数设置为True,在装载的过程会将数据随机打乱顺序并进行
打包。

import torch
from torch.autograd import Variable
from collections import OrderedDict
import torch.utils.data as Data
import torchvision
from torchvision import datasets,transforms
import matplotlib.pyplot as plt
data_train = datasets.MNIST(root = "./data/",
                            transform=transforms,
                            train = True,
                            download=True)
data_test = datasets.MNIST(root="./data/",
                           transform=transforms,
                           train = False)
transform = transforms.Compose([transforms.ToTensor(),
                                transforms.Normalize(mean = [0.5,0.5,0.5],std=
                                                     [0.5,0.5,0.5])])
data_loader_train = Data.DataLoader(dataset=data_train,
                                    batch_size = 64,
                                    shuffle=True)
data_loader_test = Data.DataLoader(dataset=data_test,
                                   batch_size=64,
                                   shuffle=True)
images,labels = next(iter(data_loader_train))
img = torchvision.utils.make_grid(images)
img = img.numpy().transpose(1,2,0)
std = [0.5,0.5,0.5]
mean = [0.5,0.5,0.5]
img = img*std+mean
print([labels[i] for i in range(64)])
plt.imshow(img)

class Model(torch.nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.conv1 = torch.nn.Sequential(torch.nn.Conv2d(1,64,kernel_size=3,stride=1,padding=1),
                                         torch.nn.ReLU(),
                                         torch.nn.Conv2d(64,128,kernel_size=3,stride=1,padding=1),
                                         torch.nn.ReLU(),
                                         torch.nn.MaxPool2d(stride=2,kernel_size=2))
        self.dense = torch.nn.Sequential(torch.nn.Linear(14*14*128,1024),
                                         torch.nn.ReLU(),
                                         torch.nn.Dropout(p=0.5),
                                         torch.nn.Linear(1024,10))
        def forward(self,x):
            x = self.conv1(x)
            x = x.view(-1,14*14*128)
            x = self.dense(x)
            return x
model = Model()
cost = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters())
n_epochs = 5
for epoch in range(n_epochs):
    running_loss = 0.0
    running_correct = 0
    print("Epoch {}/{}".format(epoch,n_epochs))
    print("-"*10)
    for data in data_loader_train:
        x_train,y_train =data
        x_train,y_train = Variable(x_train),Variable(y_train)
        outputs = model(x_train)
        _,pred = torch.max(outputs.data,1)
        optimizer.zero_grad()
        loss = cost(outputs,y_train)

        loss.backward()
        optimizer.step()
        running_loss += loss.data[0]
        running_correct += torch.sum(pred == y_train.data)
    testing_correct = 0
    for data in data_loader_test:
        x_test,y_test=data
        x_test,y_test=Variable(x_test),Variable(y_test)
        outputs = model(x_test)
        _,pred=torch.max(outputs.data,1)
        testing_correct += torch.sum(pred == y_test.data)
        print("Loss is:{:.4f},Train Accuracy is:{:.4f}%,Test Accuracy is :{:.4f}".format(running_loss/len(data_train),
              100*running_correct/len(data_train),100*testing_correct/len(data_test)))

使用了iter和next来获取一个批次的图片数据和其对应
的图片标签,然后使用torchvision.utils中的make_grid类方法将一个批次
的图片构造成网格模式。需要传递给torchvision.utils.make_grid的参数就
是一个批次的装载数据,每个批次的装载数据都是4维的,维度的构成
从前往后分别为batch_size、channel、height和weight,分别对应一个批
次中的数据个数、每张图片的色彩通道数、每张图片的高度和宽度。在
通过torchvision.utils.make_grid之后,图片的维度变成了
(channel,height,weight),这个批次的图片全部被整合到了一起,所以
在这个维度中对应的值也和之前不一样了,但是色彩通道数保持不变。
若我们想使用Matplotlib将数据显示成正常的图片形式,则使用的
数据首先必须是数组,其次这个数组的维度必须是
(height,weight,channel),即色彩通道数在最后面。所以我们要通过
numpy和transpose完成原始数据类型的转换和数据维度的交换,这样才
能够使用Matplotlib绘制出正确的图像。

模型搭建和参数优化

卷积层使用torch.nn.Conv2d类
方法来搭建;激活层使用 torch.nn.ReLU类方法来搭建;池化层使用
torch.nn.MaxPool2d类方法来搭建;全连接层使用torch.nn.Linear类方法
(1)torch.nn.Conv2d:用于搭建卷积神经网络的卷积层,主要的
输入参数有输入通道数、输出通道数、卷积核大小、卷积核移动步长和
Paddingde值。其中,输入通道数的数据类型是整型,用于确定输入数
据的层数;输出通道数的数据类型也是整型,用于确定输出数据的层
数;卷积核大小的数据类型是整型,用于确定卷积核的大小;卷积核移
动步长的数据类型是整型,用于确定卷积核每次滑动的步长;
Paddingde 的数据类型是整型,值为0时表示不进行边界像素的填充
如果值大于0,那么增加数字所对应的边界像素层数。
(2)torch.nn.MaxPool2d:用于实现卷积神经网络中的最大池化
层,主要的输入参数是池化窗口大小、池化窗口移动步长和Paddingde
值。同样,池化窗口大小的数据类型是整型,用于确定池化窗口的大
小。池化窗口步长的数据类型也是整型,用于确定池化窗口每次移动的
步长。Paddingde值和在torch.nn.Conv2d中定义的Paddingde值的用法和意
义是一样的。
(3)torch.nn.Dropout:torch.nn.Dropout类用于防止卷积神经网络
在训练的过程中发生过拟合,其工作原理简单来说就是在模型训练的过
程中,以一定的随机概率将卷积神经网络模型的部分参数归零,以达到
减少相邻两层神经连接的目的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值