連載一:PyCon2018|用slim調用PNASNet模型(附源碼)

第八屆中國Python開發者大會PyConChina2018,由PyChina.org發起,由來自CPyUG/TopGeek等社區的30位組織者,近150位志願者在北京、上海、深圳、杭州、成都等城市舉辦。致力於推進各種Python相關的技術在互聯網、企業應用等領域的研發和應用。

代碼醫生工做室有幸接受邀請,參加了此次會議的北京站專場。在會上主要分享了《人工智能實戰案例分享-圖像處理與數值分析》。

會上分享的一些案例主要是來源於《python帶我起飛——入門、進階、商業實戰》一書與《深度學習之TensorFlow:入門、原理與進階實戰》一書。另外,還擴充了若干其它案例。在本文做爲補充,將會上分享的其它案例以詳細的圖文方式補充進來,並提供源碼。共分爲4期連載。

  1. 用slim調用PNASNet模型python

  2. 用slim微調PNASNet模型git

  3. 用對抗樣本攻擊PNASNet模型github

  4. 惡意域名檢測實例api


使用AI模型來識別圖像是桌子、貓、狗,仍是其餘
數組

本章將演示一個應用AI模型進行圖像識別的例子。經過該實例可以讓讀者真真切切的感覺到AI的強大,及使用模型的操做過程。
bash

案例描述
網絡

經過代碼載入現有模型,對任意圖片進行分類識別,觀察識別結果。
框架

本案使用的是在ImgNet數據集上訓練好的PNASNet模型。PNASNet模型是目前最優秀的圖片識別模型之一。該模型在ImgNet數據集上訓練後,能夠識別1000種類別的圖片。要完成該案例,須要先下載TensorFlow中的models模塊及對應的與訓練模型。下面就來詳細介紹。函數

代碼環境及模型準備
學習

爲了使讀者可以快速完成該實例,直觀上感覺到模型的識別能力,能夠直接使用本書配套的資源。並將其放到代碼的同級目錄下便可。

若是想體驗下從零開始手動搭建,也能夠按照下面的方法準備代碼環境及預編譯模型。

1. 下載TensorFlow models模塊

TensorFlow models模塊中包含了使用TensorFlow框架完成的各類不一樣模型,能夠直接拿來使用。在TensorFlow models模塊中進行二次開發,可使AI項目開發變得簡單快捷。來到如下網址:

github.com/tensorflow/…

能夠經過git 將代碼clone下來,也能夠手動下載(具體操做見《深度學習之TensorFlow:入門、原理與進階實戰》一書的8.5.2節)。

2. 部署TensorFlow slim模塊

解壓以後,將其中\models-master\research路徑下的slim文件夾(如圖1),複製到本地代碼的同級路徑下。


圖1 slim代碼庫路徑

slim庫又叫作TF-slim,是TensorFlow 1.0以後推出的一個新的輕量級高級API接口。將不少常見TensorFlow函數作了二次封裝,使代碼變得更加簡潔。

在TF-slim模塊裏面同時提供了大量用TF-slim寫好的網絡模型結構代碼,以及用該代碼訓練出的模型文件。本例中就是使用TF-slim模塊中訓練好的PNASNet模型文件。

3. 下載PNASNet模型

訪問以下網站,能夠下載訓練好的PNASNet模型:

github.com/tensorflow/…

該連接打開後,能夠找到「pnasnet-5_large_2017_12_13.tar.gz」的下載地址,如圖2。


圖2 PNASNet模型下載頁面

下載完後,將其解壓,會獲得以下圖3中的文件結構。

圖3 PNASNet模型文件

將整個pnasnet-5_large_2017_12_13文件夾放到本地代碼的同級目錄下。在使用時,只須要指定好模型的路徑:「pnasnet-5_large_2017_12_13」,系統便會自動加載模型裏面的文件及內容。

注意:

在圖2中,能夠看到,出來本實例所用的PNASNet模型外,還有好多其餘的模型。其中倒數第二行的mobilenet_v2_1.0_224.tgz模型也是比較經常使用的,該模型體積小、運算快,經常使用於在移動設備。

4. 準備ImgNet數據集標籤

因爲本例中使用的PNASNet預訓練模型是在ImgNet數據集上訓練好的模型,在使用該模型分類是,還須要有與其對應的標籤文件。slim中已經將得到標籤文件的操做直接封裝到了代碼裏,直接調用便可。因爲標籤文件是英文分類,讀起來不太直觀。這裏提供了一個翻譯好的中文標籤分類文件「中文標籤.csv」。也在書籍同步的配套資源中。

前面4項都準備好後,總體的目錄結構如圖4所示。


圖4 實例1文件結構

在圖4中,會看到還有三個圖片文件「72.jpg」、「hy.jpg」、「ps.jpg」,這三個文件是用於測試使用的圖片,讀者能夠替換爲本身所要識別的文件。

代碼實現:初始化環境變量,並載入ImgNet標籤

首先將本地的slim做爲引用庫載入到系統的環境變量裏。接着將ImgNet標籤載入並顯示出來。

import sys                                                 #初始化環境變量
  nets_path = r'slim'
  if nets_path not in sys.path:
     sys.path.insert(0,nets_path)
  else:
     print('already add slim')
 
  import tensorflow as tf                                   #引入頭文件
  from PIL import Image
 from matplotlib import pyplot as plt
 from nets.nasnet import pnasnet
 import numpy as np
 from datasets import imagenet
 slim = tf.contrib.slim

 tf.reset_default_graph()                       
 
 image_size = pnasnet.build_pnasnet_large.default_image_size       #得到圖片輸入尺寸
 labels = imagenet.create_readable_names_for_imagenet_labels()     #得到數據集標籤
 print(len(labels),labels)                                             #顯示輸出標籤

 def getone(onestr):
    return onestr.replace(',',' ')

 with open('中文標籤.csv','r+') as f:                             #打開文件 
    labels =list( map(getone,list(f))  )
    print(len(labels),type(labels),labels[:5]) 
