pytorch uses visdom to visualize loss

Introduction

visdom is a visualization tool developed by Facebook specifically for PyTorch, which was open sourced in March 2017. Visdom is very lightweight, but it supports very rich functions and is capable of most scientific computing visualization tasks.
Visdom can create, organize and share a variety of data visualizations, including values, images, text, and even video. It supports PyTorch, Torch and Numpy. Users can organize the visualization space through programming, or create dashboards for live data through the user interface, check experiment results or debug code.
Note that it does not support Python's int and float types, so you need to convert to ndarray or tensor first.

Visdom core concepts

There are two important concepts in Visdom:

env:surroundings. The visualization results of different environments are isolated from each other and do not affect each other. If env is not specified during use, main is used by default. Different users and different programs generally use different envs.
pane:Pane. The pane can be used to visualize images, values, or print text, etc. It can be dragged, zoomed, saved, and closed. A program can use different panes in the same env, and each pane can visualize or record certain information.

When using, first create an env, and then create a pane in the env. For example, the following viz is the created env object, the name of the env is test2, and then the pane can be created in the env of test2 through the api of viz. For example, viz.text creates a pane or textwindow, and its id is randomly generated.

viz=visdom.Visdom(env=u'test2')
textwindow=viz.text('Hello World!')

Of course, you can also manually name the viz, and you can name the pane through the win attribute, so that you can modify the pane according to this id later.
(If you do not actively name the id, you can also pass the variable name as the id to win, so that you can also modify the previous one)

updatetextwindow = viz.text('Hello World! More text should be here')
viz.text('And here it is', win=updatetextwindow, append=True)
#设置了id的
viz.text("this pane has win id setted",win="new pane")
viz.text('new word',win="new pane",append=True)

result:
Insert picture description here

visdom operation

As a client object, viz can use common drawing functions, including:

line: z is similar to the plot operation in Matlab, used to record changes in certain scalars, such as loss, accuracy, etc.
image: a visualization picture, which can be an input picture, a GAN generated picture, or a convolution kernel The information
text: used to record text information such as logs, supports html format
histgram: visualized distribution, mainly to view the distribution of data and parameters
scatter: draw a scatter chart
bar: draw a bar chart
pie: draw a pie chart
Insert picture description here

When using it directly viz.XXX(), and then pass in the parameters.
For more operations, please refer to the github homepage of visdom.
This mainly introduces the common line, image and text operations in deep learning.

The parameters of the above operations are generally different, but there are two parameters that most operations have:

win : Used to specify the name of the pane. If not specified, visdom will automatically assign a new pane. If the win name specified in the two operations is the same, the new operation will overwrite the content of the current pane, so it is recommended to re-specify win for each operation.
opts : options, receive a dictionary, common options include title, xlabel, ylabel, width, etc., which are mainly used to set the display format of pane.
As mentioned before, each operation will overwrite the previous value, but often we need to constantly update the value during the training of the network, such as the loss value, then we need to specify the parameter update='append' to avoid overwriting the previous value . In addition to using the update parameter, you can also use the vis.updateTrace method to update the graph, but updateTrace can not only add a trace that is independent of the existing data on the specified pane, but also be in the same item like update='append' Add data to the trace.

viz.line example

In the example here, draw two lines in a pane L 1 = 2 x + 1 L_1=2x+1L1=2 x+1 sumL 2 = 2 x 2 − x L_2 = 2x ^ 2-xL2=2 x2The shape of x , X and Y must be the same, they are all N2, each line has N points, and one point corresponds to (X, Y), so the two lines are N2.

viz=visdom.Visdom(env="demo")
L=np.array([[2*x+1,2*x**2-x] for x in np.arange(1,10)])
X=np.array([[x,x] for x in np.arange(1,10)])
viz.line(X=X,Y=L,win="lossdemo",opts=dict(
    xlabel="Iteration",
    ylabel="Loss",
    title="xxmodel",
    legend=["Loss1","Loss2"]
    
))

result:
Insert picture description here

visdom visualizes loss during training

