#python #pytorch #transformer
#python #pytorch #transformer-model
Вопрос:
Возможно, я ошибаюсь, но кажется, что PyTorch Transformers являются авторегрессивными, для чего и предназначена маскировка. Тем не менее, я видел некоторые реализации, в которых люди используют только кодировщик и выводят его непосредственно на Linear
слой.
В моем случае я пытаюсь преобразовать спектрограмму (строки — это частоты, а столбцы — временные интервалы) в другую спектрограмму тех же размеров. У меня невозможное время, пытаясь понять, как это сделать.
Для моей модели у меня есть:
class TransformerReconstruct(nn.Module):
def __init__(self, feature_size=250, num_layers=1, dropout=0.1, nhead=10, output_dim=1):
super(TransformerReconstruct, self).__init__()
self.model_type = 'Transformer'
self.src_mask = None
self.pos_encoder = PositionalEncoding(feature_size)
self.encoder_layer = nn.TransformerEncoderLayer(d_model=feature_size, nhead=nhead, dropout=dropout)
self.transformer_encoder = nn.TransformerEncoder(self.encoder_layer, num_layers=num_layers)
self.decoder = nn.Linear(feature_size, output_dim)
self.init_weights()
def init_weights(self):
initrange = 0.1
self.decoder.bias.data.zero_()
self.decoder.weight.data.uniform_(-initrange, initrange)
def forward(self, src):
if self.src_mask is None or self.src_mask.size(0) != len(src):
device = src.device
mask = self._generate_square_subsequent_mask(len(src)).to(device)
self.src_mask = mask
src = self.pos_encoder(src)
output = self.transformer_encoder(src, self.src_mask)
output = self.decoder(output)
return output
def _generate_square_subsequent_mask(self, sz):
mask = (torch.triu(torch.ones(sz, sz)) == 1).transpose(0, 1)
mask = mask.float().masked_fill(mask == 0, float('-inf')).masked_fill(mask == 1, float(0.0))
return mask
И при обучении у меня есть:
model = TransformerReconstruct(feature_size=128, nhead=8, output_dim=128, num_layers=6).to(device)
Это возвращает правильную форму, но, похоже, не учится.
Мой базовый цикл обучения выглядит так:
for i in range(0, len(data_source) - 1, input_window):
data, target = get_batch(data_source, i, 1)
output = recreate_model(data)
и я использую MSELoss
и пытаюсь изучить очень простую идентификацию. Где входные и выходные данные одинаковы, однако это не обучение. Что я могу делать неправильно? Заранее спасибо.
Комментарии:
1. Выполняет ли pytorch.org/tutorials/beginner/transformer_tutorial.html помогите?
2. Похоже, с вашим классом модели проблем нет. Но немного странно видеть, что вы получаете результат с
recreate_model
помощью вместоmodel
. Кроме того, просто проверка: вы создали экземпляр оптимизатора и используете его, верно?
Ответ №1:
Большинство моделей в Huggingface Transformers представляют собой некоторую версию BERT и, следовательно, не являются авторегрессивными, единственными исключениями являются модели только для декодера (GPT и аналогичные) и модели последовательности в последовательности.
Существует два концептуально разных типа масок: одна — это маска ввода, специфичная для входного пакета, и ее цель — разрешить использование последовательностей разной длины в одном пакете. Когда последовательности дополняются до одинаковой длины, самоконтроль должен быть направлен на позиции заполнения. Это то, что вы должны использовать при вызове self.transformer_encoder
метода forward.
Кроме того, декодер авторегрессионного трансформатора использует другой тип маски. Это треугольная маска, которая не позволяет самоконтролю уделять внимание токенам, которые находятся справа от текущей позиции (во время вывода слова справа от текущей позиции неизвестны до того, как они фактически сгенерированы). Это то, что у вас есть в _generate_square_subsequent_mask
методе, и это то, что делает модель авторегрессивной. Она постоянна и не зависит от входного пакета.
Подводя итог: чтобы иметь двунаправленный трансформатор, просто избавьтесь от треугольной маски. Если ваши входные последовательности имеют разную длину, вам следует использовать маскировку для конкретного пакета, если нет, просто передайте матрицу с единицами.
Ответ №2:
Если вы хотите, чтобы модель перестала работать с авторегрессией, вам нужно «отобразить» токены справа от текущего токена, т.е. Изменить / удалить _generate_square_subsequent_mask
.
Как вы это измените, зависит от задачи. Вы пытаетесь восстановить «поврежденные» входные последовательности? Затем замаскируйте случайное подмножество токенов и обработайте его как автоэнкодер.
Если вы просто хотите приблизить функцию идентификации, полностью удалите маску.