質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.12%
PyTorch

PyTorchは、オープンソースのPython向けの機械学習ライブラリ。Facebookの人工知能研究グループが開発を主導しています。強力なGPUサポートを備えたテンソル計算、テープベースの自動微分による柔軟なニューラルネットワークの記述が可能です。

解決済

pytorch GPU デバイスエラー

tmc5
tmc5

総合スコア26

PyTorch

PyTorchは、オープンソースのPython向けの機械学習ライブラリ。Facebookの人工知能研究グループが開発を主導しています。強力なGPUサポートを備えたテンソル計算、テープベースの自動微分による柔軟なニューラルネットワークの記述が可能です。

1回答

0リアクション

0クリップ

288閲覧

投稿2022/09/13 17:29

前提

PyTorchでVAEの実装をしています。参考にしているサイトのコードを動かそうとしたところ、デバイスエラーになったため、これを直したいです。よろしくお願いします。
コードは参考サイトのものをコピペしたものになります。
参考サイト

発生している問題・エラーメッセージ

テンソルデータがcpuとgpuに分かれているため、計算できないよというエラーが出ました。デバックモードで確認したところ、xがcpu、yがgpuで動いていることが分かりました。

Traceback (most recent call last): File "/home/kanjouninshiki/code/models/VAE/./vae-MNIST.py", line 151, in <module> lower_bound, _, _ = model(x, device) # VAEにデータを流し込む File "/home/anaconda3/lib/python3.9/site-packages/torch/nn/modules/module.py", line 1130, in _call_impl return forward_call(*input, **kwargs) File "/home/kanjouninshiki/code/models/VAE/./vae-MNIST.py", line 123, in forward reconstruction = torch.sum(x * torch.log(y + self.eps) + (1 - x) * torch.log(1 - y + self.eps)) # 再構成誤差計算 RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cuda:2 and cpu!

該当のソースコード

