tensorflow生成图片标签_Tensorboard高维向量可视化 + 解决标签和图片不显示BUG
1.前言
本文就使用tensorboard進(jìn)行高維向量可視化過程中出現(xiàn)的一些bug和問題,進(jìn)行一次總結(jié),幫助那些和我一樣的小白快速上手Tensorboard高維向量可視化。
這里我先展示下最近我做的高維向量可視化的成果,藍(lán)色是非事故圖片,紅色是事故圖片。從結(jié)果上看出來,模型對(duì)事故和非事故的區(qū)分能力還算可以。
事故和非事故二分類結(jié)果那么如何快速上手一個(gè)空間向量可視化過程,查看模型分類結(jié)果的空間分布呢?
這里我們使用到了tensorflow的tensorboard工具包,以事故分類為例,一步步克服tensorboard中的一些BUG。
2.特征向量提取與記錄
一般而言,類似圖像分類這種任務(wù),在CNN最后幾層中,一般會(huì)添加1x1卷積或者是全連接層,將backbone(特征提取網(wǎng)絡(luò))輸出的特征圖進(jìn)行降維,便于接下來的分類。
在搭建模型的時(shí)候,也要刻意引出最后幾層全連接層(或1x1卷積層)的輸出,因?yàn)槲覀円梢暬母呔S向量就是這些層的輸出(具體層數(shù)的輸出維度,根據(jù)自己任務(wù)而定,這里我們?cè)谀骋簧窠?jīng)網(wǎng)絡(luò)的最后,加入了個(gè)維度為8的全連接層(用作可視化的高維向量),然后再接上一個(gè)維度為2的全連接層(為了分類))。
這里我們基于pytorch搭建了個(gè)模型,模型forward函數(shù)代碼如下:
def forward(self,x):batch_size, channels, height, width = x.size()feature_map=self.cnn(x)feature_map1=self.cnn_layer(feature_map)feature_map=feature_map1.view(batch_size,-1)output1=self.dense1(feature_map) #512 -> 64output2=self.dense2(output1) #64 -> 8output3=self.dense3(output2)#8 -> 2return output1,output2,output3可見,除了最后的輸入output3,我們還額外輸出了維度為64的output1和維度為8的output2。
等網(wǎng)絡(luò)訓(xùn)練完畢后,我們就用訓(xùn)練完的權(quán)重跑一遍測(cè)試集,將
- 每張測(cè)試集圖片的地址,
- 每張圖片經(jīng)過網(wǎng)絡(luò)輸出的output1,
- 每張圖片經(jīng)過網(wǎng)絡(luò)輸出的output2,
- 每張圖片經(jīng)過網(wǎng)絡(luò)輸出的output3
保存到csv文件中,代碼如下
record=[]for original_image in tqdm(image_path):with torch.no_grad():# print('現(xiàn)在處理:', original_image)prep_img = image_process(original_image)prep_img=prep_img.cuda()# print(prep_img.shape)output1, output2, output3 = model(prep_img)# print(output1.shape)record.append([original_image,output1[0],output2[0],output3[0]])record_pd=pd.DataFrame(data=record,index=None,columns=['img_path','output64','output8',"output2"])record_pd.to_csv('vector_record.csv')保存的CSV的格式如下:
CSV格式可見,output可都是tensor類型的呀!
3. 標(biāo)簽數(shù)據(jù)(meta.tsv)和圖片數(shù)據(jù)(sprite.jpg)生成
從上面可視化的結(jié)果來看,每個(gè)空間展示圖片的圖片內(nèi)容和標(biāo)簽(藍(lán)或紅)信息都被包含了,所以這里我們需要生成需要的標(biāo)簽數(shù)據(jù)和圖片數(shù)據(jù)。我們從上面的csv文件中導(dǎo)入圖片的地址數(shù)據(jù),因?yàn)橹懒说刂窋?shù)據(jù),我們就知道了圖片的內(nèi)容以及標(biāo)簽(因?yàn)榉鞘鹿屎褪鹿蕯?shù)據(jù)集的地址不同,所以可以用地址的關(guān)鍵字判斷類別)
我們先定義一些變量,用作保存時(shí)的名稱:
# PROJECTOR需要的日志文件名和地址相關(guān)參數(shù) LOG_DIR = 'log' SPRITE_FILE = 'sprite.jpg' META_FIEL = "meta.tsv" os.mkdir(LOG_DIR)接著加載數(shù)據(jù):
# 數(shù)據(jù)加載 sample_data = pd.read_csv(r'E:Deep_learning_PytorchVideo_recognitionAccident_RecognitionCNN_LSTMAccident_Clustingsample_data.csv'3.1 載入圖片并生成一張大圖(sprite image)
這里我們先導(dǎo)入地址,然后將地址中的所有圖片導(dǎo)入進(jìn)來并保存到一張list中(名為img_list)
img_path= sample_data['img_path'].values img_list=[] for path in img_path:img=cv2.imread(path,0)# print(img.shape)img=cv2.resize(img,(128,128))# print(img.shape)img_list.append(img.reshape(1,128,128))接著我們定義一個(gè)大圖像生成函數(shù)create_sprite_image,如下:
def create_sprite_image(images):"""Returns a sprite image consisting of images passed as argument. Images should be count x width x height"""if isinstance(images, list):images = np.array(images)img_h = images.shape[1] #112img_w = images.shape[2] #112# sprite圖像可以理解成是小圖片平成的大正方形矩陣,大正方形矩陣中的每一個(gè)元素就是原來的小圖片。于是這個(gè)正方形的邊長就是sqrt(n),其中n為小圖片的數(shù)量。n_plots = int(np.ceil(np.sqrt(images.shape[0]))) #根號(hào)下2000# 使用全1來初始化最終的大圖片。spriteimage = np.ones((img_h*n_plots, img_w*n_plots))for i in range(n_plots):for j in range(n_plots):# 計(jì)算當(dāng)前圖片的編號(hào)this_filter = i*n_plots + jif this_filter < images.shape[0]:# 將當(dāng)前小圖片的內(nèi)容復(fù)制到最終的sprite圖像this_img = images[this_filter]spriteimage[i*img_h:(i + 1)*img_h,j*img_w:(j + 1)*img_w] = this_imgreturn spriteimage然后使用img_list生成這個(gè)大圖像并保存:
img=np.concatenate(img_list,0) #(2000, 112, 112) # 生成sprite圖像# to_visualise = 1 - np.reshape(img, (-1, 28, 28)) sprite_image = create_sprite_image(img)# 將生成的sprite圖片放到相應(yīng)的日志目錄下 path_for_sprites = os.path.join(LOG_DIR, SPRITE_FILE) # plt.imsave(path_for_mnist_sprites,sprite_image, cmap='gray') cv2.imwrite(path_for_sprites,sprite_image,[int(cv2.IMWRITE_JPEG_QUALITY), 100])這里,sprite_image就生成好了,保存在log/sprite.jpg中。
3.2 生成標(biāo)簽數(shù)據(jù)meta.tsv
我們的事故和非事故圖片集放在文件夾:
非事故:Z:Fast_datasetAccident_model_pretrainClassficationFalse_for_classificaition事故:
Z:Fast_datasetAccident_model_pretrainClassficationTrue_for_classification
這里我們可以看出,可以用圖片地址區(qū)分事故標(biāo)簽(False為非事故,True為事故)
那么我們代碼這么寫:
# # 生成每張圖片對(duì)應(yīng)的標(biāo)簽文件并寫道相應(yīng)的日志目錄下 path_for_metadata = os.path.join(LOG_DIR,META_FIEL) with open(path_for_metadata, 'w') as f:f.write("IndextLabeln")for index, path in enumerate(img_path):label=0 if 'False' in path else 1f.write("%dt%dn"%(index, label))即完成了對(duì)meta.csv的記錄,meta.csv里面是長這樣的。
到這里,標(biāo)簽數(shù)據(jù)(meta.tsv)和圖片數(shù)據(jù)(sprite.jpg)就生成了,接下來到最后的數(shù)據(jù)的匹配和關(guān)聯(lián)+總?cè)罩疚募伞?/p>
4. 數(shù)據(jù)的匹配和關(guān)聯(lián)+總?cè)罩疚募?/h2>
上述,我們?cè)贑SV文件中保存了每個(gè)圖片在訓(xùn)練好的模型的輸出向量,這個(gè)輸出向量可以看作圖片在淺層空間的表示。那我們就從該CSV文件導(dǎo)出需要的向量,這里我們以8維的向量為例子,導(dǎo)入的程序代碼如下:
sample_data = pd.read_csv(r'E:Deep_learning_PytorchVideo_recognitionAccident_RecognitionCNN_LSTMAccident_Clustingsample_data.csv')output= sample_data['output8'].valuesoutput=[eval(i).cpu().numpy() for i in output]# print(type(output2[0]))final_result=np.asarray(output)這段代碼需要注意的是,我們保存時(shí)候,向量以torch.tensor形式保存,從CSV導(dǎo)入的時(shí)候,輸出的類型又是字符串str類型,所以我們需要做兩件事
然后我們定義我們本文最重要的函數(shù) visualisation(),代碼如下:
LOG_DIR = 'log' SPRITE_FILE = 'sprite.jpg' META_FIEL = 'meta.tsv' TENSOR_NAME = "zw" TRAINING_STEPS = 10def visualisation(final_result):# 使用一個(gè)新的變量來保存最終輸出層向量的結(jié)果,因?yàn)閑mbedding是通過Tensorflow中變量完成的,所以PROJECTOR可視化的都是TensorFlow中的變哇。# 所以這里需要新定義一個(gè)變量來保存輸出層向量的取值y = tf.Variable(final_result, name=TENSOR_NAME)summary_writer = tf.summary.FileWriter(LOG_DIR)# 通過project.ProjectorConfig類來幫助生成日志文件config = projector.ProjectorConfig()# 增加一個(gè)需要可視化的bedding結(jié)果embedding = config.embeddings.add()# 指定這個(gè)embedding結(jié)果所對(duì)應(yīng)的Tensorflow變量名稱embedding.tensor_name = y.name# Specify where you find the metadata# 指定embedding結(jié)果所對(duì)應(yīng)的原始數(shù)據(jù)信息。比如這里指定的就是每一張MNIST測(cè)試圖片對(duì)應(yīng)的真實(shí)類別。在單詞向量中可以是單詞ID對(duì)應(yīng)的單詞。# 這個(gè)文件是可選的,如果沒有指定那么向量就沒有標(biāo)簽。# embedding.metadata_path = META_FIELembedding.metadata_path = 'meta.tsv'# Specify where you find the sprite (we will create this later)# 指定sprite 圖像。這個(gè)也是可選的,如果沒有提供sprite 圖像,那么可視化的結(jié)果# 每一個(gè)點(diǎn)就是一個(gè)小困點(diǎn),而不是具體的圖片。# embedding.sprite.image_path = SPRITE_FILEembedding.sprite.image_path = 'sprite.jpg'# 在提供sprite圖像時(shí),通過single_image_dim可以指定單張圖片的大小。# 這將用于從sprite圖像中截取正確的原始圖片。embedding.sprite.single_image_dim.extend([128, 128])# Say that you want to visualise the embeddings# 將PROJECTOR所需要的內(nèi)容寫入日志文件。projector.visualize_embeddings(summary_writer, config)# 生成會(huì)話,初始化新聲明的變量并將需要的日志信息寫入文件。sess = tf.InteractiveSession()sess.run(tf.global_variables_initializer())saver = tf.train.Saver()saver.save(sess, os.path.join(LOG_DIR, "model"), TRAINING_STEPS)sess.close()summary_writer.close()需要注意的是圖片的大小和上述第三部分定義的圖片大小應(yīng)當(dāng)一致!
然后接著上面,將final_result輸入到函數(shù)visualisation中,即可完成log日志的生成!
visualisation(final_result)log文件下的內(nèi)容如下:
其中projector_config.pbtxt文件中的內(nèi)容為
包含了各成員對(duì)應(yīng)的關(guān)系
到最后,我們打開命令行CMD:
輸入
tensorboard --logdir=E:Deep_learning_PytorchVideo_recognitionAccident_RecognitionCNN_LSTMlog --host=127.0.0.1這里,一定注意--host!一定注意--host!一定注意--host!(重要的說三遍)
因?yàn)槿绻惠斎?-host,選擇默認(rèn),那去網(wǎng)頁上就是打不開的!就算打開了,也沒有標(biāo)簽文件和圖片數(shù)據(jù)的,這是花了我一個(gè)晚上血淋淋的教訓(xùn)呀!
5.總結(jié)
關(guān)于如何快速上手Tensorboard的高維向量可視化,本篇文章算是比較詳細(xì)了!算是我一晚上的工作經(jīng)驗(yàn)吧!終于可以安心做其他事了!
總結(jié)
以上是生活随笔為你收集整理的tensorflow生成图片标签_Tensorboard高维向量可视化 + 解决标签和图片不显示BUG的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 传音 Infinix 手机 260W 快
- 下一篇: 顽皮狗致歉,保证让游戏《最后生还者 Pa