精华内容
下载资源
问答
  • 加入稀疏约束项能够有效提取数据中的隐藏结构,而雅克比正则化可以描述数据点的边缘特征,提高自动编码器算法的学习能力,从而更准确地抽取样本的本质特征。实验结果表明,JSAE在分类准确率上要高于自动编码机(AE)...
  • 这些方法用于制造光学字符识别器(OCR),其中包括从纸张读取文本并将图像转换为计算机可以操纵的形式(例如,转换为ASCII码)。这项技术解决了许多问题,例如自动识别以下内容: 邮政编码:邮政编码由一些数字组成...

    手写数字是日常生活中的常见部分。如今,机器学习方法正在以超过人类准确性的精度对手写数字进行分类。这些方法用于制造光学字符识别器(OCR),其中包括从纸张读取文本并将图像转换为计算机可以操纵的形式(例如,转换为ASCII码)。这项技术解决了许多问题,例如自动识别以下内容:

    1. 邮政编码:邮政编码由一些数字组成,是字母中最重要的部分之一,可将其传递到正确的位置。许多年前,邮递员会手动读取邮政编码以进行邮递。但是,现在通过使用光学字符识别(OCR)可以使这类工作自动化。
    2. 银行支票:OCR的最常用用法是处理支票:扫描手写支票,将其内容转换为数字文本,验证签名并实时清除支票,而无需人工干预。
    3. 法律记录:誓章,判决书,文件,声明,遗嘱和其他法律文件(尤其是印刷的文件)的数量可以用最简单的OCR读者进行数字化,存储,数据库化和搜索。

    4-医疗记录:在可搜索的数字商店中存储完整的病历,意味着过去的疾病和治疗方法,诊断检查,医院记录,保险付款等可以在一个统一的位置提供,而不必费力报告和X射线文件。           可用于扫描这些文档并创建数字数据库。

    1.问题陈述:

    当前的任务是使用监督机器学习对手写数字进行分类方法。 这些数字属于0 – 9类。“给出图像形式的查询实例(一个数字),我的机器学习模型必须正确地对其适当的类别进行分类。”:汤姆·米切尔(Tom Mitchell)的机器学习形式化理论可用于配制我的机器学习问题。 它说:据说一个计算机程序可以从经验E中学习关于任务T和绩效指标P,如果其在任务T的绩效(由P衡量),随着经验E的提高。因此,我的手写数字识别问题可以表述为:

    •T –对图像中的手写数字进行分类。

    •P –正确分类的数字的百分比。

    •E –具有给定标签的手写数字数据集。

    2.所采用数据集

    MNIST手写数字数据集用于此任务。 它包含拍摄的数字图像从各种尺寸和居中标准化的扫描文档中提取。这使其成为用于评估模型的优秀数据集,使开发人员可以专注于机器只需很少的数据清理或准备工作即可学习。每个图像都是28 x 28像素的正方形(总计784像素)。 数据集包含60,000用于模型训练的图像和用于模型评估的10,000张图像。

    图表 1-来自MNIST数据集的样本图像

    3.机器学习训练方法

    使用监督机器学习模型来预测数字。 由于这是一项比较研究,因此我将首先描述K最近邻分类器作为基准方法,然后将其与多类感知器分类器和SVM分类器进行比较。 K最近邻分类器–所采用的基准方法:k最近邻(k-NN)是一种算法,该算法:•在训练集中找到一组最接近测试对象的k个对象,并且•为 在这个邻里的班级优势上的标签。 此方法包含三个关键元素:•一组带标签的对象,例如一组存储的记录(训练数据)•用于计算对象之间距离的距离或相似性度量•和k的值(最近邻居的数量) )

     

    图表 2-直观表示如何使用K-NN对测试实例进行分类

    要对未标记的图像进行分类:

    •计算出此图像与标记对象的距离(训练数据)

    •确定其k最近邻,并按照以下顺序降序排列计算相似度

    •然后将前k个邻居中最频繁出现的最近邻居分配为对象的类标签

    图表 3-KNN算法步骤

    当我使用K-NN方法时,观察到以下优点和缺点:

    优点:

    •对于小型训练数据集,K-NN快速执行。

    •没有关于数据的假设-例如对于非线性数据有用

    •简单的算法-可以解释和理解/解释

    •通用-对分类或回归有用

    •训练阶段非常快,因为它不会学习任何数据缺点

    缺点:

    •昂贵,因为该算法将测试数据与训练数据中的所有示例进行比较,然后最终确定标签

    •K的值未知,可以使用交叉验证技术进行预测

    •内存需求量大-因为所有训练数据都已存储

    •预测阶段 如果训练数据很大,可能会很慢

    图表 4-我的代码的K-NN实现

    图表 5-查询实例被馈送到Multiclass Perceptron分类器中的所有分类器

    可以使用经过1对全部策略训练的多个二进制分类器来制作多类感知器分类器。 在这种策略中,在训练感知器的同时,训练标签应使得例如 对于分类器2与全部,对于Sigmoid单位,带有2的标签将被标记为1,其余部分将被标记为0,而对于Rosenblatt的感知器,对于正例和负例,标签分别为1和-1。现在,要做的就是分别训练(学习权重)10个分类器,然后将查询实例提供给所有这些分类器(如上图所示)。 然后,具有最高置信度的分类器标签将分配给查询实例。

    图表 6-将查询实例馈送到1层多感知器分类器,并将具有最高置信度的分类器标签分配给测试实例,在这种情况下,分类器“ 6”具有最高置信度,因此将其分配给测试查询。

    查询实例被馈送到1层多感知器分类器,分类器的标签带有最高可信度分配给测试实例,在这种情况下,分类器“ 6”具有最高可信度,因此其分配给测试查询。

    4.训练算法:

    每个感知器的训练算法如下:

    1.将权重和阈值初始化为较小的随机数(在此的示例中为零)。

    2.将向量x呈现给神经元输入并计算输出。

    3.根据以下条件更新权重:

    d是所需的输出,在感知器的情况下使用信号函数规则和sigmoid函数

    t是迭代数

    eta是学习率或步长,其中0.0 <eta <1.0

    4.重复步骤2和3,直到:迭代误差小于用户指定的误差阈值或预定的迭代次数已完成

    激活功能:

    将激活函数应用于感知器的输出,以确定是否触发该神经元。 根据使用的激活函数,有两种类型的感知器:

    •具有信号激活功能的感知器规则

    •具有S形激活功能的Delta规则

    1)具有Signum激活功能的感知器规则:(Rosenblatt的感知器

    在此规则中的假设函数如下:

    下面给出的是Rosenblatt感知器的视觉表示:

    这是我对单个感知器的训练代码:

    图表 7-我的代码段,用于使用一些预定义的时期来训练Rosenblatt的感知器随机梯度下降,可最大程度地降低成本函数并提升权重

    2)具有S型激活功能的Delta规则:在此规则中的假设函数如下:

    以下是具有Sigmoid激活功能的感知器的直观表示:

    Perceptron规则和Delta规则之间的区别:感知器规则和增量规则之间有两个区别

    •感知器规则基于阶跃函数(信号函数),而增量规则使用S型激活函数。

    •假设以下条件,感知器可以收敛到一致的假设数据是线性可分离的(如果不是这样,则定义要训练的时期)。另一方面,Delta规则的收敛不取决于条件线性可分离数据。

    5.多类感知器如何减轻K-NN的局限性:

    正如之前讨论过的那样,K-NN会存储所有训练数据,并在有新查询时实例来它比较其相似性与所有训练数据,这使得它在计算和内存方面都很昂贵。 没有学习,因为这样。 另一方面,多类感知器在学习阶段需要花费一些时间,但训练完成后,它将学习可以保存然后使用的新砝码。现在,当一个查询实例到来时,只需要加点该实例的乘积有了学习的权重,就会有输出(应用激活后功能)。

    •与K-NN相比,预测阶段非常快。

    •此外,在计算方面(预测阶段),它的效率要高得多和内存(因为现在只需要存储权重即可,而不是所有培训数据)。

    6.SVM分类器:

    仅出于比较目的,我还使用了第三种监督机器学习名为支持向量机分类器的技术。该模型尚未实现。 它直接从scikit的python学习模块导入和使用。

    7.实验设定

    功能缩放:

    特征缩放是一种用于标准化自变量范围或数据特征。在数据处理中,也称为数据规范化,它是通常在数据预处理步骤中执行。由于原始数据值的范围差异很大,因此在某些机器中学习算法时,如果没有规范化,目标函数将无法正常工作。例如,大多数分类器通过以下方式计算两点之间的距离欧几里得距离。如果其中一个要素的取值范围很广,则距离将受此特定功能的约束。 因此,所有功能的范围应为标准化,以便每个特征对最终特征的贡献大致成比例距离。

    重新缩放

    最简单的方法是重新调整要素范围以将范围调整为[0,1]或[−1,1]。 选择目标范围取决于数据的性质。 通用公式为给出为:

    我的MNIST数据集首先被重新缩放。 由于每个像素的最小值为0且最大值值是255。因此,每个输入向量都被255除以重新缩放。

    K-NN的实验设置

    K-NN实验进行了两次。 一次使用余弦相似性度量,一次欧氏距离作为相似性度量。

    资料分割:

    在针对训练和测试数据的不同分割运行算法之后,以下内容选择split是因为它可以达到更好的结果:

    使用的训练数据:3000个数据点

    使用的测试数据:1000个数据点

    使用的验证数据:1000个数据点

    相似性度量(距离度量):

    对于K-NN,有两点要考虑。一种是与被使用,最重要的一个是K的值。我选择了两种相似性衡量指标,并且每次均进行了一次实验。

    1-余弦相似度:

    两个向量之间的余弦相似性是一种度量的余弦相似度他们之间的角度。 此度量标准是方向而非大小的度量。

    根据两个向量之间的角度余弦,得出两个向量的相似性

    2-欧几里得距离:

    欧几里得距离是欧几里得中两个向量之间的直线距离空间。 它通过考虑两个向量彼此之间的距离来告诉它们大小。

    两点之间的欧几里得距离p和q。

    K的最佳值:(使用弯头法)

    为了找到K的最佳值,将训练数据分为两部分。

    •第一部分是KNN的新训练数据(3000张图像)

    •第二部分是验证数据(1000张图像),其验证误差曲线将被计算。现在,为了找到验证误差最小的K值,对从1到sqrt(N)的K的不同值,其中N是新训练的大小数据。

    –对k = 1到sqrt(N)运行K-NN,并为每个k计算精度。以前计算过所有邻居一次,所以现在只更改k。

    验证误差曲线:

    使用弯头法找到K的最佳值。由于实验进行了两次,因此必须为KNN找到K的最佳值具有余弦相似度,而KNN具有欧氏距离。K的最佳值是验证误差最小的那个。

    对于K = 3,验证误差是最小的,因此对于带有余弦的K-NN选择此k相似

    –对于K = 4,验证误差为最小,因此对于具有欧几里得的K-NN选择此k距离

    8.多类感知器的实验设置:

    多类感知器实验进行了两次。一次与Perceptron一起信号激活功能,以及带有Sigmoid激活功能的感知器。

    偏压:

    为了使模型适合训练数据,还添加了偏差w0模型决策边界穿过原点的限制。为了使权重和输入要素的点积一致,功能以x0的形式添加到输入向量,其值设置为1。

    资料分割:

    在针对训练和测试数据的不同分割运行算法之后,以下内容选择split是因为它可以达到更好的结果:

    使用的训练数据:5000个数据点

    使用的测试数据:10,000个数据点

    学习率

    学习率不应太小,以免收敛太慢也不要太大,以至于梯度永远不会收敛,并且会不断地来回跳动。用不同的eta(学习率)值运行实验后,选择0.01。

    成本函数:

    •sigmoid单元:

    对于S形单位,由于使用S形时,不能使用均方成本函数激活功能已插入其中,它不会保持凸状。为了有凸梯度下降将导致全局最小值的成本函数,使用以下对数成本函数:

    m =训练量

    h(x)=预测标签

    y =原始标签

    •门槛单位(罗森布拉特的感知器)

    Perceptron成本函数为

    Epochs:

    一个Epochs基本上是对所有训练数据的完整一轮。

    •sigmoid单元:

    使用梯度下降的批处理模式对Sigmoid单元进行训练。为此模式选择的迭代次数/时期数为2000。并且绘制了一个图,用于一个感知器针对不同迭代及其各自成本的训练。显然,当迭代次数达到1500时,梯度会收敛,此后成本降低较少。

    图表 8-使用Sigmoid激活函数的梯度下降(批处理模式)的多类分类器的一个感知器的迭代与训练误差曲线

    •门槛单元(罗森布拉特的感知器)

    阈值单元是使用随机梯度下降训练的,该方法不是在一个完整的历元之后更新权重,而是为每个训练实例更新权重,这使该方法收敛速度比梯度下降快,且成本明智。最初,此感知器用于不断更新权重,直到所有训练示例正确分类为止。 为此,训练数据应该是线性可分离的。但是在这次的情况下,数据不是线性可分离的,因此为了避免无限循环,将感知器序列用于某些预定义的时期。

    为了为这次的场景选择最佳时期,针对不同时期进行了实验,并绘制了一条曲线,如下所示。

    图表 9-随着epoch的增加和融合,培训成本通常会降低。这是使用带有信号函数的随机梯度下降的多类感知器分类器的一个感知器的图

    仅出于实验目的,将epoch设定为2000,然后再次绘制成本曲线。 现在很明显,成本在10到30个epoch之间收敛,此后成本几乎没有变化。

     

    训练cost集中在10到30 ep之间。因此,根据上述实验,决定选择15个ep来训练罗森布拉特的感知器。

    9.SVM分类器的实验设置:

    在K-NN和Multiclass Perceptron分类器中,直接在原始图像上训练此模型,而不是从输入图像中计算一些特征,并在那些计算出的度量/特征上训练模型。特征描述符是图像的表示,通过提取有用的信息并丢弃无关的信息来简化图像。

    HOG描述符:

    现在,将从数字图像中计算定向梯度直方图作为特征,并在此基础上训练SVM分类器。HOG描述符技术对图像检测窗口的局部部分中梯度取向的出现进行计数。

    计算方式:

    为所有训练示例计算HOG特征向量,然后在这些特征上训练模型。 同样,在测试测试图像时,将计算测试图像的HOG特征,并根据这些特征而不是原始测试图像评估模型。要计算HOG功能,设置:

    •每个块中的像元数等于每个单个像元的大小为14×14。 由于图像大小为28×28,因此将拥有四个大小为14×14的块/单元。

    •另外,将方向向量的大小设置为9。因此,每个样本的HOG特征向量的大小将为4×9 = 36。

    10.结果分析

    每种算法使用的精度度量为:精度=正确分类的图像/总图像* 100。现在是最后阶段,用不同的算法运行实验后,总结结果。首先比较基于精度的技术:

    准确性(性能):

    当根据准确性将K-NN方法与Multiclass Perceptron和SVM进行比较时,其准确性与其他两个分类器相似,这意味着尽管其简单性,K-NN确实是一个很好的分类器。

    预测时间(效率):

    我的观察:K-NN的主要限制之一是它的计算量很大。 它的预测时间很大,因为每当一个新的查询实例到来时,它就必须将其相似性与所有训练数据进行比较,然后根据其置信度对邻居进行排序,然后分离出前k个邻居,并选择顶部出现次数最多的邻居的标签k。 在所有这些过程中,需要花费相当多的时间。

    尽管对于多类感知器分类器,观察到它将减轻效率方面的限制,从而使其预测时间较短,因为现在它仅在预测阶段计算点积。 在学习阶段,大部分时间仅花费一次。 然后就可以预测测试实例了。

    结果:

    我的结论:

    在为K-NN,Multiclass Perceptron和SVM的预测阶段计算时间时,Multiclass Perceptron显然以最短的预测时间脱颖而出,而另一方面,K-NN在预测测试实例上花费了大量时间。因此,就预测时间的效率以及计算和内存负载而言,多类感知器显然将K-NN甩在了后面。 因此,它减轻了

    展开全文
  • 一 Auto-encoder NN Encoder & NN Decoder 要一起训练。 二 Starting from PCA 三 Deep Auto-encoder ...当code为二维时,很明显看到Deep Auto-encoder使数字手写识别集分类地更好。 ...

    一 Auto-encoder

    NN Encoder & NN Decoder 要一起训练。

    二 Starting from PCA

    三 Deep Auto-encoder

    PCA&Deep Auto-encoder 比较,明显后者效果更好。

    当code为二维时,很明显看到Deep Auto-encoder使数字手写识别集分类地更好。

     

    四 Auto-encoder的几种应用

    4.1 Auto-encoder – Text Retrieval

    Bag-of-word方法将document用向量表示,每一个词都是平等的,无法考虑语义。 而Auto-encoder可以考虑语义。

    杰克逊和马蹄铁被聚到一起(可能是发型类似马铁蹄)。

    4.3 Auto-encoder for CNN

    CNN -Unpooling

    CNN - Deconvolution

    Actually, deconvolution is convolution.

    参考:

    http://speech.ee.ntu.edu.tw/~tlkagk/courses/ML_2016/Lecture/auto%20%28v7%29.pdf

    https://blog.csdn.net/soulmeetliang/article/details/73550730

     

    转载于:https://www.cnblogs.com/Terrypython/p/9458665.html

    展开全文
  • 基于自动编码机(autoencoder),这里网络的层次结构为一个输入层,两个隐层,后面再跟着一个softmax分类: 采用贪婪算法,首先把input和feature1看作一个自动编码机,训练出二者之间的参数,然后用feature1层的...

    基于自动编码机(autoencoder),这里网络的层次结构为一个输入层,两个隐层,后面再跟着一个softmax分类器:

    采用贪婪算法,首先把input和feature1看作一个自动编码机,训练出二者之间的参数,然后用feature1层的激活值作为输出,输入到feature2,即把feature1和feature2再看作一个自动编码机,训练出这两层之间的参数,这两步都没有用到分类标签,所以是无监督学习,最后把feature2的激活值作为提取的的特征,输入到分类器,这里需要标签来计算代价函数,从而由优化这个代价函数来训练出feature2与分类器之间的参数,所以这一步是有监督学习,这一步完成之后,把测试样本输入网络,最后会输出该样本分别属于每一类的概率,选出最大概率对应的类别,就是最终的分类结果。

    为了使得分类结果更加精确,可以对训练出的参数进行微调,就是在有监督学习之后,我们利用有标签的训练数据可以计算出分类残差,然后利用这个残差反向传播,对已经训练出的参数进行进一步微调,会对最终预测的精度有很大提升

    下面是第一层训学习出的特征:

    可以看出都是一些笔迹的边缘

    作为对比,训练结果显示,微调之后,分类准确度有大幅提升,所以在训练深度网络之后,利用部分标签数据进行微调是一件很有必要的学习

    Before Finetuning Test Accuracy: 91.760%
    After Finetuning Test Accuracy: 97.710%

    下面是部分程序代码,需要用到,完整代码请先下载minFunc.rar,然后下载stacked_exercise.rar,minFunc.rar里面是lbfgs优化函数,在优化网络参数时需要用到。

    %% CS294A/CS294W Stacked Autoencoder Exercise
    
    %  Instructions
    %  ------------
    % 
    %  This file contains code that helps you get started on the
    %  sstacked autoencoder exercise. You will need to complete code in
    %  stackedAECost.m
    %  You will also need to have implemented sparseAutoencoderCost.m and 
    %  softmaxCost.m from previous exercises. You will need the initializeParameters.m
    %  loadMNISTImages.m, and loadMNISTLabels.m files from previous exercises.
    %  
    %  For the purpose of completing the assignment, you do not need to
    %  change the code in this file. 
    %
    %%======================================================================
    %% STEP 0: Here we provide the relevant parameters values that will
    %  allow your sparse autoencoder to get good filters; you do not need to 
    %  change the parameters below.
    
    inputSize = 28 * 28;
    numClasses = 10;
    hiddenSizeL1 = 200;    % Layer 1 Hidden Size
    hiddenSizeL2 = 200;    % Layer 2 Hidden Size
    sparsityParam = 0.1;   % desired average activation of the hidden units.
                           % (This was denoted by the Greek alphabet rho, which looks like a lower-case "p",
                           %  in the lecture notes). 
    lambda = 3e-3;         % weight decay parameter       
    beta = 3;              % weight of sparsity penalty term       
    
    %%======================================================================
    %% STEP 1: Load data from the MNIST database
    %
    %  This loads our training data from the MNIST database files.
    
    % Load MNIST database files
    trainData = loadMNISTImages('train-images.idx3-ubyte');
    trainLabels = loadMNISTLabels('train-labels.idx1-ubyte');
    
    trainLabels(trainLabels == 0) = 10; % Remap 0 to 10 since our labels need to start from 1
    
    %%======================================================================
    %% STEP 2: Train the first sparse autoencoder
    %  This trains the first sparse autoencoder on the unlabelled STL training
    %  images.
    %  If you've correctly implemented sparseAutoencoderCost.m, you don't need
    %  to change anything here.
    
    
    %  Randomly initialize the parameters
    sae1Theta = initializeParameters(hiddenSizeL1, inputSize);
    
    %% ---------------------- YOUR CODE HERE  ---------------------------------
    %  Instructions: Train the first layer sparse autoencoder, this layer has
    %                an hidden size of "hiddenSizeL1"
    %                You should store the optimal parameters in sae1OptTheta
    addpath minFunc/;
    options = struct;
    options.Method = 'lbfgs';
    options.maxIter = 400;
    options.display = 'on';
    %训练出第一层网络的参数
    [sae1OptTheta, cost] =  minFunc(@(p) sparseAutoencoderCost(p,...
                            inputSize,hiddenSizeL1,lambda,...
                            sparsityParam,beta,trainData),...
                            sae1Theta,options);
    save('step2.mat', 'sae1OptTheta');
    W1 = reshape(sae1OptTheta(1:hiddenSizeL1 * inputSize), hiddenSizeL1, inputSize);
    display_network(W1');
    % -------------------------------------------------------------------------
    
    %%======================================================================
    %% STEP 2: Train the second sparse autoencoder
    %  This trains the second sparse autoencoder on the first autoencoder
    %  featurse.
    %  If you've correctly implemented sparseAutoencoderCost.m, you don't need
    %  to change anything here.
    
    [sae1Features] = feedForwardAutoencoder(sae1OptTheta, hiddenSizeL1, ...
                                            inputSize, trainData);
    
    %  Randomly initialize the parameters
    sae2Theta = initializeParameters(hiddenSizeL2, hiddenSizeL1);
    
    %% ---------------------- YOUR CODE HERE  ---------------------------------
    %  Instructions: Train the second layer sparse autoencoder, this layer has
    %                an hidden size of "hiddenSizeL2" and an inputsize of
    %                "hiddenSizeL1"
    %
    %                You should store the optimal parameters in sae2OptTheta
    [sae2OptTheta, cost] =  minFunc(@(p)sparseAutoencoderCost(p,...
                            hiddenSizeL1,hiddenSizeL2,lambda,...
                            sparsityParam,beta,sae1Features),...
                            sae2Theta,options);
    % figure;
    % W11 = reshape(sae1OptTheta(1:hiddenSizeL1 * inputSize), hiddenSizeL1, inputSize);
    % W2 = reshape(sae2OptTheta(1:hiddenSizeL2 * hiddenSizeL1), hiddenSizeL2, hiddenSizeL1);
    % figure;
    % display_network(W2');
    % -------------------------------------------------------------------------
    
    
    %%======================================================================
    %% STEP 3: Train the softmax classifier
    %  This trains the sparse autoencoder on the second autoencoder features.
    %  If you've correctly implemented softmaxCost.m, you don't need
    %  to change anything here.
    
    [sae2Features] = feedForwardAutoencoder(sae2OptTheta, hiddenSizeL2, ...
                                            hiddenSizeL1, sae1Features);
    
    %  Randomly initialize the parameters
    saeSoftmaxTheta = 0.005 * randn(hiddenSizeL2 * numClasses, 1);
    
    
    %% ---------------------- YOUR CODE HERE  ---------------------------------
    %  Instructions: Train the softmax classifier, the classifier takes in
    %                input of dimension "hiddenSizeL2" corresponding to the
    %                hidden layer size of the 2nd layer.
    %
    %                You should store the optimal parameters in saeSoftmaxOptTheta 
    %
    %  NOTE: If you used softmaxTrain to complete this part of the exercise,
    %        set saeSoftmaxOptTheta = softmaxModel.optTheta(:);
    softmaxLambda = 1e-4;
    numClasses = 10;
    softoptions = struct;
    softoptions.maxIter = 400;
    softmaxModel = softmaxTrain(hiddenSizeL2,numClasses,softmaxLambda,...
                                sae2Features,trainLabels,softoptions);
    saeSoftmaxOptTheta = softmaxModel.optTheta(:);
    
    save('step4.mat', 'saeSoftmaxOptTheta');
    
    
    % -------------------------------------------------------------------------
    
    
    
    %%======================================================================
    %% STEP 5: Finetune softmax model
    
    % Implement the stackedAECost to give the combined cost of the whole model
    % then run this cell.
    
    % Initialize the stack using the parameters learned
    stack = cell(2,1);
    stack{1}.w = reshape(sae1OptTheta(1:hiddenSizeL1*inputSize), ...
                         hiddenSizeL1, inputSize);
    stack{1}.b = sae1OptTheta(2*hiddenSizeL1*inputSize+1:2*hiddenSizeL1*inputSize+hiddenSizeL1);
    stack{2}.w = reshape(sae2OptTheta(1:hiddenSizeL2*hiddenSizeL1), ...
                         hiddenSizeL2, hiddenSizeL1);
    stack{2}.b = sae2OptTheta(2*hiddenSizeL2*hiddenSizeL1+1:2*hiddenSizeL2*hiddenSizeL1+hiddenSizeL2);
    
    % Initialize the parameters for the deep model
    [stackparams, netconfig] = stack2params(stack);
    stackedAETheta = [ saeSoftmaxOptTheta ; stackparams ];
    
    %% ---------------------- YOUR CODE HERE  ---------------------------------
    %  Instructions: Train the deep network, hidden size here refers to the '
    %                dimension of the input to the classifier, which corresponds 
    %                to "hiddenSizeL2".
    %
    %
    [stackedAEOptTheta, cost] =  minFunc(@(p)stackedAECost(p,inputSize,hiddenSizeL2,...
                             numClasses, netconfig,lambda, trainData, trainLabels),...
                            stackedAETheta,options);
    save('step5.mat', 'stackedAEOptTheta');
    % -------------------------------------------------------------------------
    
    
    
    %%======================================================================
    %% STEP 6: Test 
    %  Instructions: You will need to complete the code in stackedAEPredict.m
    %                before running this part of the code
    %
    
    % Get labelled test images
    % Note that we apply the same kind of preprocessing as the training set
    testData = loadMNISTImages('t10k-images.idx3-ubyte');
    testLabels = loadMNISTLabels('t10k-labels.idx1-ubyte');
    
    testLabels(testLabels == 0) = 10; % Remap 0 to 10
    
    [pred] = stackedAEPredict(stackedAETheta, inputSize, hiddenSizeL2, ...
                              numClasses, netconfig, testData);
    
    acc = mean(testLabels(:) == pred(:));
    fprintf('Before Finetuning Test Accuracy: %0.3f%%\n', acc * 100);
    
    [pred] = stackedAEPredict(stackedAEOptTheta, inputSize, hiddenSizeL2, ...
                              numClasses, netconfig, testData);
    
    acc = mean(testLabels(:) == pred(:));
    fprintf('After Finetuning Test Accuracy: %0.3f%%\n', acc * 100);
    
    % Accuracy is the proportion of correctly classified images
    % The results for our implementation were:
    %
    % Before Finetuning Test Accuracy: 87.7%
    % After Finetuning Test Accuracy:  97.6%
    %
    % If your values are too low (accuracy less than 95%), you should check 
    % your code for errors, and make sure you are training on the 
    % entire data set of 60000 28x28 training images 
    % (unless you modified the loading code, this should be the case)

     

    function [ cost, grad ] = stackedAECost(theta, inputSize, hiddenSize, ...
                                                  numClasses, netconfig, ...
                                                  lambda, data, labels)
                                             
    % stackedAECost: Takes a trained softmaxTheta and a training data set with labels,
    % and returns cost and gradient using a stacked autoencoder model. Used for
    % finetuning.
                                             
    % theta: trained weights from the autoencoder
    % visibleSize: the number of input units
    % hiddenSize:  the number of hidden units *at the 2nd layer*
    % numClasses:  the number of categories
    % netconfig:   the network configuration of the stack
    % lambda:      the weight regularization penalty
    % data: Our matrix containing the training data as columns.  So, data(:,i) is the i-th training example. 
    % labels: A vector containing labels, where labels(i) is the label for the
    % i-th training example
    
    
    %% Unroll softmaxTheta parameter
    
    % We first extract the part which compute the softmax gradient
    softmaxTheta = reshape(theta(1:hiddenSize*numClasses), numClasses, hiddenSize);
    
    % Extract out the "stack"
    stack = params2stack(theta(hiddenSize*numClasses+1:end), netconfig);
    
    % You will need to compute the following gradients
    softmaxThetaGrad = zeros(size(softmaxTheta));
    stackgrad = cell(size(stack));
    for d = 1:numel(stack)
        stackgrad{d}.w = zeros(size(stack{d}.w));
        stackgrad{d}.b = zeros(size(stack{d}.b));
    end
    
    cost = 0; % You need to compute this
    
    % You might find these variables useful
    M = size(data, 2);
    groundTruth = full(sparse(labels, 1:M, 1));
    
    
    %% --------------------------- YOUR CODE HERE -----------------------------
    %  Instructions: Compute the cost function and gradient vector for 
    %                the stacked autoencoder.
    %
    %                You are given a stack variable which is a cell-array of
    %                the weights and biases for every layer. In particular, you
    %                can refer to the weights of Layer d, using stack{d}.w and
    %                the biases using stack{d}.b . To get the total number of
    %                layers, you can use numel(stack).
    %
    %                The last layer of the network is connected to the softmax
    %                classification layer, softmaxTheta.
    %
    %                You should compute the gradients for the softmaxTheta,
    %                storing that in softmaxThetaGrad. Similarly, you should
    %                compute the gradients for each layer in the stack, storing
    %                the gradients in stackgrad{d}.w and stackgrad{d}.b
    %                Note that the size of the matrices in stackgrad should
    %                match exactly that of the size of the matrices in stack.
    %
    
    depth = numel(stack);
    z = cell(depth+1,1);
    a = cell(depth+1, 1);
    a{1} = data;
    
    for layer = (1:depth)
      z{layer+1} = stack{layer}.w * a{layer} + repmat(stack{layer}.b, [1, size(a{layer},2)]);
      a{layer+1} = sigmoid(z{layer+1});
    end
    
    M = softmaxTheta * a{depth+1};
    M = bsxfun(@minus, M, max(M));
    p = bsxfun(@rdivide, exp(M), sum(exp(M)));
    
    cost = -1/numClasses * groundTruth(:)' * log(p(:)) + lambda/2 * sum(softmaxTheta(:) .^ 2);
    softmaxThetaGrad = -1/numClasses * (groundTruth - p) * a{depth+1}' + lambda * softmaxTheta;
    
    d = cell(depth+1);
    
    d{depth+1} = -(softmaxTheta' * (groundTruth - p)) .* a{depth+1} .* (1-a{depth+1});
    
    for layer = (depth:-1:2)
      d{layer} = (stack{layer}.w' * d{layer+1}) .* a{layer} .* (1-a{layer});
    end
    
    for layer = (depth:-1:1)
      stackgrad{layer}.w = (1/numClasses) * d{layer+1} * a{layer}';
      stackgrad{layer}.b = (1/numClasses) * sum(d{layer+1}, 2);
    end
    % -------------------------------------------------------------------------
    
    %% Roll gradient vector
    grad = [softmaxThetaGrad(:) ; stack2params(stackgrad)];
    
    end
    
    
    % You might find this useful
    function sigm = sigmoid(x)
        sigm = 1 ./ (1 + exp(-x));
    end

     

    function [pred] = stackedAEPredict(theta, inputSize, hiddenSize, numClasses, netconfig, data)
                                             
    % stackedAEPredict: Takes a trained theta and a test data set,
    % and returns the predicted labels for each example.
                                             
    % theta: trained weights from the autoencoder
    % visibleSize: the number of input units
    % hiddenSize:  the number of hidden units *at the 2nd layer*
    % numClasses:  the number of categories
    % data: Our matrix containing the training data as columns.  So, data(:,i) is the i-th training example. 
    
    % Your code should produce the prediction matrix 
    % pred, where pred(i) is argmax_c P(y(c) | x(i)).
     
    %% Unroll theta parameter
    
    % We first extract the part which compute the softmax gradient
    softmaxTheta = reshape(theta(1:hiddenSize*numClasses), numClasses, hiddenSize);
    
    % Extract out the "stack"
    stack = params2stack(theta(hiddenSize*numClasses+1:end), netconfig);
    
    %% ---------- YOUR CODE HERE --------------------------------------
    %  Instructions: Compute pred using theta assuming that the labels start 
    %                from 1.
    
    depth = numel(stack);
    z = cell(depth+1,1);
    a = cell(depth+1, 1);
    a{1} = data;
    
    for layer = (1:depth)
      z{layer+1} = stack{layer}.w * a{layer} + repmat(stack{layer}.b, [1, size(a{layer},2)]);
      a{layer+1} = sigmoid(z{layer+1});
    end
    
    [~, pred] = max(softmaxTheta * a{depth+1});
    
    
    
    
    
    
    
    
    
    % -----------------------------------------------------------
    
    end
    
    
    % You might find this useful
    function sigm = sigmoid(x)
        sigm = 1 ./ (1 + exp(-x));
    end

     

    转载于:https://www.cnblogs.com/90zeng/p/Stacked_Autoencoders.html

    展开全文
  • 基于深度置信网络(DBN),提出非监督贪心逐层训练算法,为解决深层结构相关的优化难题带来希望,随后提出多层自动编码器深层结构。此外Lecun等人提出的卷积神经网络(Convolutional Neural Networks / CNNs / ...

    一、背景介绍

    1.1 卷积神经网络

    近年来,深度学习的概念非常火热。深度学习的概念最早由Hinton等人在2006年提出。基于深度置信网络(DBN),提出非监督贪心逐层训练算法,为解决深层结构相关的优化难题带来希望,随后提出多层自动编码器深层结构。此外Lecun等人提出的卷积神经网络(Convolutional Neural Networks / CNNs / ConvNets)是第一个真正多层结构学习算法,它利用空间相对关系减少参数数目以提高训练性能。Alex在2012年提出的AlexNet网络结构模型引爆了神经网络的应用热潮,并赢得了2012届图像识别大赛的冠军,使得CNN成为在图像分类上的核心算法模型。

    1.2 深度学习框架

    随着深度学习研究的热潮持续高涨,各种开源深度学习框架也层出不穷,其中包括TensorFlow、Caffe2、Keras、CNTK、Pytorch、MXNet、Leaf、Theano、DeepLearning4等等。Google、Microsoft、Facebook等巨头都参与了这场深度学习框架大战。目前,由谷歌推出的TensorFlow和Facebook推出的Pytorch、Caffe2较受欢迎。下面将简单介绍这三种框架的特点。

    Caffe全称为Convolutional Architecture for Fast Feature Embedding,是一个被广泛使用的开源深度学习框架(在TensorFlow出现之前一直是深度学习领域GitHub star最多的项目)。Caffe的主要优势包括如下几点:

    容易上手,网络结构都是以配置文件形式定义,不需要用代码设计网络。
    训练速度快,能够训练state-of-the-art的模型与大规模的数据。
    组件模块化,可以方便地拓展到新的模型和学习任务上。
    Caffe的核心概念是Layer,每一个神经网络的模块都是一个Layer。Layer接收输入数据,同时经过内部计算产生输出数据。设计网络结构时,只需要把各个Layer拼接在一起构成完整的网络。Caffe2是caffe的升级版,在各方面均有一定提升。

    2017 年初,Facebook 在机器学习和科学计算工具 Torch 的基础上,针对 Python 语言发布了一个全新的机器学习工具包 PyTorch。一经发布,这款开源工具包就受到了业界的广泛关注和讨论,经过几个月的发展,目前 PyTorch 已经成为从业者最重要的研发工具之一。其最大的特点是支持动态图的创建。其他主流框架都是采用静态图创建,静态图定义的缺陷是在处理数据前必须定义好完整的一套模型,能够处理所有的边际情况。比如在声明模型前必须知道整个数据中句子的最大长度。相反动态图模型能够非常自由的定义模型。同时,PyTorch继承了Torch,支持Python,支持更加便捷的Debug,所以非常受欢迎。

    TensorFlow是相对高阶的机器学习库,用户可以方便地用它设计神经网络结构,而不必为了追求高效率的实现亲自写C++或CUDA代码。它和Theano一样都支持自动求导,用户不需要再通过反向传播求解梯度。其核心代码和Caffe一样是用C++编写的,使用C++简化了线上部署的复杂度,并让手机这种内存和CPU资源都紧张的设备可以运行复杂模型(Python则会比较消耗资源,并且执行效率不高)。除了核心代码的C++接口,TensorFlow还有官方的Python、Go和Java接口,是通过SWIG(Simplified Wrapper and Interface Generator)实现的,这样用户就可以在一个硬件配置较好的机器中用Python进行实验,并在资源比较紧张的嵌入式环境或需要低延迟的环境中用C++部署模型。

    TensorFlow的另外一个重要特点是它灵活的移植性,可以将同一份代码几乎不经过修改就轻松地部署到有任意数量CPU或GPU的PC、服务器或者移动设备上。用户能够将训练好的模型方便地部署到多种硬件、操作系统平台上,支持Intel和AMD的CPU,通过CUDA支持NVIDIA的GPU,支持Linux和Mac、Windows,也能够基于ARM架构编译和优化,在移动设备(Android和iOS)上表现得很好。TensorFlow还有功能强大的可视化组件TensorBoard,能可视化网络结构和训练过程,对于观察复杂的网络结构和监控长时间、大规模的训练很有帮助。TensorFlow针对生产环境高度优化,它产品级的高质量代码和设计都可以保证在生产环境中稳定运行,同时TensorFlow广泛地被工业界使用,产生了良性循环,成为了深度学习领域的事实标准。

    1.3 MNIST 数据集

    除了神经网络理论体系的发展和深度学习框架的推进,数据集的完善同样促进了人工智能领域的发展。MNIST(Mixed National Institute of Standards and Technology database)是一个计算机视觉数据集,它包含70000张手写数字的灰度图片,其中每一张图片包含 28 X 28 个像素点。可以用一个数字数组来表示这张图片。如图1所示。
    在这里插入图片描述
    每一张图片都有对应的标签,也就是图片对应的数字,例如上面这张图片的标签就是 1。数据集被分成两部分:60000 行的训练数据集(mnist.train)和10000行的测试数据集(mnist.test)。

    其中:60000 行的训练集分拆为 55000 行的训练集和 5000 行的验证集。60000行的训练数据集是一个形状为 [60000, 784] 的张量,第一个维度数字用来索引图片,第二个维度数字用来索引每张图片中的像素点。在此张量里的每一个元素,都表示某张图片里的某个像素的强度值,值介于 0 和 1 之间。

    60000 行的训练数据集标签是介于 0 到 9 的数字,用来描述给定图片里表示的数字。称为 “one-hot vectors”。一个 one-hot 向量除了某一位的数字是 1 以外其余各维度数字都是 0。所以在此教程中,数字 n 将表示成一个只有在第 n 维度(从 0 开始)数字为 1 的 10 维向量。比如,标签 0 将表示成 ( [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] )。因此,其标签是一个 [60000, 10] 的数字矩阵。如图2(a)、(b)所示。
    在这里插入图片描述
    下面将借助于TensorFlow框架,在Mnist数据集的基础上,通过卷积神经网络,进行手写数字识别的仿真测试。

    # MNIST数据

    import tensorflow as tf
    from tensorflow.examples.tutorials.mnist import input_data
    mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
    

    使用单层神经网络
    占位符

    x = tf.placeholder(tf.float32, shape=[None, 784])
    y_ = tf.placeholder(tf.float32, shape=[None, 10])
    

    输入图像x将由浮点数的二维张量组成。这里我们给它赋予一个[None,784]的大小,其中784是一个图像的28×28个像素,None表示第一维度可以是任意大小。目标输出y_也将由二维张量组成,其中每一行是一个唯一的10维向量,指示对应的MNIST图像是哪个数字(0到9)。

    变量
    我们现在定义权重W,并为我们的模型赋予偏差b。

    W = tf.Variable(tf.zeros([784,10]))
    b = tf.Variable(tf.zeros([10]));
    

    我们将调用中的每个参数的初始值传递给tf.Variable。 在这种情况下,我们将W和b初始化为全0的张量。 W是784x10矩阵(因为我们有784个输入特征和10个输出),b是10维向量(因为我们有10个数字)。

    在会话中使用变量之前,必须使用该会话进行初始化变量。 这一步将已经指定的初始值(在这里,张量全零),分配给每个变量。 这可以一次完成所有变量的赋值:

    sess.run(tf.global_variables_initializer())
    

    理论输出为

    y = tf.matmul(x,W) + b
    

    在以后的训练中要尽量减少损失函数的值。 定义损失函数是目标和应用于模型预测的softmax激活函数之间的交叉熵。

    cross_entropy = tf.reduce_mean(
    tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))
    

    请注意,tf.nn.softmax_cross_entropy_with_logits在应用softmax激活函数的交叉熵代价函数,并在所有类中进行求和,tf.reduce_mean表示取这些和的平均值。

    卷积和池化
    TensorFlow也为卷积和池化操作提供了很大的灵活性。 我们如何处理边界? 我们的步幅是多少? 在这个例子中,我们选择vanilla版本。 我们使步幅大小为1,并在周围填充零,以便输出与输入大小相同。 我们的pooling是超过2x2的max pooling。 为了保证我们的代码更清晰,我们也将这些操作抽象为函数。

    def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
    
    def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
                          strides=[1, 2, 2, 1], padding='SAME')
    

    tf.nn.conv2d

    conv2d(
        input,
        filter,
        strides,
        padding,
        use_cudnn_on_gpu=True,
        data_format='NHWC',
        name=None
    )
    

    input:张量。必须是以下类型之一:half,float32。一个四维张量。维度顺序根据data_format的值来解释,详见下文。
    filter:张量。必须具有与输入相同的类型。形状的四维张量[filter_height,filter_width,in_channels,out_channels]
    strides:整数列表。一维长度的张量4.输入每个维度的滑动窗口的步幅。维度顺序由data_format的值决定,详见下文。
    padding:来自“SAME”,“VALID”的字符串。要使用的填充算法的类型。
    use_cudnn_on_gpu:一个可选的布尔。默认为True。
    data_format:来自“NHWC”,“NCHW”的可选字符串。默认为“NHWC”。指定输入和输出数据的数据格式。使用默认格式“NHWC”,数据按照[batch,height,width,channels]的顺序存储。或者,格式可以是“NCHW”,数据存储顺序为:[batch,channels,height,width]。
    name:操作的名称(可选)。

    tf.nn.max_pool
    max_pool(
        value,
        ksize,
        strides,
        padding,
        data_format='NHWC',
        name=None
    )
    

    value:由data_format指定的格式的4维张量。
    ksize:4元素的1维 int型张量。 输入张量表示窗口每个维度的大小。
    strides:4元素的1维int型张量。 输入张量表示滑动窗口每个维度的步幅。
    padding:一个字符串,可以是’VALID’ 或 ‘SAME’。
    data_format:一个字符串。 支持“NHWC”,“NCHW”和“NCHW_VECT_C”。
    name:操作的可选名称。

    代码

    1

    import tensorflow as tf
    import numpy as np # 习惯加上这句,但这边没有用到
    from tensorflow.examples.tutorials.mnist import input_data
    import matplotlib.pyplot as plt
    mnist = input_data.read_data_sets('MNIST_data/', one_hot=True)
    
    sess = tf.InteractiveSession()
    
    # 1、权重初始化,偏置初始化
    # 为了创建这个模型,我们需要创建大量的权重和偏置项
    # 为了不在建立模型的时候反复操作,定义两个函数用于初始化
    def weight_variable(shape):
        initial = tf.truncated_normal(shape,stddev=0.1)#正太分布的标准差设为0.1
        return tf.Variable(initial)
    def bias_variable(shape):
        initial = tf.constant(0.1,shape=shape)
        return tf.Variable(initial)
    
    
    # 2、卷积层和池化层也是接下来要重复使用的,因此也为它们定义创建函数
    # tf.nn.conv2d是Tensorflow中的二维卷积函数,参数x是输入,w是卷积的参数
    # strides代表卷积模块移动的步长,都是1代表会不遗漏地划过图片的每一个点,padding代表边界的处理方式
    # padding = 'SAME',表示padding后卷积的图与原图尺寸一致,激活函数relu()
    # tf.nn.max_pool是Tensorflow中的最大池化函数,这里使用2 * 2 的最大池化,即将2 * 2 的像素降为1 * 1的像素
    # 最大池化会保留原像素块中灰度值最高的那一个像素,即保留最显著的特征,因为希望整体缩小图片尺寸
    # ksize:池化窗口的大小,取一个四维向量,一般是[1,height,width,1]
    # 因为我们不想再batch和channel上做池化,一般也是[1,stride,stride,1]
    def conv2d(x, w):
        return tf.nn.conv2d(x, w, strides=[1,1,1,1],padding='SAME') # 保证输出和输入是同样大小
    def max_pool_2x2(x):
        return tf.nn.max_pool(x, ksize=[1,2,2,1], strides=[1,2,2,1],padding='SAME')
    
    
    # 3、参数
    # 这里的x,y_并不是特定的值,它们只是一个占位符,可以在TensorFlow运行某一计算时根据该占位符输入具体的值
    # 输入图片x是一个2维的浮点数张量,这里分配给它的shape为[None, 784],784是一张展平的MNIST图片的维度
    # None 表示其值的大小不定,在这里作为第1个维度值,用以指代batch的大小,means x 的数量不定
    # 输出类别y_也是一个2维张量,其中每一行为一个10维的one_hot向量,用于代表某一MNIST图片的类别
    x = tf.placeholder(tf.float32, [None,784], name="x-input")
    y_ = tf.placeholder(tf.float32,[None,10]) # 10列
    
    
    # 4、第一层卷积,它由一个卷积接一个max pooling完成
    # 张量形状[5,5,1,32]代表卷积核尺寸为5 * 5,1个颜色通道,32个通道数目
    w_conv1 = weight_variable([5,5,1,32])
    b_conv1 = bias_variable([32]) # 每个输出通道都有一个对应的偏置量
    # 我们把x变成一个4d 向量其第2、第3维对应图片的宽、高,最后一维代表图片的颜色通道数(灰度图的通道数为1,如果是RGB彩色图,则为3)
    x_image = tf.reshape(x,[-1,28,28,1])
    # 因为只有一个颜色通道,故最终尺寸为[-1,28,28,1],前面的-1代表样本数量不固定,最后的1代表颜色通道数量
    h_conv1 = tf.nn.relu(conv2d(x_image, w_conv1) + b_conv1) # 使用conv2d函数进行卷积操作,非线性处理
    h_pool1 = max_pool_2x2(h_conv1)                          # 对卷积的输出结果进行池化操作
    
    
    # 5、第二个和第一个一样,是为了构建一个更深的网络,把几个类似的堆叠起来
    # 第二层中,每个5 * 5 的卷积核会得到64个特征
    w_conv2 = weight_variable([5,5,32,64])
    b_conv2 = bias_variable([64])
    h_conv2 = tf.nn.relu(conv2d(h_pool1, w_conv2) + b_conv2)# 输入的是第一层池化的结果
    h_pool2 = max_pool_2x2(h_conv2)
    
    # 6、密集连接层
    # 图片尺寸减小到7 * 7,加入一个有1024个神经元的全连接层,
    # 把池化层输出的张量reshape(此函数可以重新调整矩阵的行、列、维数)成一些向量,加上偏置,然后对其使用Relu激活函数
    w_fc1 = weight_variable([7 * 7 * 64, 1024])
    b_fc1 = bias_variable([1024])
    h_pool2_flat = tf.reshape(h_pool2, [-1,7 * 7 * 64])
    h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, w_fc1) + b_fc1)
    
    # 7、使用dropout,防止过度拟合
    # dropout是在神经网络里面使用的方法,以此来防止过拟合
    # 用一个placeholder来代表一个神经元的输出
    # tf.nn.dropout操作除了可以屏蔽神经元的输出外,
    # 还会自动处理神经元输出值的scale,所以用dropout的时候可以不用考虑scale
    keep_prob = tf.placeholder(tf.float32, name="keep_prob")# placeholder是占位符
    h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
    
    
    # 8、输出层,最后添加一个softmax层
    w_fc2 = weight_variable([1024,10])
    b_fc2 = bias_variable([10])
    y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, w_fc2) + b_fc2, name="y-pred")
    
    
    # 9、训练和评估模型
    # 损失函数是目标类别和预测类别之间的交叉熵
    # 参数keep_prob控制dropout比例,然后每100次迭代输出一次日志
    cross_entropy = tf.reduce_sum(-tf.reduce_sum(y_ * tf.log(y_conv),reduction_indices=[1]))
    train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
    # 预测结果与真实值的一致性,这里产生的是一个bool型的向量
    correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))
    # 将bool型转换成float型,然后求平均值,即正确的比例
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    # 初始化所有变量,在2017年3月2号以后,用 tf.global_variables_initializer()替代tf.initialize_all_variables()
    sess.run(tf.initialize_all_variables())
    
    # 保存最后一个模型
    saver = tf.train.Saver(max_to_keep=1)
    
    for i in range(1000):
        batch = mnist.train.next_batch(64)
        if i % 100 == 0:
            train_accuracy = accuracy.eval(feed_dict={x: batch[0], y_: batch[1],keep_prob: 1.0})
            print("Step %d ,training accuracy %g" % (i, train_accuracy))
        train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})
    print("test accuracy %f " % accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))
    
    # 保存模型于文件夹
    saver.save(sess,"save/model")
    

    在这里插入图片描述
    可以看到经过900次的迭代,我们的准确率达到了1

    2.

    import tensorflow as tf
    import numpy as np # 习惯加上这句,但这边没有用到
    from tensorflow.examples.tutorials.mnist import input_data
    import matplotlib.pyplot as plt
    mnist = input_data.read_data_sets('MNIST_data/', one_hot=True)
    
    sess = tf.InteractiveSession()
    
    # 1、权重初始化,偏置初始化
    # 为了创建这个模型,我们需要创建大量的权重和偏置项
    # 为了不在建立模型的时候反复操作,定义两个函数用于初始化
    def weight_variable(shape):
        initial = tf.truncated_normal(shape,stddev=0.1)#正太分布的标准差设为0.1
        return tf.Variable(initial)
    def bias_variable(shape):
        initial = tf.constant(0.1,shape=shape)
        return tf.Variable(initial)
    
    
    # 2、卷积层和池化层也是接下来要重复使用的,因此也为它们定义创建函数
    # tf.nn.conv2d是Tensorflow中的二维卷积函数,参数x是输入,w是卷积的参数
    # strides代表卷积模块移动的步长,都是1代表会不遗漏地划过图片的每一个点,padding代表边界的处理方式
    # padding = 'SAME',表示padding后卷积的图与原图尺寸一致,激活函数relu()
    # tf.nn.max_pool是Tensorflow中的最大池化函数,这里使用2 * 2 的最大池化,即将2 * 2 的像素降为1 * 1的像素
    # 最大池化会保留原像素块中灰度值最高的那一个像素,即保留最显著的特征,因为希望整体缩小图片尺寸
    # ksize:池化窗口的大小,取一个四维向量,一般是[1,height,width,1]
    # 因为我们不想再batch和channel上做池化,一般也是[1,stride,stride,1]
    def conv2d(x, w):
        return tf.nn.conv2d(x, w, strides=[1,1,1,1],padding='SAME') # 保证输出和输入是同样大小
    def max_pool_2x2(x):
        return tf.nn.max_pool(x, ksize=[1,2,2,1], strides=[1,2,2,1],padding='SAME')
    
    
    # 3、参数
    # 这里的x,y_并不是特定的值,它们只是一个占位符,可以在TensorFlow运行某一计算时根据该占位符输入具体的值
    # 输入图片x是一个2维的浮点数张量,这里分配给它的shape为[None, 784],784是一张展平的MNIST图片的维度
    # None 表示其值的大小不定,在这里作为第1个维度值,用以指代batch的大小,means x 的数量不定
    # 输出类别y_也是一个2维张量,其中每一行为一个10维的one_hot向量,用于代表某一MNIST图片的类别
    x = tf.placeholder(tf.float32, [None,784], name="x-input")
    y_ = tf.placeholder(tf.float32,[None,10]) # 10列
    
    
    # 4、第一层卷积,它由一个卷积接一个max pooling完成
    # 张量形状[5,5,1,32]代表卷积核尺寸为5 * 5,1个颜色通道,32个通道数目
    w_conv1 = weight_variable([5,5,1,32])
    b_conv1 = bias_variable([32]) # 每个输出通道都有一个对应的偏置量
    # 我们把x变成一个4d 向量其第2、第3维对应图片的宽、高,最后一维代表图片的颜色通道数(灰度图的通道数为1,如果是RGB彩色图,则为3)
    x_image = tf.reshape(x,[-1,28,28,1])
    # 因为只有一个颜色通道,故最终尺寸为[-1,28,28,1],前面的-1代表样本数量不固定,最后的1代表颜色通道数量
    h_conv1 = tf.nn.relu(conv2d(x_image, w_conv1) + b_conv1) # 使用conv2d函数进行卷积操作,非线性处理
    h_pool1 = max_pool_2x2(h_conv1)                          # 对卷积的输出结果进行池化操作
    
    
    # 5、第二个和第一个一样,是为了构建一个更深的网络,把几个类似的堆叠起来
    # 第二层中,每个5 * 5 的卷积核会得到64个特征
    w_conv2 = weight_variable([5,5,32,64])
    b_conv2 = bias_variable([64])
    h_conv2 = tf.nn.relu(conv2d(h_pool1, w_conv2) + b_conv2)# 输入的是第一层池化的结果
    h_pool2 = max_pool_2x2(h_conv2)
    
    # 6、密集连接层
    # 图片尺寸减小到7 * 7,加入一个有1024个神经元的全连接层,
    # 把池化层输出的张量reshape(此函数可以重新调整矩阵的行、列、维数)成一些向量,加上偏置,然后对其使用Relu激活函数
    w_fc1 = weight_variable([7 * 7 * 64, 1024])
    b_fc1 = bias_variable([1024])
    h_pool2_flat = tf.reshape(h_pool2, [-1,7 * 7 * 64])
    h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, w_fc1) + b_fc1)
    
    # 7、使用dropout,防止过度拟合
    # dropout是在神经网络里面使用的方法,以此来防止过拟合
    # 用一个placeholder来代表一个神经元的输出
    # tf.nn.dropout操作除了可以屏蔽神经元的输出外,
    # 还会自动处理神经元输出值的scale,所以用dropout的时候可以不用考虑scale
    keep_prob = tf.placeholder(tf.float32, name="keep_prob")# placeholder是占位符
    h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
    
    
    # 8、输出层,最后添加一个softmax层
    w_fc2 = weight_variable([1024,10])
    b_fc2 = bias_variable([10])
    y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, w_fc2) + b_fc2, name="y-pred")
    
    
    # 9、训练和评估模型
    # 损失函数是目标类别和预测类别之间的交叉熵
    # 参数keep_prob控制dropout比例,然后每100次迭代输出一次日志
    cross_entropy = tf.reduce_sum(-tf.reduce_sum(y_ * tf.log(y_conv),reduction_indices=[1]))
    train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
    # 预测结果与真实值的一致性,这里产生的是一个bool型的向量
    correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))
    # 将bool型转换成float型,然后求平均值,即正确的比例
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    # 初始化所有变量,在2017年3月2号以后,用 tf.global_variables_initializer()替代tf.initialize_all_variables()
    sess.run(tf.initialize_all_variables())
    
    # 保存最后一个模型
    saver = tf.train.Saver(max_to_keep=1)
    
    for i in range(1000):
        batch = mnist.train.next_batch(64)
        if i % 100 == 0:
            train_accuracy = accuracy.eval(feed_dict={x: batch[0], y_: batch[1],keep_prob: 1.0})
            print("Step %d ,training accuracy %g" % (i, train_accuracy))
        train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})
    print("test accuracy %f " % accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))
    
    # 保存模型于文件夹
    saver.save(sess,"save/model")
    

    3.可视化界面的识别demo

    import tensorflow as tf
    import numpy as np
    import tkinter as tk
    from tkinter import filedialog
    from PIL import Image, ImageTk
    #import Image, ImageTk
    from tkinter import filedialog
    import time
    
    
    def creat_windows():
        win = tk.Tk() # 创建窗口
        sw = win.winfo_screenwidth()
        sh = win.winfo_screenheight()
        ww, wh = 400, 450
        x, y = (sw-ww)/2, (sh-wh)/2
        win.geometry("%dx%d+%d+%d"%(ww, wh, x, y-40)) # 居中放置窗口
    
        win.title('手写体识别') # 窗口命名
    
        bg1_open = Image.open("timg.jpg").resize((300, 300))
        bg1 = ImageTk.PhotoImage(bg1_open)
        canvas = tk.Label(win, image=bg1)
        canvas.pack()
    
    
        var = tk.StringVar() # 创建变量文字
        var.set('')
        tk.Label(win, textvariable=var, bg='#C1FFC1', font=('宋体', 21), width=20, height=2).pack()
    
        tk.Button(win, text='选择图片', width=20, height=2, bg='#FF8C00', command=lambda:main(var, canvas), font=('圆体', 10)).pack()
        
        win.mainloop()
    
    def main(var, canvas):
        file_path = filedialog.askopenfilename()
        bg1_open = Image.open(file_path).resize((28, 28))
        pic = np.array(bg1_open).reshape(784,)
        bg1_resize = bg1_open.resize((300, 300))
        bg1 = ImageTk.PhotoImage(bg1_resize)
        canvas.configure(image=bg1)
        canvas.image = bg1
    
        init = tf.global_variables_initializer()
    
        with tf.Session() as sess:
                sess.run(init)
                saver = tf.train.import_meta_graph('save/model.meta')  # 载入模型结构
                saver.restore(sess, 'save/model')  # 载入模型参数
                graph = tf.get_default_graph()       # 加载计算图
                x = graph.get_tensor_by_name("x-input:0")  # 从模型中读取占位符变量
                keep_prob = graph.get_tensor_by_name("keep_prob:0")
                y_conv = graph.get_tensor_by_name("y-pred:0")  # 关键的一句  从模型中读取占位符变量
                prediction = tf.argmax(y_conv, 1)
                predint = prediction.eval(feed_dict={x: [pic], keep_prob: 1.0}, session=sess)  # feed_dict输入数据给placeholder占位符
                answer = str(predint[0])
        var.set("预测的结果是:" + answer)
    
    if __name__ == "__main__":
        creat_windows()
    

    实验结果

    在这里插入图片描述
    预测结果和我们输入的图片一致,我们继续换图片测试
    在这里插入图片描述
    我们输入的是1,但是识别为8在这里插入图片描述在这里插入图片描述
    可能是我们为了运行的速度,把图片像素调太低了。
    在这里插入图片描述
    该图把1预测成6。在这里插入图片描述
    把0预测成6,可能是0的上面有一点凸起,错误的成了6。
    在这里插入图片描述
    在这里插入图片描述
    实验总结
    1.我们字体的像素会影响我们的预测结果
    2.书写的规范会导致结果有出入
    3.对于这个小的卷积网络,Dropout的存在与否对性能几乎没有影响。Dropout对减少过拟合一般十分有效,但但在训练非常大的神经网络时,它才是最有用的。

    展开全文
  • 离线手写数字识别是光学字符识别的一个重要分支,在银行票据识别、邮政编码识别等领域有着广泛的应用。由于单一分类识别率上很难达到要求,人们提出了各种集成分类器识别方案。通过对离线手写数字的特征提取,从...
  • 首先我是看到SIGAI给的机器学习算法地图里没有无监督学习里面没有自动编码器,而这个在他们的深度学习的课表目录里面,MNIST手写识别也是在他们的深度学习课程里面,CNN RNN都是深度学习课程里面的,这时候我意识到...
  • 前言 斯坦福的UFLDL教程每一个章节都配有练习 本文是自我学习这一章节的...softmax的输入是自动编码器的输出,用“无标签”数据训练自动编码机后,用得到的参数处理softmax的训练集和测试集 stlExercise完整代码 %% C
  • 将目前的各种输入产品与办公系统良好地结合,如手写体输入设备、印刷体扫描识别、语音输入设备等。 7 领导服务 是提供给领导的办公平台,包括领导日程、领导查询。在领导日程模块中,领导可对办公日程...
  • 目的:使用稀疏自编码器提取特征,使用softmax做分类器,实现手写字符识别分类。 好处:相比较前面直接使用softmax分类器(92%识别率),能够提升分类器的效果,达到98%以上。 体会:通过自学习提取特征,能够模仿...
  • 2.对特征维数过高的数据(如mnist手写识别中的维度为28*28),将对数据进行降维操作,通常的降维操作有PCA(主成分分析)与dA(降噪自动编码器)。 下面是对PCA的工作流程的简述,之后对工作流程进行数学上的解
  • 针对传统特征提取方法需要先验知识的不足,提出一种自动编码器(AutoEncoder)与卷积神经网络(convolutional neural network,CNN)相结合的深度学习特征提取方法。该方法给AutoEncoder加入快速稀疏性控制,据此对...
  • 在P-ELM中,优越的网络参数由基于ELM的自动编码器(ELM-AE)预先训练在人脸图像识别手写方面的实验和比较。图像注释应用表明,P-ELM是有前途的,并且与原始的ELM相比,效果更好。算法以及其他基于ELM的算法。
  • 29、表格绘制功能,可支持表格行和列的插入与删除、表格单元的合并与拆分、表格边框线的设置、手写识别文字输入、字体设置等; 30、不限长度和宽度的页面,提供更多的书写空间; 31、提供了大米字格纸、汉语拼音纸、...
  • 此功能非常适合导入单位的人员名单等,只需把名单一个一行粘贴进去,不需人工编码,然后就能够自动生成编码打字了!单位办公不要太方便! 也可用于维护专业特殊词汇。 添加用户自定义短语 使用记事本等文本编辑...
  • 基于不同语料+编码器+目标任务的中文预训练模型仓库、中文自然语言处理向量合集、基于金融-司法领域(兼有闲聊性质)的聊天机器人、g2pC:基于上下文的汉语读音自动标记模块、Zincbase 知识图谱构建工具包、诗歌质量...
  • 深度自动编码器(Deep Autoencoder Networks) 集成算法(Ensemble Learning) Boosting Bagging AdaBoost 堆叠泛化(混合) GBM 算法 GBRT 算法 随机森林 其他算法 特征选择算法 性能评估算法 自然语言处理 ...
  • funNLP_fighting41love.tar.gz

    2019-10-20 15:05:11
    基于不同语料+编码器+目标任务的中文预训练模型仓库、中文自然语言处理向量合集、基于金融-司法领域(兼有闲聊性质)的聊天机器人、g2pC:基于上下文的汉语读音自动标记模块、Zincbase 知识图谱构建工具包、诗歌质量...
  • chardet:字符编码检测,兼容 Python2 和 Python3。 difflib:(Python 标准库)帮助我们进行差异化比较。 ftfy:让 Unicode 文本更完整更连贯。 fuzzywuzzy:模糊字符串匹配。 Levenshtein:快速计算编辑距离...
  • vc++ 应用源码包_1

    热门讨论 2012-09-15 14:22:12
    内部包含了atl控件的开发以及如何应用,演示了COM的包容与集合、自动化、事件和连接点、枚举和集合以及线程管理等等。 ATL实现的CDHtmlDialog模板类v1.03 使用了六个类五个模块类演示了atl的调用方法 ...
  • vc++ 应用源码包_2

    热门讨论 2012-09-15 14:27:40
    内部包含了atl控件的开发以及如何应用,演示了COM的包容与集合、自动化、事件和连接点、枚举和集合以及线程管理等等。 ATL实现的CDHtmlDialog模板类v1.03 使用了六个类五个模块类演示了atl的调用方法 ...
  • vc++ 应用源码包_6

    热门讨论 2012-09-15 14:59:46
    内部包含了atl控件的开发以及如何应用,演示了COM的包容与集合、自动化、事件和连接点、枚举和集合以及线程管理等等。 ATL实现的CDHtmlDialog模板类v1.03 使用了六个类五个模块类演示了atl的调用方法 ...
  • vc++ 应用源码包_5

    热门讨论 2012-09-15 14:45:16
    内部包含了atl控件的开发以及如何应用,演示了COM的包容与集合、自动化、事件和连接点、枚举和集合以及线程管理等等。 ATL实现的CDHtmlDialog模板类v1.03 使用了六个类五个模块类演示了atl的调用方法 ...
  • vc++ 应用源码包_4

    热门讨论 2012-09-15 14:38:35
    内部包含了atl控件的开发以及如何应用,演示了COM的包容与集合、自动化、事件和连接点、枚举和集合以及线程管理等等。 ATL实现的CDHtmlDialog模板类v1.03 使用了六个类五个模块类演示了atl的调用方法 ...
  • vc++ 应用源码包_3

    热门讨论 2012-09-15 14:33:15
    内部包含了atl控件的开发以及如何应用,演示了COM的包容与集合、自动化、事件和连接点、枚举和集合以及线程管理等等。 ATL实现的CDHtmlDialog模板类v1.03 使用了六个类五个模块类演示了atl的调用方法 ...
  • vc++ 开发实例源码包

    2014-12-16 11:25:17
    内部包含了atl控件的开发以及如何应用,演示了COM的包容与集合、自动化、事件和连接点、枚举和集合以及线程管理等等。 ATL实现的CDHtmlDialog模板类v1.03 使用了六个类五个模块类演示了atl的调用方法 class ...
  • 如:安防领域的人脸识别和智能视频分析等,交通领域的交通场景识别,互联网领域基于内容的图像检索和相册自动归类,医学领域的图像识别等。 模型名称 模型简介 数据集 评估指标 top-1/top-5 accuracy AlexNet...

空空如也

空空如也

1 2
收藏数 34
精华内容 13
关键字:

自动编码器手写识别