Graphical Displays: Graphs

The Lens graphs are used to plot values over time. Although their most common use is to watch the error while the network trains, they are quite flexible and can be used for a variety of purposes. Unlike the Unit and Link Viewers, there can be multiple graphs open at the same time.

Creating Graphs

There are several ways to create a graph. The most common is to click on the "New Graph" button on the main window. This is actually a shortcut to the graphObject command, which is the way to create graphs in a script. These commands allow you to create some initial traces. If necessary, you can create an empty graph without any traces using the graph command.

Each graph is identified by an integer, which is returned by the graph creation commands, graph and graphObject, and which is shown in the title bar of the graph window. Graph structures are accessible in the Object Viewer, under the root object, and with the setObject and getObject commands. Graph 2 can be accessed as root.graph(2) or simply graph(2).

Often it is convenient to create a graph of the network's error in your network-building script using the "graphObject error" command. However, if you then re-run this script to rebuild the network, you will end up with a second graph. Therefore, it is a good idea to use this command, which will create a graph only if there are no other graphs:

    if {[graph list] == {}} {graphObject error}


A graph can contain multiple traces. A trace is a set of (x, y) values connected into a continuous series of line segments. Each trace can have its own variable or function, as well as its own color, label, and state. But all of the traces in a graph share the same scale.

You can add a new trace by clicking on Add Trace in either the Graph menu or the properties window, or by using the trace command.

You can change the parameters for the graph and for each trace by clicking on the Properties button on the graph's menubar to open the graph properties window. You can also change them using the Object Viewer or setObject. But if you do change a graph parameter in this way, you may need to refresh the graph for the change to take effect.

A trace can either get its values from a Lens object or from a Tcl procedure. If the Object/Proc field is set to the name of an object in the network, such as "error" or "output:3.input", the value will be taken from that object whenever the trace is updated. However, the object must be of type real, meaning a floating point value.

You can also plot the output of any Tcl procedure that takes no arguments and returns a number. For example, you might define the following procedure:

    proc myError {} {expr log([getObj error])}
Now if you set the Object/Proc of the trace to "myError", you can plot the log of the error. Or, you could skip the procedure definition and just set Object/Proc to "expr log([getObj error])".

As you might imagine, the ability to use arbitrary procedures gives you great flexibility in what you can graph.

If an error occurs in trying to access the object or run the procedure you have specified, you will get an error message and the trace will be deactivated to prevent further error messages.

You can change the color of a trace by clicking on the rectangle after Color in the properties window and using the color dialog window, or by directly setting the trace's color field to the name of a color.

The trace's Label is only used when exporting data from the graph.

Each trace also has three flags that control its state: Active, Visible, and Transient. These are explained later.

Graph Updates

New values are added to the traces in a graph only when it is updated. Normally a graph is updated during testing or training following actions of a certain type. These include ticks, events, examples, weight updates, and progress reports. It would not make much sense to plot the error on ticks, events, or examples, because the error is accumulating over the examples and we are normally only interested in it at the time of a weight update.

However, if you were plotting the activations of units in a continuous network, you might want to update their values every tick or every event.

In the graph properties window, the number after Update Every determines how many update signals must occur before the graph will be updated. If the number is set to 1, the graph will update every time a signal occurs. If it were set to 2, the graph would update every other time a signal occurs. If you only want the graph to update itself occasionally, you might have it update every 10 progress reports, for example.

If the graph is set to update after User Signals, it will be updated when you invoke the graph update command. You might use this to plot the output of a unit only on particular examples. Or you could use it to plot arbitrary functions.

For example, you could create a plot of a sin wave in the following way:

    set g [graphObject {{expr sin(double($i)/10)}}]
    setObject graph($g).fixMin 0
    repeat i 100 {graph update $g}


The x-axis of the graph simply counts the number of updates. Therefore, what the numbers actually refer to depends on how frequently you are updating. Basically, the x-axis just corresponds to update signals.

