2つの画像を取り込むシャムネットワークを実装しようとしています。これらのイメージをロードして、2つの個別のデータローダーを作成します。
私のループでは、両方のデータローダーを同時に通過させて、両方のイメージでネットワークをトレーニングできるようにします。
for i, data in enumerate(Zip(dataloaders1, dataloaders2)):
# get the inputs
inputs1 = data[0][0].cuda(async=True);
labels1 = data[0][1].cuda(async=True);
inputs2 = data[1][0].cuda(async=True);
labels2 = data[1][1].cuda(async=True);
labels1 = labels1.view(batchSize,1)
labels2 = labels2.view(batchSize,1)
# zero the parameter gradients
optimizer.zero_grad()
# forward + backward + optimize
outputs1 = alexnet(inputs1)
outputs2 = alexnet(inputs2)
データローダーの戻り値はタプルです。ただし、Zip
を使用してそれらを反復しようとすると、次のエラーが発生します。
OSError: [Errno 24] Too many open files
Exception NameError: "global name 'FileNotFoundError' is not defined" in <bound method _DataLoaderIter.__del__ of <torch.utils.data.dataloader._DataLoaderIter object at 0x7f2d3c00c190>> ignored
Zipはすべての反復可能なアイテムで機能しないのですか?しかし、ここではデータローダーでは使用できないようです。
これを追求する他の方法はありますか?または、シャムのネットワークの実装に間違ってアプローチしていますか?
適切なデータローダー機能を作成するのに苦労しているようです。私はやります:
class Siamese(Dataset):
def __init__(self, transform=None):
#init data here
def __len__(self):
return #length of the data
def __getitem__(self, idx):
#get images and labels here
#returned images must be tensor
#labels should be int
return img1, img2 , label1, label2
@ManojAcharyaの回答を完了するには:
発生しているエラーは、Zip()
またはDataLoader()
のどちらからも直接発生しません。 Pythonは、要求しているデータファイル(例外トレースのFileNotFoundError
を参照)の1つがおそらくDataset
。
DataLoader
とZip
を一緒に使用した実用的な例を以下に示します。データをシャッフルしたい場合、2つのデータセット間の対応を維持することが難しくなることに注意してください。これは@ManojAcharyaのソリューションを正当化します。
import torch
from torch.utils.data import DataLoader, Dataset
class DummyDataset(Dataset):
"""
Dataset of numbers in [a,b] inclusive
"""
def __init__(self, a=0, b=100):
super(DummyDataset, self).__init__()
self.a = a
self.b = b
def __len__(self):
return self.b - self.a + 1
def __getitem__(self, index):
return index, "label_{}".format(index)
dataloaders1 = DataLoader(DummyDataset(0, 9), batch_size=2, shuffle=True)
dataloaders2 = DataLoader(DummyDataset(0, 9), batch_size=2, shuffle=True)
for i, data in enumerate(Zip(dataloaders1, dataloaders2)):
print(data)
# ([tensor([ 4, 7]), ('label_4', 'label_7')], [tensor([ 8, 5]), ('label_8', 'label_5')])
# ([tensor([ 1, 9]), ('label_1', 'label_9')], [tensor([ 6, 9]), ('label_6', 'label_9')])
# ([tensor([ 6, 5]), ('label_6', 'label_5')], [tensor([ 0, 4]), ('label_0', 'label_4')])
# ([tensor([ 8, 2]), ('label_8', 'label_2')], [tensor([ 2, 7]), ('label_2', 'label_7')])
# ([tensor([ 0, 3]), ('label_0', 'label_3')], [tensor([ 3, 1]), ('label_3', 'label_1')])
データセットの長さがさまざまで、すべてを同じエポックで通過させたい場合の@Aldreamのソリューションを追加すると、itertools
からcycle()
を使用できます。a= Python標準ライブラリ。@ Aldremのコードスニペットを使用すると、更新されたコードは次のようになります。
_from torch.utils.data import DataLoader, Dataset
from itertools import cycle
class DummyDataset(Dataset):
"""
Dataset of numbers in [a,b] inclusive
"""
def __init__(self, a=0, b=100):
super(DummyDataset, self).__init__()
self.a = a
self.b = b
def __len__(self):
return self.b - self.a + 1
def __getitem__(self, index):
return index
dataloaders1 = DataLoader(DummyDataset(0, 100), batch_size=10, shuffle=True)
dataloaders2 = DataLoader(DummyDataset(0, 200), batch_size=10, shuffle=True)
num_epochs = 10
for Epoch in range(num_epochs):
for i, data in enumerate(Zip(cycle(dataloaders1), dataloaders2)):
print(data)
_
Zip()
のみでは、長さが最小のデータセット(ここでは100)と等しい場合、イテレータが使い果たされます。ただし、cycle()
を使用すると、イテレータが最大のデータセット(ここでは200)のすべてのサンプルを調べない限り、最小のデータセットを再度繰り返します。
追伸ランダムにサンプルを抽出する限り、収束を達成するためにこのアプローチは必要ないかもしれないと常に主張することができますが、このアプローチを使用すると、評価がより簡単になるかもしれません。
それがすでに述べられていることに加えて、cycle()
およびZip()
は、メモリリークの問題を引き起こす可能性があります-特に画像データセットを使用して!それを解決するには、次のように繰り返す代わりに:
dataloaders1 = DataLoader(DummyDataset(0, 100), batch_size=10, shuffle=True)
dataloaders2 = DataLoader(DummyDataset(0, 200), batch_size=10, shuffle=True)
num_epochs = 10
for Epoch in range(num_epochs):
for i, (data1, data2) in enumerate(Zip(cycle(dataloaders1), dataloaders2)):
do_cool_things()
あなたは使うことができます:
dataloaders1 = DataLoader(DummyDataset(0, 100), batch_size=10, shuffle=True)
dataloaders2 = DataLoader(DummyDataset(0, 200), batch_size=10, shuffle=True)
num_epochs = 10
for Epoch in range(num_epochs):
dataloader_iterator = iter(dataloaders1)
for i, data1 in enumerate(dataloaders2)):
try:
data2 = next(dataloader_iterator)
except StopIteration:
dataloader_iterator = iter(dataloaders1)
data2 = next(dataloader_iterator)
do_cool_things()
ラベルも使用する場合は、この例ではdata1
と(inputs1,targets1)
およびdata2
とinputs2,targets2
、@ Sajad Norouziが言ったように。
これにKUDOS: https://github.com/pytorch/pytorch/issues/1917#issuecomment-433698337
2つのデータセットを同時に反復処理する場合は、以下のようにTensorDatasetを使用するだけで、独自のデータセットクラスを定義する必要はありません。
dataset = torch.utils.data.TensorDataset(dataset1, dataset2)
dataloader = DataLoader(dataset, batch_size=128, shuffle=True)
for index, data in enumerate(dataloader):
xb1, xb2 = data
....
ラベルが必要な場合、または3つ以上のデータセットを反復処理する場合は、dataset2の後にTensorDatasetへの引数としてそれらをフィードします。