Создание эффективных пользовательских наборов данных в PyTorch

машинное обучение

Изучите все тонкости класса Dataset и используйте чистую структуру кода, сводя к минимуму проблемы с управлением большими объемами данных во время обучения.

1_2ARG_iUVAzMGgKtTMnGQOg

Обучение нейронной сети может быть сложно проводить «в масштабе» с точки зрения управления данными.

PyTorch был в моем кругу в последнее время, и, несмотря на то, что я был доволен Keras и TensorFlow, я должен был попробовать. Удивительно, но я нашел его очень свежим и приятным, тем более что PyTorch предлагает Pythonic API, более продуманную модель программирования и хороший набор встроенных служебных функций. Одна функция, которая мне особенно нравится, — это возможность легко создавать пользовательскиеDatasetобъект, который затем можно использовать со встроеннымDataLoaderвместе предоставляют данные при обучении модели.

В этой статье я буду изучать PyTorch с нуля.Datasetобъект, цель которого — создать набор данных для обработки текстовых файлов и изучить, как оптимизировать конвейер для конкретной задачи. Давайте сначала разберемся на простом примереDatasetОсновы утилиты, затем пошаговое выполнение реальной задачи. В частности, мы хотим создать конвейер, который берет имена из серии The Elder Scrolls (TES) с расовыми и гендерными атрибутами этих имен в виде тензора с одним горячим номером. ты сможешьмой веб-сайтНайдите этот набор данных на .

Основы класса набора данных

Pytorch позволяет вам свободно делать все, что вы хотите, с классом «Набор данных», если вы переопределяете две функции подкласса:

- функция, которая возвращает размер набора данных, и

- Функция функций, которая возвращает выборку из набора данных по заданному индексу.

Размер набора данных иногда может быть серой областью, но он равен количеству выборок во всем наборе данных. Итак, если в наборе данных 10 000 слов (или точек данных, изображений, предложений и т. д.), функция «uuLen_uUu» должна вернуть 10 000.

PyTorch дает вам свободуDatasetКласс может делать что угодно, пока вы переопределяете две функции в классе:

  • __len__Функция: возвращает размер набора данных
  • __getitem__Функция: возвращает образцы в наборе данных, соответствующие индексу.

Размер набора данных иногда трудно определить, но он равен количеству выборок во всем наборе данных. Итак, если у вас есть 10 000 образцов в вашем наборе данных (точки данных, изображения, предложения и т. д.), то__len__Функция должна вернуть 10 000.

простой пример

Сначала создайте список всех чисел от 1 до 1000.Datasetдля имитации простого набора данных. мы назвали это соответствующим образомNumbersDataset.

from torch.utils.data import Dataset

class NumbersDataset(Dataset):
    def __init__(self):
        self.samples = list(range(1, 1001))

    def __len__(self):
        return len(self.samples)

    def __getitem__(self, idx):
        return self.samples[idx]


if __name__ == '__main__':
    dataset = NumbersDataset()
    print(len(dataset))
    print(dataset[100])
    print(dataset[122:361])

1_M0Qw7bS02uzqEH5Q-tAR1w

Просто, верно? Во-первых, когда мы инициализируемNumbersDataset, мы сразу создаемsamplesСписок, в котором будут храниться все числа от 1 до 1000. Название списка произвольное, поэтому не стесняйтесь использовать любое имя, которое вам нравится. Функции, которые необходимо переопределить, не указаны мной (надеюсь!) и работают со списком, созданным в конструкторе. Если вы запустите этот файл Python, вы увидите значения от 1000, 101 и от 122 до 361, которые относятся к длине набора данных, данным с индексом 100 в наборе данных и фрагменту набора данных с индексом 121. до 361 соответственно.

Расширенный набор данных

Давайте расширим этот набор данных, чтобы он мог хранитьlowиhighвсе целые числа между ними.

from torch.utils.data import Dataset

class NumbersDataset(Dataset):
    def __init__(self, low, high):
        self.samples = list(range(low, high))

    def __len__(self):
        return len(self.samples)

    def __getitem__(self, idx):
        return self.samples[idx]


if __name__ == '__main__':
    dataset = NumbersDataset(2821, 8295)
    print(len(dataset))
    print(dataset[100])
    print(dataset[122:361])

1_M4NsNPSdxokejaxrftnrlg

