以一个神经网络构建、前向计算、反向传播、和对验证集进行预测验证代码入手,理解每一步书写思路和过程。
一、神经网络构建
首先,先看一下第十二节中已经写过的深学习代码,以其中一维卷积神经网络构建为例
下面是对这段代码我自己的理解:
网络搭建
首先构造一个需要的神经网络类Net,让Net继承父类nn.Module中的方法,并且对其初始化和前向计算函数进行重写。
然后重写初始化函数,这个初始化函数不需要任何参数。Net()就可以初始化网络模型。
然后使用super()方法,重写父类中的__new__方法,即使用单例模式,首先在父类__new__方法中申请一片构造类的内存空间,然后返回一个引用给__init__方法,接下来就可以进行初始化了。
然后接下来在初始化方法里,增加类属性,如下面的self.conv1 = nn.Conv1d()就是为类里增加类属性,所以其实这里类属性只是调用了pytorch中已经写好的块或者类如第一个属性是一个类,这个类是一个一维卷积神经网络层,这个nn.Conv1d类中有前向传播的计算的类方法等。即初始化一个类(或者这里可以叫一个神经网络块,因为可以将这个块放在另一个大网络模型中)。其中类的属性是一个类、类本身也是一个类,我们构造的这个包含很多用类作为类属性的类,也可以作为另一个构造类的属性。
所以在初始化类属性时候,书写顺序其实无所谓,因为前向计算方法会定义函数先使用哪个层进行计算,顺序书写是为了我们看代码的方便性。
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv1d(in_channels=1, out_channels=16, kernel_size=3, stride=1, padding=1)
self.pool1 = nn.MaxPool1d(kernel_size=2, stride=2)
self.conv2 = nn.Conv1d(in_channels=16, out_channels=32, kernel_size=3, stride=1, padding=1)
self.pool2 = nn.MaxPool1d(kernel_size=2, stride=2)
self.fc1 = nn.Linear(32 * 140, 256)
self.fc2 = nn.Linear(256, 64)
self.fc3 = nn.Linear(64, 6)
def forward(self, x):
#将张量x的维度从(a,b)变成(a,1,b)。即在第二个维度上增加一个维度,使得原本的每个元素变为一个包含一个元素的张量。
x = x.unsqueeze(1)
x = self.conv1(x)
x = nn.functional.relu(x)
x = self.pool1(x)
x = self.conv2(x)
x = nn.functional.relu(x)
x = self.pool2(x)
x = x.view(-1, 32 * 140)
x = self.fc1(x)
x = nn.functional.relu(x)
x = self.fc2(x)
x = nn.functional.relu(x)
x = self.fc3(x)
return x
二、前向计算
forward函数,是一个我们定义的类的方法,这个方法需要一个张量x作为参数,然后就像函数一样,顺序执行,先将x传入self.conv1、然后调用relu函数,依次使用各个层的方法。
类似于sequential块中添加初始化属性。
三、反向传播和训练模型
首先需要定义损失函数和优化器
net = Net()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(), lr=0.001)
#模型训练
for epoch in range(50):
running_loss = 0.0
inputs=train_X
labels = train_Y
optimizer.zero_grad()
outputs = net(inputs)
loss = criterion(outputs, train_Y)
loss.backward()
optimizer.step()
running_loss += loss.item()
if(epoch%10==0):
print("第",epoch,"轮训练")
然后定义训练轮次,每轮都需要进行损失清零、关于传播的inputs的梯度清零。然后将inputs作为net
模型输入,进行前向计算,然后计算反向传播的损失,最后通过优化函数对模型内部计算参数的更新,即反向传播。
使用模型验证或者预测
将测试的数据传入训练好的模型,进行预测前向计算。
_, predicted = torch.max(outputs.data, 1)这个的作用是,将输出数据的值给到value,然后将标签值传给predicted,1代表维度是1。
#模型预测
with torch.no_grad():
inputs=test_X
outputs = net(inputs)
_, predicted = torch.max(outputs.data, 1)