Создание простого 1D CNN в PyTorch с несколькими каналами - PullRequest
2 голосов
/ 17 апреля 2019

Размерность входных данных PyTorch не соответствует модели, и я не уверен, почему.

Насколько я понимаю ...

in_channels - это, во-первых, число 1D-входов, которые мы хотели бы передать в модель, и это предыдущий out_channel для всех последующих слоев.

out_channels - желаемое количество ядер (фильтров).

kernel_size - количество параметров на фильтр.

Таким образом, мы ожидаем, что в качестве данных, передаваемых на пересылку, будет набор данных с 7 одномерными каналами (т.е. двумерный вход).

Однако следующий код выдает ошибку, которая не соответствует ожидаемому, где этот код:

import numpy
import torch

X = numpy.random.uniform(-10, 10, 70).reshape(-1, 7)
# Y = np.random.randint(0, 9, 10).reshape(-1, 1)

class Simple1DCNN(torch.nn.Module):
    def __init__(self):
        super(Simple1DCNN, self).__init__()
        self.layer1 = torch.nn.Conv1d(in_channels=7, out_channels=20, kernel_size=5, stride=2)
        self.act1 = torch.nn.ReLU()
        self.layer2 = torch.nn.Conv1d(in_channels=20, out_channels=10, kernel_size=1)
    def forward(self, x):
        x = self.layer1(x)
        x = self.act1(x)
        x = self.layer2(x)

        log_probs = torch.nn.functional.log_softmax(x, dim=1)

        return log_probs

model = Simple1DCNN()
print(model(torch.tensor(X)).size)

Выдает следующую ошибку:

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-5-eca5856a2314> in <module>()
     21 
     22 model = Simple1DCNN()
---> 23 print(model(torch.tensor(X)).size)

~/anaconda3/envs/pytorch_p36/lib/python3.6/site-packages/torch/nn/modules/module.py in __call__(self, *input, **kwargs)
    487             result = self._slow_forward(*input, **kwargs)
    488         else:
--> 489             result = self.forward(*input, **kwargs)
    490         for hook in self._forward_hooks.values():
    491             hook_result = hook(self, input, result)

<ipython-input-5-eca5856a2314> in forward(self, x)
     12         self.layer2 = torch.nn.Conv1d(in_channels=20, out_channels=10, kernel_size=1)
     13     def forward(self, x):
---> 14         x = self.layer1(x)
     15         x = self.act1(x)
     16         x = self.layer2(x)

~/anaconda3/envs/pytorch_p36/lib/python3.6/site-packages/torch/nn/modules/module.py in __call__(self, *input, **kwargs)
    487             result = self._slow_forward(*input, **kwargs)
    488         else:
--> 489             result = self.forward(*input, **kwargs)
    490         for hook in self._forward_hooks.values():
    491             hook_result = hook(self, input, result)

~/anaconda3/envs/pytorch_p36/lib/python3.6/site-packages/torch/nn/modules/conv.py in forward(self, input)
    185     def forward(self, input):
    186         return F.conv1d(input, self.weight, self.bias, self.stride,
--> 187                         self.padding, self.dilation, self.groups)
    188 
    189 

RuntimeError: Expected 3-dimensional input for 3-dimensional weight [20, 7, 5], but got 2-dimensional input of size [10, 7] instead

Редактировать: см. Ниже решение, мотивированное Шаи.

import numpy
import torch

X = numpy.random.uniform(-10, 10, 70).reshape(1, 7, -1)
# Y = np.random.randint(0, 9, 10).reshape(1, 1, -1)

class Simple1DCNN(torch.nn.Module):
    def __init__(self):
        super(Simple1DCNN, self).__init__()
        self.layer1 = torch.nn.Conv1d(in_channels=7, out_channels=20, kernel_size=5, stride=2)
        self.act1 = torch.nn.ReLU()
        self.layer2 = torch.nn.Conv1d(in_channels=20, out_channels=10, kernel_size=1)
    def forward(self, x):
        x = self.layer1(x)
        x = self.act1(x)
        x = self.layer2(x)

        log_probs = torch.nn.functional.log_softmax(x, dim=1)

        return log_probs

model = Simple1DCNN().double()
print(model(torch.tensor(X)).shape)

1 Ответ

2 голосов
/ 17 апреля 2019

Вы забыли «измерение мини-партии», каждый образец «1D» действительно имеет два измерения: количество каналов (7 в вашем примере) и длину (10 в вашем случае).Однако Pytorch ожидает в качестве входных данных не одну выборку, а скорее мини-пакет из B выборок, собранных вместе по «измерению мини-партии».
Таким образом, «1D» CNN в Pytorch ожидает 3D-тензор в качестве входных данных: Bх C х T.Если у вас есть только один сигнал, вы можете добавить одноэлементное измерение:

 out = model(torch.tensor(X)[None, ...])
...