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

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

新規登録して質問してみよう
ただいま回答率
85.48%
深層学習

深層学習は、多数のレイヤのニューラルネットワークによる機械学習手法。人工知能研究の一つでディープラーニングとも呼ばれています。コンピューター自体がデータの潜在的な特徴を汲み取り、効率的で的確な判断を実現することができます。

PyTorch

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

メモリリーク

メモリリークは、プログラムファイルがメモリの解放に失敗した時に起こります。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

0回答

1130閲覧

grid-searchによりpythonスクリプトが繰り返し実行される度に、RAM,GPUのメモリが解放されないまま増え続ける

Jeean

総合スコア0

深層学習

深層学習は、多数のレイヤのニューラルネットワークによる機械学習手法。人工知能研究の一つでディープラーニングとも呼ばれています。コンピューター自体がデータの潜在的な特徴を汲み取り、効率的で的確な判断を実現することができます。

PyTorch

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

メモリリーク

メモリリークは、プログラムファイルがメモリの解放に失敗した時に起こります。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/09/20 04:22

grid-searchによりpythonスクリプトが繰り返し実行される度に、RAM,GPUのメモリが増え続ける

はじめまして、当方teratailでの質問が始めてなので、質問の仕方など粗が目立ちますがご了承下さい。

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

GCNというグラフを解析するニューラルネットのモデルがあるのですが、そのGCNというモデルのハイパーパラメータがgrid-searchにより最適化されるまで、モデルの学習とテストを繰り返すようなデモプログラムを作りました。

私の環境ではRAM,GPUのメモリ共に少ないため、モデルの学習が終わる度にメモリの使用量がリセットされるように動作してほしいです。

しかし実際に動かしてみると、モデルの学習が終わっても、メモリがほとんど解放されないまま次のハイパーパラメータでモデルの学習が再開されてしまいます。
そのため、数回モデルの学習を繰り返すとOut of Memoryになります。

PyTorchだけでなく、PyTorch_geometric、ogb、hydraなどthird-partyのライブラリが多く読みにくいかもしれませんが、
どんなアドバイスでも大丈夫なので、解決案や提案など頂ければ幸いです。

該当のソースコード

↓のmain関数により、とある組み合わせのハイパーパラメータによるGCNの学習とテストをします。
これを1セットとして、最適なハイパーパラメータの組み合わせが見つかるまで、grid-searchによりmain関数を繰り返し実行します。
そのため、main関数が終わる度に、つまりある組み合わせのハイパーパラメータによるGCNの学習とテストが終わる度に、RAM,GPUのメモリをリセットするように動作することが理想です。

python

