Пользуюсь PyTorch давно, но изредка будут различные баги.Когда багов накопится до определенного количества, они будут вызывать качественные изменения - пишите заметку на долгую память...
Переменная и тензор
0.4
Более поздние версии могут напрямую использовать Tensor вместо Variable, нет необходимости обертывать громоздкий слойVariable
.
Транспонировать тензор
Есть много способов транспонировать тензор, например.transpose
,.transpose_
Это наиболее часто используемый (подчеркнуто, чтобы внести изменения в исходный тензор), но этот метод транспонирования имеет ограничение, заключающееся в том, что он может работать только в двух измерениях, что является функцией транспонирования «корневой положительный красный росток».
Иногда вам нужно обменять больше измерений, вы можете использовать это время.permuate
Функция, которая принимает список измерений, а затем обновляет расположение измерений тензора в соответствии с порядком измерений в списке.
Размер вверх и вниз
Вознесение.unsqueeze
заключается в том, чтобы вставить измерение в указанное измерение, но данные фактически не изменяются. Например следующий пример:
In [1]: a
Out[1]:
tensor([[[-0.7908, -1.4576, -0.3251],
[-1.2053, 0.3667, 0.9423],
[ 0.0517, 0.6051, -0.1360],
[ 0.8666, -1.4679, -0.4511]]])
In [2]: a.shape
Out[2]: torch.Size([1, 4, 3])
In [3]: a.unsqueeze(2).shape
Out[3]: torch.Size([1, 4, 1, 3])
Снижение размерности.squeeze
является обратным восходящему измерению, которое исключает все измерения размерности 1:
In [1]: a.shape
Out[1]: torch.Size([1, 4, 3])
In [2]: a.squeeze().shape
Out[2]: torch.Size([4, 3])
Тензор смежный
После того, как тензор выполняет операцию транспонирования, данные на самом деле не меняются, но меняется порядок чтения данных. Это метод экономии места и вычислений.
Однако, если транспонированные данные необходимо.view
Для других операций, поскольку данные не являются логически непрерывными, их необходимо вызывать вручную.contiguous
Пусть данные восстанавливают вид непрерывного хранения.
Каков формат параметров функций потерь?
Это ситуация, которая часто встречается в первые дни.FloatTensor
, скороLongTensor
уже? Чтобы решить эту проблему, вам все еще нужно иметь глубокое понимание того, что делают различные функции потерь.
BCELoss
Взаимная энтропия двух классификаций рассчитывается следующим образом:
Это не трудно увидетьиоба должны бытьFloatTensor
. Если операцию выполнить на другом тензоре, возникнет ошибка:
Expected object of type torch.FloatTensor but found type torch.LongTensor
CrossEntropyLoss
вышеBCELoss
Это расчет функции потерь в случае двух классификаций, поэтому, когда вы сталкиваетесь с проблемами с несколькими классификациями, если вы хотите использовать перекрестную энтропию для расчета, вам нужно использоватьCrossEntropyLoss
.
Будь то двоичный или мультиклассовый, его можно рассчитать с простейшей потерей L2, но если вы используете
Sigmoid
В качестве функции активации градиент легко исчезает, что приводит к плохим результатам.
Пользовательская сеть должна инициализировать веса
Если веса не инициализированы, что-то произойдет...
Иногда вы сталкиваетесь с некоторыми сетями со странной структурой, и различные параметры перепутаны, поэтому функций, которые идут в комплекте с факелом, может быть недостаточно, тогда вам нужно настроить структуру сети. Как правило, он строится из самой низкой матрицы, как и тензорный поток. Например, чтобы определить полносвязный слой без условий смещения, вы можете использоватьnn.Linear(xxx, xxx, bias=False)
. Однако в особых случаях даже внутренние детали полносвязного слоя должны быть определены вами самостоятельно.В это время вам необходимо обратиться к исходному коду torch, например, к части исходного кода полносвязного слоя:
class Linear(Module):
def __init__(self, in_features, out_features, bias=True):
super(Linear, self).__init__()
self.in_features = in_features
self.out_features = out_features
self.weight = Parameter(torch.Tensor(out_features, in_features))
if bias:
self.bias = Parameter(torch.Tensor(out_features))
else:
self.register_parameter('bias', None)
self.reset_parameters()
def reset_parameters(self):
stdv = 1. / math.sqrt(self.weight.size(1))
self.weight.data.uniform_(-stdv, stdv)
if self.bias is not None:
self.bias.data.uniform_(-stdv, stdv)
def forward(self, input):
return F.linear(input, self.weight, self.bias)
На этом примере уже можно многому научиться, вот ключевая ссылкаParameters
Использование (сначала out_feature) и функции инициализации весаreset_parameters
детали интерьера.
В предыдущем задании по машинному обучению та же модель, версия PyTorch никогда не достигала точности версии Tensorflow, вероятно, из-за другой инициализации веса.
Некоторые ямы CUDA
Пользовательская сеть не будет автоматически конвертироваться в cuda? ?
Я использовал его раньше и определил простую базовую сеть, чтобы упростить построение верхней сети. Сеть, определенная таким образом, отлично работает на ЦП, но когда я переношу модель на ГП, я обнаруживаю, что модель имеет ошибку несоответствия типов:
Expected object of type torch.FloatTensor but found type torch.cuda.FloatTensor for argument
Позже при отладке выяснилось, что сеть верхнего уровня называлась.cuda
После этого базовая сеть все еще находится вdevice(type='cpu')
! Хотя самый простой способ решить эту проблему — поместить определение базовой сети в верхнюю сеть, это не способствует сопровождению кода, и будет очень сложно совместно использовать модули в разных сетях.
Миграция PyTorch на данные ЦП и ГП действительно не так удобна, как тензорный поток...
Я видел на GitHub много обходных путей для подобных проблем, и один из них — хорошая идея:
if torch.cuda.available():
import torch.cuda as t
else:
import torch as t
Если вы рассматриваете автоматический CUDA при написании кода в начале, это действительно хороший способ, если вы уже написали раздутый код, его все равно будет очень обременительно переписывать.
В конце концов, решение, которое я выбрал, состояло в том, чтобы переписать.cuda
функция:
def cuda(self, device=None):
r"""Moves all model parameters and buffers to the GPU..."""
return self._apply(lambda t: t.cuda(device))
существует.cuda
Подмодуль также вызывается в функции.cuda
Вот и все.
Данные CUDA не могут быть напрямую преобразованы в данные numpy.
Если данные были перенесены на графический процессор, преобразовать результат операции в данные, соответствующие характеристикам numpy, не так просто, и обычно будет сообщено об ошибке:
TypeError: can't convert CUDA tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first.
Выдано сообщение об ошибке решения. Конечно, вы также можете изменить операции, которые нуждаются в помощи numpy в будущем, на операции, поддерживаемые PyTorch, так скорость будет еще быстрее, ведь все дороги ведут в Рим.