Here is a demo showing how to dynamically display loss changes during training. Considering that the loss in target detection is usually composed of two (location and classification loss), the demo given here is to display location loss and classification at the same time There are 3 changes in loss and total loss, which is a case of 3 lines, and can be presented according to epoch and iteration changes (in two different panes respectively). In the case, the code to create the pane is encapsulated, and then the visualization is controlled through the command line.

The code for the training part of the demo given here is incomplete, and will be added later if necessary. *

Functions for creating and updating panes

#create the vis,with initialized 0
def create_vis_plot(_xlabel, _ylabel, _title, _legend):
    return viz.line(
        X=torch.zeros((1,)).cpu(),
        Y=torch.zeros((1, 3)).cpu(),
        opts=dict(
            xlabel=_xlabel,
            ylabel=_ylabel,
            title=_title,
            legend=_legend
        )
    )

#update visdom plot
def update_vis_plot(iteration, loc, conf, window1, window2, update_type,
                    epoch_size=1):
    viz.line(
        X=torch.ones((1, 3)).cpu() * iteration,
        Y=torch.Tensor([loc, conf, loc + conf]).unsqueeze(0).cpu() / epoch_size,
        win=window1,
        update=update_type
    )
    # initialize epoch plot on first iteration
    if iteration == 0:
        viz.line(
            X=torch.zeros((1, 3)).cpu(),
            Y=torch.Tensor([loc, conf, loc + conf]).unsqueeze(0).cpu(),
            win=window2,
            update=True
        )
        

Some specific codes of training are simplified here, just roughly write down the process

import argparse

# 解析
def str2bool(v):
    return v.lower() in ("yes", "true", "t", "1")
parser = argparse.ArgumentParser(
    description='Single Shot MultiBox Detector Training With Pytorch')
parser.parser.add_argument('--visdom', default=False, type=str2bool,
                    help='Use visdom for loss visualization')
 #这里还能输入其它可解析的参数
args = parser.parse_args()
# initialize
if args.visdom:
    import visdom
    viz = visdom.Visdom()
    vis_title = 'SSD.PyTorch on ' + dataset.name
    vis_legend = ['Loc Loss', 'Conf Loss', 'Total Loss']
    iter_plot = create_vis_plot('Iteration', 'Loss', vis_title, vis_legend)
    epoch_plot = create_vis_plot('Epoch', 'Loss', vis_title, vis_legend)
    
#初始化这些dataset,model,optimizer,lr_scheduler,loss_function,dataloader,device,
#epoch_size=len(dataset) // args.batch_size
model.train()
for epoch in total_epoch:
    loss_conf=0
    loss_loc=0
    for iteration, batch in enumerate(dataloader):
        ....
        if args.visdom and iteration != 0 and (iteration % epoch_size == 0):
            update_vis_plot(epoch, loc_loss, conf_loss, epoch_plot, None,
                            'append', epoch_size)        
        images,targets=batch[0],batch[1]
        with  torch.no_grad():
            #toTensor,and to(device)
            
        optimizer.zero_grad()
        output=model(output)
        
        lossc,lossl=loss_function(output,target)
        loss = loss_l + loss_c
        loss.backword()
        optimizer.step()
        loc_loss += loss_l.data[0]
        conf_loss += loss_c.data[0]
        if args.visdom:
            update_vis_plot(iteration, loss_l.data[0], loss_c.data[0],
                            iter_plot, epoch_plot, 'append')        
    torch.save(model.state_dict(),"path/to/save.pth")

Written at the end:

For command line parsing, you can refer to the official Python source code: argparse — parser for command line options, parameters and sub-commands . The arg parameter type added by default is str, but if you need other types such as int, you need to change the type. If you want to change it to bool You need to write a parsing function and pass it to type, as in this example, because its own mechanism for converting bool is to convert null characters to False, and others to True.

About visdom in other operations groups, such as scatter plots, you can go and see their official website case .

Guess you like

Origin blog.csdn.net/yanghao201607030101/article/details/112748898