複製代碼

使用AI模型來識別圖像

代碼中提供了英文與中文的兩種標籤。在實際應用中使用了中文的標籤。程序運行後輸出結果以下:

1001 {0: 'background', 1: 'tench, Tinca tinca', 2: 'goldfish, Carassius auratus', 3: 'great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias', 4: 'tiger shark, Galeocerdo cuvieri', 5: 'hammerhead, hammerhead shark',……,994: 'gyromitra', 995: 'stinkhorn, carrion fungus', 996: 'earthstar', 997: 'hen-of-the-woods, hen of the woods, Polyporus frondosus, Grifola frondosa', 998: 'bolete', 999: 'ear, spike, capitulum', 1000: 'toilet tissue, toilet paper, bathroom tissue'}

1001 <class 'list'> ['背景known \n', '丁鯛 \n', '金魚 \n', '大白鯊 \n', '虎鯊 \n']

一共輸出了兩行,第一行爲英文標籤,第二行爲中文標籤。

代碼實現:定義網絡結構

經過代碼,定義了佔位符input_imgs,用於輸入待識別的圖片。接着定義網絡節點end_points,對接預訓練模型的輸出節點。end_points是一個字典,裏面Predictions對應的值就是最終的輸出結果。該值中放置着1000個元素的數組,表明預測圖片在這1000個分類中的機率。經過tf.argmax函數對最終結果進行轉化,獲得數組中最大的那個數的索引,即是該圖片的分類。

sample_images = ['hy.jpg', 'ps.jpg','72.jpg']                   #定義待測試圖片路徑

 input_imgs = tf.placeholder(tf.float32, [None, image_size,image_size,3]) #定義佔位符

 x1 = 2 *( input_imgs / 255.0)-1.0                                 #歸一化圖片

 arg_scope = pnasnet.pnasnet_large_arg_scope()                  #得到模型命名空間
 with slim.arg_scope(arg_scope):
    logits, end_points = pnasnet.build_pnasnet_large(x1,num_classes = 1001, is_training=False)   
    prob = end_points['Predictions']
    y = tf.argmax(prob,axis = 1)                                  #得到結果的輸出節點
複製代碼

使用AI模型來識別圖像(續)

在34行代碼中的arg_scope是命名空間的意思。在TensorFlow中相同名稱的不一樣張量是經過命名空間來劃分的。關於命名空間的更多知識能夠參考《深度學習之TensorFlow:入門、原理與進階實戰》一書的4.3節。

代碼中第28行指定了待識別圖片的名稱。若是想識別本身的圖片,直接修改該行代碼中的圖片名稱便可。

代碼實現:載入模型進行識別

指定好要加載的預訓練模型,創建會話進行圖片識別。

checkpoint_file = r'pnasnet-5_large_2017_12_13\model.ckpt'       #定義模型路徑
 saver = tf.train.Saver()                                                #定義saver,用於加載模型
 with tf.Session() as sess:                                              #創建會話
    saver.restore(sess, checkpoint_file)                            #載入模型

    def preimg(img):                                    #定義圖片預處理函數
        ch = 3
        if img.mode=='RGBA':                            #兼容RGBA圖片
            ch = 4 

        imgnp = np.asarray(img.resize((image_size,image_size)), 
                          dtype=np.float32).reshape(image_size,image_size,ch)
        return imgnp[:,:,:3] 

    #得到原始圖片與預處理圖片
    batchImg = [ preimg( Image.open(imgfilename) ) for imgfilename in sample_images ]
    orgImg = [  Image.open(imgfilename)  for imgfilename in sample_images ]

    yv,img_norm = sess.run([y,x1], feed_dict={input_imgs: batchImg})    #輸入到模型

    print(yv,np.shape(yv))                                              #顯示輸出結果 
    def showresult(yy,img_norm,img_org):                            #定義顯示圖片函數
        plt.figure()  
        p1 = plt.subplot(121)
        p2 = plt.subplot(122)
        p1.imshow(img_org)                                        #顯示圖片
        p1.axis('off') 
        p1.set_title("organization image")

        p2.imshow(img_norm)                                        #顯示圖片
        p2.axis('off') 
        p2.set_title("input image")  

        plt.show()
        print(yy,labels[yy])

    for yy,img1,img2 in zip(yv,batchImg,orgImg):                    #顯示每條結果及圖片
        showresult(yy,img1,img2)
複製代碼

使用AI模型來識別圖像(續)

在TensorFlow中,模型運行時會有個圖的概念。在本例中,原始的網絡結構會在靜態圖中定義好,接着經過創建一個會話(代碼41行)讓當前代碼與靜態圖鏈接起來。調用sess中的run函數將數據輸入到靜態圖中,並返回結果,從而實現圖片的識別。

在模型識別以前,全部的圖片都要統一成固定大小的尺寸(代碼49行),並進行歸一化(代碼32行)。這個過程叫作圖片預處理。通過預處理後的圖片放到模型中,纔可以獲得準確的結果。

代碼運行後,輸出結果以下:


結果一共顯示了3幅圖,3段文字。每幅圖片下一行的文字,爲模型識別出來的結果。在每幅圖中,左側爲原始圖片,右側爲預處理後的圖片。

結尾

文內代碼能夠直接運行使用。若是不想手動搭建,還能夠下載本文的配套代碼。

【代碼獲取】:關注公衆號:xiangyuejiqiren    公衆號回覆「pycon1

若是以爲本文有用

能夠分享給更多小夥伴

相關文章
相關標籤/搜索