• pytorch(六)一些训练技巧


    1.dataloader训练时的num_worker设置(推荐设置为1)

    num_workers = 0 只用主进程main process (训练程序的进程)来加载数据。主进程完成一个batch的前向后向传播,再去disk搬运下一个batch到cpu,然后再转移到GPU。
    num_workers = 1 除了主进程main process外,再开一个额外的进程去disk搬运数据到内存,主进程完成一个batch的前向后向传播后,就可以直接从内存get数据而不是从disk。
    因此num_workers = 1 (共有2个进程,main process + 1 additional process),效果提升明显。20%加速

    2.关于训练数据的归一化(在ET阶段完成,即装入dataloader之前完成。)

    原因:神经网络对于输入在0-1之间时拟合效果最好

    
    train_set = torchvision.datasets.FashionMNIST(
        root='./data'
        ,train=True
        ,download=True
    transform = transforms.Compose(  #将多个transpose的操作组合成一个使用,这里是转化tensor和标准化。
        [transforms.ToTensor(),   #必须先将pil.image或ndarray转化成tensor,才能进行下面的归一化操作。
    #这里如果传进来的是torch.uint8类型即torch.ByteTensor,则transforms.ToTensor底层会自动给其/255.0归一化
         , transforms.Normalize(mean, std)) #这里是标准化输入的是(mean,std)均值和方差,因为是RGB因此mean和std都是(1,3)的vector.Normalized_image = (image - mean)/std
     )
    

    输入归一化的方法

    • 方法一:pixel value直接/255 (tarnsforms.Totensor()对torch.uint8类型的自动处理,不能再显示搞一遍,会导致输入及参数很小,无法收敛
    batch = batch.float()
    batch /= 255.0 
    
    • 方法二:通过计算各通道的均值和标准差来进行各通道的归一化
    n_channels = batch.shape[1]      #通道数
    for c in range(n_channels):
        mean = torch.mean(batch[:,c])   #只取c通道
        std = torch.std(batch[:,c])
        batch[:,c]  =  (batch[:,c]-mean)/std
    
    #结果显示,正规化的数据相同epoch后准率更高,意味着收敛的更快
    #但是不总是成立,可能有些数据不归一化更好,需要试验。
    params = OrderedDict(
          lr = [.01]
        , batch_size = [1000]
        , num_workers = [1]
        , device = ['cuda']
        , trainset = ['not_normal', 'normal']
    )
    m = RunManager()
    for run in RunBuilder.get_runs(params):
    
        device = torch.device(run.device)
        network = Network().to(device)
        loader = DataLoader(
              trainsets[run.trainset]
            , batch_size=run.batch_size
            , num_workers=run.num_workers
        )
        optimizer = optim.Adam(network.parameters(), lr=run.lr)
        
        m.begin_run(run, network, loader)
        for epoch in range(20):
            m.begin_epoch()
            for batch in loader:
                
                images = batch[0].to(device)
                labels = batch[1].to(device)
                preds = network(images) # Pass Batch
                loss = F.cross_entropy(preds, labels) # Calculate Loss
                optimizer.zero_grad() # Zero Gradients
                loss.backward() # Calculate Gradients
                optimizer.step() # Update Weights
                
                m.track_loss(loss, batch)
                m.track_num_correct(preds, labels)
            m.end_epoch()
        m.end_run()
    m.save('results')
    

    3.关于数据的底层存放方式

    • tensor的底层是一维的长向量,张量的索引实现是在长向量基于不同轴的步长实现。
    • tensor和ndaaray都是连续存储,区别是tensor可直接运行在GPU上。
    • 一般的python的序列化的存储容器如list不是连续的内存空间,因此索引等操作效率不高
  • 相关阅读:
    vue实战使用ajax请求后台数据(小白)
    jQuery实现tab栏切换效果
    jQuery下的ajax实例
    数据库之视图更新
    SQL Server 全文索引创建
    SQL Server 分区表
    数据快照 (Database Snapshot)
    FileStream
    ODBC,OLEDB,ADO,ADO.net,JDBC 理解
    拖延症?贪玩?来试试"百万金币时间管理法"
  • 原文地址:https://www.cnblogs.com/Henry-ZHAO/p/13086589.html
Copyright © 2020-2023  润新知