機械学習・深層学習モデルの実装で、学習時にlossと一緒に進捗バーを表示するライブラリを作りました。
dlprog
ループ中の進捗バーを表示するライブラリです。ループごとに出力される値を集計し、その平均値を共に表示します。深層学習モデルの学習時に役立ちます。進捗バーと一緒にlossなどをリアルタイムに表示できます。
導入
pip install dlprog
初めにProgress
オブジェクトを生成しておきます。
from dlprog import Progress
prog = Progress()
基本的な使い方
ループの初めにstart()
メソッドを呼び出し、ループ数n_iter
を指定します。ループ内ではupdate()
メソッドを呼び出し、値を渡します。
import random
import time
n_iter = 30
prog.start(n_iter=n_iter)
for _ in range(n_iter):
time.sleep(0.05)
value = random.random()
prog.update(value)
2重ループで使用することもできます。その際はn_epochs
を指定すると良いです。また、値のラベルlabel
を指定することもできます。
n_iter = 30
n_epochs = 3
prog.start(n_iter=n_iter, n_epochs=n_epochs, label="value")
for _ in range(n_epochs):
for _ in range(n_iter):
time.sleep(0.05)
value = random.random()
prog.update(value)
深層学習での使用例
深層学習モデルの実装で使ってみましょう。PyTorchを使った例です。
n_epochs = 3
n_iter = len(train_loader)
prog.start(n_epochs=n_epochs, n_iter=n_iter, label="loss")
for _ in range(n_epochs):
for x, label in train_loader:
optimizer.zero_grad()
y = model(x)
loss = loss_fn(y, label)
loss.backward()
optimizer.step()
prog.update(loss.item())
オプション
より細かい使い方の説明です。
width
バーの幅を指定する引数です。デフォルトは40
です。
n_iter = 10
prog.start(n_iter=n_iter, width=10)
for _ in range(n_iter):
time.sleep(0.1)
value = random.random()
prog.update(value)
1: ########## 100% [00:00:01.05] 0.58703
leave_freq
ログを残す頻度を指定する引数です。デフォルトは1
なので全てのログを残します。
n_epochs = 3
n_iter = 10
prog.start(n_epochs=n_epochs, n_iter=n_iter, leave_freq=4)
for _ in range(n_epochs):
for _ in range(n_iter):
time.sleep(0.1)
value = random.random()
prog.update(value)
4/12: ######################################## 100% [00:00:01.06] 0.34203
8/12: ######################################## 100% [00:00:01.05] 0.47886
12/12: ######################################## 100% [00:00:01.05] 0.40241
unit
エポックの単位を指定する引数です。複数のエポックをまとめられます。
n_epochs = 3
n_iter = 10
prog.start(n_epochs=n_epochs, n_iter=n_iter, leave_freq=4)
for _ in range(n_epochs):
for _ in range(n_iter):
time.sleep(0.1)
value = random.random()
prog.update(value)
1-4/12: ######################################## 100% [00:00:04.21] 0.49179
5-8/12: ######################################## 100% [00:00:04.20] 0.51518
9-12/12: ######################################## 100% [00:00:04.18] 0.54546
n_values
管理する値の数を指定する引数です。デフォルトは1
です。複数の値を指定した場合、update()
には値のリストを渡します。
n_iter = 10
prog.start(n_iter=n_iter, n_values=2)
for _ in range(n_iter):
time.sleep(0.1)
value1 = random.random()
value2 = random.random() * 10
prog.update([value1, value2])
1: ######################################## 100% [00:00:01.05] 0.47956, 4.96049
n_values
の代わりにlabel
を複数指定することもできます。
n_iter = 10
prog.start(n_iter=n_iter, label=['value1', 'value2'], width=20)
for _ in range(n_iter):
time.sleep(0.1)
value1 = random.random()
value2 = random.random() * 10
prog.update([value1, value2])
1: #################### 100% [00:00:01.04] value1: 0.65758, value2: 4.09566
note
バーに表示するメモなどの文字列を指定するする引数です。
n_iter = 10
prog.start(n_iter=n_iter, note='This is a note')
for _ in range(n_iter):
time.sleep(0.1)
value = random.random()
prog.update(value)
1: ######################################## 100% [00:00:01.05] 0.58703, This is a note
memo()
バーに表示するメモなどの文字列を指定するメソッドです。note
と違い、ループ中に変更できます。
defer=True
とすると、イテレーションの最後に呼び出すことができるようになります。
n_epochs = 3
prog.start(
n_epochs=n_epochs,
n_iter=len(trainloader),
label='train_loss',
defer=True,
width=20,
)
for _ in range(n_epochs):
for x, label in train_loader:
optimizer.zero_grad()
y = model(x)
loss = loss_fn(y, label)
loss.backward()
optimizer.step()
prog.update(loss.item())
test_loss = eval_model(model)
prog.memo(f'test_loss: {test_loss:.5f}')
1/3: #################### 100% [00:00:02.83] train_loss: 0.34094, test_loss: 0.18194
2/3: #################### 100% [00:00:02.70] train_loss: 0.15433, test_loss: 0.12987
3/3: #################### 100% [00:00:02.79] train_loss: 0.10651, test_loss: 0.09783
この進捗バーは、n_iter
回目のupdate()
呼び出されたタイミングで次のエポックに進むため、イテレーションの最後(のupdate()
の後)にmemo()
を呼び出すとその文字列は次のエポックのバーに表示されます。defer=True
とすることで、エポックが進むタイミングがmemo()
の呼び出し時に変更されるため、その文字列表示されてからエポックが進みます。
オワリ
おわりです。その他細かい使い方はAPI referenceを参照してください。