對於計算機視覺的應用如今是很是普遍的,可是它背後的原理其實很是簡單,就是將每個像素的值pixel輸入到一個DNN中,而後讓這個神經網絡去學習這個模型,最後去應用這個模型就能夠了。聽起來是否是很簡單,其實若是你們深刻研究的話,這裏面仍是有不少內容去學習的,例如:我們的圖片大小可能不同,同一張圖片不一樣的旋轉角度可到的結果可能不同,如何給我們的本地圖片來label(實際中並非全部的數據都想mnist那樣,谷歌都給我們label好了,拿來用就行),等等這些問題我們在實際中確定都是要用到的。這一節首先會先介紹一下如何直接將圖片的塞進網絡訓練;第二部分會介紹一下卷積網絡的結構原理和應用(用谷歌本身提供的mnist數據集);第三部分我會介紹一下如何用卷及網絡CNN來訓練我們本身的圖片數據。其中的核心重點是我們的第二部分。node
傳統的DNN確定你們都是知道的,就是經過構建Sequential layers, 而後將我們的圖片的pixel值做爲數據傳遞給這個DNN的input layer, 只有這個input layer後面的dense layers是根據用戶本身的需求進行建立架構的。那麼經過什麼流程來訓練呢?首先第一步我們得加載數據,以下所示網絡
mnist = tf.keras.datasets.fashion_mnist (training_images, training_labels), (test_images, test_labels) = mnist.load_data() training_images=training_images/255.0 test_images=test_images/255.0
上面的數據是我們TensorFlow自帶的,它都幫助我們這裏好了,也幫助我們把圖片的labels都設定好了,幫助我們省了不少的功夫,可是很遺憾,這些數據只能在學習的時候用,在實際的工業環境中,我們是不可能這麼幸運的,嘿嘿。那麼我們這裏就先用這個demo 數據來學習吧。接下來第二步,我們來構建我們的DNN,我們接着往下看架構
model = tf.keras.models.Sequential([ tf.keras.layers.Flatten(), tf.keras.layers.Dense(512, activation=tf.nn.relu), tf.keras.layers.Dense(10, activation=tf.nn.softmax) ])
這裏跟我們前面說的普通DNN稍微有點不一樣,那就是我們在dense layers以前加了一個tf.keras.layers.Flatten()函數,由於我們的圖片不像我們以前dataframe數據那樣每一行數據都是將features排列好的,每一張圖片都是一個二維(或者三維)的pixel值,這些pixel就是我們這個model的features,因此我們必須得將這個圖片的像素所有轉化成一列數據,而我們的Flatten()函數就是作這個工做的。在這個classification的場景中,我們一共有的classes是10個,因此我們最後的output layer的units的數量是10個,這個數量必需要匹配,不然會有error。第三部就是configure這個模型,以下函數
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy')
固然啦,在這裏我們能夠加一個callbacks,當我們的loss小於0.4的時候,我們就中止我們模型的訓練學習
class myCallback(tf.keras.callbacks.Callback): def on_epoch_end(self, epoch, logs={}): if(logs.get('loss')<0.4): print(logs) print("\nReached 0.4 loss so cancelling training!") self.model.stop_training = True callbacks = myCallback()
最後固然就是我們的訓練的過程啦,lua
model.fit(training_images, training_labels, epochs=5, callbacks=[callbacks])
至於後面的predict和evaluate的過程,更前面章節講的都是如出一轍的,這裏就不在展現啦。上面展現的是一個用傳統的DNN來訓練label好了的圖片來建立一個神經網絡,惋惜的是在實際中咱們幾乎不會用這種方式來作圖片的classification,由於在實際中每個圖片的大小都是不同的,因此每個input layer都是不同,很顯然這不符合我們的實際狀況;另外實際中圖片不可能都是給你label好了,而且放在dataset裏面,這些都須要我們額外去作的工做,那麼我們這裏就要來看看我們如何來解決這些問題。spa
我們都知道在實際中,我們沒有準備好的mnist dataset,全部的圖片都須要我們本身去label,那麼如何給不一樣的本地圖片分配不一樣的labels, 而且最後怎麼組織這是圖片和label數據來訓練呢?這裏我們就要用到一個TensorFlow裏面專門用於處理圖片的一個庫了,那就是ImageDataGenerator,它會給我們的圖片根據文件夾的名稱來label,而且將這些圖片和labels組織起來變成一個相似於dataset的數據集,咱們稱之於generator,我們在這裏就將它當作一個相似於dataset的數據集就好了,而且能夠直接傳遞給model.fit()來訓練,就跟dataset同樣。那我們就來看一下這個具體的流程吧,我們這裏就以一個本地的壓縮文件爲例來展現一下,如何將一個本地的圖片來label而且生成一個generator。code
第一步:解壓文件夾對象
import os import zipfile local_zip = "C:\\Users\\tangx\\OneDrive\\Desktop\\DATA\\cats_and_dogs_filtered.zip" zip_ref = zipfile.ZipFile(local_zip,'r') zip_ref.extractall("C:\\Users\\tangx\\OneDrive\\Desktop\\DATA")#where we extract our zip file to zip_ref.close
上面將一個壓縮的文件夾cats_and_dogs_filtered.zip解壓到C:\\Users\\tangx\\OneDrive\\Desktop\\DATA這個文件夾中,而且解壓後的文件名就是cats_and_dogs_filtered。blog
第二步:define all subdirectories
base_dir = "C:\\Users\\tangx\\OneDrive\\Desktop\\DATA\\cats_and_dogs_filtered"
train_dir = os.path.join(base_dir, "train") val_dir = os.path.join(base_dir,"validation") train_cats_dir = os.path.join(train_dir,"cats") train_dogs_dir = os.path.join(train_dir,"dogs") val_cats_dir = os.path.join(val_dir,"cats") val_dogs_dir = os.path.join(val_dir,"dogs")
這一步我們定義了我們全部圖片的子文件夾,這些子文件夾中裝着的正是我們的圖片。
第三步:生成ImageDataGenerator
from tensorflow.keras.preprocessing.image import ImageDataGenerator #rescale train_imagegen = ImageDataGenerator(rescale=1/255.0) val_imagegen = ImageDataGenerator(rescale=1/255.0) #flow image data """ train_dir: which directory our image data are embeded in batch_size:the number of images our image generator yields each time target_size: our oringial images are various shape, so here we set all the image to a fixed size, wich is (150,150) """ #the labels will be based on the directories's name, wwhich is sorted alphanumeric; for example: cats:0; dogs:1 train_imagegen = train_imagegen.flow_from_directory(train_dir,batch_size=20,class_mode="binary",target_size=(150,150)) val_imagegen = val_imagegen.flow_from_directory(val_dir,batch_size=20,class_mode="binary",target_size=(150,150))
這裏首先我們實例化一個ImageDatagenerator而且對我們後面要導入的照片進行一個rescale, 而後經過這個generator調用它的對象方法flow_from_directory()來給我們的圖片label而且生成我們的最終的數據對generator。這裏有幾個參數須要瞭解一下,一個batch_size是指到時候在訓練數據的時候每個gradient選擇多少個數據來計算, class_mode是指你的classification是什麼類型,這裏有這幾種多是 「binary」,「sparse」, "categorical", "input"和None這幾種狀況,根據我們的實際狀況來選擇。還有一個很重要的參數,那就是target_size, 這個參數能把我們的圖片所有轉化成相同的大小,這給我們後面建立神經網絡的時候帶來了極大的方便,在建立神經網絡的時候我們能夠固定我們input layer中node的數量了。還有一個很小的細節容易忽視,那就是imagegenerator給我們圖片label的時候是根據裝我們圖片的文件夾的名稱的字母順序來得,例如cats,label是0;dogs, label是1。至此,我們已經完成了全部的圖片的準備工做的了,包括圖片的label,圖片的大小統一等工做。下面我們就要來講說我們在計算機視覺中應用的最普遍的一種網絡結構了,那就是卷積網絡CNN。
對於Convolutional Neuro Network (CNN), 我們第一步得了解他的結構是什麼樣的,而後才能理解它的一些概念,例如:filter, pooling等概念。那麼下面我本身花了一張簡易的CNN的網絡結構圖,若是你們理解了下面的這個網絡結構,那麼你們確定也就當即了CNN的一下概念,我們直接看下面的圖片
上面的圖片展現的就是一個含有一個convolution layer, 一個pooling layer的一個卷積網絡。首先我們的原始圖片是一張28*28像素的圖片,以後我們讓TensorFlow隨機生成9個filter,每個filter都是一個3*3結構的filter,這裏就是我們整個CNN的核心了。而後讓每個filter都去cover一下我們的原始圖片都會生成一個26*26的圖片,因此我們一共生成了9個26*26的圖片;注意實際上這裏每個filter都是根據不一樣的角度來提取我們原始圖片的特徵,這就是這些filter的本質。以後全部的這些通過過濾後的26*26size 的圖片再通過一個Maxpooling(2*2)層來壓縮我們的26*26的圖片,結果就是生成了9個13*13的圖片。爲了將這個數據加載在我們後面的DNN中進行計算,很顯然我們仍是得將這9個13*13的圖片通過flatten操做後才能將它做爲我們的input layer。後面的步驟就跟我們傳統的DNN是如出一轍的了。那麼這裏的核心就是filter的過程,它是用來提取不一樣角度的圖片的特徵的。若是上面的CNN的結構理解了,那麼咱們就接着上面的imagegenerator的例子,看看如何用TensorFlow來應用CNN吧。首先搭建CNN結構
model = tf.keras.Sequential([ # Note the input shape is the desired size of the image 150x150 with 3 bytes color tf.keras.layers.Conv2D(32, (3,3), activation='relu', input_shape=(150, 150, 3)), tf.keras.layers.MaxPooling2D(2,2), tf.keras.layers.Conv2D(16, (3,3), activation='relu'), tf.keras.layers.MaxPooling2D(2,2), tf.keras.layers.Conv2D(64, (3,3), activation='relu'), tf.keras.layers.MaxPooling2D(2,2), # Flatten the results to feed into a DNN tf.keras.layers.Flatten(), tf.keras.layers.Dense(1024, activation='relu'), tf.keras.layers.Dense(128, activation='relu'), # Only 1 output neuron. It will contain a value from 0-1 where 0 for 1 class ('cats') and 1 for the other ('dogs') tf.keras.layers.Dense(1, activation='sigmoid') ]) model.compile( optimizer = tf.optimizers.Adam(0.0001), loss = "binary_crossentropy", metrics = ["acc"] )
首先我們看出這個網絡結構中,我們構建了3個convolutional layers, 第一個卷積層的filter數量四32,第二個卷積層的filter數量是16,第三個卷積層數量是64。而且在第一個卷積層我們聲明瞭我們每個圖片的size和dimension,例如我們的圖片是彩色的圖片,長寬都是150,而後彩色圖片有3個channel,因此我們的input_shape=(150, 150, 3)。接下來就是我們的training的過程了。
model.fit(train_imagegen, epochs=15, validation_data=val_imagegen, shuffle=True)
這裏的fit函數我們能夠看出來,我們就是直接傳遞的generator當作數據傳遞給它當作我們的數據源了。至於後面的predict,evaluate等方式,跟前面章節講的DNN的過程徹底同樣,這裏我就不在贅述了。好了這就是CNN在計算機視覺中的應用。