Modifying dataset after creating dataset instance

HiroIshida: <h2>
<a name="problem-1" class="anchor" href="#problem-1"></a>Problem</h2>
<p>I would like to modify the dataset values while in learning. The code below is what I want: modifying the dataset value label in the optimization loop, though the dataset is not MNIST but my research-specific dataset. Of course, the following code <strong>won’t</strong> work as changing <code>labels</code> will not change <code>datasets</code> value iteself.</p>
<p>If anybody in the community try the similar thing, it would be really nice how to do this.</p>
<pre><code class="lang-python">import torch
from torchvision import datasets
from torchvision import transforms
torch.manual_seed(0)

mnist_dataset = datasets.MNIST("/tmp", download=True, transform=transforms.ToTensor()) # whatever
mnist_small_dataset, _ = torch.utils.data.random_split(mnist_dataset, [4, len(mnist_dataset)-4])
loader = torch.utils.data.DataLoader(mnist_small_dataset, batch_size=2, shuffle=False)

for samples in loader:
    _, labels = samples
    # compute loss and backward() and optimize...
    labels[0] = 100000 # whatever
</code></pre>
<h2>
<a name="a-naive-workaround-that-actually-does-not-work-2" class="anchor" href="#a-naive-workaround-that-actually-does-not-work-2"></a>A naive workaround that actually does not work</h2>
<p>Also, a workaround arose to me is like defining a dataset class wrapping the original dataset and return dataset index at the same time as below:</p>
<pre><code class="lang-python">class WorkaroundDataset(torch.utils.data.Dataset):
    def __init__(self, dataset):
        self._dataset = dataset

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

    def __getitem__(self, idx):
        return (*self._dataset[idx], idx)
</code></pre>
<p>Then, I tried to modify the dataset value by indexing, but it’s not possible as each element in sample is <a href="https://github.com/pytorch/pytorch/blob/604e885925af78106e12a3ffd77687da5891761d/torch/utils/data/dataset.py#L246" rel="noopener nofollow ugc">returned by tuple</a>. I could directly modify the source code of pytorch so that it returns list, but it seems dirty and I don’t want to do that.</p>
<pre><code class="lang-python">mnist_dataset = WorkaroundDataset(mnist_dataset)
mnist_small_dataset, _ = torch.utils.data.random_split(mnist_dataset, [4, len(mnist_dataset)-4])
loader_workaround = torch.utils.data.DataLoader(mnist_small_dataset, batch_size=2, shuffle=False)

for samples in loader_workaround:
    _, labels, idxes = samples
    # compute loss and backward() and optimize...
    for idx in idxes:
        mnist_dataset._dataset[idx][1] = 100000 # whatever
</code></pre>

zetyquickly: <p>Hi <a class="mention" href="/u/hiroishida">@HiroIshida</a></p>
<p>Your workaround approach is quite ok.</p>
<p>Why don’t you try:</p>
<ol>
<li>to inherit <code>WorkaroundDataset</code> from <code>datasets.MNIST</code>,</li>
<li>properly call a constructor of the parent class in the <code>__init__</code>,</li>
<li>then just override <code>__getitem__</code> to get item from a <code>super</code>'s <code>__getitem__</code>
</li>
<li>and finally do your stuff with labels before the return of <code>__getitem__</code>
</li>
</ol>