对于计算机视觉的应用如今是很是普遍的,可是它背后的原理其实很是简单,就是将每个像素的值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在计算机视觉中的应用。