天天看點

PyTorch 學習筆記01 - 20210611一、model.train()和model.eval()用法和差別二、model.test() 與torch.no_grad()的差別三、Python時間測試(time幫助文檔)

一、model.train()和model.eval()用法和差別

例如:定義一個網絡:

# 線性網絡
class Net(nn.Module):
    def __init__(self):
        super(generator, self).__init__()
        self.gen = nn.Sequential(
            nn.Linear(100, 256),
            nn.ReLU(True),
            nn.Linear(256, 256),
            nn.ReLU(True),
            nn.Linear(256, 784),
            nn.Tanh())  # Tanh激活函數是希望生成的假的圖檔資料分布能夠在-1~1之間。

    def forward(self, x):
        x = self.gen(x)
        return x
    
# 執行個體化這個網絡
model = Net()    
# 訓練模式使用.train()
model.train()
# 測試模型使用.eval()
model.eval()
           

(1)model.train()的作用及位置:啟用 Batch Normalization 和 Dropout。

(2)model.eval()的作用:不啟用 Batch Normalization 和 Dropout。model.eval()是保證BN層能夠用全部訓練資料的均值和方差。對于Dropout,model.eval()利用了所有的網絡連接配接,即不随機舍棄神經元。

正确的位置:

for epoch in range(10):
        # train
        model.train()                    
        running_loss = 0.0
        t1 = time.perf_counter()
        for step, data in enumerate(train_loader, start=0):
            images, labels = data
            images = images.to(device)
            labels = labels.to(device)
            optimizer.zero_grad()               # 清空之前的梯度資訊
            outputs = model(images)
            loss = loss_function(outputs, labels)   # 計算loss
            #print(loss.size())
            loss.backward()               # 反向傳播
            optimizer.step()              # 更新所有的參數
            # print statistics
            running_loss += loss.item()
        # validate
        model.eval()      
        acc = 0.0  # accumulate accurate number / epoch
        with torch.no_grad():
            # 關閉 梯度更新  進而節省了GPU算力和顯存       #
            for val_data in validate_loader:
                val_images, val_labels = val_data
                outputs = model(val_images.to(device))
                predict_y = torch.max(outputs, dim=1)[1]
                acc += (predict_y == val_labels.to(device)).sum().item()
            val_accurate = acc / val_num  
            print('[epoch %d] train_loss: %.3f  test_accuracy: %.3f' %
                  (epoch + 1, running_loss / step, val_accurate))
           

二、model.test() 與torch.no_grad()的差別

  1. 在eval模式下,dropout層會讓所有的激活單元都通過,而BN層會停止計算和更新mean和var,直接使用在訓練階段已經學出的mean和var值。
  2. with torch.no_grad()則主要是用于停止autograd子產品的工作,以起到加速和節省顯存的作用。

    作用是停止梯度的更新,進而節省了GPU算力和顯存,但是并不會影響dropout和BN層的行為。

參考連結

三、Python時間測試(time幫助文檔)

1. time.time() 秒

以浮點數形式傳回自紀元以來的時間(**以秒為機關**)。
紀元的具體日期和閏秒的處理取決于平台。
在 Windows 和大多數 Unix 系統上,紀元是 1970 年 1 月 1 日的 00:00:00 (UTC),閏秒不計入紀元以來的時間(以秒為機關)。
這通常稱為 Unix 時間。要找出給定平台上的紀元,請檢視 gmtime(0)。
           

用法:

import time
st = time.time()
time.sleep(5)
et = time.time()
print(et-st)         # 秒
           
PyTorch 學習筆記01 - 20210611一、model.train()和model.eval()用法和差別二、model.test() 與torch.no_grad()的差別三、Python時間測試(time幫助文檔)
PyTorch 學習筆記01 - 20210611一、model.train()和model.eval()用法和差別二、model.test() 與torch.no_grad()的差別三、Python時間測試(time幫助文檔)

2. time.perf_counter() 秒

傳回性能計數器的值(以秒為機關),即具有最高可用分辨率的時鐘以測量短持續時間。

它确實包括睡眠期間經過的時間,并且是系統範圍的。

傳回值的參考點未定義,是以隻有兩次調用結果的差異才有效。

import time
t2 = time.perf_counter()
time.sleep(5) 
t2 = time.perf_counter() - t2
print(f"process_time()用時:{t2} s")  # 包含休眠時間
           
PyTorch 學習筆記01 - 20210611一、model.train()和model.eval()用法和差別二、model.test() 與torch.no_grad()的差別三、Python時間測試(time幫助文檔)
PyTorch 學習筆記01 - 20210611一、model.train()和model.eval()用法和差別二、model.test() 與torch.no_grad()的差別三、Python時間測試(time幫助文檔)

3. time.process_time() 秒

傳回目前程序的系統和使用者 CPU 時間總和的值(以秒為機關)。

它不包括睡眠期間經過的時間。

根據定義,它是流程範圍的。

傳回值的參考點未定義,是以隻有兩次調用結果之間的差異才有效。

import time
t3 = time.process_time()
time.sleep(5)  
t3 = time.process_time() - t3
print(f"process_time()用時:{t3} s")  # 不計休眠時間
           
PyTorch 學習筆記01 - 20210611一、model.train()和model.eval()用法和差別二、model.test() 與torch.no_grad()的差別三、Python時間測試(time幫助文檔)

繼續閱讀