淺談一下基于Pytorch的可視化工具
深度學(xué)習(xí)網(wǎng)絡(luò)通常具有很深的層次結(jié)構(gòu),而且層與層之間通常會(huì)有并聯(lián)、串聯(lián)等連接方式。當(dāng)使用PyTorch建立一個(gè)深度學(xué)習(xí)網(wǎng)絡(luò)并輸出文本向讀者展示網(wǎng)絡(luò)的連接方式是非常低效的,所以需要有效的工具將建立的深度學(xué)習(xí)網(wǎng)絡(luò)結(jié)構(gòu)有層次化的展示,這就需要使用相關(guān)的深度學(xué)習(xí)網(wǎng)絡(luò)結(jié)構(gòu)可視化庫(kù)。
準(zhǔn)備網(wǎng)絡(luò)
import torch
import torch.nn as nn
import torchvision
import torchvision.utils as vutils
from torch.optim import SGD
import torch.utils.data as Data
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
"""
下面導(dǎo)入手寫(xiě)字體數(shù)據(jù),并將數(shù)據(jù)處理為數(shù)據(jù)加載器
"""
train_data=torchvision.datasets.MNIST(
root="./Dataset",
train=True,
#將數(shù)據(jù)轉(zhuǎn)化為torch使用的張量,取值范圍為[0-1]
transform=torchvision.transforms.ToTensor(),
download=False#因?yàn)閿?shù)據(jù)已經(jīng)下載過(guò)所以這里不在下載
)
#定義一個(gè)數(shù)據(jù)加載器
train_loader=Data.DataLoader(
dataset=train_data,#使用的數(shù)據(jù)集
batch_size=128,#批處理樣本大小
shuffle=True,
num_workers=0
)
#準(zhǔn)備需要的測(cè)試集
test_data=torchvision.datasets.MNIST(
root="./Dataset",
train=False,
download=False
)
#為數(shù)據(jù)添加一個(gè)通道維度,并且取值范圍縮放到[0-1]之間
test_data_x=test_data.data.type(torch.FloatTensor)/255.0
test_data_x=torch.unsqueeze(test_data_x,dim=1)
test_data_y=test_data.targets#測(cè)試集的標(biāo)簽
print(test_data_x.shape)
print(test_data_y.shape)
"""
(1)針對(duì)訓(xùn)練集使用torchvision.datasets.MNIST()函數(shù)導(dǎo)入數(shù)據(jù),
并將其像素值轉(zhuǎn)化到0~1之間,然后使用Data.DataLoader()函數(shù)定義一個(gè)數(shù)據(jù)加載器,
每個(gè)batch包含128張圖像。
(2)針對(duì)測(cè)試數(shù)據(jù),同樣使用torchvision.datasets.MNIST()函數(shù)導(dǎo)入數(shù)據(jù),
但不將數(shù)據(jù)處理為數(shù)據(jù)加載器,而是將整個(gè)測(cè)試集作為一個(gè)batch,方便計(jì)算模型在測(cè)試集上的預(yù)測(cè)精度。
"""
#搭建一個(gè)卷積神經(jīng)網(wǎng)絡(luò)
class ConvNet(nn.Module):
def __init__(self):
super(ConvNet,self).__init__()
#定義第一個(gè)卷積層
self.conv1=nn.Sequential(
nn.Conv2d(
in_channels=1,#輸入的feature_map
out_channels=16,#輸出的feature_map
kernel_size=3,#卷積核尺寸
stride=1,#卷積核步長(zhǎng)
padding=1,#進(jìn)行填充
),
nn.ReLU(),#激活函數(shù)
nn.AvgPool2d(
kernel_size=2,#平均值池化層,使用2*2
stride=2,#池化步長(zhǎng)為2
),
)
#定義第二個(gè)卷積層
self.conv2=nn.Sequential(
nn.Conv2d(16,32,3,1,1),
nn.ReLU(),#激活函數(shù)
nn.MaxPool2d(2,2)#最大值池化
)
#定義全連接層
self.fc=nn.Sequential(
nn.Linear(
in_features=32*7*7,#輸入特征
out_features=128#輸出特征
),
nn.ReLU(),#激活層
nn.Linear(128,64),#
nn.ReLU()#激活層
)
self.out=nn.Linear(64,10)#最后的分類層
def forward(self,x):
x=self.conv1(x),
x=self.conv2(x),
x=x.view(x.size(0),-1),#展平多維的卷積圖層
x=self.fc(x),
output=self.out(x),
return output
myConvNet=ConvNet()網(wǎng)絡(luò)結(jié)構(gòu)的可視化---PytorchViz
從定義網(wǎng)絡(luò)和網(wǎng)絡(luò)的輸出可以看出,在myConvNet網(wǎng)絡(luò)結(jié)構(gòu)中,共包含兩個(gè)使用nn.Sequential()函數(shù)連接的卷積層,即conv1和conv2,每個(gè)層都包含有卷積層、激活函數(shù)層和池化層。在fc層中,包含兩個(gè)全連接層和激活函數(shù)層,out層則由一個(gè)全連接層構(gòu)成。通過(guò)文本輸出myConvNet網(wǎng)絡(luò)的網(wǎng)絡(luò)結(jié)構(gòu)得到上面的輸出結(jié)果,但這并不容易讓讀者理解在網(wǎng)絡(luò)中層與層之間的連接方式,所以需要將PyTorch搭建的深度學(xué)習(xí)網(wǎng)絡(luò)進(jìn)行可視化,通過(guò)圖像來(lái)幫助讀者理解網(wǎng)絡(luò)層與層之間的連接方式。PyTorchViz庫(kù)是一個(gè)可視化網(wǎng)絡(luò)結(jié)構(gòu)的庫(kù),學(xué)習(xí)和了解這些庫(kù)對(duì)網(wǎng)絡(luò)結(jié)構(gòu)進(jìn)行可視化,可以幫助我們查看、理解所搭建深度網(wǎng)絡(luò)的結(jié)構(gòu)。
from torchviz import make_dot
x=torch.randn(1,1,28,28).requires_grad_(True)
y=myConvNet(x)
#make_dot用來(lái)得到網(wǎng)絡(luò)的可視化圖像
myConvNets=make_dot(y,params=dict(list(myConvNet.named_parameters())+[("x",x)]))
myConvNets.format='png'#指定可視化圖像的格式
myConvNets.directory="model_graph/"#指定圖像保存的文件夾
myConvNets.view()得到的圖像如下圖所示:

