精华内容
下载资源
问答
  • 导读在CVPR 2020上,商汤研究院链接与编译团队、高性能计算团队和北航刘祥龙老师团队合作提出了用于加速卷积神经网络训练过程的INT8训练技术。该工作通过将网络的输入、权重和梯度量化到8比特来加速网络的前向传播和...

    在CVPR 2020上,商汤研究院链接与编译团队、高性能计算团队和北航刘祥龙老师团队合作提出了用于加速卷积神经网络训练过程的INT8训练技术。该工作通过将网络的输入、权重和梯度量化到8比特来加速网络的前向传播和反向传播过程,缩短卷积神经网络训练时间。论文观察到梯度的独特分布给量化训练带来了极大挑战,为了解决梯度量化带来的精度损失和不稳定问题,该论文进行了量化训练收敛稳定性的理论分析并基于此提出了误差敏感的学习率调节和基于方向自适应的梯度截断方法。同时为了保证更高的加速比,该论文还提出使用周期更新、量化卷积融合等技术来减少量化操作带来的时间开销。应用了上述方法之后,INT8训练在图像分类任务和检测任务上都仅仅损失微小的精度,且训练过程相比浮点训练加速了22%。

    Part.1

    动机与背景

    卷积神经网络被广泛应用在多种计算机视觉任务中并且取得了优异的精度。由于拥有庞大的参数量,训练和部署卷积神经网络需要耗费大量计算资源和漫长的训练时间,如何用更少资源训练卷积神经网络一直是一个学术研究热点,也是工业界关心的话题。

    神经网络量化技术是一种使用定点计算代替浮点的加速技术,目前被广泛地应用在神经网络部署中,可以极大地提升部署速度,并降低内存资源占用。现有很多工作均表明将网络前向过程的浮点计算替换成INT8计算,不会带来明显的精度下降[1][2]

    下图展示了现代神经网络加速芯片对于不同精度计算的理论计算峰值对比,可以看到,INT8算力相比于FP32和FP/INT16均能有超过2倍峰值性能提升。

    4832ffee777474595b55fb8a55dc6cd7.png

    当考虑将神经网络量化技术应用在卷积神经网络训练中时,为了加速卷积的反向梯度传播过程,不得不对梯度进行量化操作。在将浮点的梯度量化到INT8数值范围内之后,训练过程变得极其不稳定,并且收敛到非常差的精度。如何解决量化梯度给训练带来的收敛稳定性问题,是十分重要的问题。与此同时,在提升训练精度的同时,也不应当进入过多额外的计算,否则加速效果将会大打折扣。

    一方面是高效的计算峰值保障,一方面是困难重重的算法设计,这是INT8训练技术的机遇与挑战。

    Part.2

    何为INT8训练

    标准的线性量化操作指的是,将一个浮点张量(tensor)进行线性映射,变换到整数空间中[3]。这个整数空间的大小由于量化比特数来决定,比如常见的8bit量化数,就有256个取值,本文中使用的是对称量化,因此量化数的取值是从-128到127。具体公式如下,其中x是被量化的数据,q是量化后的数据,s是量化系数,clip是截断函数:

    e97b6751bbf94e215d0ae748f4be14b0.png

    在8bit的场景里,截断函数和量化系数的计算公式如下:

    435948dae841a0bbfc78ecf3d73817c7.png

    为了降低量化带来的误差,一个常见做法是对取整过程进行随机化,使得取整函数从期望上更接近原始的数,具体随机取整的公式如下:

    1f2416cf70b16f5af92b72eaeb087096.png

    相反的,将8bit量化数变换回浮点的过程称之为反量化。反量化公式如下所示,其中q为量化计算结果,s为量化系数,x为反量化后的结果。

    6efbdf251603fed876c628563378622e.pngf27b789c13a6907e4ebdfd01d2ac11a7.png

    上图的上半部分展示了标准的卷积神经网络量化计算前向过程,该过程被广泛应用在INT8部署加速中。在卷积计算之前,量化器会对输入和权重进行量化操作,将浮点数量化到8bit数值上,通过INT8卷积计算核心,即可完成一次INT8前向计算,最终将求和得到的32bit数进行反量化操作回算到浮点数域中,以供给下一层计算使用。

    INT8训练的一个核心的加速点在于卷积计算的反向过程,上图展示了INT8训练中卷积计算在反向传播过程中的计算细节。在卷积的反向梯度传播过程,同样的将梯度进行浮点量化操作,不过为了降低量化的误差,针对梯度的量化采用了随机取整操作。通过INT8的反向卷积计算核心,可以得到下一层所需的回传梯度,以及当前层的权重所需的梯度。由于INT8反向卷积输出的是32bit数,与前传类似,需要引入一次反量化操作,将32bit数反算回到浮点数域中。

    Part.3

    梯度为何难以量化

    为什么对梯度进行量化会给网络训练带来如此大的影响?我们可以观察训练过程中的梯度分布情况来进一步的分析。

    253268662307f5b0fd58b14f1e144f0d.png

    通过图(a)中对比梯度和输入、权重的分布,可以发现:梯度分布相比输入和权重分布更加尖锐,同时范围更大。相比于输入和权重,梯度有更多的值集中在0附近,但同时梯度还有许多较大值,让梯度的分布范围变得相当广,这些特征都会导致梯度量化的量化误差比输入和权重更大。

    dd309c96d704226ba212071918a70a2c.png

    图(b)展示的是layers16随着训练,其梯度从epoch 0到epoch 300的变化情况。从中可以看出,随着训练的进行,梯度分布越变得更加尖锐,同时仍然保持着较广的分布范围,这意味着梯度量化的误差会随着训练的进行变得越来越大。

    302221ecf1d41a3172c79d41c38928a4.png

    梯度的分布随网络深度变化情况从图(c)中可以看出。很容易发现,卷积层的深度越浅,梯度分布越尖锐,这也会导致梯度量化的误差更大。

    e632cbc503066a3f7b8178cd2529aac1.png

    从图(d)中可以看出卷积的结构也会影响梯度分布,对于MobileNetV2来说,conv2为depthwise卷积其相比conv1和conv3具有更加尖锐的分布。

    由于卷积神经网络的梯度具有如上四个特点,所以当我们直接在训练中对梯度进行量化时,训练精度非常容易出现突发的崩溃情况。下图展示了在CIFAR-10数据集上进行实验的精度和损失函数变化曲线,以MobileNetv2在CIFAR-10数据集上训练为例,其训练的精度曲线和loss曲线如下图,从图中可以发现INT8训练的loss在训练初期正常下降,但随后迅速上升,对应的精度也不断下降。

    0ab0f8e8d9723516de3ed1a7d6f55027.png

    Part.4

    是什么影响了收敛稳定性

    根据以上的观察和初步启发,我们希望通过理论的分析和推导,对量化训练的收敛稳定性进行建模。根据Adam等相关论文的经验和优化理论中的Regret analysis,不失一般性地定义R(T)为:

    3a936ead22845c61c042d47f5cdfc497.pngf98c91d04de508a27839838f2616a297.png

    基于以下两个朴素的假设:

    4783c80a28efdcf0266bad88d19eda24.png

    通过推导证明可以得到:

    c79ce7ff71a600b6379d28c6c12c5b0c.pnge37fe54d76683158f2adbb382866b3ed.png

    为了确保网络能够稳定收敛,R(T)/T在T变大时需要能够达到足够小。通过上式可以发现,在T趋于无穷大时,第(1)项可以忽略不计,主要考虑减小第(2)项和第(3)项。

    我们发现,第(2)项与量化误差正相关,第(3)项与学习率以及量化后的梯度大小有关。

    因此我们不难得到两个直观的提升训练收敛稳定性的策略:

    • 通过调节量化函数中的截断减小量化误差;

    • 通过适当调低学习率来提高量化训练精度。

    Part.5

    主要方法

    依据以上分析,我们针对量化误差和学习率提出了基于方向自适应的梯度截断误差敏感的学习率调节两个方法来解决量化训练带来的精度损失问题。同时,为了减少量化操作带来的额外开销,本文还提出了周期更新量化卷积融合的方法。

    0cece6384454c24da56af42221d2cbcb.png

    1、基于方向自适应的梯度截断:调整截断值,让梯度方向保持正确。

    为了最小化量化误差,之前有很多研究提出优化截断值的方法,其中就有研究提出通过假设数据分布直接求解最优截断值。但是已有的研究都针对于权重量化的截断值进行优化。就如本文观察所显示,梯度的分布特征与权重区别较大,无法直接使用。本文通过KS检验发现梯度的分布并不符合常见的高斯分布、拉普拉斯分布和学生t分布,因此很难通过假设梯度分布来直接求解最优的截断值。

    16388c83238639486ea5718ca57c08dd.png

    基于以上的分析,本文采用梯度下降的方法来自适应地学习最优截断值,常见的目标函数有均方误差函数,但是由于梯度的分布特征,均方误差的大小会受到梯度的影响,影响优化过程;同时对于梯度来说,均方误差并不能很好地体现梯度的量化误差对于优化过程的影响,因此本文提出使用能够体现梯度方向的余弦距离来衡量梯度的量化误差,并以余弦距离为目标函数来优化求解最优截断值。余弦距离定义如下:

    99ab2b60b30324263e0136ed69eee856.png

    2286815069b6533eb2ea200f7b80d01d.png

    2、误差敏感的学习率调节:在错误的方向上尽量少更新。

    根据上述的理论分析,降低学习率能够有助于模型量化训练的收敛。针对学习率的调整,本文提出误差敏感的学习率调节方法,使用学习率系数对原学习率进行调整,学习率系数与余弦距离负相关,学习率系数定义如下:

    36a42d247b61159b0ed6f31a158fffd6.png

    729e057b5af26b78b6378e2a46d53e67.png

    3、周期更新:降低由于统计而带来的额外计算耗时

    由于量化操作需要的统计数据范围和计算截断值等操作十分耗时,为了减少这些操作的时间开销,本文采用周期更新的方式,周期性地统计数据范围和计算截断值。通过周期更新的方法能够有效地提高减少因量化引入的额外时间开销。下表为ResNet50在ImageNet数据集上不同周期的单次训练时间统计表。

    7acfe0985a03df57d19c5e96431cc0e2.png

    4、量化卷积融合:减少访存次数、节省cuda kernel launch次数

    通过将量化和反量化操作融合入卷积计算的CUDA核函数里,可以减少一次数据的访存,有效地减少量化和反量化操作的时间开销。

    4c89ee453e0975fdcec3d81a41ab109f.png

    Part.6

    实验结果

    图像分类任务:本文在CIFAR10和ImageNet等图像分类数据集进行INT8训练实验。从下表结果中可以看出,在大多数网络结构中均取得了比现有最好方法更优的精度,并且首次在MobileNet、Inception等网络上进行量化训练实验,精度损失也在1.5%以内。

    d4a6f3b8fce3b98063e692b6013e3aca.pnge820b9521f16d87c18b2c479467dfbc1.png

    目标检测任务:同时,本文也首次尝试在PASCAL和COCO等目标检测数据集上进行INT8训练实验,精度损失也在2%以内。

    66c31b816dd31fd76ec40baea2b8239c.png

    已有的少量探究梯度量化的论文[4]均未报告算法在实际训练任务中的真实加速性能,为了最大限度将方法实用化,本文在GeForce GTX1080TI显卡上编写并优化了用于支持INT8训练的卷积前向和后向计算核心。实测结果表明,使用INT8卷积计算的前向和后向过程相比于浮点计算有明显的加速,其中前向过程平均加速1.63倍,后向过程平均加速1.94倍。如下图所示:

    af3dad685ac8c17f88c4f37e2c08d49b.png

    同时,本文在实际训练过程中进行了完整的端到端测试,可以看到,INT8训练可以将ResNet50的一轮训练过程从0.360秒降低到0.293秒,整体训练过程提速了22%。

    70a3b73e368bb4debbec50c46d840587.png284d969f507f45fc51604a00c43a469d.gif

    论文地址:

    https://arxiv.org/pdf/1912.12607.pdf 

    论文讲解近期将有线上直播的论文讲解及专题交流课程,欢迎点击下方“商汤泰坦公开课”课程专题链接进行报名

    报名链接:https://jinshuju.net/f/RKOLf9

    6be29102ef76096de95333d382dbe06c.gif

    商汤研究院-链接与编译团队致力于通过System+AI技术打造顶尖的深度学习核心引擎。开发的模型训练和模型部署工具链已服务于公司多个核心业务。团队在量化模型的在线/离线生产、部署对齐、加速训练等方向有着明确的技术规划。

    团队目前正在招聘模型量化方向的系统算法研究员/实习生,欢迎感兴趣的小伙伴投递简历到yufengwei@sensetime.com。

    Reference

    [1]Ruihao Gong, Xianglong Liu, Shenghu Jiang, Tianxiang Li,Peng Hu, Jiazhen Lin, Fengwei Yu, and Junjie Yan. Differen-tiable soft quantization: Bridging full-precision and low-bitneural networks. In ICCV, October 2019.

    [2]Rundong Li, Yan Wang, Feng Liang, Hongwei Qin, Junjie Yan, and Rui Fan. Fully quantized network for object detection. In The IEEE Conference on Computer Vision and Pattern Recognition (CVPR), June 2019.

    [3]Benoit Jacob, Skirmantas Kligys, Bo Chen, Menglong Zhu, Matthew Tang, Andrew Howard, Hartwig Adam, and Dmitry Kalenichenko. Quantization and training of neural networks for efficient integer-arithmetic-only inference. 2018 IEEE Conference on Computer Vision and Pattern Recognition(CVPR), June 2018.

    [4]Yukuan Yang, Shuang Wu, Lei Deng, Tianyi Yan, Yuan Xie, and Guoqi Li. Training high-performance and large-scale deep neural networks with full 8-bit integers, 2019.

    5bfd941c4a6d9ff5f9753bf1e64a9d44.png

    94d7fc44e08901dd6c36fa7bf4746715.gif

    点击阅读原文即可留下你的评论

    展开全文
  • 在初学卷积神经网络的过程中,有时会遇到loss在训练过程中出现NaN的情况,本文列出了几个可能原因及症状并提供了一些方法解决,希望对初学者有所帮助。

    1.梯度爆炸


    原因:在学习过程中,梯度变得非常大,使得学习的过程偏离了正常的轨迹。

    症状:观察输出日志(runtime log)中每次迭代的loss值,你会发现loss随着迭代有明显的增长,最后因为loss值太大以致于不能用浮点数去表示,所以变成了NaN

    可采取的方法:1.降低学习率,比如solver.prototxtbase_lr,降低一个数量级(至少)。如果在你的模型中有多个loss层,就不能降低基础的学习率base_lr,而是需要检查日志,找到产生梯度爆炸的层,然后降低train_val.prototxt中该层的loss_weight

    2.错误的学习率策略及参数


    原因:在学习过程中,caffe不能得出一个正确的学习率,相反会得到inf或者nan的值。这些错误的学习率乘上所有的梯度使得所有参数变成无效的值。

    症状:观察输出日志(runtime log),你应该可以看到学习率变成NaN,例如:

    ... sgd_solver.cpp:106] Iteration 0, lr = -nan

    可采取的方法:修改solver.prototxt文件中所有能影响学习率的参数。比如,如果你设置的学习率策略是 lr_policy: “poly” ,而你又忘了设置最大迭代次数max_iter,那么最后你会得到lr=NaN

    关于caffe学习率及其策略的内容,可以在github的/caffe-master/src/caffe/proto/caffe.proto 文件中看到 (传送门)。
    下面是源文件的注释部分的描述:

    // The learning rate decay policy. The currently implemented learning rate
    // policies are as follows:
    //    - fixed: always return base_lr.
    //    - step: return base_lr * gamma ^ (floor(iter / step))
    //    - exp: return base_lr * gamma ^ iter
    //    - inv: return base_lr * (1 + gamma * iter) ^ (- power)
    //    - multistep: similar to step but it allows non uniform steps defined by
    //      stepvalue
    //    - poly: the effective learning rate follows a polynomial decay, to be
    //      zero by the max_iter. return base_lr (1 - iter/max_iter) ^ (power)
    //    - sigmoid: the effective learning rate follows a sigmod decay
    //      return base_lr ( 1/(1 + exp(-gamma * (iter - stepsize))))
    //
    // where base_lr, max_iter, gamma, step, stepvalue and power are defined
    // in the solver parameter protocol buffer, and iter is the current iteration.

    3.错误的损失函数


    原因:有时,在损失层计算损失值时会出现NaN的情况。比如,向InfogainLoss层没有归一化输入值,使用自定义的损失层等。

    症状:观察输出日志(runtime log)的时候,你可能不会发现任何异常:loss逐渐下降,然后突然出现NaN

    可采取的方法:尝试重现该错误,打印损失层的值并调试。

    举个栗子:有一回,我根据批量数据中标签出现的频率去归一化惩罚值并以此计算loss。如果有个label并没有在批量数据中出现,频率为0,结果loss出现了NaN的情况。在这种情况下,需要用足够大的batch来避免这个错误。

    4.错误的输入


    原因:你的输入中存在NaN

    症状:一旦学习过程中碰到这种错误的输入,输出就会变成NaN。观察输出日志(runtime log)的时候,你可能也不会发现任何异常:loss逐渐下降,然后突然出现NaN

    可采取的方法:重建你的输入数据集(lmdb/leveldn/hdf5…),确保你的训练集/验证集中没有脏数据(错误的图片文件)。调试时,使用一个简单的网络去读取输入,如果有一个输入有错误,这个网络的loss也会出现NaN

    5.Pooling层的步长大于核的尺寸


    由于一些原因,步长stride>核尺寸kernel_size的pooling层会出现NaN。比如:

    layer {
      name: "faulty_pooling"
      type: "Pooling"
      bottom: "x"
      top: "y"
      pooling_param {
        pool: AVE
        stride: 5
        kernel: 3
      }
    }

    结果y会出现NaN

    原文链接:https://stackoverflow.com/questions/33962226/common-causes-of-NaNs-during-training

    展开全文
  • 最近在利用DCNN模型训练自己的数据集,利用SS数据集进行测试,做二分类,结果刚开始训练模型的准确率就为1,后面也是这样,主要原因还是数据集打乱的还不够,不能只靠tensorflow的shuffle操作来打乱,最好先打乱顺序...

    最近在利用DCNN模型训练自己的数据集,利用SS数据集进行测试,做二分类,结果刚开始训练模型的准确率就为1,后面也是这样,主要原因还是数据集打乱的还不够,不能只靠tensorflow的shuffle操作来打乱,最好先打乱顺序后制作好tfrecords文件,再用shuffle函数打乱一次。
    主要步骤如下:
    (1)找到SS标签文件
    (2)制作TFRecords文件
    (3)开始训练

    关于制作TFRecords文件:

    制作TFrecords文件代码如下:

    import tensorflow as tf
    # 7,8 -- 9,10 -- 11,12
    from PIL import Image
    import csv
    import random
    
    number_pic = 50000  # 空与非空的数量,保存相等
    
    with open('/media/sj/Elements/S5_event_train.csv', 'r') as r:
        next(r)
        reader = csv.reader(r)
        images_list_null = []
        images_list_full = []
    
        writer = tf.python_io.TFRecordWriter('./train_SS_50.tfrecords')
        for row in reader:
            if row[8] == 'NA':
                images_list_null.append([row[7], 0])
            else:
                if row[8] != '':
                    images_list_full.append([row[7], 1])
    
                else:
                    print("skip null_8")
    
            if row[10] == 'NA':
                images_list_null.append([row[9], 0])
    
            else:
                if row[10] != '':
                    images_list_full.append([row[9], 1])
                else:
                    print("skip null_10")
    
            if row[12] == 'NA':
                images_list_null.append([row[11], 0])
            else:
                if row[12] != '':
                    images_list_full.append([row[11], 1])
                else:
                    print('skip null_12')
        print(len(images_list_null), len(images_list_full))
    
        good_null = []
        good_full = []
        # 将好的写入到列表
        for null in images_list_null:
            try:
                img = Image.open(null[0], "r")
                good_null.append(null)
            except:
                pass
        for full in images_list_full:
            try:
                img = Image.open(full[0], "r")
                good_full.append(full)
            except:
                pass
        print(len(good_null), len(good_full))
        filename = good_null[:number_pic] + good_full[:number_pic]
        random.shuffle(filename)
        m = 0
        j = 0
        if m < 6:
            for file in filename:
                if m == 1:
                    img = file[0].transpose(Image.ROTATE_90)  # 旋转
                    img = Image.open(img, "r")
    
                elif m == 2:
                    img = file[0].transpose(Image.ROTATE_180)  # 旋转
                    img = Image.open(img, "r")
                elif m == 3:
                    img = file[0].transpose(Image.ROTATE_270)  # 旋转
                    img = Image.open(img, "r")
                elif m == 4:
                    img = file[0].transpose(Image.FLIP_TOP_BOTTOM)
                    img = Image.open(img, "r")
                elif m == 5:
                    img = file[0].transpose(Image.FLIP_LEFT_RIGHT)
                    img = Image.open(img, "r")
                else:
                    img = Image.open(file[0], "r")
    
                label = file[1]
                with open('./SS_50.csv', 'a+') as f:
                    f_csv = csv.writer(f)
                    f_csv.writerow([file[0],label])
                img_raw = img.tobytes()
                example = tf.train.Example(
                    features=tf.train.Features(feature={
                        'path': tf.train.Feature(bytes_list=tf.train.BytesList(value=[img_raw])),
                        'label': tf.train.Feature(int64_list=tf.train.Int64List(value=[label])),
    
                    }))
                writer.write(example.SerializeToString())  # 序列化为二进制格式
    
                if j == number_pic * 2:
                    break
                j += 1
    
                print(j, m)
    
            m += 1
    
        print("successful")
        writer.close()
    
    

    代码关键部分解释:

    上面是从SS数据集里面的S5制作一个包含10万张照片的tfrecords文件,其中空照片5万,非空5万。制作平衡数据集。
    (1)第一步先遍历csv文件读取相应的图片路径和标签名称,空标记为0,非空标记为1.

        for row in reader:
            if row[8] == 'NA':
                images_list_null.append([row[7], 0])
            else:
                if row[8] != '':
                    images_list_full.append([row[7], 1])
    
                else:
                    print("skip null_8")
    
            if row[10] == 'NA':
                images_list_null.append([row[9], 0])
    
            else:
                if row[10] != '':
                    images_list_full.append([row[9], 1])
                else:
                    print("skip null_10")
    
            if row[12] == 'NA':
                images_list_null.append([row[11], 0])
            else:
                if row[12] != '':
                    images_list_full.append([row[11], 1])
                else:
                    print('skip null_12')
        print(len(images_list_null), len(images_list_full))
    

    (2)读取完成后,两个列表下面存在一损坏或者不存在的图片路径,需要检查并且从列表中删除,利用Image.open检查图片是否存在或者损坏,代码如下:

    good_null = []
        good_full = []
        # 将好的写入到列表
        for null in images_list_null:
            try:
                img = Image.open(null[0], "r")
                good_null.append(null)
            except:
                pass
        for full in images_list_full:
            try:
                img = Image.open(full[0], "r")
                good_full.append(full)
            except:
                pass
        print(len(good_null), len(good_full))
    

    (3)为了构建平衡数据集,可以通过列表截取的方式各取number_pic万张,最后合并并使用随机函数打乱顺序。

    filename = good_null[:number_pic] + good_full[:number_pic]
        random.shuffle(filename)
    

    (4)开始制作和写入tfrecords文件,如果数据不够,可以通过旋转,翻转等操作进行操作再写入。这里介绍几种方式。

    m = 0
        j = 0
        if m < 6:
            for file in filename:
                if m == 1:
                    img = file[0].transpose(Image.ROTATE_90)  # 逆时针旋转90
                    img = Image.open(img, "r")
    
                elif m == 2:
                    img = file[0].transpose(Image.ROTATE_180)  # 旋转180
                    img = Image.open(img, "r")
                elif m == 3:
                    img = file[0].transpose(Image.ROTATE_270)  # 旋转270
                    img = Image.open(img, "r")
                elif m == 4:
                    img = file[0].transpose(Image.FLIP_TOP_BOTTOM)#上下翻转
                    img = Image.open(img, "r")
                elif m == 5:
                    img = file[0].transpose(Image.FLIP_LEFT_RIGHT)#水平翻转
                    img = Image.open(img, "r")
                else:
                    img = Image.open(file[0], "r")
    
                label = file[1]
                with open('./SS_50.csv', 'a+') as f:
                    f_csv = csv.writer(f)
                    f_csv.writerow([file[0],label])
                img_raw = img.tobytes()
                example = tf.train.Example(
                    features=tf.train.Features(feature={
                        'path': tf.train.Feature(bytes_list=tf.train.BytesList(value=[img_raw])),
                        'label': tf.train.Feature(int64_list=tf.train.Int64List(value=[label])),
    
                    }))
                writer.write(example.SerializeToString())  # 序列化为二进制格式
    
                if j == number_pic * 2:
                    break
                j += 1
    
                print(j, m)
    
            m += 1
    

    (5)在进行训练时,每读取一个batch_size,就利用shuffle打乱一次。
    (6)开始训练,我的训练结果如下:
    在这里插入图片描述

    注释:

    关于数据集的制作和打乱的顺序,我也尝试过先写第一类,再写第二类,这样交替的写入数据集,但是也存在相同的问题,可能在前几轮下不会出现这样的问题,但是后面还是会出现,我怀疑是这样的数据分布的太有规律,所以最后迫不得已,先随机打乱再写入。这样的处理目前实验结果来看是最好的。缺点就是需要遍历csv文件,循环比较多,处理的有点慢,欢迎各位多加改进。

    展开全文
  • 作者 |Aymeric Damien编辑|奇予纪出品 |磐创AI团队原项目 |https://github.com/aymericdamien/TensorFlow-Examples/AI学习路线之TensorFlow篇神经...这个例子使用低级方法来更好地理解构建神经网络训练过程背后...

    d5cbb196c9fe4cc8ebdd85a4f0500c67.png

    作者 |  Aymeric Damien

    编辑 | 奇予纪

    出品 | 磐创AI团队

    原项目 |  https://github.com/aymericdamien/TensorFlow-Examples/

    7a78b58fc8981a84b0e826e5feed43d0.png  AI学习路线之TensorFlow篇

    神经网络示例

    使用TensorFlow v2构建一个两层隐藏层完全连接的神经网络(多层感知器)。这个例子使用低级方法来更好地理解构建神经网络和训练过程背后的所有机制。

    神经网络概述:

    f011c8e75872416079bef71da3849382.png

    MNIST数据集概述:

    此示例使用手写数字的MNIST数据集。该数据集包含60,000个用于训练的示例和10,000个用于测试的示例。这些数字已经过尺寸标准化并位于图像中心,图像是固定大小(28x28像素),值为0到255。在此示例中,每个图像将转换为float32并归一化为[0,1],并展平为784个特征的一维数组(28 * 28)
    ccbe2b0e9be4a6056711dd29c75e2959.png

    更多信息请查看链接: http://yann.lecun.com/exdb/mnist/

    from __future__ import absolute_import, division, print_function

    import tensorflow as tf
    from tensorflow.keras import Model, layers
    import numpy as np
    # MNIST 数据集参数
    num_classes = 10 # 所有类别(数字 0-9)
    num_features = 784 # 数据特征数目 (图像形状: 28*28)

    # 训练参数
    learning_rate = 0.001
    training_steps = 2000
    batch_size = 256
    display_step = 100

    # 网络参数
    n_hidden_1 = 128 # 第一层隐含层神经元的数目
    n_hidden_2 = 256 # 第二层隐含层神经元的数目
    # 准备MNIST数据
    from tensorflow.keras.datasets import mnist
    (x_train, y_train), (x_test, y_test) = mnist.load_data()
    # 转化为float32
    x_train, x_test = np.array(x_train, np.float32), np.array(x_test, np.float32)
    # 将每张图像展平为具有784个特征的一维向量(28 * 28)
    x_train, x_test = x_train.reshape([-1, num_features]), x_test.reshape([-1, num_features])
    # 将图像值从[0,255]归一化到[0,1]
    x_train, x_test = x_train / 255., x_test / 255.
    # 使用tf.data API对数据进行随机排序和批处理
    train_data = tf.data.Dataset.from_tensor_slices((x_train, y_train))
    train_data = train_data.repeat().shuffle(5000).batch(batch_size).prefetch(1)
    # 创建 TF 模型
    class NeuralNet(Model):
        # 设置层
        def __init__(self):
            super(NeuralNet, self).__init__()
            # 第一层全连接隐含层
            self.fc1 = layers.Dense(n_hidden_1, activation=tf.nn.relu)
            # 第二层全连接隐含层
            self.fc2 = layers.Dense(n_hidden_2, activation=tf.nn.relu)
            # 全连接输出层
            self.out = layers.Dense(num_classes, activation=tf.nn.softmax)

        # 设置前向传播
        def call(self, x, is_training=False):
            x = self.fc1(x)
            x = self.out(x)
            if not is_training:
                # tf交叉熵期望输出没有softmax,所以只有
                #不训练时使用softmax。
                x = tf.nn.softmax(x)
            return x

    # 构建神经网络模型
    neural_net = NeuralNet()
    # 交叉熵损失
    # 注意这将会对输使用'softmax'
    def cross_entropy_loss(x, y):

        # 将标签转化为int64以使用交叉熵函数
        y = tf.cast(y, tf.int64)
        #将softmax应用于输出并计算交叉熵。
        loss = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=x)
        # 批的平均损失。
        return tf.reduce_mean(loss)

    # 准确率评估
    def accuracy(y_pred, y_true):
        # 预测类是预测向量中最高分的索引(即argmax)
        correct_prediction = tf.equal(tf.argmax(y_pred, 1), tf.cast(y_true, tf.int64))
        return tf.reduce_mean(tf.cast(correct_prediction, tf.float32), axis=-1)

    # 随机梯度下降优化器
    optimizer = tf.optimizers.SGD(learning_rate)
    # 优化过程
    def run_optimization(x, y):
       # 将计算封装在GradientTape中以实现自动微分
        with tf.GradientTape() as g:
            # 前向传播
            pred = neural_net(x, is_training=True)
            # 计算损失
            loss = cross_entropy_loss(pred, y)

        # 要更新的变量,即可训练的变量
        trainable_variables = neural_net.trainable_variables

        # 计算梯度
        gradients = g.gradient(loss, trainable_variables)

        # 按gradients更新 W 和 b
        optimizer.apply_gradients(zip(gradients, trainable_variables))
    # 针对给定步骤数进行训练
    for step, (batch_x, batch_y) in enumerate(train_data.take(training_steps), 1):
        # 运行优化以更新W和b值
        run_optimization(batch_x, batch_y)

        if step % display_step == 0:
            pred = neural_net(batch_x, is_training=True)
            loss = cross_entrop

            ···y_loss(pred, batch_y)
            acc = accuracy(pred, batch_y)
            print("step: %i, loss: %f, accuracy: %f" % (step, loss, acc))
    step: 100, loss: 2.031049accuracy: 0.535156
    step: 200, loss: 1.821917accuracy: 0.722656
    step: 300, loss: 1.764789accuracy: 0.753906
    step: 400, loss: 1.677593accuracy: 0.859375
    step: 500, loss: 1.643402accuracy: 0.867188
    step: 600, loss: 1.645116accuracy: 0.859375
    step: 700, loss: 1.618012accuracy: 0.878906
    step: 800, loss: 1.618097accuracy: 0.878906
    step: 900, loss: 1.616565accuracy: 0.875000
    step: 1000, loss: 1.599962accuracy: 0.894531
    step: 1100, loss: 1.593849accuracy: 0.910156
    step: 1200, loss: 1.594491accuracy: 0.886719
    step: 1300, loss: 1.622147accuracy: 0.859375
    step: 1400, loss: 1.547483accuracy: 0.937500
    step: 1500, loss: 1.581775accuracy: 0.898438
    step: 1600, loss: 1.555893accuracy: 0.929688
    step: 1700, loss: 1.578076accuracy: 0.898438
    step: 1800, loss: 1.584776accuracy: 0.882812
    step: 1900, loss: 1.563029accuracy: 0.921875
    step: 2000, loss: 1.569637accuracy: 0.902344
    # 在验证集上测试模型
    pred = neural_net(x_test, is_training=False)
    print("Test Accuracy: %f" % accuracy(pred, y_test)
    # 可视化预测
    import matplotlib.pyplot as plt
    # 从验证集中预测5张图像
    n_images = 5
    test_images = x_test[:n_images]
    predictions = neural_net(test_images)

    # 显示图片和模型预测结果
    for i in range(n_images):
        plt.imshow(np.reshape(test_images[i], [2828]), cmap='gray')
        plt.show()
        print("Model prediction: %i" % np.argmax(predictions.numpy()[i]))

    output:

    939a8babcba1b2237c4cb9ffecacccc3.png
    Model prediction: 7
    6f3f70033d3ef98951a54b429a7b3a88.png
    Model prediction:2
    51e7e663935ac419635cb28c0302696b.png
    Model prediction: 1
    8ac16a5a870ebba38c2a59f4f1c50741.png
    Model prediction: 0
    215c4de5f272a96a4d08b6b4557ce028.png
    Model prediction: 44ed80e252d58976d6089dbd2b18c70be.png

    384451bcfc52e04609e0b28387f23cd2.gif还想看更多TensorFlow2.0专栏文章?可在公众号底部菜单栏子菜单“独家原创”中找到TensorFlow2.0系列文章(如下图)同步更新中,关注公众号了解更多吧~

    ea0bdfe4eab8757bdbba1b0cbe70b04e.png

    或点击下方“阅读原文”,进入TensorFlow2.0专栏,即可查看往期文章。

    嗨,你还在看吗?
    展开全文
  • \ 里面主要的两个算法比较难以赘述,miniset主要就是求最小公共子集。(个人认为) 转载于:https://www.cnblogs.com/TheKat/p/9799923.html...
  • 卷积神经网络训练过程

    万次阅读 多人点赞 2018-09-28 14:51:05
    卷积神经网络训练过程分为两个阶段。第一个阶段是数据由低层次向高层次传播的阶段,即前向传播阶段。另外一个阶段是,当前向传播得出的结果与预期不相符时,将误差从高层次向底层次进行传播训练的阶段,即反向传播...
  • 卷积神经网络训练

    2021-01-13 21:42:01
    卷积神经网络输出的结果与我们的期望值不相符时,则进行反向传播过程。 求出结果与期望值的误差,再将误差一层一层的返回,计算出每一层的误差,然后进行权值更新。该过程的主要目的是通过训练样本和期望值来调整...
  • 卷积神经网络超详细介绍

    万次阅读 多人点赞 2018-09-19 10:16:59
    1、卷积神经网络的概念 2、 发展过程 3、如何利用CNN实现图像识别的任务 4、CNN的特征 5、CNN的求解 6、卷积神经网络注意事项 7、CNN发展综合介绍 8、LeNet-5结构分析 9、AlexNet 10、ZFNet 10.1 意义 ...
  • 卷积神经网络训练过程分为两个阶段。第一个阶段是数据由低层次向高层次传播的阶段,即前向传播阶段。另外一个阶段是,当前向传播得出的结果与预期不相符时,将误差从高层次向底层次进行传播训练的阶段,即反向传播...
  • 因此卷积神经网络就又活了起来,再开始前,我们需要明确的是网上讲的卷积神经网络的相关教程一般指的是神经网络的前向传导过程,反向传播都是用梯度下降法进行训练。一、理论阶段讲解这个算法...
  • 针对深层卷积神经网络在有限标记样本下训练时存在的过拟合和梯度弥散问题,提出一种从源模型中迁移知识训练一个深层目标模型的策略.迁移的知识包括样本的类别分布和源模型的低层特征,类别分布提供了样本的类间相关...
  • 卷积神经网络算法是n年前就有的...在开始前,我们需要明确的是网上讲的卷积神经网络的相关教程一般指的是神经网络的前向传导过程,反向传播都是用梯度下降法进行训练,大部分深度学习库,都已经把反向求导的功能给...
  • 卷积神经网络(CNN)的训练过程

    千次阅读 2018-05-09 11:46:00
    卷积神经网络训练过程 卷积神经网络训练过程分为两个阶段。第一个阶段是数据由低层次向高层次传播的阶段,即前向传播阶段。另外一个阶段是,当前向传播得出的结果与预期不相符时,将误差从高层次向底层次进行...
  • 简单卷积神经网络训练MNIST(利用GPU计算) 本篇不分享神经网络的知识,只分享pytorch下如何构建简单的卷积神经网络模型并让模型学习MNIST手写数字识别。学习和预测过程利用GPU计算减轻cpu的负担。在pytorch中,把...
  • 瑕疵品鉴定:CNN卷积神经网络本博文记录了搭建神经网络的全过程功能快捷键如何改变文本的样式设定内容居中、居左、居右SmartyPantsKaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出...
  • 四、卷积神经网络LeNet-5结构分析CNN是一种带有卷积结构的深度神经网络,通常至少有两个非线性可训练的卷积层,两个非线性的固定卷积层(又叫Pooling Layer或降采样层)和一个全连接层,一共至少5个隐含层。...
  • 理解卷积和子采样卷积过程:用一个可训练的滤波器fx去卷积一个输入的图像(第一阶段是输入的图像,后面的阶段就是卷积特征map),然后加一个偏置bx,得到卷积层Cx;子采样过程:邻域四个像素求和变为一个像素,然后...
  • # 先对网络的输出 Logits 进行 Softmax 概率化 # Cross-Entropy 每个样本的交叉熵(损失) cross_entropy_mean = tf . reduce_mean ( cross_entropy , name = 'cross_entropy' ) # 一个 batch 内样本求...
  • 深度学习是学习样本数据的内在规律和表示层次,这些学习过程中获得的信息对诸如文字,图像和声音等数据的解释有很大的帮助。因此,它在搜索技术,数据挖掘,机器学习,机器翻译,自然语言处理,多媒体学习,语音,...
  • 卷积神经网络基础 卷积神经网络:包括卷积层、池化层 二维卷积层: 最常用,用于处理图像数据,将输入和卷积核做互相关运算,并加上一个标量偏置来得到输出。 其模型参数=卷积核+标量偏置。 训练模型的时候,通常...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,064
精华内容 425
关键字:

卷积神经网络训练过程