iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 10
6

前言

上一篇我們詳細介紹了 VGG 16 模型的使用方法,現在,我們就來應用它來進行照片比對,根據照片內主體的相似度(Visual Similarity)判斷,找出相關的照片,例如,我們要在 3D 模型網站搜尋『卡通人物』模型,我們可以輸入一張照片,程式就可以幫我們找出相似的 3D 模型,有興趣的讀者想了解詳情可參閱 Using Keras' Pretrained Neural Networks for Visual Similarity Recommendations

https://ithelp.ithome.com.tw/upload/images/20171207/20001976w3Cq6yWHRt.png
圖. 照片比對,輸入最上面一張圖,找出下面類似的模型,圖片來源:Using Keras' Pretrained Neural Networks for Visual Similarity Recommendations

實作

本程式名稱vgg16_vs.py,可在這裡找到,先準備一組照片檔,內含幾類照片,例如,狗、貓、熊等,放在程式所在目錄下的images子目錄,然後執行下列指令:
python vgg16_vs.py 1
vgg16_vs.py 程式需要一個參數,是images子目錄下第N張照片(即上面指令的 1,注意,陣列索引起始值是0)。執行結果會顯示最相似的兩張照片,我實驗結果相當好,可以找出不同姿勢的動物,相似度的判斷非常準確。

from keras.applications.vgg16 import VGG16
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input, decode_predictions
import numpy as np
import os
import sys

# 計算相似矩陣
def cosine_similarity(ratings):
    sim = ratings.dot(ratings.T)
    if not isinstance(sim, np.ndarray):
        sim = sim.toarray()
    norms = np.array([np.sqrt(np.diagonal(sim))])
    return (sim / norms / norms.T)
    
def main():
    # 自 images 目錄找出所有 JPEG 檔案    
    y_test=[]
    x_test=[]
    for img_path in os.listdir("images"):
        if img_path.endswith(".jpg"):
            img = image.load_img("images/"+img_path, target_size=(224, 224))
            y_test.append(img_path[0:4])
            x = image.img_to_array(img)
            x = np.expand_dims(x, axis=0)
            if len(x_test) > 0:
                x_test = np.concatenate((x_test,x))
            else:
                x_test=x
    
    # 轉成 VGG 的 input 格式
    x_test = preprocess_input(x_test)

    # include_top=False,表示會載入 VGG16 的模型,不包括加在最後3層的卷積層,通常是取得 Features (1,7,7,512)
    model = VGG16(weights='imagenet', include_top=False) 


    # 萃取特徵
    features = model.predict(x_test)
    # 計算相似矩陣
    features_compress = features.reshape(len(y_test),7*7*512)
    sim = cosine_similarity(features_compress)

    # 依命令行參數,取1個樣本測試測試
    inputNo = int(sys.argv[1]) # tiger, np.random.randint(0,len(y_test),1)[0]
    top = np.argsort(-sim[inputNo], axis=0)[1:3]

    # 取得最相似的前2名序號
    recommend = [y_test[i] for i in top]
    print(recommend)

if __name__ == "__main__":
    main()

程式說明

  1. cosine_similarity 函數:這是程式最重要的部分,將images目錄內的每一張照片轉成特徵向量,再兩兩作比較,利用 cosine 函數計算兩個特徵向量的角度,越接近 1,表示越相似,這幾行程式碼來自Using Keras' Pretrained Neural Networks for Visual Similarity Recommendations

  2. main 函數:

    • 先自 images 目錄找出所有 JPEG 檔案,讀出圖檔內容,將他們轉成 VGG input 格式。
    • 使用 VGG 16 模型,include_top=False,表示會載入 VGG16 的模型,不包括加在最後3層的卷積層,只計算特徵(Features)向量。
    • 呼叫 VGG 16 模型,將images目錄內的每一張照片萃取出特徵向量,再轉為一維,呼叫 cosine_similarity 函數,計算每一張照片與其他照片的相似度。
    • 依命令行參數,取一張照片當作 input 樣本測試。
    • 根據該樣本所在列查詢與其他圖檔的相似度,找出最相似的前2名序號。
      https://ithelp.ithome.com.tw/upload/images/20171208/20001976s3rolx2wD1.png
      圖. 相似度矩陣,例如紅框為第2個圖檔與其他圖檔的相似度。

