链接:https://www.jianshu.com/p/5b4e51869e64

这个可以说是一个绝对的福利中的福利。
一整套的AI图片识别以及模型的利用。

一贯都在说人工智能,图像识别,又有几个人会呢,网上文章成山,前一段韶光因事情须要,我一个做后端开拓的,要做图片识别。

于是开始了猖獗的地毯式搜索,先说网上先容最多,最好,也是最坑的模型---AIimage,10行代码完成图像识别,通过代码是可以识现,但必须利用它们的模型,不能自己演习,于是开始找AIimage的演习模型,也找到了,也能演习,用演习好的模型,正式测试,哇,屎一样!

python人工智能完整的图片识别非图片验证码以及模型的运用

后来得到一位大哥真传,给了这套完全的演习+利用的完全代码,先说说这位大哥,那人真是一个好啊,我从git上获取代码,然后自己跑,各种bug+不会调试,我都不好意思问,这位大哥亲自帮忙调试,办理bug,远程调试,帮我弄到后半夜,太辛劳了,给大哥发个红包,没收,留下一句话:为了学习!


大哥永久是大哥

我之以是写这篇文章紧张是方便像我一样的纯小白利用代码,由于源代码里没有完全的构造,也存在一些小小的问题,献上完全通过的代码。

我不会人工智能,下面内容来自大哥的原文章TensorFlow 复现ResNet系列模型

阅前须知:

为了使本文构造精简,理解大略,以是会只管即便少涉及到有关数学公式,降落学习门槛,带领读者快速搭建ResNet-152经典模型并投入演习。

本文的末了会放出博主自己复现的ResNet模型,投入自己的数据集进行演习。

如读者在阅读时创造有缺点的地方欢在评论的地方指出,共同进步

编译环境:Python3.5

TensorFlow-gpu 1.3.0

一、构造剖析

关于ResNet的来源我就不进行赘述了,相信读者都对这个经办各大图像识别赛事冠军的模型或多或少有一定的理解。

图片来源Google

提及卷积模型,LeNet、Inception、Vgg都是我们在学习图像识别领域神经网络的经典模型,以上图片模型便是经典的Vgg-19与34层传统卷积网络、ResNet-34的比拟。

从打算量上来讲,Vgg-19的三层全连接神经网络的打算量明显大于传统卷积网络和resnet,传统卷积网络和resnet的参数数量相同

plain与resnet

从演习拟合度上讲,论文等分别给出了plain-18、plain-34和resnet-18、resnet-34的比拟,我们不难创造plain随着层数的增加,精度并没有得到明显的提升,而resnet不仅随着层数的增加提高了演习精度,且相较同深度的plain而言精度更高

在以往的学习之中,我们知道深度网络随着层数的增加,很随意马虎造成“退化”和“梯度消逝”的问题,演习数据的过拟合。
但在ResNet中,作者给出了一种办理方案:增加一个identity mapping(恒等映射,由于本文面向读者根本不同,就不加以详述,有能力的同学可以看一下ResNet作者的论文)

残差模块

上图是一个残差模块的构造示意,残差块想要有效果须要有两层或两层以上的layer,同时,输入x与输出F(x)的维度也须相同

residual block

在对付高于50层深度的resnet模型中,为了进一步减少打算量且担保模型精度,作者对残差模块进行了优化,将内部两层33layer换成11 → 33 → 11,。
首先采取11卷积进行深度降维,减少残差模块在深度上的打算量,第二层33layer和之前的模块功能一样,提取图像特色,第三层11layer用于维度还原。

那么问题又来了,既然已经经由了33卷积,那输出维度怎么会一样呢?作者在论文中给出了三种办理方案:

1、维度不敷部分全0添补

2、输入输出维度同等时利用恒等映射,不一致时利用线性投影

3、对付所有的block均利用线性投影。

在本文中,我们对模型紧张采取全0添补。

好,以上便是大略的理论入门,接下来我们开始动手用TensorFlow对理论进行代码实现

二、实现方案(ResNet-50-101-152)

我们来选取最具有代表性的152层ResNet来进行搭建,论文的作者便是用152层模型来得到Imagenet大赛冠军的。

不同深度的ResNet构造

构造定义字典

在本文中,我们的模型搭建办法因此字典的形式进行循环堆砌

构造字典

