Load new training files after previous one is exhausted

HelixPiano: <p>Hello everyone,<br>
I know that something like this was asked before, but I never saw any details (maybe I missed it. Feel free to point me to the right thread).</p>
<p>I have 60 data sets with hourly data split by year. They are in total around 60GB, so too large to load into memory.<br>
I should be able to load 4 of them at a time.<br>
My current idea is to change the data class in a way that it loads new files once the current training set is exhausted.<br>
So basically: load 4 years of data → train on the daily data → load the next 4 years → continue training → … → finish epoch.</p>
<p>My questions are:</p>
<ol>
<li>I assume that saving the data sets in pytorch format is the fastest way for training, so that I don’t have to convert them to pytorch data everytime?</li>
<li>How/where does the dataloader keep track of which indices he used and how many are still available?</li>
<li>My current idea would be to somehow tell the dataset class once it used all indices to load the next data sets and reset the internal index tracker of the dataloader. Does this idea work at all and how would I pull this off? Or would I rather create some sort of custom dataloader?</li>
</ol>
<p>My current dataset class is very simple</p>
<pre><code class="lang-auto">class MyDataset(Dataset):
    def __init__(self, data, labels):
        self.data = data
        self.targets = torch.LongTensor(labels)

    def __getitem__(self, index):
        x = self.data[index]
        y = self.targets[index]

        return x, y

    def __len__(self):
        return len(self.data)</code></pre>

shivammehta007: <p>I think a better approach would be to define multiple <code>MyDataset</code> and use <code>torch.utils.data.ConcatDataset</code> <a href="https://pytorch.org/docs/stable/data.html#torch.utils.data.ConcatDataset" rel="noopener nofollow ugc">(link)</a> to concatenate them all the dataloader will only put only one batch at a time in the memory.</p>

HelixPiano: <p>Thank you for the suggestion. I have several questions on your approach, because I am new to pytorch.</p>
<ol>
<li>
<p>Does ConcatDataset actually concat (load them all into memory and create one large data set) the dataset or basically just link them (tell the data loader to treat all the data classes as one data set)? As I said: I can’t read all the data into memory at the same time due to the size.</p>
</li>
<li>
<p>If I concat the datasets, does it then only pick from one dataset until it has used everything and then moves on to the next?</p>
</li>
<li>
<p>If I create multiple MyDataset classes with the different data, do I have to somehow prevent it from loading the data at the point of the creation?</p>
</li>
</ol>
<p>Sorry for all the questions, I am just worried about the available amount of RAM and try to understand how these systems work.</p>

shivammehta007: <p>So, torch’s datasets should not load everything in memory, the dataloader’s num workers call the <code>__getitem__</code> method of each dataset and should be responsible for putting the data into the memory. (To confirm make sure that you are not loading all data in the <code>__init__</code> function of <code>Dataset</code> it should just have a metadata file in which you have a location of the actual datapoint which you load with the get_item method. The example is below ).</p>
<ol>
<li>ConcatDataset, therefore, doesn’t puts anything into the memory but just links them together.</li>
<li>If you turn off shuffle in Dataloader then this should be the expected behaviour</li>
<li>As I said before as long as you don’t load data in the <code>__init__</code> function and just metadata pointing to the datapoint at a certain index. a common approach is to have a CSV file with a filename, which you load in init instead and then you load it in the getitem, My idea would be to do something like:</li>
</ol>
<pre><code class="lang-python">class MyDataset(Dataset):
    def __init__(self, metadata_file_loc):
        self.data = pd.read_csv(metadata_file_loc)

    def __getitem__(self, index):
        x = torch.load(self.data['location'][i])
        y = self.data['target'][i]
        return x, y

    def __len__(self):
        return len(self.data)
</code></pre>
<p>So you actually do not load the entire data but rather iterate over it as it should be with large datasets.</p>
<p>Where <code>metadata.csv</code>should have format similar to</p>
<pre><code class="lang-auto">location, target
1.png, 0
2.png, 0
3.png, 1
...
</code></pre>

HelixPiano: <p>Ah that explains a couple of things and is an interesting approach.<br>
The only problem is that this approach might not work that well for me.<br>
My files contain one large numpy array each (size is like 365x24x173x373). I could do your approach by creating a new numpy file (or pytorch file) for each day, but this would result in 22,000 separate files and I am not sure on the performance implications.<br>
I just saw that <a href="https://numpy.org/doc/stable/reference/generated/numpy.memmap.html" rel="noopener nofollow ugc">numpy.memmap</a> is a thing. Maybe I could get it working in a certain way, but it is actually a function and not a file that would get loaded.</p>