Запуск приведенного выше кода должен вывести на консоль числа от 5474, 2921 и от 2943 до 3181. Написав конструктор, мы теперь можем преобразовать набор данныхlowиhighУстановите желаемый контент. Это простое изменение показывает, что мы можем сделать из PyTorch.DatasetРазличные преимущества, полученные классом. Например, мы можем сгенерировать несколько разных наборов данных и использовать эти значения, не думая о написании новых классов или создании множества сложных для понимания матриц, как в NumPy.

читать данные из файла

Давайте расширяться дальшеDatasetфункциональность класса. Интерфейс PyTorch для стандартной библиотеки Python красиво оформлен, а это значит, что вам не нужно беспокоиться об интеграции функций. Здесь мы будем

  • Создайте новый, используя ввод-вывод Python и несколько статических файлов.Datasetсвоего рода
  • Соберите имена персонажей TES (на моем сайтеесть доступные наборы данных), эти имена персонажей разделены на папки этнической принадлежности и гендерные файлы для заполненияsamplesсписок
  • вsamplesВ списке хранится кортеж, а не только сами имена, чтобы отслеживать расу и пол каждого имени.

Набор данных имен TES имеет следующую структуру каталогов:

.
|-- Altmer/
|   |-- Female
|   `-- Male
|-- Argonian/
|   |-- Female
|   `-- Male
... (truncated for brevity)(为了简洁,这里进行省略)
`-- Redguard/
    |-- Female
    `-- Male

Каждый файл содержит имена TES, разделенные символами новой строки, поэтому мы должны читать каждый файл построчно, чтобы зафиксировать все имена персонажей для каждой расы и пола.

import os
from torch.utils.data import Dataset

class TESNamesDataset(Dataset):
    def __init__(self, data_root):
        self.samples = []

        for race in os.listdir(data_root):
            race_folder = os.path.join(data_root, race)

            for gender in os.listdir(race_folder):
                gender_filepath = os.path.join(race_folder, gender)

                with open(gender_filepath, 'r') as gender_file:
                    for name in gender_file.read().splitlines():
                        self.samples.append((race, gender, name))

    def __len__(self):
        return len(self.samples)

    def __getitem__(self, idx):
        return self.samples[idx]


if __name__ == '__main__':
    dataset = TESNamesDataset('/home/syafiq/Data/tes-names/')
    print(len(dataset))
    print(dataset[420])

Давайте посмотрим на код: сначала создайте пустойsampleslist, затем просмотрите каждую папку расы и файл пола и прочитайте имена в каждом файле, чтобы заполнить список. Затем сохраните расу, пол и имя в кортеже и добавьте его вsamplesСписок. Запуск файла должен напечатать 19491 и('Bosmer', 'Female', 'Gluineth')(Вывод может варьироваться от компьютера к компьютеру). Давайте посмотрим, как выглядит пакет набора данных:

# 将main函数改成下面这样:
if __name__ == '__main__':
    dataset = TESNamesDataset('/home/syafiq/Data/tes-names/')
    print(dataset[10:60])

1_zReMM6fh9m4efrvl9fwQeQ

Как вы понимаете, он работает точно так же, как список. Чтобы завершить этот раздел, мы только что добавили стандартный ввод-вывод Python в набор данных PyTorch, и нам не нужны никакие другие специальные оболочки или помощники, только простой код Python. Фактически, мы также можем включить другие библиотеки, такие как NumPy или Pandas, и с помощью некоторых умных манипуляций заставить их хорошо работать с PyTorch. Давайте теперь посмотрим, как эффективно перемещаться по набору данных во время обучения.

Загрузить данные с помощью DataLoader

несмотря на то чтоDatasetКлассы — отличный способ создания наборов данных, ноказатьсяВо время обучения нам понадобитсяsamplesСписки индексируются или нарезаются. Это не проще, чем мы делаем со списками или матрицами NumPy. PyTorch не идет по этому пути, но предоставляет еще один служебный класс.DataLoader.DataLoaderвести себя какDatasetФидер данных для объекта. Если вы знакомы, этот объект такой же, как и в Керасе.flowФункции генератора данных аналогичны.DataLoaderнужен одинDatasetобъект (который расширяет любые подклассы) и некоторые другие необязательные параметры (параметры перечислены вДокументация PyTorch DataLoaderсередина). Среди этих параметров мы можем выбрать перемешивание данных, определить размер пакета и количество потоков (задания), загружающих данные параллельно. ЭтоTESNamesDatasetПростой пример вызова в цикле.