The Columns parameter (and the graph's cols field) determines the number of X values that will appear in the window.

If there are more values than there are columns, you can use the scrollbar at the bottom to move through the graph. If the traces reach the edge of the window while the graph is being plotted, it will be scrolled automatically.

The y-axis reflects whatever values were returned by the objects or procedures associated with the traces. Max and Min determines the maximum and minimum y-values visible. If set to Auto, they will automatically become the max or min value in the graph. Otherwise, you can fix them at a particular value.

By default, Max is on auto and Min is fixed at 0.

The tick labels on the x- and y-axes are placed automatically. You have no control over this.

If you resize the graph window, the graph will rescale itself to fill the window, but it will not affect the number of columns visible or the min or max values.

Trace States

If a trace is Active, it will add a new point to itself whenever the graph is updated. Otherwise, the trace will remain unchanged.

If a trace is Visible, it will be visible. Otherwise, it will not show up on the graph and will not be printed if you export the graph data.

If a trace is Transient, it will be deleted whenever the graph is cleared.

Storing the Graph

While experimenting with various training parameters, it is nice to compare the learning curves of the network under various conditions. Once the network has trained and you are ready to reset the network and try again, you may want to leave the old error trace on the graph and start drawing a new trace.

In Lens this is known as storing the traces. When a trace is stored, its values are copied to a new trace which is inactive and transient and has a randomly chosen color. The old trace will be cleared so it is ready to start plotting from the beginning.

When the graph is stored, each active trace is stored and the graph's X value is reset to 0. In other words, any new values will be added to active traces starting at the left edge of the graph. You can store a graph by clicking Store Graph in the properties window or the Graph menu or using the "graph store" command.

If you activate the checkbutton next to Store following On Net Reset in the graph properties window, then the graph will be stored automatically whenever you reset the network. This is the default behaviour. If you check both Clear and Store, clear wins.

Clearing the Graph

If you clear a trace, you remove all of its data points. If you clear the graph, every transient trace is deleted, every active trace is cleared, and the graph's X value is reset to 0.

You can clear a graph by clicking Clear Graph in the properties window or the Graph menu or using the "graph clear" command.

If you activate the checkbutton next to Clear following On Net Reset in the graph properties window, then the graph will be cleared automatically whenever you reset the network.

So a typical way to use a graph of error is to train the network repeatedly, storing the graph each time you reset the network. Once you have too many old traces on the graph, you can clear it to get rid of all the old traces and start over fresh.

Hidden Graphs

Unless you are running in batch mode, graphs are visible by default and a window will be created for any new graph. However, graphs can be hidden to remove this window. Hidden graphs continue to update as before, but the updates are much faster because there is no need to draw the graphics. If the graphs are updating frequently, you are worried about training time, and you are not actively watching the graphs update, it is a good idea to hide them.

Graphs can be hidden with the option in the graph's Graph menu or with the "graph hide" command. Hidden graphs are revealed by "graph show".

Printing the Graph

You can print the contents of the graph window as a postscript file with "Graph/Print...". However, due to the way the graph is constructed, the resulting file will not contain the y-axis labels. But this feature may be useful for quick and dirty printouts of your data.

If you want to make a nice looking graph from your data, you can export the data and use a real chart drawing program, as described in the next section.

Exporting Data

The Lens graphs are useful for collecting data and quickly viewing it. If you would like to create nice charts based on the data you collect, it is best to export it to a file and use a third-party chart-making program, like gnuplot or xmgrace, to make a pretty picture.

Graphs can be exported to a file using the "Export Data..." window in the graph's Graph menu, or with the exportGraph command. Lens will export data in one of two formats: tabular or gnuplot. In either format, only visible traces will be included in the output.

The tabular format has tab separated columns. The first column contains the x-values and there is a column for the corresponding value in each visible trace. If you have selected Include Trace Labels, the first row will contain the trace labels.

If a trace is missing a point for a particular x-value, then there will be a "-" in that trace's column. This occurs most frequently when one trace is shorter than the others.

In gnuplot mode, the traces are output one at a time with two blank rows between them. Each trace will have two columns for the x and y values. This format ought to be compatible with gnuplot.

Douglas Rohde
Last modified: Fri Nov 10 18:09:25 EST 2000