Chunked Data Randomization

bencherian: <p>Hi everyone. I’m trying to implement chunked data randomization in order to effectively randomize a dataset where getting random access to individual samples is impractical. Is there a good/canonical way to do this with the Dataset/DataLoaders classes?</p>
<p>I’m basically trying to do the following:</p>
<p>My dataset of N samples is split into M chunks (where M &lt;&lt; N). I’d like to load K randomly selected chunks into memory and then randomly sample data from those chunks. As approximately one chunk worth of data is exhausted, you’d randomly load an additional chunk and continue to randomly draw samples from the chunks that are in memory.</p>
<p>(As some background, this is essentially how Deserializers in CNTK work, in which dataloading code returns chunks which are then randomized in the manner described above.)</p>
<p>Is there a simple way to do this? Based on my initial read of the documentation the only way to do this is to implement all of this buffering logic in the Sampler.</p>

xzhu1900: <p>Hi Bencherian,</p>
<p>I think Pytorch’s ChunkDataset meets exactly what you need here. It works with a ChunkDataReader to randomly pick chunks, shuffle examples in the chunk and caches them into a internal buffer. Dataloader will retrieve batch data from this buffer. When the buffer is exhausted, ChunkDataset will automatically loads more chunks.</p>
<p>To make this tailored for your data format, all you need to do is to implement your own ChunkDataReader, which knows how to read a single chunk of data with a given index. Pass this class to ChunkDataset and the rest logic is handled by ChunkDataset.</p>
<p>If this is something you are interested in, you can take a look at some example code in the test: DataLoaderTest::ChunkDataSetGetBatch</p>
<p>Hope this helps <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=9" title=":slight_smile:" class="emoji" alt=":slight_smile:"></p>

bencherian: <p>Thanks for the reply <a class="mention" href="/u/xzhu1900">@xzhu1900</a>. I was able to find out that this functionality exists in the C++ API, but I’m not sure how to use that functionality in my Python code as there don’t seem to be any existing bindings. I was told that you can use pybind for this but I’m not exactly sure how to structure that so I can write the <code>ChunkDataReader</code> in Python. Are there any good examples of similar work in the pytorch codebase that might serve as a good example?</p>
<p>Edit:<br>
Soon after writing this I saw that there are PRs under way to create Python bindings for this. For anyone who is interested, see <a href="https://github.com/pytorch/pytorch/pull/21232" rel="nofollow noopener">https://github.com/pytorch/pytorch/pull/21232</a> for details.</p>

xzhu1900: <p>Yep, I was about to mention this PR <img src="https://discuss.pytorch.org/images/emoji/apple/slightly_smiling_face.png?v=9" title=":slightly_smiling_face:" class="emoji" alt=":slightly_smiling_face:"></p>
<p>This change includes the python binding for ChunkDataset and modifies python dataloader to accommodate it. Once it is merged, I think you just need to write the logic to parse your chunk data (ChunkDataReader) in c++ and the rest should be in python.</p>
<p><a class="mention" href="/u/thiagocrepaldi">@thiagocrepaldi</a>  (the PR owner) should be able to answer more questions about this.</p>

thiagocrepaldi: <p>Thanks <a class="mention" href="/u/xzhu1900">@xzhu1900</a>!</p>
<p><a class="mention" href="/u/bencherian">@bencherian</a> based on the PR you mentioned, you could write a chunk datareader entirely in python if and only if your batch is a vector basic types. Currently, there are bindings for the following basic type readers available on python:<br>
<code>ChunkDataReaderDouble,</code> <code>ChunkDataReaderInt16T</code>, <code>ChunkDataReaderInt64T</code>, <code>ChunkDataReaderUint8T</code>, <code>ChunkDataReaderFloat</code>, <code>ChunkDataReaderInt32T</code>, <code>ChunkDataReaderInt8T</code></p>
<p>In that case, you could do this:</p>
<pre><code class="lang-python">import torch

# A batch is a array of floats
class PythonChunkDatareaderDouble(torch._C.data.ChunkDataReaderDouble):
    def __init__(self):
        print('constructor')
    def read_chunk(self, index):
        print('read_chunk {}'.format(index))
    def chunk_count(self):
        print('chunk_count')
        return 0
    def reset(self, size=None):
        print('reset {}'.format(size))

y=PythonChunkDatareaderDouble()
y.reset()
y.chunk_count()
y.read_chunk(0)
</code></pre>

ra312: <p>can you please specify dependencies versions ? I tried with python 3.8 and torch 2.0.1 but get “Traceback (most recent call last):<br>
File “chunk_reader.py”, line 7, in <br>
class PythonChunkDatareaderDouble(torch._C.data.ChunkDataReaderDouble):<br>
AttributeError: module ‘torch._C’ has no attribute ‘data’”</p>