文档章节

deeplearning4j——卷积神经网络对验证码进行识别

 冷血狂魔
发布于 10/09 20:02
字数 1444
阅读 463
收藏 6

一、前言  

  计算机视觉长久以来没有大的突破,卷积神经网络的出现,给这一领域带来了突破,本篇博客,将通过具体的实例来看看卷积神经网络在图像识别上的应用。

    导读

    1、问题描述

    2、解决问题的思路

    3、用DL4J进行实现

二、问题

    有如下一组验证码的图片,图片大小为60*160,验证码由5个数字组成,数字的范围为0到9,并且每个验证码图片上都加上了干扰背景,图片的文件名,表示验证码上的数字,样本图片如下:

    穷举每张图片的可能性几乎不可能,所以传统的程序思路不可能解这个问题,那么必须让计算机通过自我学习,获取识别验证码的能力。先让计算机看大量的验证码的图片,并告诉计算机这些图片的结果,让计算机自我学习,慢慢地计算机就学会了识别验证码。

三、解决思路

    1、特征

    每个数字的形状各异,各自特征明显,这里的特征实际上指的是线条的走向、弯曲程度等等形状上的不同表征,那么对于侦测图形上的形状,卷积神经网络加上Relu和Max采样,可以很精确的做到这一点,本质原因在于,把卷积核拉直了看,本质上所做的事情就算向量的点积运算,求一个向量在另一个向量上的投影。对于卷积神经网络的原理可以看看《有趣的卷积神经网络》

    2、网络结构设计

    对于每张图片而言,有5个数字作为输出结果,那么得设计一个有5个output的深度神经网络,首先用多个卷积核+Max采样层的结构来抽取明显特征,最后获得的特征经过两个全连接层逼近,这里加全连接层有两个目的,第一:经过sigmoid函数把值压缩到0到1之间,便于softmax计算,第二,加上全连接层可以更加抽象特征,让函数的逼近更加容易。最终的网络结构如下:

    3、张量表示

    对于Label的表示用one-hot来表示,这样可以很好的配合softmax,下图展示了从0到9的数字表示,沿着行的方向,由上而下,分别表示0到9

    

    对于图片上的像素点,值域在0到255之间,图片如果是彩色,那么实际上会有三个通道,这里都是黑白色,所以,只有一个通道,取图片上真实像素点的值,除以255进行归一化即可。

四、代码实现

    1、网络结构

public static ComputationGraph createModel() {

        ComputationGraphConfiguration config = new NeuralNetConfiguration.Builder()
            .seed(seed)
            .gradientNormalization(GradientNormalization.RenormalizeL2PerLayer)
            .l2(1e-3)
            .updater(new Adam(1e-3))
            .weightInit( WeightInit.XAVIER_UNIFORM)
            .graphBuilder()
            .addInputs("trainFeatures")
            .setInputTypes(InputType.convolutional(60, 160, 1))
            .setOutputs("out1", "out2", "out3", "out4", "out5", "out6")
            .addLayer("cnn1",  new ConvolutionLayer.Builder(new int[]{5, 5}, new int[]{1, 1}, new int[]{0, 0})
                .nIn(1).nOut(48).activation( Activation.RELU).build(), "trainFeatures")
            .addLayer("maxpool1",  new SubsamplingLayer.Builder(PoolingType.MAX, new int[]{2,2}, new int[]{2, 2}, new int[]{0, 0})
                .build(), "cnn1")
            .addLayer("cnn2",  new ConvolutionLayer.Builder(new int[]{5, 5}, new int[]{1, 1}, new int[]{0, 0})
                .nOut(64).activation( Activation.RELU).build(), "maxpool1")
            .addLayer("maxpool2",  new SubsamplingLayer.Builder(PoolingType.MAX, new int[]{2,1}, new int[]{2, 1}, new int[]{0, 0})
                .build(), "cnn2")
            .addLayer("cnn3",  new ConvolutionLayer.Builder(new int[]{3, 3}, new int[]{1, 1}, new int[]{0, 0})
                .nOut(128).activation( Activation.RELU).build(), "maxpool2")
            .addLayer("maxpool3",  new SubsamplingLayer.Builder(PoolingType.MAX, new int[]{2,2}, new int[]{2, 2}, new int[]{0, 0})
                .build(), "cnn3")
            .addLayer("cnn4",  new ConvolutionLayer.Builder(new int[]{4, 4}, new int[]{1, 1}, new int[]{0, 0})
                .nOut(256).activation( Activation.RELU).build(), "maxpool3")
            .addLayer("maxpool4",  new SubsamplingLayer.Builder(PoolingType.MAX, new int[]{2,2}, new int[]{2, 2}, new int[]{0, 0})
                .build(), "cnn4")
            .addLayer("ffn0",  new DenseLayer.Builder().nOut(3072)
                .build(), "maxpool4")
            .addLayer("ffn1",  new DenseLayer.Builder().nOut(3072)
                .build(), "ffn0")
            .addLayer("out1", new OutputLayer.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)
                .nOut(10).activation(Activation.SOFTMAX).build(), "ffn1")
            .addLayer("out2", new OutputLayer.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)
                .nOut(10).activation(Activation.SOFTMAX).build(), "ffn1")
            .addLayer("out3", new OutputLayer.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)
                .nOut(10).activation(Activation.SOFTMAX).build(), "ffn1")
            .addLayer("out4", new OutputLayer.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)
                .nOut(10).activation(Activation.SOFTMAX).build(), "ffn1")
            .addLayer("out5", new OutputLayer.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)
                .nOut(10).activation(Activation.SOFTMAX).build(), "ffn1")
            .addLayer("out6", new OutputLayer.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)
                .nOut(10).activation(Activation.SOFTMAX).build(), "ffn1")
            .pretrain(false).backprop(true)
            .build();
        ComputationGraph model = new ComputationGraph(config);
        model.init();

        return model;
    }

    2、训练集构建

 public MultiDataSet convertDataSet(int num) throws Exception {
        int batchNumCount = 0;

        INDArray[] featuresMask = null;
        INDArray[] labelMask = null;

        List<MultiDataSet> multiDataSets = new ArrayList<>();

        while (batchNumCount != num && fileIterator.hasNext()) {
            File image = fileIterator.next();
            String imageName = image.getName().substring(0,image.getName().lastIndexOf('.'));
            String[] imageNames = imageName.split("");
            INDArray feature = asMatrix(image);
            INDArray[] features = new INDArray[]{feature};
            INDArray[] labels = new INDArray[6];

            Nd4j.getAffinityManager().ensureLocation(feature, AffinityManager.Location.DEVICE);
            if (imageName.length() < 6) {
                imageName = imageName + "0";
                imageNames = imageName.split("");
            }
            for (int i = 0; i < imageNames.length; i ++) {
                int digit = Integer.parseInt(imageNames[i]);
                labels[i] = Nd4j.zeros(1, 10).putScalar(new int[]{0, digit}, 1);
            }
            feature =  feature.muli(1.0/255.0);

            multiDataSets.add(new MultiDataSet(features, labels, featuresMask, labelMask));

            batchNumCount ++;
        }
        MultiDataSet result = MultiDataSet.merge(multiDataSets);
        return result;
    }