1from tqdm import tqdm 2import hydra 3from omegaconf import DictConfig 4from hydra import utils 5 6import torch 7import torch.nn as nn 8import torch.nn.functional as F 9from torch_scatter import scatter 10from torch_geometric.data import RandomNodeSampler 11from torch_geometric.nn import GCNConv 12from ogb.nodeproppred import PygNodePropPredDataset, Evaluator 13 14 15# GCNのモデルの定義 16class GCN(nn.Module): 17 def __init__(self, cfg): 18 super(GCN, self).__init__() 19 self.dropout = cfg.NN.dropout 20 21 self.convs = nn.ModuleList() 22 self.convs.append(GCNConv(cfg.Dataset.n_feat, cfg.NN.n_hid)) 23 for _ in range(1, cfg.NN.n_layer-1): 24 self.convs.append(GCNConv(cfg.NN.n_hid, cfg.NN.n_hid)) 25 self.convs.append(GCNConv(cfg.NN.n_hid, cfg.Dataset.n_class)) 26 27 def forward(self, x, edge_index): 28 for l, conv in enumerate(self.convs): 29 x = conv(x, edge_index) 30 if l < len(self.convs)-1: # skips relu activate and cfg.dropout iff last layer 31 x = F.relu(x) 32 x = F.dropout(x, self.dropout, training=self.training) 33 34 return x 35 36 37def train(epoch, cfg, loader, model, optimizer, device): 38 # train 39 model.train() 40 criteria = torch.nn.BCEWithLogitsLoss() 41 42 num_batches = len(loader) 43 for batch_id, data in enumerate(loader): # in [g1, g2, ..., g20] 44 data = data.to(device) 45 optimizer.zero_grad() 46 out = model(data.x, data.edge_index) 47 loss = criteria(out[data.train_mask], data.y[data.train_mask]) 48 loss.backward() 49 optimizer.step() 50 51 52@torch.no_grad() 53def test(cfg, loader, model, evaluator, device): 54 model.eval() 55 56 ys, preds = [], [] 57 for data in loader: # only one graph (=g1+g2) 58 data = data.to(device) 59 out = model(data.x, data.edge_index) 60 mask = data['test_mask'] 61 ys.append(data.y[mask].cpu()) 62 preds.append(out[mask].cpu()) 63 64 test_rocauc = evaluator.eval({ 65 'y_true': torch.cat(ys, dim=0), 66 'y_pred': torch.cat(preds, dim=0), 67 })['rocauc'] 68 69 return test_rocauc.item() 70 71 72@hydra.main(config_path='conf', config_name='config') 73def main(cfg: DictConfig): # cfgは全てのハイパーパラメータを辞書型として保持する変数 74 device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') 75 root = utils.get_original_cwd() + '/data/ogbn_proteins' 76 77 # データセットのローディング 78 dataset = PygNodePropPredDataset('ogbn-proteins', root) 79 splitted_idx = dataset.get_idx_split() 80 data = dataset[0] 81 data.node_species = None 82 data.y = data.y.to(torch.float) 83 84 # データセットの前処理 85 row, col = data.edge_index 86 data.x = scatter(data.edge_attr, col, 0, dim_size=data.num_nodes, reduce='add') 87 cfg.Dataset.n_feat = cfg.Dataset.e_feat 88 89 # 各サンプル(今回の場合頂点)を学習とテストどちらに使うかの印を'mask'としてつける 90 for split in ['train', 'valid', 'test']: 91 mask = torch.zeros(data.num_nodes, dtype=torch.bool) 92 mask[splitted_idx[split]] = True 93 data[f'{split}_mask'] = mask 94 95 # ミニバッチをつくる 96 train_loader = RandomNodeSampler(data, num_parts=40, shuffle=True, 97 num_workers=5) 98 test_loader = RandomNodeSampler(data, num_parts=5, num_workers=5) 99 100 # 学習とテストの開始 101 model = GCN(cfg).to(device) 102 optimizer = torch.optim.Adam(params = model.parameters(), 103 lr = cfg.NN.learning_rate) 104 evaluator = Evaluator('ogbn-proteins') 105 106 for epoch in tqdm(range(1, cfg.NN.epochs)): 107 train(epoch, cfg, train_loader, model, optimizer, device) 108 acc = test(cfg, test_loader, model, evaluator, device) 109 print('acc: {:.2f}'.format(acc)) 110 111 return acc 112 113 114if __name__ == "__main__": 115 main()

↑上記のpythonスクリプトで使われるハイパーパラメータは↓このconfig.yamlファイルで設定しています

yaml

1defaults: 2 - override hydra/sweeper: basic 3 4Dataset: &Dataset 5 n_feat: 1 6 e_feat: 8 7 n_class: 112 8 9NN: &NN 10 learning_rate: 0.01 11 epochs: 20 12 n_hid: 256 13 n_layer: 3 14 dropout: 0. 15

↓のようにターミナルで実行すると、hydraというライブラリにより、指定された候補の中から最適なハイパーパラメータの組み合わせを、grid-searchで探索してくれます。

bash

1python3 train.py -m 'NN.learning_rate=choice(0.01,0.001)' 'NN.n_hid=choice(64,128,256)' 'NN.n_layer=range(3,6)'

補足情報

上記のソースコードでは、ミニバッチ学習を行っています。また、このメモリがほとんど解放されないまま学習を繰り返しOut of Memoryを引き起こす問題は、ミニバッチ学習の時限定で置きます。バッチ学習時では毎回ちゃんとRAMメモリが解放されました。

試したこと

下記のように、ガーベージコレクターやpytorchのcudaのキャッシュを消したりなどすると、GPUのメモリについては解放されましたがRAMのメモリは依然として解放されませんでした。

python

1dataset = PygNodePropPredDataset('ogbn-proteins', root) 2# main関数の最後に下記を実行 3del dataset 4torch.cuda.empty_cache() 5gc.collect()

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問