神经网络入门之二 网络搭建
此篇文章在2022年12月1日被记录
入门神经网络二
网络搭建
-
使用哪种深度学习框架
目前主流的神经网络框架有tensorflow、kears,国产的有百度的PaddlePaddle,但是我是从yolov5入坑的,yolov5官方代码使用的是pytorch框架,所以我使用torch,而且torch框架上手很简单,资源较多坑较少。
-
建立一个怎样的网络结构
- 网络层
网络层很简单,只有一个卷积层和一个全连接层,一个卷积层包括卷积、激活、下采样。我是用5个卷积核进行卷积,网络结构非常简单,是因为模型训练出来后需要部署在C平台上,作为一个新手,我想网络尽量简单从而避免过量的参数带来的工作量。
self.conv1 = torch.nn.Conv2d(in_channels=1, out_channels=5, kernel_size=3, stride=(3, 1)) # 只进行横向卷积
self.pooling = torch.nn.MaxPool2d(kernel_size=(1, 2))
self.fc1 = torch.nn.Linear(in_features=5*1*24, out_features = 3)
- 构建损失函数
损失函数(loss function)就是用来度量模型的预测值与真实值的差异程度的运算函数,它是一个非负实值函数,损失函数越小,模型的鲁棒性就越好。损失函数使用主要是在模型的训练阶段,每个批次的训练数据送入模型后,通过前向传播输出预测值,然后损失函数会计算出预测值和真实值之间的差异值,也就是损失值。得到损失值之后,模型通过反向传播去更新各个参数,来降低真实值与预测值之间的损失,使得模型生成的预测值往真实值方向靠拢,从而达到学习的目的。
criterion = torch.nn.CrossEntropyLoss()
- 构建优化器
优化器就是需要根据网络反向传播的梯度信息来更新网络的参数,以起到降低loss函数计算值的作用,我在这里测试了torch的四种优化器,我暂时不了解四种优化器的原理,但是实际训练时差异较大(后面注释是在不同网络结构下的loss,可以看出RMSprop与Adam的优化器效果最好)。
#optimizer = torch.optim.SGD(model.parameters(),lr = 0.001,momentum=0.8) #0.4741 conv2
#optimizer = torch.optim.SGD(model.parameters(),lr = 0.001) #0.0037 conv2 0.4931 conv1
#optimizer = torch.optim.RMSprop(model.parameters(),lr=0.001,alpha=0.9)#0.0000 conv2 0.0000 conv1
optimizer = torch.optim.Adam(model.parameters(),lr=0.0001,betas=(0.9,0.99))#0.0000 conv2 0.0000 conv1
-
开始训练
- 读取数据
上文中提到我们将采集到的样本保存为npy数据,本文来读取它
rest_sample = np.load('sample/rest.npy')
walk_sample = np.load('sample/walk.npy')
run_sample = np.load('sample/run.npy')
print(rest_sample.shape)
print(walk_sample.shape)
print(run_sample.shape)
- 上文中提到我们采集到的每种姿态的样本数量是300帧,按照网络上传统的训练比重,我将训练样本与测试样本按照7:3分开,也就是210:90个样本比例,建立训练网络结构:
class Net(torch.nn.Module):#这个网络结构只有一层卷积
def __init__(self):
super(Net, self).__init__()
self.conv1 = torch.nn.Conv2d(
in_channels=1, out_channels=5, kernel_size=3, stride=(3, 1)) # 只进行横向卷积
self.pooling = torch.nn.MaxPool2d(kernel_size=(1, 2))
self.fc1 = torch.nn.Linear(in_features=5*1*24, out_features = 3)
def forward(self, x):
x = self.conv1(x)
x = F.relu(x)
x = self.pooling(x)
x = x.view(x.size(0), -1)
x = self.fc1(x)
return x
model = Net()
print(model)
#构建损失
criterion = torch.nn.CrossEntropyLoss()
#构建优化器
#optimizer = torch.optim.SGD(model.parameters(),lr = 0.001,momentum=0.8) #0.4741 conv2
#optimizer = torch.optim.SGD(model.parameters(),lr = 0.001) #0.0037 conv2 0.4931 conv1
#optimizer = torch.optim.RMSprop(model.parameters(),lr=0.001,alpha=0.9)#0.0000 conv2 0.0000 conv1
optimizer = torch.optim.Adam(model.parameters(),lr=0.0001,betas=(0.9,0.99))#0.0000 conv2 0.0000 conv1
def train():
epoches = 100
targets = torch.tensor([0,1,2])
for epoch in range(epoches):
for i in range(0,210):
inputs= torch.Tensor(([rest_sample[i]],[walk_sample[i]],[run_sample[i]]))
outputs = model(inputs)
loss = criterion(outputs,targets)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print('Epoch: ', epoch, '| train loss: %.10f' % loss.data.numpy())
这个训练过程,我们每次同时训练三个样本(batch = 3),循环迭代100次,得到best_model.pth模型文件,并将其保存在本地。
-
模型测试
我们读取本地保存的模型,编写测试函数,其中pred_y为测试结果。实际测试中模型准确率在80%以上。也可以在这个网站查看我的网络结构示例如下图:
def test(model):
for i in range(210,300):
test_output = model(torch.Tensor(([rest_sample[i]],[walk_sample[i]],[run_sample[i]])))
pred_y = torch.max(test_output, 1)[1].data.numpy().squeeze()
#print(test_output)
print(pred_y)
整体网络代码如下:
import torch
import torch.nn.functional as F
import numpy as np
rest_sample = np.load('sample/rest.npy')
walk_sample = np.load('sample/walk.npy')
run_sample = np.load('sample/run.npy')
print(rest_sample.shape)
print(walk_sample.shape)
print(run_sample.shape)
#构建CNN模型
# class Net(torch.nn.Module):
# def __init__(self):
# super(Net, self).__init__()
# self.conv1 = torch.nn.Conv2d(
# in_channels=1, out_channels=5, kernel_size=3, stride=(3, 1), padding=1) # 只进行横向卷积
# self.conv2 = torch.nn.Conv2d(
# in_channels=5, out_channels=10, kernel_size=3, stride=(3, 1), padding=1) # 只进行横向卷积
# self.pooling = torch.nn.MaxPool2d(kernel_size=(1, 2))
# self.fc1 = torch.nn.Linear(in_features=10*1*12, out_features = 3)
# def forward(self, x):
# # 先做Relu在做pooling
# x = self.pooling(F.relu(self.conv1(x)))
# x = self.pooling(F.relu(self.conv2(x)))
# x = x.view(x.size(0), -1)
# x = self.fc1(x)
# return x
class Net(torch.nn.Module):#这个网络结构只有一层卷积
def __init__(self):
super(Net, self).__init__()
self.conv1 = torch.nn.Conv2d(
in_channels=1, out_channels=5, kernel_size=3, stride=(3, 1)) # 只进行横向卷积
self.pooling = torch.nn.MaxPool2d(kernel_size=(1, 2))
self.fc1 = torch.nn.Linear(in_features=5*1*24, out_features = 3)
def forward(self, x):
x = self.conv1(x)
x = F.relu(x)
x = self.pooling(x)
x = x.view(x.size(0), -1)
x = self.fc1(x)
return x
model = Net()
print(model)
#构建损失
criterion = torch.nn.CrossEntropyLoss()
#构建优化器
#optimizer = torch.optim.SGD(model.parameters(),lr = 0.001,momentum=0.8) #0.4741 conv2
#optimizer = torch.optim.SGD(model.parameters(),lr = 0.001) #0.0037 conv2 0.4931 conv1
#optimizer = torch.optim.RMSprop(model.parameters(),lr=0.001,alpha=0.9)#0.0000 conv2 0.0000 conv1
optimizer = torch.optim.Adam(model.parameters(),lr=0.0001,betas=(0.9,0.99))#0.0000 conv2 0.0000 conv1
def train():
epoches = 100
targets = torch.tensor([0,1,2])
for epoch in range(epoches):
for i in range(0,210):
inputs= torch.Tensor(([rest_sample[i]],[walk_sample[i]],[run_sample[i]]))
outputs = model(inputs)
loss = criterion(outputs,targets)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print('Epoch: ', epoch, '| train loss: %.10f' % loss.data.numpy())
def test(model):
for i in range(210,300):
test_output = model(torch.Tensor(([rest_sample[i]],[walk_sample[i]],[run_sample[i]])))
pred_y = torch.max(test_output, 1)[1].data.numpy().squeeze()
#print(test_output)
print(pred_y)
if __name__ == '__main__':
# train()
# torch.save(model, 'best_model.pth')
my_model = torch.load('best_model.pth')
test(my_model)
# print("parameters")
# torch.set_printoptions(profile="full")
# for parameters in my_model.parameters():
# print(parameters)
# print("------------------------------------")
# print("name,parameters")
# for name,parameters in my_model.named_parameters():
# print(name,':',parameters.size())
后记
从代码中能看出来我曾经测试过两层的卷积网络,实际测试效果比单纯一层网络好很多,但是后续需要将其部署到C环境中,为了减少后续的工作量,只用了一层网络,并且这层的卷积核参数只有五个,所以说效果一般般。下一章讲一下如何将这个比较简单的网络结构:怎样读取模型数据,用C语言实现输入参数预测结果。
本文作者:shumei52
本文链接:https://www.cnblogs.com/shumei52/p/18599775
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步