給出論文(Explainable Image Similarity Integrating Siamese Networks and Grad-CAM)的內容解讀、代碼運行說明
論文鏈接:J. Imaging | Free Full-Text | Explainable Image Similarity: Integrating Siamese Networks and Grad-CAM (mdpi.com)
代碼文件:ioannislivieris/Grad_CAM_Siamese (github.com)
論文理解
Grad CAM Siamese 算法集成了孿生網絡和 Grad-CAM,以提供圖像相似性任務的可解釋性。前者用于計算兩個輸入圖像之間的相似性,而后者用于可視化和解釋由基于卷積的孿生網絡做出的決策。
該算法的一個優點是,它能夠提供圖像相似度評分以及支持決策的視覺直觀解釋(事實解釋)和不支持決策的解釋(反事實解釋)。
非事實性解釋:當刪除這些特征,決策會更加準確,或理解為:a description of “what would have not happened when a certain decision was taken”。詳見參考文獻19:Grad-CAM: Visual Explanations from Deep Networks via Gradient-based Localization
數據集
- 花卉數據集(Flowers dataset):
- 包含4242張花卉圖片,分辨率為320×240。
- 圖片被分類為五個類別:“chamomile”(甘菊)、“tulip”(郁金香)、“rose”(玫瑰)、“sunflower”(向日葵)和“dandelion”(蒲公英)。
- 皮膚癌數據集(Skin cancer dataset):
- 包含2800張圖片,分辨率為224×224。
- 圖片涉及1400個惡性(Malignant)和1400個良性(Benign)的腫瘤病例。
- AirBnB數據集(AirBnB dataset):
- 包含864張室內和室外房屋圖片,分辨率為600×400。
- 圖片被分類為12個類別:“backyard”(后院)、“basement”(地下室)、“bathroom”(浴室)、“bedroom”(臥室)、“decor”(裝飾)、“dining-room”(餐廳)、“entrance”(入口)、“house-exterior”(房屋外觀)、“kitchen”(廚房)、“living-room”(客廳)、“outdoor”(戶外)、“staircase”(樓梯)和“TV room”(電視房)。
模型訓練過程
- 創建訓練對。對于訓練數據集中的每張圖片,研究者會隨機選擇另外兩張圖片。其中一張圖片與原始圖片屬于同一個類別(同類圖片),另一張圖片屬于不同的類別(異類圖片)。也因此,Training instances、Validation instances、Testing instances輸出均為偶數,而且三者和為輸入圖片數的兩倍。
- 分配標簽。如果兩張圖片屬于同一個類別,這對圖片會被標記為標簽零(0)。這意味著它們是相似的或相同的。如果兩張圖片屬于不同的類別,這對圖片會被標記為標簽一(1)。這意味著它們是不同的。
- 定義相似度。孿生網絡的輸出是一個距離值,它表示兩張圖片之間的相似程度。距離值越小,表示圖片越相似;距離值越大,表示圖片越不相似。相似度是通過 1 減去距離值 d 來定義的,即相似度 = 1 ? d。這樣,如果d接近0(即圖片非常相似),相似度就會接近1;如果d較大(即圖片不相似),相似度就會接近0。當然可以預設閾值為 0.5 來準確判斷相似與否,這也是論文中所采用的方式。
- 通過隨機選擇正樣本(同一類別的圖片)和負樣本(不同類別的圖片),孿生網絡可以通過對比學習來優化其參數,使得正樣本間的距離減小,負樣本間的距離增大。
- 對于正樣本對(同一類別的圖片),我們希望這個得分接近1(或較高的值),表示它們是相似的;對于負樣本對(不同類別的圖片),我們希望得分接近0(或較低的值),表示它們是不相似的。
關于計算相似度值的細節:
02.Inference.py
中 pred = model(image1, image2)
,調用 utils/Siamese.py
的 forward()
,進一步利用歐氏距離 F.pairwise_distance
計算距離值,并將這個距離視為不相似度,后面 1-model() 就是相似度。
損失函數計算公式
L = 1 2 [ ( 1 ? y ) ( D w ) 2 + y { max ? ( 0 , m ? D w ) } 2 ] , \mathcal{L}=\frac{1}{2}\left[(1-y)\left(D_w\right)^2+y\left\{\max \left(0, m-D_w\right)\right\}^2\right], L=21?[(1?y)(Dw?)2+y{max(0,m?Dw?)}2],
where D w D_w Dw? is the model’s output and m m m is the margin value, which was set to 2 .
損失函數的取值范圍為:[0, +∞],詳見參考文獻34:Understanding the Behaviour of Contrastive Loss
應用場景
論文針對三種數據集分別進行訓練和評估,下面詳細介紹花卉、房間數據集的結果,以便更好理解事實性解釋和非事實性解釋以及對模型輸出的解讀。
上面兩個圖象均屬于玫瑰類別。模型的預測值為 0.24,也即模型預測輸入圖像間的相似性為 76%。由于相似度得分大于預定義的閾值 0.5,因此模型提示輸入圖像屬于同一類。圖 a、d 為原圖,對比圖 b、e,可知模型做出相似的的決策依據為花瓣處,對比圖 c、f,可知模型做出不相似的的決策依據為花莖處,或者說,如果改變兩朵花的花莖處,那么能提高圖像的相似度,使得相似這一決策更加準確。
上面兩個圖象均屬于 AirBnB 數據集中的不同類別,即第一張圖片屬于臥室類,而第二張圖片屬于客廳類。模型預測值為 0.516,即相似度得分為 48.4%,表明該模型預測輸入圖像大致屬于不同的類。圖 b、e 表明模型將重點放在第一張圖像中的椅子和第二張圖像中的燈、壁爐和時鐘上,以預測圖像不相似。圖 c、f 給出了兩幅圖像的反事實解釋,這表明模型分別關注了第一幅和第二幅圖像中的床和沙發,以及兩幅圖像中呈現的桌子。兩張圖像都有一個共同的項目(桌子)以及兩個視覺上相似的項目(床和沙發),所以有 48.4% 的相似得分。
代碼復現
代碼層級目錄
- checkpoints # 存放訓練好的模型- car|-- model.pth # 此文件為未訓練至擬合的模型
- Data # AirBnB、Flowers、Skin_cancer 均為論文提供的數據集# data_for_compare 是用于計算相似度的圖片文件夾- AirBnB|-- class 1 # 每個class文件夾下,存放圖片文件|-- class 2|-- ...- car|-- class 1|-- class 2|-- ...- Flowers|-- class 1|-- class 2|-- ...- ...
- utils # 工具類文件夾- dataset.py- early_stopping.py- Grad_CAM.py- imshow.py- ...
- 01.Train_Siamese_model.ipynb # 用于訓練模型,測試集評估模型
- 02.Inference.ipynb # 利用訓練好的模型計算兩個圖片的相似度
- environment.yml # 環境依賴
- README.md
環境配置
conda 環境
基礎環境:Anaconda 3、文本編輯器(非必要,如:vscode、notepad++)
方式一:
# 切換路徑至 environment.yml 所在目錄
> conda env create -f environment.yml
# 切換虛擬環境
> conda activate pytorch_siamese
方式二:(推薦)
# 根據 environment.yml 文件中的 python 版本信息,先創建帶有 Python 版本的虛擬環境(h6244533_0 標識特定版本)
> conda create -n pytorch_siamese python=3.8.17=h6244533_0
# 切換虛擬環境
> conda activate pytorch_siamese
# 若網絡下載慢,則做如下設置。意為:若 1000s 沒有收到任何數據,就認為是一個超時錯誤,默認值為 60s
> conda config --set remote_read_timeout_secs 1000.0
# 切換目錄至 environment.yml 所在路徑,安裝其他包
> conda env update --file environment.yml
不需要設置鏡像源,保持默認即可。
如果下載擴展包失敗,可以嘗試將
environment.yml
文件拆封成多個文件,多次小批量下載 Python 擴展包,定位到不易下載的擴展包,搜索相關解決辦法。添加鏡像源下載 Python 擴展包時,可能出現報錯信息有:error3、error4,因未能解決,故不推薦設置鏡像源。
GPU 配置
nvcc -V
查看 CUDA 編譯器版本;nvidia-smi
查看 NVIDIA 驅動支持 CUDA 的版本。
較低版本的 CUDA 編譯版本可以在較高版本驅動下運行,為了確保最佳兼容性和充分利用新特性,理想的情況是確保 CUDA 工具包版本與 GPU 驅動支持的 CUDA 運行時版本相匹配或相近。
有時需要指定某一塊 GPU 用于訓練模型,需要為每塊 GPU 指定唯一的編號,而后在代碼中指定 GPU。
代碼運行
- 更新數據集。汽車圖片數據存放在
\Data\car
中,圖片大小與已有汽車圖片保持統一,均為:寬 1200px,高 800px,若大小不一致,則02.Inference.ipynb
輸出的圖像變形,暫時未知是否對模型訓練有影響。子文件夾按汽車類別劃分,文件夾名稱無要求,最好直觀可理解,目錄層級關系詳見「代碼層級目錄」。 - 更新
config.yml
文件中的參數,如:backbone_model、optimizer。 - 運行
01.Train_Siamese_model.ipynb
,訓練模型并用測試集評估。運行 Training 部分可能會報錯 「報錯記錄及解決」部分的 error1,按提供的解決方法操作即可。 - 運行
02.Inferences.ipynb
計算兩個圖像的相似度,并以熱力圖的形式展示兩張圖像的事實性解釋(Factual explanations)和非事實性解釋(Counterfactual explanations),以獲得可解釋的結果。其中,用于比對相似度的圖像,需要手動設置路徑。代碼會輸出熱力圖等圖片到當前路徑下,需及時存放輸出圖片,以免被覆蓋。
報錯記錄及解決
error1 - Initializing libiomp5md.dll, but found libiomp5md.dll already initialized
本報錯信息,出現在 Training 部分。
詳細報錯信息:
OMP: Error #15: Initializing libiomp5md.dll, but found libiomp5md.dll already initialized.
OMP: Hint This means that multiple copies of the OpenMP runtime have been linked into the program. That is dangerous, since it can degrade performance or cause incorrect results. The best thing to do is to ensure that only a single OpenMP runtime is linked into the process, e.g. by avoiding static linking of the OpenMP runtime in any library. As an unsafe, unsupported, undocumented workaround you can set the environment variable KMP_DUPLICATE_LIB_OK=TRUE to allow the program to continue to execute, but that may cause crashes or silently produce incorrect results. For more information, please see http://www.intel.com/software/products/support/.
解決辦法:
若代碼基于 conda
虛擬環境 pytorch_siamese
中的 Python 運行,那么刪除 .\anaconda3\envs\pytorch_siamese\Library\bin
中的 libiomp5md.dll
。
若代碼基于 base 環境中的 Python運行(不建議這樣),則刪除 .\anaconda3\Library\bin\libiomp5md.dll
文件。
參考鏈接:
關于OMP: Error #15: Initializing libiomp5md.dll, but found libiomp5md.dll already initialized.錯誤解決方法 - 知乎 (zhihu.com)
就是他!讓你的python內核莫名掛掉 | KMP_DUPLICATE_LIB_OK=TRUE 的始作俑者 - 知乎 (zhihu.com)
error2 - CondaError: Downloaded bytes did not match Content-Length
CondaError: Downloaded bytes did not match Content-Lengthurl: https://conda.anaconda.org/nvidia/win-64/libcublas-dev-11.11.3.6-0.tar.bz2target_path: D:\Program\anaconda3\pkgs\libcublas-dev-11.11.3.6-0.tar.bz2Content-Length: 394161490downloaded bytes: 389249421
> conda config --set remote_read_timeout_secs 1000.0
error3 - CondaHTTPError: HTTP 429 TOO MANY REQUESTS
CondaHTTPError: HTTP 429 TOO MANY REQUESTS for url <https://mirrors.ustc.edu.cn/anaconda/cloud/menpo/win-64/repodata.json>
Elapsed: 00:49.357271An HTTP error occurred when trying to retrieve this URL.
HTTP errors are often intermittent, and a simple retry will get you on your way.
'https//mirrors.ustc.edu.cn/anaconda/cloud/menpo/win-64'
不清楚是不是訪問量太多,導致報錯。嘗試刪除在鏡像源中報錯鏈接,但又會出現新的報錯鏈接。
error4 - 嘗試 aliyun 報錯
UnavailableInvalidChannel: HTTP 403 FORBIDDEN for channel anaconda/pkgs/msys2 <http://mirrors.aliyun.com/anaconda/pkgs/msys2>
應該是阿里云的鏈接無法訪問。
error5 - 根據 environment.yml 下載擴展包時,報錯 UnicodeDecodeError
詳細報錯信息:UnicodeDecodeError: 'gbk' codec can't decode byte 0xff in position 0: illegal multibyte sequence
原因:yaml 文件編碼非 utf-8,重新設置編碼即可
具體操作(以 vscode 為例):用 vscode 打開 yaml 文件后,點擊右下角文件編碼,save with Encoding
-> UTF-8
error6 - torch.cuda.OutOfMemoryError: CUDA out of memory
x詳細報錯信息:torch.cuda.OutOfMemoryError: CUDA out of memory. Tried to allocate 236.00 MiB (GPU 0; 23.65 GiB total capacity; 13.64 GiB already allocated; 49.12 MiB free; 18.92 GiB allowed; 13.85 GiB reserved in total by PyTorch) If reserved memory is >> allocated memory try setting max_split_size_mb to avoid fragmentation
解決辦法:減小batch_size
error7 - 下載包時,報錯 Solving environment: failed、ResolvePackageNotFound
原因:environment.yml
中對擴展包除了有版本號約束,還有特定版本標識,如: tqdm=4.65.0=pyhd8ed1ab_1
,這導致難以找到對應的版本。
解決方法1:將 conda-forge
添加到 channel 列表,以便搜索擴展包時也在 conda-forge channel 中查找:
> conda config --append channels conda-forge
解決方法2:根據報錯信息的提示,進入 Anaconda Cloud 中,尋找指定版本的擴展包并下載。
- 搜索指定擴展包
- 查看列表中的擴展包及版本號
- 點擊目標版本的擴展包鏈接
- 在
intallers
部分,找到 conda 下載命令
解決方法3:刪除 yaml
文件中的第二個等號后的內容。如果仍報錯,則將報錯的擴展包暫時不安裝,等其他擴展包安裝好后再安裝。
解決方法4:在 Anaconda Cloud 中尋找指定版本擴展包的 Files
,離線下載擴展包。此方法不推薦,可能導致 conda 無法識別到來源(unknown),并報錯。
補充:Linux 系統/服務器中安裝 Anaconda
-
通過在
Linux
終端中運行uname -m
命令來確定的系統架構 -
下載 Anaconda。訪問 Anaconda 官方網站 或者 清華大學開源軟件鏡像站 等提供下載鏈接的網站。
-
選擇版本。在下載頁面,找到對應于的操作系統和系統架構的 Anaconda 安裝包鏈接。
-
使用
wget
命令在 Linux 終端中下載安裝包。例如:wget https://repo.anaconda.com/archive/Anaconda3-2024.02-1-Linux-x86_64.sh
-
下載完成后,給予安裝腳本執行權限:
chmod +x Anaconda3-2024.02-1-Linux-x86_64.sh
-
執行安裝腳本開始安裝過程:
./Anaconda3-2024.02-1-Linux-x86_64.sh
-
按照安裝程序的提示進行操作,閱讀并接受許可協議,選擇安裝路徑,并決定是否要初始化 Anaconda 環境變量。瀏覽協議,enter,最后yes
-
配置環境變量
vim ~/.bashrc# 在末尾添加如下語句,此處路徑為 anacodda3 實際安裝路徑 export PATH=/home/xxxx/anacodnae/bin:$PATH# 添加完后激活環境 source ~/bashrc
-
conda -V
測試
參考文章:
PyTorch 代碼中 GPU 編號與 nvidia-smi 命令中的 GPU 編號不一致問題解決方法
PackagesNotFoundError: The following packages are not available from current channels的解決辦法-CSDN博客
解決創建conda環境時Solving environment: failed 和 ResolvePackageNotFound 的錯誤_solving environment: failed resolvepackagenotfound-CSDN博客
圖像相似度分析——相似度算法 (qq.com)
圖片相似度計算(CVPR2015-DeepCompare) (qq.com)
無需訓練/部署模型,一文學會圖像相似度算法pHash原理和實戰 (qq.com)
圖像相似度分析——相似度算法 (qq.com)
圖片相似度計算(CVPR2015-DeepCompare) (qq.com)
無需訓練/部署模型,一文學會圖像相似度算法pHash原理和實戰 (qq.com)
教你如何實現圖片特征向量提取與相似度計算 (qq.com)