3)plotting繪圖
我們已經包裝了幾種常見的plot類型,以便輕松創建基本的可視化。這些可視化是由Plotly驅動的。
Visdom支持下列API。由 Plotly 提供可視化支持。
- vis.scatter : 2D 或 3D 散點圖
- vis.line : 線圖
- vis.stem : 莖葉圖
- vis.heatmap : 熱力圖
- vis.bar : 條形圖
- vis.histogram: 直方圖
- vis.boxplot : 箱型圖
- vis.surf : 表面圖
- vis.contour : 輪廓圖
- vis.quiver : 繪出二維矢量場
- vis.mesh : 網格圖
這些API的確切輸入類型有所不同,盡管大多數API 的輸入包含,一個tensor X(保存數據)和一個可選的tensor Y(保存標簽或者時間戳)。所有的繪圖函數都接收一個可選參數win,用來將圖畫到一個特定的Pane上。每個繪圖函數也會返回當前繪圖的win。您也可以指定繪出的圖添加到哪個env上。
Visdom同時支持PyTorch的tensor和Numpy的ndarray兩種數據結構,但不支持Python的int、float等類型,因此每次傳入時都需先將數據轉成ndarray或tensor。上述操作的參數一般不同,但有兩個參數是絕大多數操作都具備的:
- win:用於指定pane的名字,如果不指定,visdom將自動分配一個新的pane。如果兩次操作指定的win名字一樣,新的操作將覆蓋當前pane的內容,因此建議每次操作都重新指定win。
- opts:選項,接收一個字典,常見的option包括
title
、xlabel
、ylabel
、width
等,主要用於設置pane的顯示格式。
之前提到過,每次操作都會覆蓋之前的數值,但往往我們在訓練網絡的過程中需不斷更新數值,如損失值等,這時就需要指定參數update='append'
來避免覆蓋之前的數值。
而除了使用update參數以外,還可以使用vis.updateTrace
方法來更新圖,但updateTrace
不僅能在指定pane上新增一個和已有數據相互獨立的Trace,還能像update='append'
那樣在同一條trace上追加數據。
Customizing plots
繪圖函數接受一個可選的opts表作為輸入,可用於更改繪圖的(通用的或特定於繪圖的)屬性。所有輸入參數在一個表中指定;輸入參數是基於它們在輸入表中擁有的鍵進行匹配的。
1> plot.scatter
這個函數是用來畫2D或3D數據的散點圖。它需要輸入 N*2或N*3的張量 X來指定N個點的位置。一個可供選擇的長度為N的向量用來保存X中的點對應的標簽(1 到 K)。 – 標簽可以通過點的顏色反應出來。
update可用於有效地更新現有圖的數據。使用'append'附加數據,'replace'使用新數據,或'remove'刪除按名稱指定的跟蹤。如果不存在update='append',則使用update='append'將創建一個繪圖,否則將追加到現有繪圖。如果更新單個跟蹤,請使用name指定要更新的跟蹤的名稱。忽略所有NaN的更新數據(可用於屏蔽更新)。
scatter()支持下列的選項:
- opts.markersymbol: 標記符號 (string; default = 'dot')
- opts.markersize : 標記大小(number; default = '10')
- opts.markercolor : 每個標記的顏色. (torch.*Tensor; default = nil)
- opts.legend : 包含圖例名字的table
- opts.textlabels : 每一個點的文本標簽 (list: default = None)
- opts.layoutopts : 圖形后端為布局接受的任何附加選項的字典. 比如 layoutopts = {'plotly': {'legend': {'x':0, 'y':0}}}.
- opts.traceopts : 將跟蹤名稱或索引映射到plot.ly為追蹤接受的附加選項的字典. 比如 traceopts = {'plotly': {'myTrace': {'mode': 'markers'}}}.
- opts.webgl : 使用WebGL繪圖(布爾值;default= false。如果一個圖包含太多的點,它會更快。要謹慎使用,因為瀏覽器不會在一個頁面上允許多個WebGL上下文。
options.markercolor 是一個包含整數值的Tensor。Tensor的形狀可以是 N 或 N x 3 或 K 或 K x 3.
- Tensor of size N: 表示每個點的單通道顏色強度。 0 = black, 255 = red
- Tensor of size N x 3: 用三通道表示每個點的顏色。 0,0,0 = black, 255,255,255 = white
- Tensor of size K and K x 3: 為每個類別指定顏色,不是為每個點指定顏色。
舉例:
1》
# scatter plots
Y = np.random.rand(100) old_scatter = viz.scatter( X=np.random.rand(100, 2), Y=(Y[Y > 0] + 1.5).astype(int), opts=dict( legend=['Didnt', 'Update'], xtickmin=-50, xtickmax=50, xtickstep=0.5, ytickmin=-50, ytickmax=50, ytickstep=0.5, markersymbol='cross-thin-open', ), ) viz.update_window_opts( win=old_scatter, opts=dict( legend=['Apples', 'Pears'], xtickmin=0, xtickmax=1, xtickstep=0.5, ytickmin=0, ytickmax=1, ytickstep=0.5, markersymbol='cross-thin-open', ), )
圖示:
2》3D版的:
# 3d scatterplot with custom labels and ranges
viz.scatter(
X=np.random.rand(100, 3), Y=(Y + 1.5).astype(int), opts=dict( legend=['Men', 'Women'], markersize=5, xtickmin=0, xtickmax=2, xlabel='Arbitrary', xtickvals=[0, 0.75, 1.6, 2], ytickmin=0, ytickmax=2, ytickstep=0.5, ztickmin=0, ztickmax=1, ztickstep=0.5, ) )
圖示:
3》帶有自定義強度的2D散點圖(紅色通道)
# 2D scatterplot with custom intensities (red channel)
viz.scatter(
X=np.random.rand(255, 2), Y=(np.random.rand(255) + 1.5).astype(int), opts=dict( markersize=10, markercolor=np.random.randint(0, 255, (2, 3,)), ), )
圖示:
4》2D散點圖,每個標簽自定義顏色:
# 2D scatter plot with custom colors per label:
viz.scatter(
X=np.random.rand(255, 2), Y=(np.random.randn(255) > 0) + 1, opts=dict( markersize=10, markercolor=np.floor(np.random.random((2, 3)) * 255), ), )
圖示:
5》添加新的追蹤
win = viz.scatter(
X=np.random.rand(255, 2), opts=dict( markersize=10, markercolor=np.random.randint(0, 255, (255, 3,)), ), ) #斷言該窗口是否存在 assert viz.win_exists(win), 'Created window marked as not existing' # 添加新的追蹤到散點圖中 viz.scatter( X=np.random.rand(255), Y=np.random.rand(255), win=win, name='new_trace', update='new' )
圖示:
6》帶着文本標簽的散點圖
# 2D scatter plot with text labels:
viz.scatter(
X=np.random.rand(10, 2), opts=dict( textlabels=['Label %d' % (i + 1) for i in range(10)] ) ) viz.scatter( X=np.random.rand(10, 2), Y=[1] * 5 + [2] * 3 + [3] * 2, opts=dict( legend=['A', 'B', 'C'], textlabels=['Label %d' % (i + 1) for i in range(10)] ) )
圖示:
7》更新
1〉一開始的底圖
colors = np.random.randint(0, 255, (2, 3,)) win = viz.scatter( X=np.random.rand(255, 2), Y=(np.random.rand(255) + 1.5).astype(int), opts=dict( markersize=10, markercolor=colors, legend=['1', '2'] ), )
圖是:
2〉append
viz.scatter(
X=np.random.rand(255), Y=np.random.rand(255), opts=dict( markersize=10, markercolor=colors[0].reshape(-1, 3), ), name='1', update='append', win=win)
圖為:
3〉append
viz.scatter(
X=np.random.rand(255, 2), Y=(np.random.rand(255) + 1.5).astype(int), opts=dict( markersize=10, markercolor=colors, ), update='append', win=win)
圖為:
2>vis.line
這個函數畫了一條線。它接受一個N或NxM張量Y作為輸入,它指定連接N個點的M條線的值。它還接受一個可選的X張量,指定相應的X軸值;X可以是一個N張量(在這種情況下,所有的線都有相同的X軸值),或者和Y大小相同。
update可用於有效地更新現有圖的數據。使用'append'附加數據,'replace'使用新數據,或'remove'刪除按名稱指定的跟蹤。如果更新單個跟蹤,請使用name指定要更新的跟蹤的名稱。忽略所有NaN的更新數據(可用於屏蔽更新)。
下面是支持的opts:
opts.fillarea
: 填滿線下區域(boolean
)opts.markers
: 顯示標記 (boolean
; default =false
)opts.markersymbol
: 標記符號(string
; default ='dot'
)opts.markersize
:標記大小(number
; default ='10'
)opts.linecolor
:線顏色 (np.array
; default = None)opts.dash
: 每一行的破折號類型 (np.array
; default = 'solid'), 實線、破折號、虛線或破折號中的一個,其大小應與所畫線的數目相匹配opts.legend
: 包含圖例名稱的表- opts.layoutopts : 圖形后端為布局接受的任何附加選項的字典. 比如 layoutopts = {'plotly': {'legend': {'x':0, 'y':0}}}.
- opts.traceopts : 將跟蹤名稱或索引映射到plot.ly為追蹤接受的附加選項的字典. 比如 traceopts = {'plotly': {'myTrace': {'mode': 'markers'}}}.
- opts.webgl : 使用WebGL繪圖(布爾值;default= false。如果一個圖包含太多的點,它會更快。要謹慎使用,因為瀏覽器不會在一個頁面上允許多個WebGL上下文。
1》
# line plots
viz.line(Y=np.random.rand(10), opts=dict(showlegend=True)) Y = np.linspace(-5, 5, 100) viz.line( Y=np.column_stack((Y * Y, np.sqrt(Y + 5))), X=np.column_stack((Y, Y)), opts=dict(markers=False), )
圖示:
2》
# line using WebGL webgl_num_points = 200000 webgl_x = np.linspace(-1, 0, webgl_num_points) webgl_y = webgl_x**3 viz.line(X=webgl_x, Y=webgl_y, opts=dict(title='{} points using WebGL'.format(webgl_num_points), webgl=True), win="WebGL demo")
圖示:
3》更新
# line updates
win = viz.line( X=np.column_stack((np.arange(0, 10), np.arange(0, 10))), Y=np.column_stack((np.linspace(5, 10, 10), np.linspace(5, 10, 10) + 5)), )
圖為:
append:
viz.line(
X=np.column_stack((np.arange(10, 20), np.arange(10, 20))), Y=np.column_stack((np.linspace(5, 10, 10), np.linspace(5, 10, 10) + 5)), win=win, update='append' )
圖為:
append:
viz.line(
X=np.arange(21, 30), Y=np.arange(1, 10), win=win, name='2', update='append' )
圖示:
append:
viz.line(
X=np.arange(1, 10), Y=np.arange(11, 20), win=win, name='delete this', update='append' )
圖為:
insert:
viz.line(
X=np.arange(1, 10), Y=np.arange(11, 20), win=win, name='4', update='insert' )
圖為:
remove:
viz.line(X=None, Y=None, win=win, name='delete this', update='remove')
圖又會回到上上面一個:
這個更改的是之前使用WebGL的那個圖:
viz.line(
X=webgl_x+1., Y=(webgl_x+1.)**3, win="WebGL demo", update='append', opts=dict(title='{} points using WebGL'.format(webgl_num_points*2), webgl=True) )
圖變為:
4》實線、虛線等不同線的實現
win = viz.line(
X=np.column_stack(( np.arange(0, 10), np.arange(0, 10), np.arange(0, 10), )), Y=np.column_stack(( np.linspace(5, 10, 10), np.linspace(5, 10, 10) + 5, np.linspace(5, 10, 10) + 10, )), opts={ 'dash': np.array(['solid', 'dash', 'dashdot']), 'linecolor': np.array([ [0, 191, 255], [0, 191, 255], [255, 0, 0], ]), 'title': 'Different line dash types' } ) viz.line( X=np.arange(0, 10), Y=np.linspace(5, 10, 10) + 15, win=win, name='4', update='insert', opts={ 'linecolor': np.array([ [255, 0, 0], ]), 'dash': np.array(['dot']), } )
圖示:
5》堆疊區域
Y = np.linspace(0, 4, 200) win = viz.line( Y=np.column_stack((np.sqrt(Y), np.sqrt(Y) + 2)), X=np.column_stack((Y, Y)), opts=dict( fillarea=True, showlegend=False, width=800, height=800, xlabel='Time', ylabel='Volume', ytype='log', title='Stacked area plot', marginleft=30, marginright=30, marginbottom=80, margintop=30, ), )
圖示:
更新參數:
# 確保堆疊區域不過大
viz.update_window_opts(
win=win, opts=dict( width=300, height=300, ), )
圖變為:
6)pytorch tensor
# PyTorch tensor try: import torch viz.line(Y=torch.Tensor([[0., 0.], [1., 1.]])) except ImportError: print('Skipped PyTorch example')
圖示:
3>vis.stem
這個函數繪制一個根莖圖。它接受一個N或NxM張量X作為輸入,它指定M時間序列中N個點的值。還可以指定一個包含時間戳的可選N或NxM張量Y;如果Y是一個N張量,那么所有M個時間序列都假設有相同的時間戳。
下面是支持的opts:
opts.colormap
: 色圖 (string
; default ='Viridis'
)opts.legend
: 包含圖例名稱的表- opts.layoutopts : 圖形后端為布局接受的任何附加選項的字典. 比如 layoutopts = {'plotly': {'legend': {'x':0, 'y':0}}}.
舉例:
# stemplot
Y = np.linspace(0, 2 * math.pi, 70) X = np.column_stack((np.sin(Y), np.cos(Y))) viz.stem( X=X, Y=Y, opts=dict(legend=['Sine', 'Cosine']) )
圖示:
4>vis.heatmap
此函數繪制熱點圖。它接受一個NxM張量X作為輸入,它指定了熱圖中每個位置的值。
下面是支持的opts:
opts.colormap
: 色圖 (string
; default ='Viridis'
)opts.xmin
: 修剪的最小值 (number
; default =X:min()
)opts.xmax
: 修剪的最大值(number
; default =X:max()
)opts.columnnames
:包含
x-axis 標簽的表opts.rownames
:包含
y-axis 標簽的表opts.layoutopts : 圖形后端為布局接受的任何附加選項的字典. 比如 layoutopts = {'plotly': {'legend': {'x':0, 'y':0}}}.
舉例:
# heatmap
viz.heatmap(
X=np.outer(np.arange(1, 6), np.arange(1, 11)), opts=dict( columnnames=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'], rownames=['y1', 'y2', 'y3', 'y4', 'y5'], colormap='Electric', ) )
圖示:
5>vis.bar
此函數繪制規則的、堆疊的或分組的條形圖。它接受一個N或NxM張量X作為輸入,它指定了每個條的高度。如果X包含M列,則對每一行對應的值進行堆疊或分組(取決於opts.stacked的選擇方式)。除了X,還可以指定一個(可選的)N張量Y,它包含相應的X軸值。
以下是目前支持的特定plot的選項:
opts.rownames
:包含
x-axis 標簽的表opts.stacked
:在X中堆疊多個列
opts.legend
: 包含圖例名稱的表opts.layoutopts : 圖形后端為布局接受的任何附加選項的字典. 比如 layoutopts = {'plotly': {'legend': {'x':0, 'y':0}}}.
1》
# bar plots
viz.bar(X=np.random.rand(20))
圖示:
2》
viz.bar(
X=np.abs(np.random.rand(5, 3)), opts=dict( stacked=True, legend=['Facebook', 'Google', 'Twitter'], rownames=['2012', '2013', '2014', '2015', '2016'] ) )
圖示:
3》
viz.bar(
X=np.random.rand(20, 3), opts=dict( stacked=False, legend=['The Netherlands', 'France', 'United States'] ) )
圖示:
6>vis.histogram
這個函數繪制指定數據的直方圖。它接受一個N張量X作為輸入,它指定了用來構造直方圖的數據。
以下是目前支持的特定plot的選項:
opts.numbins
: bins數量 (number
; default = 30)opts.layoutopts : 圖形后端為布局接受的任何附加選項的字典. 比如 layoutopts = {'plotly': {'legend': {'x':0, 'y':0}}}.
舉例:
# histogram
viz.histogram(X=np.random.rand(10000), opts=dict(numbins=20))
圖示:
7> vis.boxplot
此函數繪制指定數據的箱形圖。它接受一個N或一個NxM張量X作為輸入,該張量X指定了N個數據值,用來構造M個箱形圖。
以下是目前支持的特定plot的選項:
opts.legend
: 在X中每一列的標簽opts.layoutopts : 圖形后端為布局接受的任何附加選項的字典. 比如 layoutopts = {'plotly': {'legend': {'x':0, 'y':0}}}.
舉例:
# boxplot
X = np.random.rand(100, 2) X[:, 1] += 2 viz.boxplot( X=X, opts=dict(legend=['Men', 'Women']) )
圖示:
8>vis.surf
這個函數繪制一個曲面圖。它接受一個NxM張量X作為輸入,該張量X指定了曲面圖中每個位置的值。
下面是支持的opts:
opts.colormap
: 色圖 (string
; default ='Viridis'
)opts.xmin
: 修剪的最小值 (number
; default =X:min()
)opts.xmax
: 修剪的最大值(number
; default =X:max()
)opts.layoutopts : 圖形后端為布局接受的任何附加選項的字典. 比如 layoutopts = {'plotly': {'legend': {'x':0, 'y':0}}}.
舉例:
# surface
viz.surf(X=X, opts=dict(colormap='Hot'))
圖示:
9>vis.contour
這個函數繪制等高線。它接受一個NxM張量X作為輸入,該張量X指定等高線圖中每個位置的值。
下面是支持的opts:
opts.colormap
: 色圖 (string
; default ='Viridis'
)opts.xmin
: 修剪的最小值 (number
; default =X:min()
)opts.xmax
: 修剪的最大值(number
; default =X:max()
)opts.layoutopts : 圖形后端為布局接受的任何附加選項的字典. 比如 layoutopts = {'plotly': {'legend': {'x':0, 'y':0}}}.
舉例:
# contour
x = np.tile(np.arange(1, 101), (100, 1)) y = x.transpose() X = np.exp((((x - 50) ** 2) + ((y - 50) ** 2)) / -(20.0 ** 2)) viz.contour(X=X, opts=dict(colormap='Viridis'))
圖示:
10>vis.quiver
該函數繪制一個抖動圖,其中箭頭的方向和長度由NxM張量X和y決定。可以提供兩個可選的NxM張量gridX和gridY,指定箭頭的偏移量;默認情況下,箭頭將在常規網格上執行。
下面是支持的opts:
opts.normalize
: 最長箭頭長度 (number
)opts.arrowheads
: 顯示箭頭 (boolean
; default =true
)opts.layoutopts : 圖形后端為布局接受的任何附加選項的字典. 比如 layoutopts = {'plotly': {'legend': {'x':0, 'y':0}}}.
舉例:
# quiver plot
X = np.arange(0, 2.1, .2) Y = np.arange(0, 2.1, .2) X = np.broadcast_to(np.expand_dims(X, axis=1), (len(X), len(X))) Y = np.broadcast_to(np.expand_dims(Y, axis=0), (len(Y), len(Y))) U = np.multiply(np.cos(X), Y) V = np.multiply(np.sin(X), Y) viz.quiver( X=U, Y=V, opts=dict(normalize=0.9), )
圖示:
11>vis.mesh
這個函數從一組在Nx2或Nx3矩陣X中定義的頂點和在可選的Mx2或Mx3矩陣Y中定義的多邊形中繪制網格圖。
下面是支持的opts:
opts.color
: 顏色 (string
)opts.opacity
: 多邊形的不透明度 (number
between 0 and 1)opts.layoutopts : 圖形后端為布局接受的任何附加選項的字典. 比如 layoutopts = {'plotly': {'legend': {'x':0, 'y':0}}}.
舉例:
# mesh plot
x = [0, 0, 1, 1, 0, 0, 1, 1] y = [0, 1, 1, 0, 0, 1, 1, 0] z = [0, 0, 0, 0, 1, 1, 1, 1] X = np.c_[x, y, z] i = [7, 0, 0, 0, 4, 4, 6, 6, 4, 0, 3, 2] j = [3, 4, 1, 2, 5, 6, 5, 2, 0, 1, 6, 3] k = [0, 7, 2, 3, 6, 7, 1, 1, 5, 5, 7, 6] Y = np.c_[i, j, k] viz.mesh(X=X, Y=Y, opts=dict(opacity=0.5))
圖為:
12>vis.pie餅圖
舉例:
# pie chart
X = np.asarray([19, 26, 55]) viz.pie( X=X, opts=dict(legend=['Residential', 'Non-Residential', 'Utility']) )
圖示: