一、Cifar-10的说明
cifar10是一个32*32 的图像10分类问题,一共有60000张图片,我们拿50000张做训练数据,另外拿2000张做测试数据。
为了学习不同网络,这里统一拿这个用作实验材料,关于下载cifar10,或更多说明可以查看官网CIFAR-10
二、LeNet5模型
如图所示这个模型就是2个卷积、池化,再连3个全连接
第一个卷积层6个大小为5*5卷积核,第二卷积层为16个5*5卷积核,其他的都比较简单
def build_model_lenet5():
model = PowerCNNMode('cifar10_lenet5', is_debug=True)
model.set_input_placeholder([None, IMAGE_SIZE, IMAGE_SIZE, 3], [None, 10])
model.set_is_train()
model.set_dropout()
mode_config = [{
't': 'conv2d', 'x': 5, 'y': 5, 'n': 6, 's': 1, 'a': tf.nn.relu},
{
't': 'max_pool', 'k': 2, 's': 2},
{
't': 'dropout'},
{
't': 'conv2d', 'x': 5, 'y': 5, 'n': 16, 's': 1, 'a': tf.nn.relu},
{
't': 'max_pool', 'k': 2, 's': 2},
{
't': 'dropout'},
{
't': 'flatten'},
{
't': 'dense', 'u': 120, 'a': tf.nn.relu},
{
't': 'dropout'},
{
't': 'dense', 'u': 84, 'a': tf.nn.relu},
{
't': 'dense', 'u': 10, 'a': tf.nn.softmax},
]
model.inference(mode_config)
model.set_loss()
model.set_adamoptimizer(1e-4)
model.set_accuracy()
return model
我训练了100轮,可以达到66%
三、AlexNet模型
ps:这个模型及后面的resnet原始模型都是处理imagenet那种大数据库的,cifar10图片尺寸相对比较小,所以这里都做适当的简化
这个介绍下这个模型的几个特点:
1、激活函数全部都使用ReLU(Rectified Linear Unit)
如图它关闭了右边,从而会使得很多的隐层输出为0,即网络变得稀疏,起到了类似L1的正则化作用,可以在一定程度上缓解过拟合。本质上是分段线性模型,前向计算非常简单,无需指数之类操作,Tanh和Logistic激活函数在两端的时候导数容易趋近于零,多级连乘后梯度更加约等于0,相比下它更不容易发生梯度发散问题
2、局部响应归一化LRN(Local Response Normalization)
原理是仿造生物学上活跃的神经元对相邻神经元的抑制现象(侧抑制)
i表示第i个核在位置(x,y)运用激活函数ReLU后的输出,n是同一位置上临近的kernal map的数目,N是kernal的总数。参数K,n,alpha,belta都是超参数,我这里是这么设置的
tf.nn.lrn(in_data, depth_radius=4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name=name)
3、防止过拟合使用dropout
dropout是以配置的概率将隐层神经元的输出设置为零。以这种方式“dropped out”的神经元既不参与前向传播,也不参与反向传播。所以每次提出一个输入,该神经网络就尝试一个不同的结构,但是所有这些结构之间共享权重。因为神经元不能依赖于其他特定神经元而存在,所以这种技术降低了神经元复杂的互适应关系.
ps:其他的特性比如双GPU、对数据做预处理这里没有实践
4、实验模型代码
def build_model_alexnet():
model = PowerCNNMode('cifar10_alexnet', is_debug=True)
model.set_input_placeholder([None, IMAGE_SIZE, IMAGE_SIZE, 3], [None, 10])
model.set_is_train()
model.set_dropout()
mode_config = [{
't': 'conv2d', 'x': 3, 'y': 3, 'n': 32, 's': 1, 'a': tf.nn.relu},
{
't': 'lrn'},
{
't': 'max_pool', 'k': 2, 's': 2},
{
't': 'dropout'},
{
't': 'conv2d', 'x': 3, 'y': 3, 'n': 64, 's': 1, 'a': tf.nn.relu},
{
't': 'lrn'},
{
't': 'max_pool', 'k': 2, 's': 2},
{
't': 'dropout'},
{
't': 'conv2d', 'x': 3, 'y': 3, 'n': 64, 's': 1, 'a': tf.nn.relu},
{
't': 'dropout'},
{
't': 'conv2d', 'x': 3, 'y': 3, 'n': 128, 's': 1, 'a': tf.nn.relu},
{
't': 'dropout'},
{
't': 'conv2d', 'x': 3, 'y': 3, 'n': 256, 's': 1, 'a': tf.nn.relu},
{
't': 'max_pool', 'k': 2, 's': 2},
{
't': 'flatten'},
{
't': 'dense', 'u': 1024, 'a': tf.nn.relu},
{
't': 'dropout'},
{
't': 'dense', 'u': 1024, 'a': tf.nn.relu},
{
't': 'dense', 'u': 10, 'a': tf.nn.softmax},
]
model.inference(mode_config)
model.set_loss()
model.set_adamoptimizer(1e-4)
model.set_accuracy()
return model
训练100轮,效果果然提升了
四、ResNet模型
这个只展示个34层的图,最大的有152层
这个模型比之前又改进了不少,在imagenet等其他大赛中大放异彩
1、残差块
随着网络的逐步加深,梯度经过一层层的卷积层会逐渐衰减,这个现象也叫梯度弥散
残差神经网络由于存在shorcut connections,网络间的数据流通更为顺畅。ResNet作者认为深度残差网络不太可能由于梯度消失而形成欠拟合,因为这在batch normalized network中就很难出现。残差网络结构的解决方案是,增加卷积层输出求和的捷径连接。
这是我的残差块:
def res_block(self, in_data, param):
out_filter = param['n']
id = param['id']
name = 'res_block_' + str(id)
in_filter = in_data.shape.as_list()[-1]
self.debug(name + ' in shape', in_data.shape.as_list())
with tf.variable_scope(name):
if in_filter != out_filter: #输出是否需要变小
x = self.conv2d(in_data, {
'x':3,'y':3,'n':out_filter,'s':2,'b':False,'id':id})
orig_x = self.conv2d(in_data, {
'x':3,'y':3,'n':out_filter,'s':2,'b':False,'id':id})
else:
x = self.conv2d(in_data, {
'x': 3, 'y': 3, 'n': out_filter, 's': 1, 'b': False, 'id': id})
orig_x = tf.identity(in_data, 'orig_x')
x = self._batch_norm(x, self._is_train, 'bn1')
x = self._relu(x, self._relu_leakiness)
x = self.conv2d(x, {
't': 'conv2d', 'x'