PyTorch 学习笔记01 - 20210611

一、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_第1张图片
PyTorch 学习笔记01 - 20210611_第2张图片

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_第3张图片
PyTorch 学习笔记01 - 20210611_第4张图片

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_第5张图片

你可能感兴趣的:(Python,Pytorch,python,机器学习,深度学习,pytorch)