1、VGG 是视觉领域竞赛 ILSVRC 在 2014 年的获胜模型,以 7.3% 的错误率在 ImageNet 数据集上大幅刷新了前一年 11.7% 的世界纪录。VGG16 基本上继承了 AlexNet深的思想,并且发扬光大,做到了更深。AlexNet 只用到了 8 层网络,而 VGG 的两个版本分别是 16 层网络版和 19 层网络版。在接下来的迁移学习实践中,我们会采用稍微简单的一些的 VGG16,他和 VGG19 有几乎完全一样的准确度,但是运算起来更快一些。VGG 的结构图如下:VGG 的输入数据格式是 244 * 224 * 3 的像素数据,经过一系列的卷积神经网络和池化网络处理之后,
2、输出的是一个 4096 维的特征数据,然后再通过 3 层全连接的神经网络处理,最终由 softmax 规范化得到分类结果。VGG16 模型可以通过这里下载(密码 78g9),模型是一个. npy 文件,本质上是一个巨大的 numpy 对象,包含了 VGG16 模型中的所有参数,该文件大约有 500M,所以可见如果是从头训练这样一个模型是非常耗时的,借助于迁移学习的思想,我们可以直接在这个模型的基础上进行训练。接下来我们稍微解释一下卷积神经网络和池化网络:卷积神经网络卷积神经网络在图像数据中使用得尤其多,不同于一般的全连接的神经网络需要对上下两层网络中的任意两个节点之间训练权值,每层卷积网络仅仅
3、训练若干个卷积核,下一层的网络的输入即是前一个层的输出的卷积,因此,多层卷积神经网络会把一个薄薄的图片数据,转化为更小但是也更厚的数组,如下图所示卷积神经网络具有良好的统计不变性,而且每个层可以学习到不同层次的知识。比如第一层会学习到识别图片中的简单形状,例如直线和纯色块等。而之后的层将会上升到更高的抽象层次,比如例如形状,物体的组成部分,直到能够识别整个物体。如果我们将卷积神经网络中激活神经元的图像可视化出来,那么会得到如下的结果,首先第一层能识别出一些对角线和颜色的分界。然后第二层网络可以学习到了一些稍微复杂的概念,比如圈和条纹。第三层学习到了一些简单的物体,比如轮胎和脸。到了更高的层数,
4、卷积神经网络能够识别出越来越复杂的物体,这个过程也非常符合人类识别物体的过程,即从简单模式越来越复杂的模式。Max Pooling 和 Drop out最大池化和 Drop out 都是卷积神经网络中常用的技巧,他们的原理都非常简单,最大池化是一个滤波器,该滤波器按照一定的步长把一个区域内的值选出一个最大值作为这个区域的代表值。如下图所示:这样的做的一个好处是可以使神经网络专注于最重要的元素,减少输入元素的大小。而 Drop out 则是按照一个概率随机丢弃输入特征中的值,这样做的目的是迫使神经网络在学习过程中保持一定程度的冗余度,这样训练出来的模型会更加稳定,而且不容易过拟合。识花数据集我们
5、要使用的花数据集可以在这里下载。该数据集有包含如下数据:花的种类图片数量(张)daisy633dandelion898roses641sunflowers699tulips799迁移学习实践有了预备知识之后,我们可以开始搭建属于自己的识花网络了。首先我们会将所有的图片交给 VGG16,利用 VGG16 的深度网络结构中的五轮卷积网络层和池化层,对每张图片得到一个 4096 维的特征向量,然后我们直接用这个特征向量替代原来的图片,再加若干层全连接的神经网络,对花朵数据集进行训练。因此本质上,我们是将 VGG16 作为一个图片特征提取器,然后在此基础上再进行一次普通的神经网络学习,这样就将原先的
6、244 * 224 * 3 维度的数据转化为了 4096 维的,而每一维度的信息量大大提高,从而大大降低了计算资源的消耗,实现了把学习物体识别中得到的知识应用到特殊的花朵分类问题上。文件结构为了更加方便的使用 VGG 网络,我们可以直接使用 tensorflow 提供的 VGG 加载模块,该模块可以在这里下载。首先保证代码或者 jupyter notebook 运行的工作目录下有 flowerphotos,tensorflowvgg 这两个文件夹,分别是花朵数据集和 tensorflowvgg,然后将之前下载的 VGG16 拷贝到 tensorflowvgg 文件夹中。 transfer_le
7、arning.py(运行代码) flower_phtots daisy dandelion roses . tensorflow_vgg vgg16.py vgg16.npy然后导入需要用的 python 模块import osimport numpy as npimport tensorflow as tffrom tensorflow_vgg import vgg16from tensorflow_vgg import utils加载识花数据集接下来我们将 flower_photos 文件夹中的花朵图片都载入到进来,并且用图片所在的子文件夹作为标签值。data_dir = flower_p
8、hotos/contents = os.listdir(data_dir)classes = each for each in contents if os.path.isdir(data_dir + each)利用 VGG16 计算得到特征值# 首先设置计算batch的值,如果运算平台的内存越大,这个值可以设置得越高batch_size = 10# 用codes_list来存储特征值codes_list = # 用labels来存储花的类别labels = # batch数组用来临时存储图片数据batch = codes = Nonewith tf.Session() as sess: #
9、构建VGG16模型对象 vgg = vgg16.Vgg16() input_ = tf.placeholder(tf.float32, None, 224, 224, 3) with tf.name_scope(content_vgg): # 载入VGG16模型 vgg.build(input_) # 对每个不同种类的花分别用VGG16计算特征值 for each in classes: print(Starting images.format(each) class_path = data_dir + each files = os.listdir(class_path) for ii, f
10、ile in enumerate(files, 1): # 载入图片并放入batch数组中 img = utils.load_image(os.path.join(class_path, file) batch.append(img.reshape(1, 224, 224, 3) labels.append(each) # 如果图片数量到了batch_size则开始具体的运算 if ii % batch_size = 0 or ii = len(files): images = np.concatenate(batch) feed_dict = input_: images # 计算特征值 c
11、odes_batch = sess.run(vgg.relu6, feed_dict=feed_dict) # 将结果放入到codes数组中 if codes is None: codes = codes_batch else: codes = np.concatenate(codes, codes_batch) # 清空数组准备下一个batch的计算 batch = print( images processed.format(ii)这样我们就可以得到一个 codes 数组,和一个 labels 数组,分别存储了所有花朵的特征值和类别。可以用如下的代码将这两个数组保存到硬盘上:with op
12、en(codes, w) as f: codes.tofile(f)import csvlabels writer = csv.writer(f, delimiter=n) writer.writerow(labels)准备训练集,验证集和测试集一次严谨的模型训练一定是要包含验证和测试这两个部分的。首先我把 labels 数组中的分类标签用 One Hot Encode 的方式替换。from sklearn.preprocessing import LabelBinarizerlb = LabelBinarizer()lb.fit(labels)labels_vecs = lb.transform(labels)接下来就是抽取数据,因为不同类型的花的数据数量并不是完全一样的,而且 labels 数组中的数据也还没有被打乱,所以最合适的方法是使用 StratifiedShuffleSplit 方法来进行分层随机划分。假设我们使用训练集:验证集:测试集 = 8:1:1,那么代码如下:from sklearn.model_selecti
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1