ResNet_demo = { \"大众layer_50\公众:[{\公众depth\"大众: 256,\"大众num_class\公众: 3}, {\"大众depth\公众: 512,\公众num_class\公众: 4}, {\"大众depth\"大众: 1024,\公众num_class\"大众: 6}, {\"大众depth\"大众: 2048,\"大众num_class\"大众: 3}], \"大众layer_101\公众: [{\"大众depth\"大众: 256, \公众num_class\公众: 3}, {\公众depth\"大众: 512, \公众num_class\公众: 4}, {\"大众depth\"大众: 1024, \公众num_class\公众: 23}, {\"大众depth\"大众: 2048, \"大众num_class\"大众: 3}], \公众layer_152\"大众: [{\"大众depth\"大众: 256, \公众num_class\"大众: 3}, {\公众depth\"大众: 512, \"大众num_class\"大众: 8}, {\公众depth\公众: 1024, \"大众num_class\"大众: 36}, {\"大众depth\"大众: 2048, \"大众num_class\"大众: 3}]

子类模块方案

在ResNet网络通报的过程中,我们来磋商一些即将碰着的问题:

1.降采样过程

2.通道添补

降采样示意

降采样过程用于不同类瓶颈模块之间通报的过程,例如上图中粉色卷积层和蓝色卷积层之间的数据交互,蓝色卷积层中的/2便是降采样处理

降采样模块代码实现

def sampling(input_tensor, #Tensor入口 ksize = 1, #采样块大小 stride = 2): #采样步长 data = input_tensor data = slim.max_pool2d(data,ksize,stride = stride) return data

通道添补用于输入数据x与结果数据F(x)天生残差和时造成的通道不匹配问题

通道添补模块代码实现

def depthFilling(input_tensor, #输入 Tensor depth): #输出深度 data = input_tensor #取出输入tensor的深度 input_depth = data.get_shape().as_list()[3] #tf.pad用与维度添补,不理解的同学可以去TensoFLow官网理解一下data = tf.pad(data,[[0,0], [0,0], [0,0], [abs(depth - input_depth)//2, abs(depth - input_depth)//2]]) return data

好的,两个子类问题已经得到办理,下面来对残差模块进行方案实现

残差模块

由于搭建方向选择layer大于即是50层,以是我们采取论文中给出的第二种残差模块(11+33+11)

残差模块代码实现

def bottleneck(input_tensor,output_depth): #取出通道 redepth = input_tensor.get_shape().as_list()[3] # 当通道不符合时,进行全零添补并降采样 if output_depth != redepth: #全零添补 input_tensor = depthFilling(input_tensor,output_depth) #降采样 input_tensor= sampling(input_tensor)data = input_tensor #降通道处理 data = slim.conv2d(inputs = data, num_outputs = output_depth//4, kernel_size = 1,stride = 1) #提取特色 data = slim.conv2d(inputs = data, num_outputs = output_depth//4, kernel_size = 3,stride = 1)#通道还原 data = slim.conv2d(inputs = data, num_outputs = output_depth, kernel_size = 1,stride = 1, activation_fn=None, normalizer_fn=None) #天生残差 data = data + input_tensor data = tf.nn.relu(data) return data

有了残差模块,我们就可以对网络构造进行堆砌了

不过,为了精简我们的代码块,我选择把全连接层拿出来单独写成一个模块

FC代码实现

这一模块没有什么技能含量,和我们入门时的BP神经网络差不多

def cnn_to_fc(input_tensor, #Tensor入口 num_output, #输出接口数量 train = False, #是否利用dropout regularizer = None): #正则函数 data = input_tensor #得到输出信息的维度,用于全连接层的输入 data_shape = data.get_shape().as_list() nodes = data_shape[1] data_shape[2] data_shape[3] reshaped = tf.reshape(data, [data_shape[0], nodes]) #末了全连接层 with tf.variable_scope('layer-fc'): fc_weights = tf.get_variable(\"大众weight\"大众, [nodes,num_output], initializer=tf.truncated_normal_initializer(stddev=0.1)) if regularizer != None: tf.add_to_collection('losses', regularizer(fc_weights)) fc_biases = tf.get_variable(\"大众bias\公众, [num_output], initializer=tf.constant_initializer(0.1)) fc = tf.nn.relu(tf.matmul(reshaped, fc_weights) + fc_biases) if train: fc = tf.nn.dropout(fc, 0.5) return fc

定义通报规则

inference

#堆叠ResNet模块def inference(input_tensor, #数据入口 demos, #模型资料(list) num_output, #出口数量 is_train):data = input_tensor #第一层卷积77,stride = 2,深度为64data = conv2d_same(data,64,7,2,is_train,None,normalizer_fn = False)data = slim.max_pool2d(data,3,2,scope=\"大众pool_1\"大众)with tf.variable_scope(\"大众resnet\"大众): #堆叠总类瓶颈模块 demo_num = 0 for demo in demos: demo_num += 1 print(\"大众--------------------------------------------\"大众) #堆叠子类瓶颈模块 for i in range(demo[\"大众num_class\公众]): print(demo_num) if demo_num is not 4: if i == demo[\公众num_class\公众] - 1: stride = 2 else: stride = 1 else: stride = 1 data = bottleneck(data,demo[\公众depth\"大众],stride,is_train) print(\公众--------------------------------------------\"大众)data = tf.layers.batch_normalization(data,training=is_train)data = tf.nn.relu(data) #均匀池化,也可用Avg_pool函数data = tf.reduce_mean(data, [1, 2], keep_dims=True)print(\"大众output : \"大众, data) #末了全连接层data = slim.conv2d(data,num_output,1,activation_fn=None)data_shape = data.get_shape().as_list()nodes = data_shape[1] data_shape[2] data_shape[3]data = tf.reshape(data, [-1, nodes])return data

inference调用办法

inference(input_tensor = 数据入口 demos = ResNet_demo[\"大众layer_101\公众], #获取模型词典 num_output = 出口数量, is_train = False) # BN是否被演习

参考文献:

https://arxiv.org/pdf/1512.03385.pdf

http://blog.csdn.net/xxy0118/article/details/78324256

http://blog.csdn.net/mao_feng/article/details/52734438

利用先容

图片分类以及目录构造

Snip20181114_1.png

第一步、运行FlowIO.py

image.png

第二步、运行train.py 演习模型 我这里图片少,演习的次数也少,真实情形要大量演习

image.png

第三步、运行Evaluation.py,测试结果集,可跳过

选择精确的模型:

精确的模型.png

第四步、利用模型useModel.py,进行图片识别

image.png

结果是对的!


请忽略我的结果,由于我只有8张演习集,这个每类最少要80张演习集。

稍后我多下些演习集试试