PyTorch下的可視化工具
來(lái)源:知乎—錦恢
01
import torchimport torch.nn as nnclass ConvNet(nn.Module):def __init__(self):super(ConvNet, self).__init__()self.conv1 = nn.Sequential(nn.Conv2d(1, 16, 3, 1, 1),nn.ReLU(),nn.AvgPool2d(2, 2))self.conv2 = nn.Sequential(nn.Conv2d(16, 32, 3, 1, 1),nn.ReLU(),nn.MaxPool2d(2, 2))self.fc = nn.Sequential(nn.Linear(32 * 7 * 7, 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()print(MyConvNet)
ConvNet((conv1): Sequential((0): Conv2d(1, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(1): ReLU()(2): AvgPool2d(kernel_size=2, stride=2, padding=0))(conv2): Sequential((0): Conv2d(16, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(1): ReLU()(2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False))(fc): Sequential((0): Linear(in_features=1568, out_features=128, bias=True)(1): ReLU()(2): Linear(in_features=128, out_features=64, bias=True)(3): ReLU())(out): Linear(in_features=64, out_features=10, bias=True))
需要說(shuō)明的是,這兩個(gè)庫(kù)都是基于Graphviz開(kāi)發(fā)的,因此倘若你的電腦上沒(méi)有安裝并且沒(méi)有添加環(huán)境變量,請(qǐng)自行安裝Graphviz工具,https://blog.csdn.net/lizzy05/article/details/88529483
1.1 通過(guò)HiddenLayer可視化網(wǎng)絡(luò)
pip install hiddenlayer
import hiddenlayer as hvis_graph = h.build_graph(MyConvNet, torch.zeros([1 ,1, 28, 28])) # 獲取繪制圖像的對(duì)象vis_graph.theme = h.graph.THEMES["blue"].copy() # 指定主題顏色vis_graph.save("./demo1.png") # 保存圖像的路徑

1.2 通過(guò)PyTorchViz可視化網(wǎng)絡(luò)
pip install torchviz
from torchviz import make_dotx = torch.randn(1, 1, 28, 28).requires_grad_(True) # 定義一個(gè)網(wǎng)絡(luò)的輸入值y = MyConvNet(x) # 獲取網(wǎng)絡(luò)的預(yù)測(cè)值MyConvNetVis = make_dot(y, params=dict(list(MyConvNet.named_parameters()) + [('x', x)]))MyConvNetVis.format = "png"# 指定文件生成的文件夾MyConvNetVis.directory = "data"# 生成文件MyConvNetVis.view()
默認(rèn)情況下,上述程序運(yùn)行后會(huì)自動(dòng)打開(kāi).png文件

02
import torchvisionimport torch.utils.data as Data# 準(zhǔn)備訓(xùn)練用的MNIST數(shù)據(jù)集train_data = torchvision.datasets.MNIST(root = "./data/MNIST", # 提取數(shù)據(jù)的路徑train=True, # 使用MNIST內(nèi)的訓(xùn)練數(shù)據(jù)transform=torchvision.transforms.ToTensor(), # 轉(zhuǎn)換成torch.tensordownload=False # 如果是第一次運(yùn)行的話,置為T(mén)rue,表示下載數(shù)據(jù)集到root目錄)# 定義loadertrain_loader = Data.DataLoader(dataset=train_data,batch_size=128,shuffle=True,num_workers=0)test_data = torchvision.datasets.MNIST(root="./data/MNIST",train=False, # 使用測(cè)試數(shù)據(jù)download=False)# 將測(cè)試數(shù)據(jù)壓縮到0-1test_data_x = test_data.data.type(torch.FloatTensor) / 255.0test_data_x = torch.unsqueeze(test_data_x, dim=1)test_data_y = test_data.targets# 打印一下測(cè)試數(shù)據(jù)和訓(xùn)練數(shù)據(jù)的shapeprint("test_data_x.shape:", test_data_x.shape)print("test_data_y.shape:", test_data_y.shape)for x, y in train_loader:print(x.shape)print(y.shape)break
test_data_x.shape: torch.Size([10000, 1, 28, 28])test_data_y.shape: torch.Size([10000])torch.Size([128, 1, 28, 28])torch.Size([128])
2.1 通過(guò)tensorboardX可視化訓(xùn)練過(guò)程
pip install tensorboardXpip install tensorboard
from tensorboardX import SummaryWriterlogger = SummaryWriter(log_dir="data/log")# 獲取優(yōu)化器和損失函數(shù)optimizer = torch.optim.Adam(MyConvNet.parameters(), lr=3e-4)loss_func = nn.CrossEntropyLoss()log_step_interval = 100 # 記錄的步數(shù)間隔for epoch in range(5):print("epoch:", epoch)# 每一輪都遍歷一遍數(shù)據(jù)加載器for step, (x, y) in enumerate(train_loader):# 前向計(jì)算->計(jì)算損失函數(shù)->(從損失函數(shù))反向傳播->更新網(wǎng)絡(luò)predict = MyConvNet(x)loss = loss_func(predict, y)optimizer.zero_grad() # 清空梯度(可以不寫(xiě))loss.backward() # 反向傳播計(jì)算梯度optimizer.step() # 更新網(wǎng)絡(luò)global_iter_num = epoch * len(train_loader) + step + 1 # 計(jì)算當(dāng)前是從訓(xùn)練開(kāi)始時(shí)的第幾步(全局迭代次數(shù))if global_iter_num % log_step_interval == 0:# 控制臺(tái)輸出一下print("global_step:{}, loss:{:.2}".format(global_iter_num, loss.item()))# 添加的第一條日志:損失函數(shù)-全局迭代次數(shù)logger.add_scalar("train loss", loss.item() ,global_step=global_iter_num)# 在測(cè)試集上預(yù)測(cè)并計(jì)算正確率test_predict = MyConvNet(test_data_x)_, predict_idx = torch.max(test_predict, 1) # 計(jì)算softmax后的最大值的索引,即預(yù)測(cè)結(jié)果acc = accuracy_score(test_data_y, predict_idx)# 添加第二條日志:正確率-全局迭代次數(shù)logger.add_scalar("test accuary", acc.item(), global_step=global_iter_num)# 添加第三條日志:這個(gè)batch下的128張圖像img = vutils.make_grid(x, nrow=12)logger.add_image("train image sample", img, global_step=global_iter_num)# 添加第三條日志:網(wǎng)絡(luò)中的參數(shù)分布直方圖for name, param in MyConvNet.named_parameters():logger.add_histogram(name, param.data.numpy(), global_step=global_iter_num)

logdir后面的參數(shù)是日志文件的文件夾的路徑



以下是筆者安裝使用tensorboard時(shí)遇到的一些錯(cuò)誤

2.2 HiddenLayer可視化訓(xùn)練過(guò)程
import hiddenlayer as hlimport time# 記錄訓(xùn)練過(guò)程的指標(biāo)history = hl.History()# 使用canvas進(jìn)行可視化canvas = hl.Canvas()# 獲取優(yōu)化器和損失函數(shù)optimizer = torch.optim.Adam(MyConvNet.parameters(), lr=3e-4)loss_func = nn.CrossEntropyLoss()log_step_interval = 100 # 記錄的步數(shù)間隔for epoch in range(5):print("epoch:", epoch)# 每一輪都遍歷一遍數(shù)據(jù)加載器for step, (x, y) in enumerate(train_loader):# 前向計(jì)算->計(jì)算損失函數(shù)->(從損失函數(shù))反向傳播->更新網(wǎng)絡(luò)predict = MyConvNet(x)loss = loss_func(predict, y)optimizer.zero_grad() # 清空梯度(可以不寫(xiě))loss.backward() # 反向傳播計(jì)算梯度optimizer.step() # 更新網(wǎng)絡(luò)global_iter_num = epoch * len(train_loader) + step + 1 # 計(jì)算當(dāng)前是從訓(xùn)練開(kāi)始時(shí)的第幾步(全局迭代次數(shù))if global_iter_num % log_step_interval == 0:# 控制臺(tái)輸出一下print("global_step:{}, loss:{:.2}".format(global_iter_num, loss.item()))# 在測(cè)試集上預(yù)測(cè)并計(jì)算正確率test_predict = MyConvNet(test_data_x)_, predict_idx = torch.max(test_predict, 1) # 計(jì)算softmax后的最大值的索引,即預(yù)測(cè)結(jié)果acc = accuracy_score(test_data_y, predict_idx)# 以epoch和step為索引,創(chuàng)建日志字典history.log((epoch, step),train_loss=loss,test_acc=acc,hidden_weight=MyConvNet.fc[2].weight)# 可視化with canvas:canvas.draw_plot(history["train_loss"])canvas.draw_plot(history["test_acc"])canvas.draw_image(history["hidden_weight"])
不同于tensorboard,hiddenlayer會(huì)在程序運(yùn)行的過(guò)程中動(dòng)態(tài)生成圖像,而不是模型訓(xùn)練完后

03
from visdom import Visdomfrom sklearn.datasets import load_irisimport torchimport numpy as npfrom PIL import Image
# 繪制圖像需要的數(shù)據(jù)iris_x, iris_y = load_iris(return_X_y=True)# 獲取繪圖對(duì)象,相當(dāng)于pltvis = Visdom()# 添加折線圖x = torch.linspace(-6, 6, 100).view([-1, 1])sigmoid = torch.nn.Sigmoid()sigmoid_y = sigmoid(x)tanh = torch.nn.Tanh()tanh_y = tanh(x)relu = torch.nn.ReLU()relu_y = relu(x)# 連接三個(gè)張量plot_x = torch.cat([x, x, x], dim=1)plot_y = torch.cat([sigmoid_y, tanh_y, relu_y], dim=1)# 繪制線性圖vis.line(X=plot_x, Y=plot_y, win="line plot", env="main",opts={"dash" : np.array(["solid", "dash", "dashdot"]),"legend" : ["Sigmoid", "Tanh", "ReLU"]})
# 繪制2D和3D散點(diǎn)圖# 參數(shù)Y用來(lái)指定點(diǎn)的分布,win指定圖像的窗口名稱,env指定圖像所在的環(huán)境,opts通過(guò)字典來(lái)指定一些樣式vis.scatter(iris_x[ : , 0 : 2], Y=iris_y+1, win="windows1", env="main")vis.scatter(iris_x[ : , 0 : 3], Y=iris_y+1, win="3D scatter", env="main",opts={"markersize" : 4, # 點(diǎn)的大小"xlabel" : "特征1","ylabel" : "特征2"})
# 添加莖葉圖x = torch.linspace(-6, 6, 100).view([-1, 1])y1 = torch.sin(x)y2 = torch.cos(x)# 連接張量plot_x = torch.cat([x, x], dim=1)plot_y = torch.cat([y1, y2], dim=1)# 繪制莖葉圖vis.stem(X=plot_x, Y=plot_y, win="stem plot", env="main",opts={"legend" : ["sin", "cos"],"title" : "莖葉圖"})
# 計(jì)算鳶尾花數(shù)據(jù)集特征向量的相關(guān)系數(shù)矩陣iris_corr = torch.from_numpy(np.corrcoef(iris_x, rowvar=False))# 繪制熱力圖vis.heatmap(iris_corr, win="heatmap", env="main",opts={"rownames" : ["x1", "x2", "x3", "x4"],"columnnames" : ["x1", "x2", "x3", "x4"],"title" : "熱力圖"})
# 可視化圖片img_Image = Image.open("./example.jpg")img_array = np.array(img_Image.convert("L"), dtype=np.float32)img_tensor = torch.from_numpy(img_array)print(img_tensor.shape)# 這次env自定義vis.image(img_tensor, win="one image", env="MyPlotEnv",opts={"title" : "一張圖像"})
# 可視化文本text = "hello world"vis.text(text=text, win="text plot", env="MyPlotEnv",opts={"title" : "可視化文本"})


在Environment中輸入不同的env參數(shù)可以看到我們?cè)诓煌h(huán)境下繪制的圖片。對(duì)于分類(lèi)圖集特別有用
04



import jsonwith open(r"...\.visdom\normal.json", "r", encoding="utf-8") as f:dataset : dict = json.load(f)jsons : dict = dataset["jsons"] # 這里存著你想要恢復(fù)的數(shù)據(jù)reload : dict = dataset["reload"] # 這里存著有關(guān)窗口尺寸的數(shù)據(jù) print(jsons.keys()) # 查看所有的win
dict_keys(['jsons', 'reload'])dict_keys(['1.wav', '2.wav', '3.wav', '4.wav', '5.wav', '6.wav', '7.wav', '8.wav', '9.wav', '10.wav', '11.wav', '12.wav', '13.wav', '14.wav'])
from visdom import Visdomvis = Visdom()print(vis.get_env_list())Setting up a new session...['main', 'normal']
from visdom import Visdomimport jsonvis = Visdom()window = vis.get_window_data(win="1.wav", env="normal") window = json.loads(window) # window 是 str,需要解析為字典content = window["content"]data = content["data"][0]print(data.keys())Setting up a new session...dict_keys(['z', 'x', 'y', 'zmin', 'zmax', 'type', 'colorscale'])
猜您喜歡:
戳我,查看GAN的系列專(zhuān)輯~!
一頓午飯外賣(mài),成為CV視覺(jué)前沿弄潮兒! CVPR 2022 | 25+方向、最新50篇GAN論文 ICCV 2021 | 35個(gè)主題GAN論文匯總 超110篇!CVPR 2021最全GAN論文梳理 超100篇!CVPR 2020最全GAN論文梳理
附下載 | 《可解釋的機(jī)器學(xué)習(xí)》中文版
附下載 |《TensorFlow 2.0 深度學(xué)習(xí)算法實(shí)戰(zhàn)》
附下載 |《計(jì)算機(jī)視覺(jué)中的數(shù)學(xué)方法》分享
《基于深度學(xué)習(xí)的表面缺陷檢測(cè)方法綜述》
《基于深度神經(jīng)網(wǎng)絡(luò)的少樣本學(xué)習(xí)綜述》
評(píng)論
圖片
表情