### ていねいなVAE解説[https://academ-aid.com/ml/vae#index_id18]をそのまま転記しています。 ### 動作を確認するために使用します。 import os # tensorboardの出力先作成 import matplotlib.pyplot as plt # 可視化 import numpy as np # 計算 import torch # 機械学習フレームワークとしてpytorchを使用 import torch.nn as nn # クラス内で利用するモジュールのため簡略化 import torch.nn.functional as F # クラス内で利用するモジュールのため簡略化 from torch import optim # 最適化アルゴリズム from torch.utils.tensorboard import SummaryWriter # tensorboardの利用 from torchvision import datasets, transforms # データセットの準備 # tensorboardのログの保存先 logDir = "./logs" if not os.path.exists(logDir): os.makedirs(logDir) # MNISTのデータをとってくるときに一次元化する前処理 transform = transforms.Compose([transforms.ToTensor(), transforms.Lambda(lambda x: x.view(-1))]) # trainデータとtestデータに分けてデータセットを取得 dataset_train_valid = datasets.MNIST("./", train=True, download=True, transform=transform) dataset_test = datasets.MNIST("./", train=False, download=True, transform=transform) # trainデータの20%はvalidationデータとして利用 size_train_valid = len(dataset_train_valid) # 60000 size_train = int(size_train_valid * 0.8) # 48000 size_valid = size_train_valid - size_train # 12000 dataset_train, dataset_valid = torch.utils.data.random_split(dataset_train_valid, [size_train, size_valid]) # 取得したデータセットをDataLoader化する dataloader_train = torch.utils.data.DataLoader(dataset_train, batch_size=1000, shuffle=True) dataloader_valid = torch.utils.data.DataLoader(dataset_valid, batch_size=1000, shuffle=False) dataloader_test = torch.utils.data.DataLoader(dataset_test, batch_size=1000, shuffle=False) class VAE(nn.Module): def __init__(self, z_dim): """コンストラクタ Args: z_dim (int): 潜在空間の次元数 Returns: None. Note: eps (float): オーバーフローとアンダーフローを防ぐための微小量 """ super(VAE, self).__init__() # VAEクラスはnn.Moduleを継承しているため親クラスのコンストラクタを呼ぶ必要がある self.eps = np.spacing(1) # オーバーフローとアンダーフローを防ぐための微小量 self.x_dim = 28 * 28 # MNISTの場合は28×28の画像であるため self.z_dim = z_dim # インスタンス化の際に潜在空間の次元数は自由に設定できる self.enc_fc1 = nn.Linear(self.x_dim, 400) # エンコーダ1層目 self.enc_fc2 = nn.Linear(400, 200) # エンコーダ2層目 self.enc_fc3_mean = nn.Linear(200, z_dim) # 近似事後分布の平均 self.enc_fc3_logvar = nn.Linear(200, z_dim) # 近似事後分布の分散の対数 self.dec_fc1 = nn.Linear(z_dim, 200) # デコーダ1層目 self.dec_fc2 = nn.Linear(200, 400) # デコーダ2層目 self.dec_drop = nn.Dropout(p=0.2) # 過学習を防ぐために最終層の直前にドロップアウト self.dec_fc3 = nn.Linear(400, self.x_dim) # デコーダ3層目 def encoder(self, x): """エンコーダ Args: x (torch.tensor): (バッチサイズ, 入力次元数)サイズの入力データ Returns: mean (torch.tensor): 近似事後分布の平均 logvar (torch.tensor): 近似事後分布の分散の対数 """ x = F.relu(self.enc_fc1(x)) x = F.relu(self.enc_fc2(x)) return self.enc_fc3_mean(x), self.enc_fc3_logvar(x) def sample_z(self, mean, log_var, device): """Reparametrization trickに基づく潜在変数Zの疑似的なサンプリング Args: mean (torch.tensor): 近似事後分布の平均 logvar (torch.tensor): 近似事後分布の分散の対数 device (String): GPUが使える場合は"cuda"でそれ以外は"cpu" Returns: z (torch.tensor): (バッチサイズ, z_dim)サイズの潜在変数 """ epsilon = torch.randn(mean.shape, device=device) return mean + epsilon * torch.exp(0.5 * log_var) def decoder(self, z): """デコーダ Args: z (torch.tensor): (バッチサイズ, z_dim)サイズの潜在変数 Returns: y (torch.tensor): (バッチサイズ, 入力次元数)サイズの再構成データ """ z = F.relu(self.dec_fc1(z)) z = F.relu(self.dec_fc2(z)) z = self.dec_drop(z) return torch.sigmoid(self.dec_fc3(z)) def forward(self, x, device): """順伝播処理 Args: x (torch.tensor): (バッチサイズ, 入力次元数)サイズの入力データ device (String): GPUが使える場合は"cuda"でそれ以外は"cpu" Returns: KL (torch.float): KLダイバージェンス reconstruction (torch.float): 再構成誤差 z (torch.tensor): (バッチサイズ, z_dim)サイズの潜在変数 y (torch.tensor): (バッチサイズ, 入力次元数)サイズの再構成データ """ mean, log_var = self.encoder(x.to(device)) # encoder部分 z = self.sample_z(mean, log_var, device) # Reparametrization trick部分 y = self.decoder(z) # decoder部分 KL = 0.5 * torch.sum(1 + log_var - mean**2 - torch.exp(log_var)) # KLダイバージェンス計算 reconstruction = torch.sum(x * torch.log(y + self.eps) + (1 - x) * torch.log(1 - y + self.eps)) # 再構成誤差計算 return [KL, reconstruction], z, y # GPUが使える場合はGPU上で動かす device = torch.device("cuda:2" if torch.cuda.is_available() else "cpu") # VAEクラスのコンストラクタに潜在変数の次元数を渡す model = VAE(2).to(device) # 今回はoptimizerとしてAdamを利用 optimizer = optim.Adam(model.parameters(), lr=0.001) # 最大更新回数は1000回 num_epochs = 1000 # 検証データのロスとその最小値を保持するための変数を十分大きな値で初期化しておく loss_valid = 10 ** 7 loss_valid_min = 10 ** 7 # early stoppingを判断するためのカウンタ変数 num_no_improved = 0 # tensorboardに記録するためのカウンタ変数 num_batch_train = 0 num_batch_valid = 0 # tensorboardでモニタリングする writer = SummaryWriter(log_dir=logDir) # 学習開始 for num_iter in range(num_epochs): model.train() # 学習前は忘れずにtrainモードにしておく for x, t in dataloader_train: # dataloaderから訓練データを抽出する lower_bound, _, _ = model(x, device) # VAEにデータを流し込む loss = -sum(lower_bound) # lossは負の下限 model.zero_grad() # 訓練時のpytorchのお作法 loss.backward() optimizer.step() writer.add_scalar("Loss_train/KL", -lower_bound[0].cpu().detach().numpy(), num_iter + num_batch_train) writer.add_scalar("Loss_train/Reconst", -lower_bound[1].cpu().detach().numpy(), num_iter + num_batch_train) num_batch_train += 1 num_batch_train -= 1 # 次回のエポックでつじつまを合わせるための調整 # 検証開始 model.eval() # 検証前は忘れずにevalモードにしておく loss = [] for x, t in dataloader_valid: # dataloaderから検証データを抽出する lower_bound, _, _ = model(x, device) # VAEにデータを流し込む loss.append(-sum(lower_bound).cpu().detach().numpy()) writer.add_scalar("Loss_valid/KL", -lower_bound[0].cpu().detach().numpy(), num_iter + num_batch_valid) writer.add_scalar("Loss_valid/Reconst", -lower_bound[1].cpu().detach().numpy(), num_iter + num_batch_valid) num_batch_valid += 1 num_batch_valid -= 1 # 次回のエポックでつじつまを合わせるための調整 loss_valid = np.mean(loss) loss_valid_min = np.minimum(loss_valid_min, loss_valid) print(f"[EPOCH{num_iter + 1}] loss_valid: {int(loss_valid)} | Loss_valid_min: {int(loss_valid_min)}") # もし今までのlossの最小値よりも今回のイテレーションのlossが大きければカウンタ変数をインクリメントする if loss_valid_min < loss_valid: num_no_improved += 1 print(f"{num_no_improved}回連続でValidationが悪化しました") # もし今までのlossの最小値よりも今回のイテレーションのlossが同じか小さければカウンタ変数をリセットする else: num_no_improved = 0 torch.save(model.state_dict(), f"./z_{model.z_dim}.pth") # カウンタ変数が10回に到達したらearly stopping if (num_no_improved >= 10): print(f"{num_no_improved}回連続でValidationが悪化したため学習を止めます") break # tensorboardのモニタリングも停止しておく writer.close() z_dim = 2 model = VAE(z_dim) cm = plt.get_cmap("tab10") # カラーマップの用意 # 可視化開始 for num_batch, data in enumerate(dataloader_test): fig_plot, ax_plot = plt.subplots(figsize=(9, 9)) fig_scatter, ax_scatter = plt.subplots(figsize=(9, 9)) # 学習済みVAEに入力を与えたときの潜在変数を抽出 _, z, _ = model(data[0], device) z = z.detach().numpy() # 各クラスごとに可視化する for k in range(10): cluster_indexes = np.where(data[1].detach().numpy() == k)[0] ax_plot.plot(z[cluster_indexes,0], z[cluster_indexes,1], "o", ms=4, color=cm(k)) fig_plot.savefig(f"./latent_space_z_{z_dim}_{num_batch}_plot.png") fig_scatter.savefig(f"./latent_space_z_{z_dim}_{num_batch}_scatter.png") plt.close(fig_plot) plt.close(fig_scatter)

試したこと

各xをx.to(device)に変更などしました。
ただ、一部をいじると他のところでまたデバイスエラーがでてしまいます。そもそも手を加えていないサンプルが動かないというのもおかしいと思い、自分の仮想環境が何か悪さしているのではと思っております。特に特別な環境構築ではないです。
参考サイトのコードを動かしたいとき、上記のサンプルコードで動くのか?を教えていただきたいです。(自分の環境に特別問題があるのか否かがまずわからずにいます。)コードに問題があるとすれば教えていただけたら幸いです。

以下のような質問にはリアクションをつけましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

リアクションが多い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

2022/09/14 00:11

こちらの質問が他のユーザーから「やってほしいことだけを記載した丸投げの質問」という指摘を受けました。

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.12%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

PyTorch

PyTorchは、オープンソースのPython向けの機械学習ライブラリ。Facebookの人工知能研究グループが開発を主導しています。強力なGPUサポートを備えたテンソル計算、テープベースの自動微分による柔軟なニューラルネットワークの記述が可能です。