Срез 1D-тензора в PyTorch с тензорами начального и конечного индексов

Я пытаюсь создать 2D-тензор четных срезов из 1D-тензора в PyTorch. Скажем, у нас есть тензор одномерных данных и тензоры индексов как:

>>> data = torch.arange(10)
>>> data
tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> starts = torch.tensor([0, 3, 4, 1])
>>> ends = starts + 2
>>> starts
tensor([0, 3, 4, 1])
>>> ends
tensor([2, 5, 6, 3])

Как я могу проиндексировать тензор data, не зацикливаясь и не разрезая каждый набор индексов, чтобы получить следующий результат:


>>> dataSlices
tensor([[0, 1],
        [3, 4],
        [4, 5],
        [1, 2]])

Моя первая очевидная мысль — просто поставить starts и ends, как если бы вы использовали отдельные индексы, но это просто ошибка:

>>> data[starts:ends]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: only integer tensors of a single element can be converted to an index

Я просмотрел некоторые части документации, но не могу найти способ, я упустил что-то очевидное?

Потяните за рычаг выброса энергососущих проектов
Потяните за рычаг выброса энергососущих проектов
На этой неделе моя команда отменила проект, над которым я работал. Неделя усилий пошла насмарку.
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Библиотека для работы с мороженым
Библиотека для работы с мороженым
Лично я попрощался с операторами print() в python. Без шуток.
Эмиссия счетов-фактур с помощью Telegram - Python RPA (BotCity)
Эмиссия счетов-фактур с помощью Telegram - Python RPA (BotCity)
Привет, люди RPA, это снова я и я несу подарки! В очередном моем приключении о том, как создавать ботов для облегчения рутины. Вот, думаю, стоит...
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на...
Учебник по веб-скрапингу
Учебник по веб-скрапингу
Привет, ребята... В этот раз мы поговорим о веб-скрейпинге. Целью этого обсуждения будет узнать и понять, что такое веб-скрейпинг, а также узнать, как...
0
0
52
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Если бы это был список, zip решил бы вашу проблему

Похоже, вам нужно: torch.transpose().

И используйте решение из этого ответа @bachr: https://stackoverflow.com/a/60367265/3456886

Я не уверен, как функция транспонирования связана с вопросом, который я задал. Не могли бы вы уточнить?

EternalTrail 14.02.2023 15:58

Переход от строки: starts = torch.tensor([0, 3, 4, 1]) И изменение рядом с: ends = starts+ 1, чтобы получить правильный массив. Затем транспонирование позволит вам объединить тензор в желаемый результат dataSlices

user3456886 15.02.2023 16:29
Ответ принят как подходящий

Вы можете сделать это с помощью torch.take. Чтобы получить желаемый результат, вам нужно вычесть 1 из ваших конечных индексов, так как он принимает точные индексы, а не интервалы. (В качестве альтернативы вы можете сгенерировать такие концы в первую очередь)

indices=torch.stack((starts,ends-1),axis=1)
newtensor=torch.take(data,indices)

tensor([[0, 1],
        [3, 4],
        [4, 5],
        [1, 2]])

Если вы хотите взять реальные интервалы (исходя из того, что вы назвали начало и конец индекса), это будет решением для этого:

indices=torch.stack((starts,ends),axis=1)
rangeindices=[torch.range(i[0],i[1]) for i in indices]
tensorindices=torch.stack(rangeindices).type(torch.LongTensor)
newtensor=torch.take(data,tensorindices)

tensor([[0, 1, 2],
        [3, 4, 5],
        [4, 5, 6],
        [1, 2, 3]])

Но это (по понятным причинам) приведет к другому тензору, чем ожидаемый результат.

Обновлено:

С тех пор я нашел питонический способ для диапазонов без понимания списка! Для этого ваши концы должны быть на единицу больше, так как этот метод будет принимать диапазоны Python, которые не содержат конца диапазона.

indices=torch.stack((starts,ends),axis=1)
newtensor=torch.stack([data[slice(idx[0], idx[1])] for idx in indices])

Решение для интервалов - это именно то, что я искал. Как вы думаете, сложение индексов будет более быстрым решением по сравнению с выполнением чего-то вроде rangeindices = [torch.arange(s, e) for s, e in zip(starts, ends)] ?

EternalTrail 14.02.2023 14:30

Наверное, я просто не смог придумать решение, как их складывать для этой задачи

Franciska 14.02.2023 15:28

@EternalTrail Я нашел для этого меньше возможностей для понимания списка python, поэтому я отредактировал свой ответ, добавив это

Franciska 22.02.2023 13:13

Другие вопросы по теме