GitHub新項目:輕鬆使用多種預訓練卷積網路抽取圖像特徵

選自GitHub,機器之心整理。

最近 GitHub 有一個非常有意思的項目,它可以使用多種預訓練 TensorFLow 模型計算圖像特徵。對於每一個模型,它們都會輸出最後的全連接層,即 AlexNet 的第七個全連接層、VGG_19 的第 8 個全連接層等。這些層級將最終抽取出圖像的特徵,並能進一步用於圖像分類和聚類等。機器之心簡要地介紹了該項目,並測試了使用Inception_V1預訓練模型抽取圖像特徵。

項目地址:github.com/cameronfabbr

這個項目的用法非常簡單,我們只需要下載項目中的預訓練模型檢查點,例如 Inception V1 等。然後再使用如下命令行載入數據與預訓練模型就能抽取出圖像的特徵:

tar -xvf inception_v1_2016_08_28.tar.gzpython compute_features.py --data_dir=test_images/ --checkpoint_file=inception_v1.ckpt --model=inception_v1

預訓練模型的輸出將會寫入 inception_v1_features.pkl 文件,它包含了一個如下形式的字典:{image_path:feature}。案例 load_features.py 展示了如何使用預計算的特徵。例如我們可以使用如下命令行將預抽取的特徵用於其它任務:

python load_features.py features/inception_v1_features.pkl

有一些模型用上述方法可能並不能載入,例如 inception_v4 有不同的模型檢查點和模型定義等。讀者可查與具體的模型定義並構建適合於我們自己任務的用法。

預訓練模型

我們下載所有的預訓練模型:drive.google.com/file/d

所有模型的獨立下載地址在項目中都有展示。這些預訓練的卷積神經網路都在 ILSVRC-2012-CLS 圖像分類數據集中訓練,且它們在 ImageNet 測試集中的 Top-1 和 Top-5 準確度都在下表給出。每個模型都給出了對應的論文和 TF-Sim 寫的模型代碼,這些模型代碼都來自 TensorFLow 中的 models 子項目。

注意 VGG 和 ResNet V1 的參數轉換自它們的原始 Caffe 格式,而 Inception 和 ResNet V2 的預訓練參數由谷歌內部完成。此外,這些準確度都是在單個圖像 crop 下評估的,也有一些學術論文使用多個 crops 在不同規模上有更好的準確度。

在使用預訓練模型抽取圖像特徵的同時,我們還需要了解各個模型的架構與特點,這樣才能更有效地利用它們抽取出來的特徵向量。如下展示了經典 Inception_V3 模型的一個 Inception 模塊,卷積層都是使用 TensorFlow-Slime 實現,因此我們可以在一行中實現一個卷積層的前向傳播演算法。一般而言,slim.conv2d 有三個參數必填,第一個參數是輸入矩陣、第二個是當前卷積層的卷積核數量,最後就是卷積核尺寸。

with slim.arg_scope([slim.conv2d, slim.max_pool2d, slim.avg_pool2d], stride=1, padding=SAME): # mixed: 35 x 35 x 256. end_point = Mixed_5b with tf.variable_scope(end_point): with tf.variable_scope(Branch_0): branch_0 = slim.conv2d(net, depth(64), [1, 1], scope=Conv2d_0a_1x1) with tf.variable_scope(Branch_1): branch_1 = slim.conv2d(net, depth(48), [1, 1], scope=Conv2d_0a_1x1) branch_1 = slim.conv2d(branch_1, depth(64), [5, 5], scope=Conv2d_0b_5x5) with tf.variable_scope(Branch_2): branch_2 = slim.conv2d(net, depth(64), [1, 1], scope=Conv2d_0a_1x1) branch_2 = slim.conv2d(branch_2, depth(96), [3, 3], scope=Conv2d_0b_3x3) branch_2 = slim.conv2d(branch_2, depth(96), [3, 3], scope=Conv2d_0c_3x3) with tf.variable_scope(Branch_3): branch_3 = slim.avg_pool2d(net, [3, 3], scope=AvgPool_0a_3x3) branch_3 = slim.conv2d(branch_3, depth(32), [1, 1], scope=Conv2d_0b_1x1) net = tf.concat(axis=3, values=[branch_0, branch_1, branch_2, branch_3]) end_points[end_point] = net

以上展示了 Inception_V3 的一個模塊,簡單而言,該模塊就是將四個並行的卷積(branch_0 到 branch_3)分別執行不同的卷積運算,例如 branch_2 是由三個卷積層疊加而成,然後再將 4 份卷積特徵圖拼接起來作為這一模塊的輸出。

其它還有很多如特徵抽取的效果或模型架構等還需要各位讀者自己嘗試。

我們測試了 inception_V1 預訓練模型,它完成特徵計算後會輸出一個包含特徵的 pkl 文件。我們發現其它如 Inception V3 會報錯說權重文件中名為 InceptionV3/AuxLogits/Conv2d_2a_3x3/BatchNorm/beta 的張量沒有定義,Inception V4 中會報錯 tf.train.Saver() 沒有需要保存的變數。

也許這些錯誤可能是由環境配置或其它問題,但還有很多如特徵抽取的效果或模型架構等還需要各位讀者自己嘗試。

推薦閱讀:

TAG:卷積神經網路CNN | 人工智慧 |