# 将main函数改成下面这样:
if __name__ == '__main__':
    from torch.utils.data import DataLoader
    dataset = TESNamesDataset('/home/syafiq/Data/tes-names/')
    dataloader = DataLoader(dataset, batch_size=50, shuffle=True, num_workers=2)
    for i, batch in enumerate(dataloader):
        print(i, batch)

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

1_p93YQcPTqbWHHBalicRtvA

Подождите, это не то, как это выглядело, когда мы раньше нарезали набор данных! Что, черт возьми, здесь происходит? Что ж, оказывается,DataLoaderЗагружайте данные систематически, чтобы мы располагали данные вертикально, а не горизонтально. Это особенно полезно для потоков тензоров в пакете, поскольку тензоры складываются вертикально (т.е. в первом измерении) для формирования пакетов. также,DataLoaderДанные также переупорядочиваются, поэтому нет необходимости переупорядочивать матрицы или отслеживать индексы при подаче данных.

Тензоры и другие типы

Для дальнейшего изучения различных типов данных вDataLoaderКак он загружен, мы обновим наш ранее смоделированный набор данных чисел, чтобы создать две пары тензоров: тензор для последних 4 чисел каждого числа в наборе данных и тензор с добавлением некоторого случайного шума. чтобы броситьDataLoaderCurveball, мы также хотим вернуть само число, а не тип тензора, возвращается в виде строки Python.__getitem__Функция вернет три разнородных элемента данных в кортеже.

from torch.utils.data import Dataset
import torch

class NumbersDataset(Dataset):
    def __init__(self, low, high):
        self.samples = list(range(low, high))

    def __len__(self):
        return len(self.samples)

    def __getitem__(self, idx):
        n = self.samples[idx]
        successors = torch.arange(4).float() + n + 1
        noisy = torch.randn(4) + successors
        return n, successors, noisy


if __name__ == '__main__':
    from torch.utils.data import DataLoader

    dataset = NumbersDataset(100, 120)
    dataloader = DataLoader(dataset, batch_size=10, shuffle=True)
    print(next(iter(dataloader)))

Обратите внимание, что вместо изменения конструктора набора данных мы изменили__getitem__функция. Для набора данных PyTorch это хорошая практика, потому что набор данных будет масштабироваться со все большим количеством образцов, поэтому мы не хотимDatasetКогда объект запускается, он сохраняет в памяти слишком много данных типа тензор. Вместо этого, когда мы перебираем список выборок, мы хотим, чтобы он был тензорного типа, жертвуя некоторой скоростью для экономии памяти. В следующих разделах я объясню его полезность.

1_aXX9tKENoSYlej35QYWxnQ

Обратите внимание на вывод выше, хотя наш новый__getitem__Функция возвращает огромный кортеж строк и тензоров, ноDataLoaderСпособность идентифицировать данные и складывать их соответствующим образом. Строковые числа образуют кортежи того же размера, что и созданные.DataLoaderРазмер пакета, настроенный во время, тот же. Для двух тензоровDataLoaderСложите их вертикально до размера10x4тензор. Это связано с тем, что мы настроили размер пакета равным 10, и__getitem__Функция возвращает два тензора размера 4.

как правило,DataLoaderПопробуйте сложить пакет одномерных тензоров в двухмерные тензоры, сложить пакет двумерных тензоров в трехмерные тензоры и так далее. На этом этапе я прошу вас обратить внимание на огромное влияние, которое это оказало на традиционную обработку данных в других библиотеках машинного обучения, и на то, насколько это элегантно. Невероятный! Если вы со мной не согласны, то по крайней мере теперь знаете, что такой способ есть.

Завершите код для набора данных TES.

