2017-11-21 5 views
1

私はPyTorchで転送学習アプローチを実装しようとしています。これは私が使用しているデータセットです:Dog-Breed転送学習[resnet18]を使用してPyTorch。データセット:Dog-Breed-Identification

ここに私が従うステップがあります。 CSV(labels.csv)

def read_csv(csvf): 
    # print(pandas.read_csv(csvf).values) 
    data=pandas.read_csv(csvf).values 
    labels_dict = dict(data) 
    idz=list(labels_dict.keys()) 
    clazz=list(labels_dict.values()) 
    return labels_dict,idz,clazz 

を読む

1. Load the data and read csv using pandas. 
2. Resize (60, 60) the train images and store them as numpy array. 
3. Apply stratification and split the train data into 7:1:2 (train:validation:test) 
4. use the resnet18 model and train. 

データセットの場所

LABELS_LOCATION = './dataset/labels.csv' 
TRAIN_LOCATION = './dataset/train/' 
TEST_LOCATION = './dataset/test/' 
ROOT_PATH = './dataset/' 

ため、私は、私が使用してデータをロードしていたときに、私は次の言及う制約のこれをしませんでしたDataLoader。

def class_hashmap(class_arr): 
    uniq_clazz = Counter(class_arr) 
    class_dict = {} 
    for i, j in enumerate(uniq_clazz): 
     class_dict[j] = i 
    return class_dict 

labels, ids, class_names = read_csv(LABELS_LOCATION) 
train_images = os.listdir(TRAIN_LOCATION) 
class_numbers = class_hashmap(class_names) 

次に、私はopencvを用い60,60に画像をリサイズし、numpyの配列として結果を格納します。

resize = [] 
indexed_labels = [] 
for t_i in train_images: 
    # resize.append(transform.resize(io.imread(TRAIN_LOCATION+t_i), (60, 60, 3))) # (60,60) is the height and widht; 3 is the number of channels 
    resize.append(cv2.resize(cv2.imread(TRAIN_LOCATION+t_i), (60, 60)).reshape(3, 60, 60)) 
    indexed_labels.append(class_numbers[labels[t_i.split('.')[0]]]) 

resize = np.asarray(resize) 
print(resize.shape) 

ここでは、indexed_labelsに各ラベルに番号を付けます。 1:

次に、I 7にデータを分割する2部

X = resize # numpy array of images [training data] 
y = np.array(indexed_labels) # indexed labels for images [training labels] 

sss = StratifiedShuffleSplit(n_splits=3, test_size=0.2, random_state=0) 
sss.get_n_splits(X, y) 


for train_index, test_index in sss.split(X, y): 
    X_temp, X_test = X[train_index], X[test_index] # split train into train and test [data] 
    y_temp, y_test = y[train_index], y[test_index] # labels 

sss = StratifiedShuffleSplit(n_splits=3, test_size=0.123, random_state=0) 
sss.get_n_splits(X_temp, y_temp) 

for train_index, test_index in sss.split(X_temp, y_temp): 
    print("TRAIN:", train_index, "VAL:", test_index) 
    X_train, X_val = X[train_index], X[test_index] # training and validation data 
    y_train, y_val = y[train_index], y[test_index] # training and validation labels 

次に、私はトーチDataLoaders

batch_size = 500 
learning_rate = 0.001 

train = torch.utils.data.TensorDataset(torch.from_numpy(X_train), torch.from_numpy(y_train)) 
train_loader = torch.utils.data.DataLoader(train, batch_size=batch_size, shuffle=False) 

val = torch.utils.data.TensorDataset(torch.from_numpy(X_val), torch.from_numpy(y_val)) 
val_loader = torch.utils.data.DataLoader(val, batch_size=batch_size, shuffle=False) 

test = torch.utils.data.TensorDataset(torch.from_numpy(X_test), torch.from_numpy(y_test)) 
test_loader = torch.utils.data.DataLoader(test, batch_size=batch_size, shuffle=False) 

# print(train_loader.size) 

dataloaders = { 
    'train': train_loader, 
    'val': val_loader 
} 

次のページに前のステップからのデータをロードし、私はpretrainedロードレンネットモデル。

model_ft = models.resnet18(pretrained=True) 

# freeze all model parameters 
# for param in model_ft.parameters(): 
#  param.requires_grad = False 

num_ftrs = model_ft.fc.in_features 
model_ft.fc = nn.Linear(num_ftrs, len(class_numbers)) 

if use_gpu: 
    model_ft = model_ft.cuda() 
    model_ft.fc = model_ft.fc.cuda() 

criterion = nn.CrossEntropyLoss() 

# Observe that all parameters are being optimized 
optimizer_ft = optim.SGD(model_ft.fc.parameters(), lr=0.001, momentum=0.9) 

# Decay LR by a factor of 0.1 every 7 epochs 
exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1) 

model_ft = train_model(model_ft, criterion, optimizer_ft, exp_lr_scheduler, 
         num_epochs=25) 

そして私はtrain_modelを使用し、方法はPyTorchのドキュメントでhereを説明しました。

しかし、これを実行するとエラーが発生します。

Traceback (most recent call last): 
    File "/Users/nirvair/Sites/pyTorch/TL.py", 
    line 244, in <module> 
     num_epochs=25) 
     File "/Users/nirvair/Sites/pyTorch/TL.py", line 176, in train_model 
     outputs = model(inputs) 
     File "/Library/Python/2.7/site-packages/torch/nn/modules/module.py", line 224, in __call__ 
     result = self.forward(*input, **kwargs) 
     File "/Library/Python/2.7/site-packages/torchvision/models/resnet.py", line 149, in forward 
     x = self.avgpool(x) 
     File "/Library/Python/2.7/site-packages/torch/nn/modules/module.py", line 224, in __call__ 
     result = self.forward(*input, **kwargs) 
     File "/Library/Python/2.7/site-packages/torch/nn/modules/pooling.py", line 505, in forward 
     self.padding, self.ceil_mode, self.count_include_pad) 
     File "/Library/Python/2.7/site-packages/torch/nn/functional.py", line 264, in avg_pool2d 
     ceil_mode, count_include_pad) 
     File "/Library/Python/2.7/site-packages/torch/nn/_functions/thnn/pooling.py", line 360, in forward 
     ctx.ceil_mode, ctx.count_include_pad) 
    RuntimeError: Given input size: (512x2x2). Calculated output size: (512x0x0). Output size is too small at /Users/soumith/code/builder/wheel/pytorch-src/torch/lib/THNN/generic/SpatialAveragePooling.c:64 

私はここで何がうまくいかないのか分からないようです。

+0

あなたがエラーを取得しているラインに言及してください。 –

+0

@WasiAhmad質問が更新されました – nirvair

答えて

1

あなたのネットワークは、使用しているイメージのサイズ(60x60)が深すぎます。ご存知のように、CNNレイヤーは、入力画像がレイヤーを伝播するにつれて、小さくて小さなフィーチャマップを生成します。これは、パディングを使用していないためです。

このエラーは、次のレイヤーが2ピクセル×2ピクセルの512フィーチャマップを期待しているという単純なエラーです。フォワードパスから生成された実際のフィーチャマップは、サイズ0x0の512マップでした。この不一致が原因でエラーが発生しました。

一般に、RESNET-18、Inceptionなどのすべてのストックネットワークは、入力イメージのサイズが224x224(少なくとも)であることが必要です。 torchvision transforms [1]を使って簡単にこれを行うことができます。 [2]の私の答えで説明したように、ハードコードされた特徴ベクトルのサイズを持つAlexNetの例外を除いて、より大きな画像サイズを使うこともできます。

ボーナスヒント:事前設定モードでネットワークを使用している場合は、[3]のpytorchドキュメントのパラメータを使用してデータをホワイトニングする必要があります。

リンク

  1. http://pytorch.org/docs/master/torchvision/transforms.html
  2. https://stackoverflow.com/a/46865203/7387369
  3. http://pytorch.org/docs/master/torchvision/models.html
+0

私はモデルに挿入する前にデータを階層化する必要があるため、トーチビジョン変換ではできません。私のソリューションに代わるものがあれば、それをお勧めしますか? – nirvair

+0

画像のサイズを変更するためにtorchvision変換は必要ありません。あなたは既にOpenCVでこれをやっています。あなたは(60,60)を(224,224)で置き換えるだけです。 私は、pytorchにsklearnインターフェイスを持たないことを認めなければならないのは、その最大の欠点の1つです。それを正しく実行したい場合は、独自のデータローダーを作成し、列車テスト分割のパラメータを含めることをお勧めします。あなたがそれを行う場合は、コードを共有してください。今はよくある質問です。 –

+0

イメージサイズを224に変更した後、ロス機能でエラーが発生します。 'loss.backward()' RuntimeError:cudaランタイムエラー(2):メモリ不足/pytorch/torch/lib/THC/generic/THCStorage.cu:66' – nirvair

関連する問題