Набор данных PyTorch и Conv1d, использующий тонну памяти - PullRequest
0 голосов
/ 27 апреля 2020

Я пытаюсь написать сверточную нейронную сеть в pytorch. Я очень плохо знаком с машинным обучением и PyTorch, поэтому я не очень знаком с пакетом.

Я написал собственный набор данных, и он правильно загрузил мои данные из файла CSV. Однако, когда я загружаю его в загрузчик данных, мой системный монитор показывает python, используя огромный объем памяти. В настоящее время я использую только часть моего набора данных, и один экземпляр использует около 5 гигабайт в качестве загрузчика данных.

Мой набор данных - это одномерные тензоры. Каждый из них очень длинный - около 33 миллионов значений. Я использовал sys.getsizeof(train_set.sample_list[0][0].storage()), чтобы проверить размер базового тензора, и он был всего 271 мегабайт.

Кроме того, если я продолжу и создаю экземпляр моего CNN, инициализатор пожирает память, пока мое ядро ​​не падает , Причина этого мне неясна.

Вот код для моего пользовательского набора данных:


    def __init__(self, csv_file, train):

        self.train = train
        self.df_tmp = pd.read_csv(csv_file, header=None, sep='\t')
        self.df_tmp.drop(self.df_tmp.shape[1]-1, axis=1, inplace=True)
        self.df = self.df_tmp.transpose()
        self.sample_list = []

        for i in range(self.df.shape[0]): #num rows,  33 million ish 
            sample = torch.tensor([self.df.iloc[i][1:].values])
            label = torch.tensor(self.df.iloc[i][0])
            self.sample_list.append((sample, label))

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

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

И код для NN:


    #input batch shape is (9 x 33889258 x 1)
    def __init__(self):
        super(CNN, self).__init__()

        #input channels 1, output 3
        self.conv1 = torch.nn.Conv1d(1, out_channels=3, kernel_size=(100), stride=10, padding=1)

        #size in is 3,1,33889258
        self.pool = torch.nn.MaxPool1d(kernel_size=2, stride=2, padding=0)

        self.fc1 = torch.nn.Linear(45750366, 1000) #3 * 1 * 3388917

        self.fc2 = torch.nn.Linear(1000, 2)


    def forward(self, x):
        #size: (1x1x33889258) to (3x1x33889258)
        tmp = self.conv1(x.float())
        x = F.relu(tmp) #


        x = self.pool(x)
        #whatever shape comes out of here needs to go into x.view

        x = x.view(45750366) #-1, 1*1*3388927
        x = self.fc1(x)
        x = F.relu(x)

        x = self.fc2(x)
        return(x) 

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

1 Ответ

2 голосов
/ 27 апреля 2020

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

def __init__(self, csv_file, train):

    self.train = train
    self.df_tmp = pd.read_csv(csv_file, header=None, sep='\t')
    self.df_tmp.drop(self.df_tmp.shape[1]-1, axis=1, inplace=True)
    self.df = self.df_tmp.transpose()

def __len__(self):
    return self.df.shape[0]

def __getitem__(self, idx):
    sample = torch.tensor([self.df.iloc[idx][1:].values])
    label = torch.tensor(self.df.iloc[idx][0])
    return sample, label

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...