五、后记

    用deeplearning4j构建一个深度神经网络,几乎没有多余的代码,非常优雅就可以解一个复杂的图像识别问题,对于上述代码有几点说明:

    1、对于DenseLayer层,这里没有设置网络输入的size,实际上在dl4j内部已经做了这个set操作

    2、对于梯度更新优化,这里选用Adam,Adam融合了动量和自适应learningRate两方面的因素,通常会有更好的效果

    3、损失函数用的类Log函数,和交叉熵有相同的效果

    4、模型训练好可以使用 ModelSerializer.writeModel(model, modelPath, true)来保存网络结构,就可以用于图像识别了

    完整的代码,可以查看deeplearning4j的example

 

---------------------------------------------------------------------------------------------------------

快乐源于分享。

   此博客乃作者原创, 转载请注明出处

© 著作权归作者所有

共有 人打赏支持
粉丝 80
博文 36
码字总数 43730
作品 0
杭州
程序员
大神带你分分钟超越最好结果——基于分布式CPU计算的Deeplearning4j迁移学习应用实例

首发地址:https://yq.aliyun.com/articles/114669 更多深度文章,请关注:https://yq.aliyun.com/cloud 2016年,欧莱礼媒体公司首席数据科学家罗瑞卡宣称:“2017年将是数据科学和大数据圈参...

uncle_ll
2017/07/27
0
0
分布式深度学习库--Deeplearning4j

Deeplearning4j(简称DL4J)是为Java和Scala编写的首个商业级开源分布式深度学习库。DL4J与Hadoop和Spark集成,为商业环境(而非研究工具目的)所设计。Skymind是DL4J的商业支持机构。 Deep...

匿名
2016/04/21
15K
10
省钱利器!基于TensorFlow的端到端验证码识别

最近机器学习很热,作为机器学习在图像识别方面最火的研究领域,神经网络将图像识别带入了新的高度,很多之前还只能在实验室中的理想情况下的成果,目前已经大量的运用在了实际生产环境中了,...

陋室
07/20
0
0
使用DeepLearning4j训练和保存模型

一、前言 最近一直在研究深度学习,联想起之前所学,感叹数学是一门朴素而神奇的科学。F=Gm1m2/r²万有引力描述了宇宙星河运转的规律,E=mc²描述了恒星发光的奥秘,V=H*d哈勃定律描述了宇宙...

孟飞阳
06/28
0
0
理解卷积神经网络的利器:9篇重要的深度学习论文(上)

手把手教你理解卷积神经网络(一) 手把手教你理解卷积神经网络(二) 本文将介绍过去五年内发表的一些重要论文,并探讨其重要性。论文1—5涉及通用网络架构的发展,论文6—9则是其他网络架构的论...

【方向】
03/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

kubeadm部署kubernetes集群

一、环境要求 这里使用RHEL7.5 master、etcd:192.168.10.101,主机名:master node1:192.168.10.103,主机名:node1 node2:192.168.10.104,主机名:node2 所有机子能基于主机名通信,编辑...

人在艹木中
今天
2
0
Shell特殊符号总结以及cut,sort,wc,uniq,tee,tr,split命令

特殊符号总结一 * 任意个任意字符 ? 任意一个字符 # 注释字符 \ 脱义字符 | 管道符 # #号后的备注被忽略[root@centos01 ~]# ls a.txt # 备注 a.txt[root@centos01 ~]# a=1[root@centos01...

野雪球
今天
2
0
OSChina 周二乱弹 —— 程序员圣衣

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @达尔文:分享Skeeter Davis的单曲《The End of the World》 《The End of the World》- Skeeter Davis 手机党少年们想听歌,请使劲儿戳(这里...

小小编辑
今天
14
0
[ python import module ] 导入模块

import moudle_name ----> import module_name.py ---> import module_name.py文件路径 -----> sys.path (这里进行查找文件) # from app.web import Personimport app.web.Person as Pe......

_______-
昨天
5
0
Redis性能问题排查解决手册

一、性能相关的数据指标 通过Redis-cli命令行界面访问到Redis服务器,然后使用info命令获取所有与Redis服务相关的信息。通过这些信息来分析文章后面提到的一些性能指标。 nfo命令输出的数据可...

IT--小哥
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部