淺談一下基于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)入手寫字體數(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)建編寫器,保存日志 | 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手寫字體識(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-08python函數(shù)常見(jiàn)關(guān)鍵字分享
這篇文章主要向大家介紹的是python函數(shù)常見(jiàn)關(guān)鍵字,文章基于python的相關(guān)資料展開(kāi)對(duì)文章主題的詳細(xì)介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-04-04Python求解任意閉區(qū)間的所有素?cái)?shù)
本篇文章是一篇關(guān)于python求素?cái)?shù)的知識(shí)點(diǎn)內(nèi)容,如果大家在應(yīng)用中有用的到,不妨跟著學(xué)習(xí)下。2018-06-06