torch.max(F.softmax(out, dim=1), 1)[1]
方括号里面的如果是1,输出的就是1和0的矩阵。如果是0,输出的就是概率的矩阵。
中间那个1是max函数索引的维度0/1,0是每列的最大值,1是每行的最大值。
左边那个1,是说,按行进行归一化。
loss_func = torch.nn.CrossEntropyLoss()
loss = loss_func(out, y)
这里的out和y并不是同一个shape的。y是标签值,是单列的布尔矩阵,但是注意这个shape是[32423423]这样的,而不是[32423423,1]。 out是多列的,有几列取决于你最后一层的神经元个数。理解见此文章。所以说,给他的out就是网络最后输出的几个值的矩阵,y相当于是类别,他这里有两步计算,一个是LogSoftmax,一个是NLLLoss。也就是说在定义网络时,最后一层要写class数目的神经元,之后在训练时for循环里面拿输出出来求loss。如果要求正确率,就在后面用prediction = torch.max(F.softmax(out, dim=1), 1)[1]
获得预测的class,再通过判断求正确率。
解释一下我的模型
# Define model
class NeuralNetwork(nn.Module):
def __init__(self):
super(NeuralNetwork, self).__init__()#先是继承一下nn.module
self.linear_relu_stack = nn.Sequential(
nn.Conv1d(in_channels=1,out_channels=10,kernel_size=3,padding=1),
# 这个conv1d实际上就是先看输入的维度,很明显,
#这里的时域的信息只有一种,所以in_channels=1,
#然后我希望他能提取出多个维度的信息,所以我给了out_channels=10
#所以会得到一个470806*10*480的tensor,470806是我的数据的行数,480是我的数据的列数。
#卷积核的大小先给了个3看看效果,如果想让输出的还是480,就要padding=1.
nn.BatchNorm1d(10),#这个函数意思是纠正数据分布,里面的数字是数据的维度,因为我上面卷积把维度提高到了10,所以这里面应该是10.
nn.Linear(480, 100),#注意这里,前面的480,是和维度无关的,也就是说不管卷积提取了多少维,都只和每个维度上的数据有关,也就是和之前的数据长度,卷积核大小和填白大小有关。
nn.ReLU(),
nn.Conv1d(in_channels=10,out_channels=1,kernel_size=3,padding=1),
#可能是提高维度后参数数模大大增加了,所以我在让他经过一个线性层后变成了1个维度,这样减少计算量。
nn.Linear(100, 10),
nn.BatchNorm1d(1),
nn.ReLU(),
nn.Linear(10, 2)#因为是2分类问题,所以输出是两个神经元。
)
def forward(self, x):
logits = self.linear_relu_stack(x)
# print(logits.shape)
logits=logits.reshape([logits.shape[0],logits.shape[2]])
#这里输出不知道为什么是三维的,所以我把他变成两维的。
return logits
然后我直接打开GPU进行运算,发现几十G,运行不了,想起来应该是要我手动再做batchsize。
然后得到了结果后。我发现这个1的标签和0的标签的比例相差太大了,1的比例占到了95%。所以,需要改loss,不能直接用crossentropy了,需要拆开来做。
还有就是训练和测试时,要进行模式切换,也就是在训练前加上model.train() 测试前加model.eval() 。
在测试时,还要注意,因为我们现在的数据是在GPU的tensor,所以要先把数据搬运到CPU上,再把tensor变成numpy数组,就像这样
pred_y = prediction.cpu().numpy()
target_y = test_label.cpu().numpy()
反正,我是觉得这个pytorch比TensorFlow麻烦多了。。。
今天先写这么多,明天继续。
还需解决的问题是
1、训练速度较慢,不知道是不是没有开启平行训练还是什么情况。
2、标签占比相差太大的问题,需要把loss的weight调一下。
3、模型的逻辑问题,我认为30ms的信号,如果不给足够的前文,人类也不一定能分辨出是否有语音,所以可能后续需要用到LSTM。这个可能需要较久了。
2021年7月25日21:29:51
开启平行训练,有两种方式,一种是分布式训练,一种是并行训练。前者是
model = torch.nn.parallel.DistributedDataParallel(model,
device_ids=[arg.local_rank],
output_device=arg.local_rank)
我没有用这个`。我用的是dataparallel
device = torch.device("cuda:{}".format(0) if torch.cuda.is_available() else "cpu")
net = NeuralNetwork()
net = nn.DataParallel(net, device_ids=[0,1,2,3])
net=net.to(device)
现在就可以了。还有一个坑,就是如果你训练代码中有任何的tensor没有放到GPU上,比如损失函数中的权重。这都会造成他用上CPU,导致用上两个设备而报错。具体可以参考此文
但是我发现dataparallel在我这个服务器用不了,实际上没有给其他的卡分配任务,就那个主卡在工作。。。还是得看分布式的,这篇文章
明天看下别人的代码
https://blog.csdn.net/lqfarmer/article/details/109101549
2021年7月27日23:51:11