Вернемся к набору данных TES. Кажется, что код для функции инициализации немного неэлегантен (по крайней мере, для меня, действительно должен быть способ сделать код лучше. Помните, что я сказал, похож ли PyTorch API на python (Pythonic)? служебные функции набора данных и даже инициализировать внутренние функции.Чтобы очистить код для набора данных TES, мы обновимTESNamesDatasetкод для достижения следующего:

  • Обновите конструктор, чтобы включить кодировку
  • Создайте внутреннюю функцию для инициализации набора данных
  • Создайте служебную функцию, которая преобразует скаляр в однократный тензор.
  • Создайте служебную функцию, которая преобразует выборочные данные в набор из трех однозначных тензоров расы, пола и имени.

Для корректной работы функции полезности воспользуемсяscikit-learnБиблиотека кодирует числовые значения (т.е. данные об этнической принадлежности, поле и имени). В частности, нам понадобитсяLabelEncoderсвоего рода. Мы внесли ряд обновлений в код, и я объясню эти измененные коды в следующих нескольких подразделах.

import os
from sklearn.preprocessing import LabelEncoder
from torch.utils.data import Dataset
import torch

class TESNamesDataset(Dataset):
    def __init__(self, data_root, charset):
        self.data_root = data_root
        self.charset = charset
        self.samples = []
        self.race_codec = LabelEncoder()
        self.gender_codec = LabelEncoder()
        self.char_codec = LabelEncoder()
        self._init_dataset()

    def __len__(self):
        return len(self.samples)

    def __getitem__(self, idx):
        race, gender, name = self.samples[idx]
        return self.one_hot_sample(race, gender, name)

    def _init_dataset(self):
        races = set()
        genders = set()

        for race in os.listdir(self.data_root):
            race_folder = os.path.join(self.data_root, race)
            races.add(race)

            for gender in os.listdir(race_folder):
                gender_filepath = os.path.join(race_folder, gender)
                genders.add(gender)

                with open(gender_filepath, 'r') as gender_file:
                    for name in gender_file.read().splitlines():
                        self.samples.append((race, gender, name))

        self.race_codec.fit(list(races))
        self.gender_codec.fit(list(genders))
        self.char_codec.fit(list(self.charset))

    def to_one_hot(self, codec, values):
        value_idxs = codec.transform(values)
        return torch.eye(len(codec.classes_))[value_idxs]

    def one_hot_sample(self, race, gender, name):
        t_race = self.to_one_hot(self.race_codec, [race])
        t_gender = self.to_one_hot(self.gender_codec, [gender])
        t_name = self.to_one_hot(self.char_codec, list(name))
        return t_race, t_gender, t_name


if __name__ == '__main__':
    import string

    data_root = '/home/syafiq/Data/tes-names/'
    charset = string.ascii_letters + "-' "
    dataset = TESNamesDataset(data_root, charset)
    print(len(dataset))
    print(dataset[420])

Модифицированная инициализация конструктора

Здесь есть много вариантов конструкторов, поэтому давайте объясним это по частям. Вы могли заметить, что в конструкторе отсутствует логика обработки файлов. Мы перенесли эту логику в_init_datasetфункцию и очистил конструктор. Кроме того, мы добавляем несколько кодировщиков для преобразования необработанных строк в целые числа и обратно.samplesСписок также является пустым списком, мы будем_init_datasetфункция для заполнения списка. Конструктор также принимает новый параметрcharset. Как следует из названия, это просто строка, которую можноchar_codecПреобразовать в целое число.

Обработка файлов была улучшена, чтобы захватывать уникальные теги для расы и пола при просмотре папок. Это полезно, если у вас нет хорошо структурированного набора данных; например, если бы имя аргонианцев не зависело от пола, у нас был бы файл с именем «Неизвестно» и мы поместили бы его в набор пола, независимо от того, имеет ли он другое значение. «Неизвестный» пол существует для расы. После того, как все имена сохранены, мы инициализируем кодировщик набором данных, состоящим из расы, пола и имени.

Вспомогательная функция

Мы добавили две служебные функции:to_one_hotиone_hot_sample.to_one_hotИспользуйте внутренний кодировщик набора данных, чтобы преобразовать список значений в список целых чисел перед вызовом, казалось бы, неуместногоtorch.eyeфункция. На самом деле, это отличный способ быстро преобразовать список целых чисел в вектор.torch.eyeФункция создает единичную матрицу произвольного размера со значениями 1 по диагонали. Если вы проиндексируете строку матрицы, вы получите вектор-строку со значением 1 по этому индексу, что является определением горячего вектора!1_6ae9xOJQPk1DnxHmFfxAPA

Поскольку нам нужно преобразовать три данных в тензоры, мы будем вызывать каждый кодировщик для соответствующих данных.to_one_hotфункция.one_hot_sampleбудетданные одной выборкиПреобразуйте в кортеж тензоров. Раса и пол преобразуются в двумерные тензоры, которые на самом деле являются расширенными векторами-строками. Вектор также преобразуется в двумерный тензор, но двумерный вектор содержит каждый однократный вектор для каждого символа имени.

__getitem__перечислить

Наконец,__getitem__Код функции был обновлен, чтобы работать только вone_hot_sampleЭта функция называется данной расой, полом и именем. Обратите внимание, что нам не нужноsamplesпредварительно подготовить тензоры в списке, но только при вызове__getitem__функция (т.е.DataLoaderформируют тензор при загрузке потока данных). Это делает набор данных очень масштабируемым, когда у вас есть тысячи образцов для загрузки во время обучения.

Вы можете себе представить, как этот набор данных можно использовать в сценариях обучения компьютерному зрению. Набор данных будет иметь список имен файлов и путь к каталогу изображений, что позволяет__getitem__Функция просто считывает файлы изображений и вовремя преобразовывает их в тензоры для обучения. Предоставляя соответствующее количество рабочих потоков,DataLoaderНесколько файлов изображений могут обрабатываться параллельно, что может ускорить его работу.Учебник по загрузке данных PyTorchСуществуют более подробные наборы данных изображений, загрузчики и дополнительные наборы данных. Они сделаныtorchvisionБиблиотека запакована (часто устанавливается вместе с PyTorch).torchvisionИспользуется в компьютерном зрении, упрощая построение конвейеров обработки изображений (таких как отбеливание, нормализация, случайное смещение и т. д.).

Вернуться к оригиналу. Набор данных создан и, похоже, мы готовы использовать его для обучения...

...но у нас нет

Если мы попытаемся использоватьDataLoaderдля загрузки данных с размером пакета больше 1 вы столкнетесь с ошибкой:

1_xwhvq-EptkRLoiqiRY5e3A

您可能已经看到过这种情况,但现实是,文本数据的不同样本之间很少有相同的长度。 результат,DataLoaderПопробуйте объединить несколько тензоров имен разной длины, что невозможно в тензорном формате, как в массивах NumPy. Чтобы проиллюстрировать проблему, рассмотрим следующую ситуацию: когда мы складываем имена вроде «Джон» и «Стивен» вместе, чтобы сформировать единую горячую матрицу. «Джон» преобразуется в размер4xC2D-тензор Стивена преобразован в размер6xC2D-тензор, где C — длина набора символов.DataLoaderпопробуйте сложить эти имена по размеру2x?xC3D тензор (DataLoaderСчитайте размер стека равным1x4xCи1x6xC). Поскольку второе измерение не совпадает,DataLoaderвыдает ошибку, препятствующую продолжению.

возможные решения

Чтобы обойти это, вот два подхода, каждый со своими плюсами и минусами.

  • Установите размер пакета равным 1, чтобы никогда не возникало ошибок. Если размер пакета равен 1, один тензор не будет складываться с любым другим тензором (потенциально) другой длины. Однако этот подход страдает при обучении, потому что нейронная сеть будет очень медленно сходиться с градиентным спуском в одной партии. С другой стороны, это полезно для быстрого тестирования, загрузки данных или тестирования в песочнице, когда размер пакета не важен.
  • Фиксированная длина получается путем дополнения или усечения имени нулевыми символами. Усечение длинных имен или дополнение коротких имен нулевыми символами позволяет правильно сформировать все имена и иметь одинаковый размер выходного тензора, что позволяет выполнять пакетную обработку. С другой стороны, в зависимости от задачи нулевой символ может быть вредным, поскольку он не представляет необработанные данные.

Для целей этой статьи я выберу второй подход, которого можно достичь с минимальными изменениями в общем конвейере данных. Обратите внимание, что это также работает для любых символьных данных различной длины (хотя существуют различные способы заполнения данных, см.NumPyиPyTorchв разделе опций). В моем случае я решил дополнить имя нулями, поэтому я обновил конструктор и_init_datasetфункция:

... 
    def __init__(self, data_root, charset, length):
        self.data_root = data_root
        self.charset = charset + '\0'
        self.length = length
    ...
        with open(gender_filepath, 'r') as gender_file:
            for name in gender_file.read().splitlines():
                if len(name) < self.length:
                    name += '\0' * (self.length - len(name))
                else:
                    name = name[:self.length-1] + '\0'
                self.samples.append((race, gender, name))
    ...

Во-первых, я ввожу в конструктор новый параметр, который фиксирует все входящие символы имени какlengthценность. я также буду\0В набор символов добавлены символы для заполнения кратких имен. Далее была обновлена ​​логика инициализации набора данных. Имена с недостающей длиной используются только\0Прокладывайте до тех пор, пока не будет достигнута необходимая длина. Имена, превышающие фиксированную длину, будут усечены, а последний символ будет заменен на\0. Замена не является обязательной и зависит от конкретной задачи.

Кроме того, если вы попытаетесь загрузить этот набор данных сейчас, вы должны получить то, что ожидали: тензоры в правильном формате размера пакета. На изображении ниже показаны тензоры с размером пакета 2, но обратите внимание, что тензоров три:

1_ADQCaScWubmkFnbTqKd4rw

  • Тензоры гонок с накоплением, форма с горячим кодированием указывает, что тензор является одной из десяти гонок.
  • Сложенные гендерные тензоры, представление одного из двух полов, присутствующих в наборе данных, в горячем кодировании.
  • Сложенные тензоры имен, последнее измерение должно бытьcharset, второе измерение — это длина имени (после фиксированного размера), а первое измерение — размер пакета.

утилита разделения данных

Все эти функции встроены в PyTorch, и это здорово. Вопрос, который может возникнуть сейчас, заключается в том, как сделать валидацию или даже набор тестов, и как выполнить валидацию или тест, не нарушая кодовую базу и сохраняя ее как можно более СУХОЙ. Один из подходов к тестовому набору состоит в том, чтобы предоставить разные обучающие и тестовые данные.data_root, и сохраняйте две переменные набора данных (и два дополнительных загрузчика данных) во время выполнения, особенно если тестирование выполняется сразу после обучения.

Если вы хотите создать проверочный набор из обучающего набора, вы можете использовать утилиту данных PyTorch вrandom_splitФункция справляется с этим легко.random_splitФункция принимает набор данных и список для разделения размера подмножества, функция случайным образом разбивает данные для создания меньшего размера.Datasetобъекты, которые сразу доступны сDataLoaderиспользовать вместе. Вот пример.

Создавайте проверочные наборы, легко разделяя пользовательские наборы данных PyTorch с помощью встроенных функций.

На самом деле вы можете разбивать через произвольные интервалы, что очень полезно для сворачивания наборов перекрестной проверки. Моя единственная претензия к этому методу заключается в том, что вы не можете определить процентное разделение, что раздражает. По крайней мере, размер поднабора данных четко определен с самого начала. Также обратите внимание, что для каждого набора данных требуется отдельныйDataLoader, что определенно чище, чем управление двумя случайно упорядоченными наборами данных и индексами в цикле.

заключительные замечания

Надеюсь, эта статья дала вам представление о том, что делать в PyTorchDatasetиDataLoaderПолезные функции. В сочетании с чистым Pythonic API это может сделать кодирование намного проще и приятнее, обеспечивая при этом эффективный способ работы с данными. Я думаю, что простота использования разработки PyTorch укоренилась в их философии разработки, и после использования PyTorch в моей работе я больше никогда не вернусь к использованию Keras и TensorFlow. Я должен сказать, что мне не хватает индикатора выполнения, который идет с моделью Keras, иfit /predictAPI, но это небольшая неудача, потому что последняяPyTorch с интерфейсом TensorBoardВерните привычную рабочую среду. Тем не менее, на данный момент PyTorch — мой выбор для будущих проектов глубокого обучения.

Я рекомендую создавать свои собственные наборы данных таким образом, потому что это избавляет меня от многих беспорядочных привычек программирования, которые у меня были при управлении данными. В сложных ситуациях,Datasetявляется спасательным кругом. Я помню, что мне приходилось управлять данными, относящимися к одному образцу, но эти данные должны были поступать из трех разных матричных файлов MATLAB, и их нужно было правильно нарезать, нормализовать и транспонировать. если нетDatasetиDataLoaderКомбинация, я не знаю, как с этим справиться, тем более, что объем данных огромен и нет простого способа объединить все данные в матрицу NumPy без сбоя компьютера.

Наконец, см.Страница документации по утилитам данных PyTorch, который содержит другие категории и функции, представляет собой небольшую, но ценную служебную библиотеку. Вы можете найти код для набора данных TES на моем GitHub, где я создаю синхронизацию с набором данных.Предсказатель имени LSTM в PyTorch. Дайте мне знать, была ли эта статья полезной или неясной, и если вы хотели бы больше об этом в будущем.

Оригинальная ссылка:к data science.com/building-EF…

Добро пожаловать на сайт блога Panchuang AI:panchuang.net/

sklearn машинное обучение китайские официальные документы:sklearn123.com/

Добро пожаловать на станцию ​​сводки ресурсов блога Panchuang:docs.panchuang.net/