訓(xùn)練過(guò)程可視化---TensorboardX
網(wǎng)絡(luò)結(jié)構(gòu)可視化,主要是幫助使用者理解所搭建的網(wǎng)絡(luò)或檢查搭建網(wǎng)絡(luò)時(shí)存在的錯(cuò)誤。而網(wǎng)絡(luò)訓(xùn)練過(guò)程的可視化,通常用于監(jiān)督網(wǎng)絡(luò)的訓(xùn)練過(guò)程或呈現(xiàn)網(wǎng)絡(luò)的訓(xùn)練效果。tensorboardX是幫助pytorch使用tensornoard工具來(lái)可視化的庫(kù),在tensorboardX庫(kù)中,提供了多種向tensorboard中添加事件的函數(shù)。
| 函數(shù) | 功能 | 用法 |
| SummaryWriter() | 創(chuàng)建編寫(xiě)器,保存日志 | writer=SummaryWriter() |
| writer.add_scalar() | 添加標(biāo)量 | writer.add_scalar(''myscalar",value,iteration) |
| writer.add_image() | 添加圖像 | writer.add_image("imresult",x,iteration) |
| writer.add_histogram() | 添加直方圖 | writer.add_histogram('hist',array,iteration) |
| writer.add_graph() | 添加網(wǎng)絡(luò)結(jié)構(gòu) | writer.add_graph(model,input_to_model=None) |
| writer.add_audio() | 添加音頻 | add_audio(tag,audio,iteration,sample_rate) |
| writer.add_text() | 添加文本 | writer.add_text(tag,text_string,global_step=None) |
下面針對(duì)建立好的MNIST手寫(xiě)字體識(shí)別網(wǎng)絡(luò),使用rensorboardX庫(kù)對(duì)網(wǎng)絡(luò)在訓(xùn)練過(guò)程中的損失函數(shù)的變化情況、精度變化情況、權(quán)重分布等內(nèi)容進(jìn)行可視化,程序如下:
from tensorboardX import SummaryWriter
SumWriter=SummaryWriter(log_dir='./log')#日志保存路徑
#定義優(yōu)化器
optimizer=torch.optim.Adam(myConvNet.parameters(),lr=0.003)
#定義損失函數(shù)
loss_func=nn.CrossEntropyLoss()
train_loss=0
print_step=100#每經(jīng)過(guò)100次迭代,輸出損失
#對(duì)模型進(jìn)行迭代訓(xùn)練,對(duì)所有的數(shù)據(jù)訓(xùn)練epoch輪
for epoch in range(5):
#對(duì)訓(xùn)練數(shù)據(jù)的加載器進(jìn)行迭代計(jì)算
for step,(b_x,b_y) in enumerate(train_loader):
#計(jì)算每個(gè)batch上的損失
output=myConvNet(b_x)
loss=loss_func(output,b_y)#交叉熵?fù)p失函數(shù)
optimizer.zero_grad()#每個(gè)迭代步的梯度初始化為0
loss.backward()#損失后向傳播
optimizer.step()#使用梯度進(jìn)行優(yōu)化
train_loss=train_loss+loss#計(jì)算累加損失
niter=epoch*len(train_loader)+step+1#計(jì)算迭代次數(shù)
#計(jì)算每經(jīng)過(guò)print_step次迭代后的輸出
if niter % print_step==0:
#為日志添加訓(xùn)練集損失函數(shù)
SumWriter.add_scalar("train loss",train_loss.item() / niter,global_step=niter)
#計(jì)算在測(cè)試集上的精度
output=myConvNet(test_data_x)
_,pre_lab=torch.max(output,1)
acc=accuracy_score(test_data_y,pre_lab)
#為日志添加測(cè)試集上的預(yù)測(cè)精度
SumWriter.add_scalar("test acc",acc.item(),niter)
#為日志中添加訓(xùn)練數(shù)據(jù)的可視化圖像,使用當(dāng)前batch的圖像
#將一個(gè)batch的數(shù)據(jù)進(jìn)行預(yù)處理
b_x_im=vutils.make_grid(b_x,nrow=12)
SumWriter.add_image('train image sample',b_x_im,niter)
#使用直方圖可視化網(wǎng)絡(luò)中參數(shù)的分布情況
for name,param in myConvNet.named_parameters():
SumWriter.add_histogram(name,param.data.numpy(),niter)
在網(wǎng)絡(luò)訓(xùn)練完畢之后,會(huì)得到網(wǎng)絡(luò)的訓(xùn)練過(guò)程文件,該文件的可視化結(jié)果可以通過(guò)tensorboard可視化工具進(jìn)行查看。

日志文件保存路徑
在conda環(huán)境下執(zhí)行>tensorboard --logdir="文件路徑"

成功后,tensorboard會(huì)返回一個(gè)本地網(wǎng)址鏈接,瀏覽器打開(kāi)該鏈接即可查看到可視化界面

Visdom可視化
Visdom庫(kù)中包含多種用于可視化圖像的接口
| 可視化函數(shù) | 功能描述 |
| vis.image | 可視化一張圖像 |
| vis.image | 可視化一個(gè)batch的圖像,或者一個(gè)圖像列表 |
| vis.text | 可視化文本 |
| vis.audio | 用于播放音頻 |
| vis.matplot | 可視化Matplotlib的圖像 |
| vis.scatter | 2D或者3D的散點(diǎn)圖 |
| vis.line | 線圖 |
| vis.stem | 莖葉圖 |
| vis.heatmap | 熱力圖 |
| vis.bar | 條形圖 |
| vis.histogram | 直方圖 |
| vis.boxplot | 盒形圖 |
| vis.surf | 曲面圖 |
| vis.contour | 等高線圖 |
| vis.quiver | 箭頭圖 |
| vis.video | 播放音頻 |
| vis.mesh | 網(wǎng)格圖 |
下面使用具體的數(shù)據(jù)集進(jìn)行可視化圖像:
import numpy as np
import torch
from visdom import Visdom
from sklearn.datasets import load_iris
iris_x,iris_y=load_iris(return_X_y=True)
print(iris_x.shape)
print(iris_y.shape)
"""
上面的程序?qū)肓锁S尾花數(shù)據(jù)集,包含3類數(shù)據(jù),150個(gè)樣本,每個(gè)樣本包含4個(gè)特征。
"""
vis=Visdom()
#2D散點(diǎn)圖
vis.scatter(iris_x[:,0:2],Y=iris_y+1,win="windows1",env="main")
#3D散點(diǎn)圖
vis.scatter(iris_x[:,0:3],Y=iris_y+1,win="3D 散點(diǎn)圖",env="main",opts=dict(markersize=4,xlabel="特征一",ylabel="特征二"))
"""
程序中使用vis = Visdom()初始化一個(gè)繪圖對(duì)象,通過(guò)vis.scatter()為對(duì)象添加散點(diǎn)圖。
在該函數(shù)中,如果輸入的X為二維則可得到2D散點(diǎn)圖,如果輸入的X為三維則可得到3D散點(diǎn)圖,
其中參數(shù)Y用于指定數(shù)據(jù)的分組情況,參數(shù)win指定圖像的窗口名稱,參數(shù)env則指定圖像所在的環(huán)境。
可以發(fā)現(xiàn)兩幅圖像都在主環(huán)境main中。圖像的其他設(shè)置可使用opts參數(shù)通過(guò)字典的形式設(shè)置。
在上述初始化的可視化圖像環(huán)境main中,繼續(xù)添加其他窗口,以繪制不同類型的圖像,如添加折線圖.
"""
#添加折線圖
x=torch.linspace(-6,6,100).view((-1,1))
sigmoid=torch.nn.Sigmoid()
sigmoidy=sigmoid(x)
tanh=torch.nn.Tanh()
tanhy=tanh(x)
relu=torch.nn.ReLU()
reluy=relu(x)
#連接3個(gè)張量
ploty=torch.cat((sigmoidy,tanhy,reluy),dim=1)
plotx=torch.cat((x,x,x),dim=1)
vis.line(Y=ploty,X=plotx,win="line plot",env="main",opts=dict(dash=np.array(["solid","dash","dashdot"]),legend=["Sigmoid","Tanh","ReLU"]))
"""
上面的程序中,可視化出了sigmoid、Tanh和ReLU三種激活函數(shù)的圖像。
在可視化折線時(shí),使用vis.line()函數(shù)進(jìn)行繪圖,圖像在環(huán)境main中,
通過(guò)win參數(shù)指定窗口名稱為line plot,然后通過(guò)opts參數(shù)為不同的線設(shè)置了不同的線型。
"""
#添加莖葉圖
x=torch.linspace(-6,6,100).view((-1,1))
y1=torch.sin(x)
y2=torch.cos(x)
#連接2個(gè)變量
plotx=torch.cat((y1,y2),dim=1)
ploty=torch.cat((x,x),dim=1)
vis.stem(X=plotx,Y=ploty,win="stem plot",env="main",
#設(shè)置圖例
opts=dict(legend=["sin","cos"],title="莖葉圖") )
"""
上面的程序中,可視化出了正弦和余弦函數(shù)的莖葉圖。
在可視化時(shí)通過(guò)vis.stem()函數(shù)繪圖,圖像在環(huán)境main中,
通過(guò)win參數(shù)指定窗口名稱為stem plot,然后通過(guò)opts參數(shù)為圖像添加圖例和標(biāo)題。
"""
#添加熱力圖
iris_corr=torch.from_numpy(np.corrcoef(iris_x,rowvar=False))
vis.heatmap(iris_corr,win="heatmap",env="main",
#設(shè)置每個(gè)特征的名稱
opts=dict(rownames=["x1","x2","x3","x4"],columnnames=["x1","x2","x3","x4"],title="熱力圖"))
"""
程序中可視化出了鳶尾花數(shù)據(jù)集中4個(gè)特征的相關(guān)系數(shù)熱力圖。
在可視化時(shí)通過(guò)vis.heatmap()函數(shù)進(jìn)行繪圖,圖像在環(huán)境main中,
通過(guò)win參數(shù)指定窗口名稱為heatmap,然后通過(guò)opts參數(shù)為圖像添加X(jué)軸的變量名稱、Y軸變量名稱和標(biāo)題。
"""注意:在使用visdom可視化圖像之前,應(yīng)該在命令行激活visdom服務(wù),否則程序報(bào)錯(cuò)
python -m visdom.server

命令執(zhí)行成功后會(huì)返回一個(gè)本地鏈接: http://localhost:8097
然后在pycharm中執(zhí)行代碼,再用瀏覽器打開(kāi)上述鏈接即可得到下面的可視化圖像:

到此這篇關(guān)于淺談一下基于Pytorch的可視化工具的文章就介紹到這了,更多相關(guān)Pytorch的可視化工具內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
tensorflow 實(shí)現(xiàn)數(shù)據(jù)類型轉(zhuǎn)換
今天小編就為大家分享一篇tensorflow 實(shí)現(xiàn)數(shù)據(jù)類型轉(zhuǎn)換,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-02-02
用Python爬取QQ音樂(lè)評(píng)論并制成詞云圖的實(shí)例
今天小編就為大家分享一篇用Python爬取QQ音樂(lè)評(píng)論并制成詞云圖的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-08-08
python函數(shù)常見(jiàn)關(guān)鍵字分享
這篇文章主要向大家介紹的是python函數(shù)常見(jiàn)關(guān)鍵字,文章基于python的相關(guān)資料展開(kāi)對(duì)文章主題的詳細(xì)介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-04-04
Python求解任意閉區(qū)間的所有素?cái)?shù)
本篇文章是一篇關(guān)于python求素?cái)?shù)的知識(shí)點(diǎn)內(nèi)容,如果大家在應(yīng)用中有用的到,不妨跟著學(xué)習(xí)下。2018-06-06

