はじめに
多層パーセプトロンのネットワークを使ったシンプルなモデルで自分が用意したデータを学習してほしかった。
そうしたら、エラーがでてきた。
実行環境
- Windows10 64bit
- Anaconda(Spyder)
- Python 3.6.12
- Pytorch 1.7.0
- torchvision 0.8.1
エラー
RuntimeError: Expected object of scalar type Long but got scalar type Double for argument #2 'target' in call to _thnn_nll_loss_forward
上のエラーはだいたいこんなかんじ
「私はLONG型を扱いたいのに渡されてきたのがDouble型でした」
pytorchは基本このLong型を用いるらしい。
学習データのことを指摘しているということは察したのだが、これだけだと一体「入力データ」がDouble型なのか「ラベル」がDouble型なのかわからないので、dtype
を使う
net.train()#訓練モード
for i, (images, labels) in enumerate(train_loader):#学習データを読み込んだ
print(images.dtype)#追加 imagesの型を表示
print(labels.dtype)#追加 labelsの型を表示
imagesは入力データ、labelsはラベルを示している。
ここにはコードを記載していないが、train_loaderはtorch.utils.data.DataLoader
の戻り値(?)である。
先ほどの構文を追加して実行すると、imagesのほうは「torch.float32」と表示した。
これはいわゆるFloat型だ。Doubleではない。
一方、labelsのほうは「torch.float64」と表示。
こっちはDouble型だ。こいつが悪い!
解決方法
for i, (images, labels) in enumerate(train_loader):#学習データを読み込んだ
labels = labels.long()#追加 Long型に変換
単刀直入に書くと、上のコードlabels.long()
を追加するだけ。
この「long」の部分をほかの型(intやfloat等)に変えてあげれば好きな型に変換される。
考察
自分がラベルとして用意したデータはただの整数(具体的に0,1,2の3種類)であったのが、いつの間にかDouble型になっていた。番号を記載したテキストファイルを読み込んでラベルデータを作成したのだが、その際にDouble型にされたのかもしれない。
そう思って、このデータ作成の時点でLong型にするべく、コードを見直した。
numpyの配列(array)にデータが入っているのでこれをLong型に変換する
# yがラベルデータ(numpyのarray)
y = np.dtype('int64').type(y)#追加
yをreturnする前にこの構文を追加した。
int64
としているがlong
でもOK
そうしたら普通にうまくいった。
torch.utils.data.DataLoader
を行う前でも後でも型変換できると分かった。
おわりに
型を変換することについてググったのだが、どのサイトも「作成時に型を指定する方法」しか書いておらず、肝心なもう出来上がっているデータを型変換する方法が載っていなかった。
そのせいなのか、こんな単純なコードのために数日犠牲になったのだが、それもよい経験なんだと思う。
この記事が「サンプルコードを使えば今すぐにオリジナルデータを学習出来るんじゃね?」と思った少年少女達の助けになってくれれば幸いである。
参考文献
第2回 PyTorchのテンソル&データ型のチートシート:PyTorch入門 - @IT
https://www.atmarkit.co.jp/ait/articles/2002/13/news006.html