結語

由於相似度矩陣要倆倆比較,如果圖檔很多,執行就要等一下了,另外,我一開始是使用 keras 現成資料集 CIFAR100 small image ,準確率一直很差,我以為程式寫錯了,後來才發覺 CIFAR100 圖像素只有 32 x 32,太小了,不適合 VGG 訓練模型,所以,讀者找圖時要找像素大一點(224x224以上)的圖檔測試。

這個程式可應用在哪裡呢?

  1. 現在每個人一支手機在手,都會拍了很多照片,我們如果要從幾千張照片中找出與某個人有關的照片,就可以用本篇介紹的建模方式,自動比對就搞定了。

  2. 幾年前參加一場演講,講師談到『如何評估NBA球賽的廣告看板效益』,他們計算整段轉播影片中出現多少次某個廣告看板,藉此判斷是否符合成本效益? 以及放在哪一個位置的看板曝光率最高,當時覺得很神奇,現在,看完這一篇,讀者也可以做得到了,只要利用VGG模型,將看板、影片放入訓練資料,就可以找到有出現看板的影片了。

  3. 另類的商品推薦(cross sale/Up sale):例如我們在電子商務網站上瀏覽某一項商品時,網站常常會推薦一些相關商品給我們,可能是熱銷或搭配使用的商品,譬如瀏覽電腦主機,系統就會推薦其他型號或廠牌的主機,推薦的商品通常是由後台依照產品分類、使用者偏好、促銷活動及商品銷售狀況統計出來的,如果用這個程式,要找到其他相似外型的商品就簡單多了。

  4. 罪犯追蹤:現在街頭監視器滿街都是,犯罪現場常能拍到嫌疑犯身影,若要追查行蹤,聽說刑警必須緊盯螢幕,看錄影帶一整天,才能找出嫌疑犯的藏匿處,若是能應用本篇介紹的演算法應用,也許在短時間內,就可以找到有嫌疑犯身影的相關影片了。

這次我們學會如何使用 Keras Applications,作出實際可用的應用,下次,我們就來討論另一個應用『風格轉換』(Style Transfer),讓人人都可以變成畢卡索、梵谷,今天剛好看到一個新聞『催生全球首位AI繪師Andy,美圖搶攻人工智慧卻面臨一大挑戰』,這個主題很夯喔。


上一篇
Day 09:CNN 經典模型應用
下一篇
Day 11:風格轉換(Style Transfer) -- 人人都可以是畢卡索
系列文
以100張圖理解 Neural Network -- 觀念與實踐31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
神Q超人
iT邦研究生 5 級 ‧ 2018-07-09 17:04:59

這好厲害!!!
抱歉姍姍來遲XD

晚到總比不到好,善哉。

1
watgh196
iT邦新手 5 級 ‧ 2019-02-25 11:24:39

您好,想請問執行後出現
Traceback (most recent call last):
File "vgg16_vs.ipynb", line 7, in
"collapsed": false
NameError: name 'false' is not defined

是因為python的版本不同嗎?

應該是 Keras 版本的問題,要安裝 keras 2.2,指令如下:
pip install keras=2.2.0

0
Denny Chang
iT邦新手 2 級 ‧ 2020-02-25 15:37:16

您好,當我在執行inputNo = int(sys.argv[1])這行程式碼時,會出現錯誤list index out of range,想請問要怎麼解決,經上網查詢獲得以下資訊:
sys.argv[]是用來獲取命令行參數的,sys.argv[0]表示代碼本身文件路徑,所以參數從1開始,從cmd輸入......
但我程度太差,看不太懂/images/emoticon/emoticon06.gif

就是該程式執行時,須帶一參數,如下:
python vgg16_vs.py 1
1: 表示第一張,可參考『實作』說明

0
nillis
iT邦新手 5 級 ‧ 2022-03-04 09:36:44

收穫良多 感謝
終於感覺理論可以應用
cosine_similarity 可以這樣在高維空間使用
終於一步一步了解了更多cnn應用相關延伸

謝謝

讚,分享的動力+1。

我要留言

立即登入留言