接上篇,CNN在短文本分类中的应用遇到的一些问题/GPU/cuda/tensorflow

主要记录一些用CNN在文本分类(tensorflow)时遇到的问题/GPU、cuda等开发环境的配置问题

有一些是模型算法问题,还有一些是工具工程问题:

  • 首先,说下双gpu的安装过程(电脑组装)中的坑经历以及cuda、cudnn安装时的情况,以及tensorflow官网上不去的情况,反正好多坑啊!哈哈,感觉这一轮下来软硬通吃蛤蛤蛤。结论就是多思考,多查阅,多动手尝试摸索,毕竟那些教程也是摸索出来的

  • 接着,会说下个人对VGG、GoogLeNet、Resnet等模型的理解,因为在利用CNN进行文本分类的时候想借鉴一下他们的想法,所以看了一下,也实现了一下,暂时没有特别的好消息,和之前的87%差不多,一方面可能和样本的纯净度(70%~80%)相关,另一方面可能是在文本处理时这些模型应该有不同于图像的意义

  • 然后,会说下关于tensorflow上name_scope和variable_scope的理解,通俗解释一下,分享一个自己困扰了一段时间的小错误,这个是关于tensorflow里graph的理解

  • 顺便,分享一个tf上的好东西slim,如果不是他,我可不敢写GoogLenet和Resnet,因为代码太长了……slim封装了conv、pooling、repeat等操作,写起来跟torch差不多简洁了。这里浅薄的说一下,从代码的简洁程度,torch真是舒服多了,可惜语言冷门了(Lua)

  • 最后讨论下,文本处理和图像处理的区别,图像的原子信息是像素值,是一个有二维空间顺序的方阵,而文本的原子信息暂且看做词汇,是一个有一维空间顺序的序列,那么图像上深度学习已经那么厉害了,怎么发挥在NLP领域呢?另外大家有没发现,图像像素值空间打乱顺序可能就面目全非了,但是一个短文本就算字词顺序打乱,还是较容易理解,难道是我的错觉?


1)安装cuda的坑爹经历/“软硬”通吃的我

  1. 安装cuda之前,先来了一发双硬盘双系统(win7+Ubuntu16.04)这种东西大家去查教程,一箩筐总有一款适合你;然后买了个GTX1060(那些黄牛居然把1070、1080、1080ti给买断货了。。。)、大机箱、电源来了一个电脑组装,哈哈折腾(我是技术党,装个电脑算个啥),一个老的GTS450用来接显示器,1060用来计算咯,双GPU的存在为后来tensorflow的运行留下了一个坑!

  2. cuda的安装带着血与泪,出现最多的就是“循环登录问题”问题,试了无数的教程,还是重装多次系统(Ubuntu16.04),终于找到个好东西,https://zhuanlan.zhihu.com/p/25193943,(其实问题主要出在linux下NVIDIA驱动安装的问题,这个教程解决好重复登录的问题以后,其他教程关于cuda+cuDnn的安装都差不多),哈哈解脱!

  3. 重装系统,因为我的电脑没插网线,最麻烦的是无限网卡驱动,没网怎么破?我就是自己用手机usb连着热点装了个无线网卡,但是没有直接用系统设置(System Setting里的Software&Updates),因为他会让你更新所有需要的驱动,我的流量…所以我找到了一个好东西,只安装无线网卡驱动http://www.cnblogs.com/tcysky/p/6354118.html里我直接用sudo apt-get install –reinstall bcmwl-kernel-source ,蛤蛤蛤ok!

  4. 我就说一句,Python3.5的anaconda3版本是4.2.0,怎么来的,其实官网说的很清楚,https://docs.continuum.io/anaconda/faq#anaconda-faq-35,上面写着“A third option … version 4.2.0”,我是比较喜欢anaconda的,毕竟那么多包,安装起来太麻烦,哈哈ok!

  5. 说一下个人认为最简便的tensorflow安装:(1)conda建立环境,选择常用的python版本,conda create -n tensorflow python=3.5,(2)source activate tensorflow,(3)pip install tensorflow_gpu,(4)收工哈哈

  6. tensorflow官网上不去,解法一,自己翻墙吧,你肯定有vpn,解法二,修改hosts文件:首先修改hosts文件的权限“sudo chmod 777 /etc/hosts”,然后修改文件“vim /etc/hosts”(我是习惯用vim的),加入“64.233.188.121 www.tensorflow.org”(这些引号只是我为了排版方便,事实上不存在的),至于修改权限和修改hots文件的原理,自己百度去,哈哈!

  7. 运行tensorflow出现惊天大bug,“InternalError:Failed to create session”,原因找了好一会儿发现问题出在我的两块GPU上,我没有指定任务由哪一个GPU去执行,于是解决办法为“CUDA_VISIBLE_DEVICES=0 python xxx.py”,=1是另一个GPU,搞定,oook!

2)关于一系列大佬们网络的思路整理-LeNet/AlexNet/VGG/GoogLeNet/ResNet

1. LeNet/AlexNet/VGG

  • 先看各自的结构

    (1)首先LeNet被公认为CNN的鼻祖网络,细节自行baidu/google;
    输入为32*32的图像 ->
    6个5*5的卷积核得到6个28*28 feature map(无激活函数) ->
    Subsampling得6个14*14(2*2的视野先求和然后线性映射(wx+b)+Sigmoid) ->
    16个5*5的卷积核得16个10*10 ->
    Subsampling 得16个5*5 ->
    120个5*5的卷积核得120个1*1 ->
    全连接到84 ->
    欧式径向基函数(Euclidean Radial Basis Function)
    —一共7层,参数很少几万个,主要在16*5*5->120这一层

    (2)AlexNet基本是CNN的标配了,12年,细节http://blog.csdn.net/sunbaigui/article/details/39938097
    输入为224*224*3的图像 ->
    96个11*11的卷积核得96个55*55 feature map(ReLu) -> maxpooling得96个27*27(LRN) ->
    256个5*5的卷积核得256个27*27 (ReLu) -> maxpooling得到256个13*13 (LRN) ->
    384个3*3的卷积核得384个13*13 (ReLu)->
    384个3*3的卷积核得384个13*13 (ReLu)->
    256个3*3的卷积核得256个13*13 (ReLu)-> maxpooling得256个6*6 ->
    full connect/6*6的卷积核得4096(ReLu+dropout) ->
    full connect得4096(ReLu+dropout) ->
    full connect得1000(高斯过滤器)
    –一共8层,该模型参数大概5kw+,主要参数在256*6*6->4096和4096->4096这两层,相比之前的进步:Data Augmentation、Dropout、ReLu、LRN、Overlapping Pooling、 多GPU并行(这个666)

    (3)VGG深度学习的代表了,14年,深度你懂得,层数多;
    这个不一层一层说了,因为多,贴个链接http://www.cnblogs.com/52machinelearning/p/5821591.html,以VGG-19看下,64个3*3卷-卷(+池化)-> 128个3*3卷-卷(+池化)-> 256个3*3卷-卷-卷-卷(+池化)->512 个3*3卷-卷-卷-卷(+池化)-> 512个3*3卷-卷-卷-卷(+池化)-> 全连接4096 -> 全连接4096 -> 全连接1000,参数据说是1.4亿左右,我没数,来源http://hacker.duanshishi.com/?p=1690,与上一个Alex主要区别,哈哈,层数多在于7*7被几个3*3代替了,这里只有小卷积核,另外就是没有LRN

  • LRN与BN的对比见http://www.cnblogs.com/houkai/p/6553186.html
    计算卷积/池化之后的数据规格(padding)见http://www.jianshu.com/p/05c4f1621c7e

    这里总结一下上述网络,结构上一个套路,就是卷积层的堆叠+全连接(有没有不重要其实?),为什么后面的人比最初的LeNet参数多那么多,这计算量,哪儿来的勇气呢,GPU给的!

2. GoogLeNet/ResNet

  • 真正的变化,两次,一次是GoogLeNet(14年)

    一般来说,提升网络性能最直接的办法就是增加网络深度和宽度,这也就意味着巨量的参数。但是,巨量参数容易产生过拟合也会大大增加计算量。这就算了,据说直接继续在VGG上堆叠下去效果也不咋地了,换句话说,简单的堆叠到了瓶颈

    具体结构我不写了,很多人写过如http://blog.csdn.net/shuzfan/article/details/50738394http://blog.csdn.net/langb2014/article/details/52787095

    说改进:(1)V1 不同大小的卷积核处理后,拼接,这是宽度上的改进,原来只用一种卷积核多个,这里用几种卷积核多个,把pooling也看做一种,整体算是一个新的改进型卷积方法;(2)V1 使用1*1卷积核进行参数削减(听说效果并没有啥减弱?),参数少有啥好处?拒绝过拟合/算得快;(3)V2 ,使用小卷积核多层代替大卷积核,其实这个VGG就有这个意思;(4)V2 BN层的出现,对学习速率不敏感/抗拒过拟合/学得快;(5)V3 厉害的是n*1和1*n代替n*n,你知道参数下降了多少么,自己算!那么问题来了,会有信息缺失么,答案是据说没有,1*7、1*3…;(6)还有一个,Szegedy用了将近一页的篇幅叙述label smooth,公式就是new_labels = (1.0 - label_smoothing) * one_hot_labels + label_smoothing / num_classes,还提高一丢丢0.2%,没用过就不发言了;(7)V4 加入ResNet思想

    总的来说就是加大了网络的宽度,原始卷积->改进型卷积,本质上就是将卷积核通道比如300个,100个用3*3、100个5*5、100个1*1,原来就是直接300个3*3,再加上一些“奇技淫巧”,大卷积核的拆解、1*1的降维、BN层的加入,效果上降低了参数量(V1是几百万好像是),准确率比VGG好一些。

    其实吧,你看了前面网络参数产生的主要地方就知道,都是全连接闹得啊,所以主要是去掉了全连接层罢了,这点倒是没多么那啥。

    但是并没有解决深度的问题,只是宽度上多了花样,层数20多层吧。

  • 再一次,ResNet解决了深度的问题(15年)
    naive的增加深度是不行的,见这里http://blog.csdn.net/andrewseu/article/details/70194017,ResNet让你的深度随意飞涨,其实也可以看做一种“改进型卷积层”,可堆很多层的那种;

    其实个人角度来看,有点像GBDT,残差学习,那就是有点boosting的感觉了;这个时候再想想drop out是不是有种随机森林bagging的感觉,难道说本质上是神经网络的集成学习??黑人问号

    这个地方再联想一下,集成学习里面的stacking将训练集弱学习器的学习结果作为输入,将训练集的输出作为输出,重新训练一个学习器来得到最终结果,感觉又有点神经网络连接的味道?

    当然了,我对集成学习暂时没有啥实战经验,这都是猜想,后续玩一下Xgboost等之后继续更新吧

3) tensorflow使用的相关问题

这里可以贴一下我的新版textCNN代码,加入Inception和ResNet的思路,顺便安利一下slim这种,代码跑了一次,同样的上一版本数据,效果差不多87%~88%;扩大样本3倍多(原来23w左右,扩大到80w左右,过大会炸我内存)后效果91%~92%左右,后续改进放在大样本下分布式训练(后续技能的get)看看。

  • 先说slim,简要介绍下新的代码

    代码没想象中那么长,分两部分来吧,
    这里主要是弄了一个模块,就是残差训练多次重复的地方,这里为什么不是3*3需要往后看,就先留个疑问吧,接上文,等于是一个“改进型卷积层”,看到slim没!!?,写卷积就是一句话!一句话!一句话!

#! coding:utf-8
"""
Created on Fri Jun 30 16:41:00 2017
@author: Richard Wu
"""

import tensorflow as tf
import numpy as np
slim=tf.contrib.slim


def block35(net,scale=1.0,activation_fn=tf.nn.relu,scope=None,reuse=None):
    with tf.variable_scope(scope,'Block',[net],reuse=reuse):
        with tf.variable_scope('Branch_0'):
            tower_conv=slim.conv2d(net,32,[1,1],scope='Conv2d_1x1')
        with tf.variable_scope('Branch_1'):
            tower_conv1_0 = slim.conv2d(net, 32, [1,1], scope='Conv2d_0a_1x1')
            tower_conv1_1 = slim.conv2d(tower_conv1_0, 32, [3,1], scope='Conv2d_0b_3x1')
        with tf.variable_scope('Branch_2'):
            tower_conv2_0 = slim.conv2d(net, 32, [1,1], scope='Conv2d_0a_1x1')
            tower_conv2_1 = slim.conv2d(tower_conv2_0, 48, [3,1], scope='Conv2d_0b_3x1')
            tower_conv2_2 = slim.conv2d(tower_conv2_1, 64, [3,1], scope='Conv2d_0c_3x1')
        mixed=tf.concat(axis=3,values=[tower_conv, tower_conv1_1, tower_conv2_2])
        up=slim.conv2d(mixed,net.get_shape()[3], 1, normalizer_fn=None,
                      activation_fn=None, scope='Conv2d_1x1')
        net+=scale*up
        if activation_fn:
            net = activation_fn(net)
    return net
  • 稍微解释下,大佬看见了可以指点下

    接着往下就是网络主体了,看到没,slim的repeat,重复10层一句话,舒服!
    这里解释一下:
    (1)为什么用2*256这样的卷积核而不是2*2,因为我的猜想是不破坏词向量本身,与像素相同,我认为一个词向量是一个基本元素(有心的同学可以验证了私信我讨论),所以输出的feature都是n*1的形状,也就解释了上面block的写法;
    (2)为什么2*256,3*256的个数多一些,个人感觉小范围的组合词可能更加有意义?也算是可调节的超参吧;
    (3)整体样式为:卷积(256的那种带拼接)-卷积-maxpooling-卷积-maxpooling-mixed卷-res*10个-mixed卷-mixed卷-avgpooling*2-(flatten)全连接,后续有突破再更新

class TextCNN(object):#定义了1个TEXTCNN的类,包含一张大的graph
    """
    A CNN for text classification.
    Uses an embedding layer, followed by a convolutional, max-pooling and softmax layer.
    embedding层,卷积层,池化层,softmax层
    """
    def __init__(
      self, sequence_length, num_classes, vocab_size,
      embedding_size, filter_sizes, num_filters, l2_reg_lambda=0.0):#定义各种输入参数,这里的输入是句子各词的索引?

        # Placeholders for input, output and dropout
        self.input_x = tf.placeholder(tf.int32, [None, sequence_length], name="input_x")
        #定义一个operation,名称input_x,利用参数sequence_length,None表示样本数不定,
        #不一定是一个batchsize,训练的时候是,验证的时候None不是batchsize
        #这是一个placeholder,
        #数据类型int32,(样本数*句子长度)的tensor,每个元素为一个单词
        self.input_y = tf.placeholder(tf.float32, [None, num_classes], name="input_y")
        #这个placeholder的数据输入类型为float,(样本数*类别)的tensor
        self.dropout_keep_prob = tf.placeholder(tf.float32, name="dropout_keep_prob")
        #placeholder表示图的一个操作或者节点,用来喂数据,进行name命名方便可视化

        # Keeping track of l2 regularization loss (optional)
        l2_loss = tf.constant(0.0)
        #l2正则的初始化,有点像sum=0
        #其实softmax是需要的

        # Embedding layer
        #参见
        with tf.device('/cpu:0'), tf.name_scope("embedding"):#封装了一个叫做“embedding'的模块,使用设备cpu,模块里3个operation
            self.W = tf.Variable(
                tf.random_uniform([vocab_size, embedding_size], -1.0, 1.0),
                name="W")#operation1,一个(词典长度*embedsize)tensor,作为W,也就是最后的词向量
            self.embedded_chars = tf.nn.embedding_lookup(self.W, self.input_x)
            #operation2,input_x的tensor维度为[none,seq_len],那么这个操作的输出为none*seq_len*em_size
            self.embedded_chars_expanded = tf.expand_dims(self.embedded_chars, -1)
            #增加一个维度,变成,batch_size*seq_len*em_size*channel(=1)的4维tensor,符合图像的习惯

        # Create a convolution + maxpool layer for each filter size
        with tf.variable_scope('InceptionResnetV2'):
            with slim.arg_scope([slim.conv2d, slim.max_pool2d, slim.avg_pool2d],
                                stride=[1,1], padding='SAME'):
                padding='VALID'

                #输入batch*298*256*1,后续省略batch
                #输出149 x 1 x 192
                net0 = slim.conv2d(self.embedded_chars_expanded, 64, [1,256], stride=[2,256],normalizer_fn=slim.batch_norm,
                                scope='Conv2d_1a_1x256')
                net1 = slim.conv2d(self.embedded_chars_expanded, 96, [2,256], stride=[2,256],normalizer_fn=slim.batch_norm,
                                scope='Conv2d_1b_2x256')
                net2 = slim.conv2d(self.embedded_chars_expanded, 96, [3,256], stride=[2,256],normalizer_fn=slim.batch_norm,
                                scope='Conv2d_1c_3x256')
                net3 = slim.conv2d(self.embedded_chars_expanded, 32, [4,256], stride=[2,256],normalizer_fn=slim.batch_norm, 
                                scope='Conv2d_1d_4x256')
                net4 = slim.conv2d(self.embedded_chars_expanded, 32, [5,256], stride=[2,256],normalizer_fn=slim.batch_norm, 
                                scope='Conv2d_1e_5x256')                               
                net = tf.concat([net0, net1, net2, net3, net4], 3)

                #输出147 x 1 x 192
                net = slim.conv2d(net, 192, [3,1], padding=padding,normalizer_fn=slim.batch_norm,scope='Conv2d_2a_3x1')

                #147 x 1 x 64
                #net = slim.conv2d(net, 64, [3,1], scope='Conv2d_2b_3x1')

                #73 x 1 x 192
                net = slim.max_pool2d(net, [3,1], stride=[2,1], padding=padding,scope='MaxPool_3a_3x1')

                #73 x 1 x 80
                #net = slim.conv2d(net, 80, [1,1], padding=padding,scope='Conv2d_3b_1x1')

                #71 x 1 x 192
                net = slim.conv2d(net, 192, [3,1], padding=padding,normalizer_fn=slim.batch_norm,scope='Conv2d_4a_3x1')

                #35 x 1 x 192
                net = slim.max_pool2d(net, [3,1], stride=[2,1], padding=padding,scope='MaxPool_5a_3x1')

            #35 x 1 x 320
            with tf.variable_scope('Mixed_5b'):
                with tf.variable_scope('Branch_0'):
                    tower_conv = slim.conv2d(net, 96, [1,1], scope='Conv2d_1x1')
                with tf.variable_scope('Branch_1'):
                    tower_conv1_0 = slim.conv2d(net, 48, [1,1], scope='Conv2d_0a_1x1')
                    tower_conv1_1 = slim.conv2d(tower_conv1_0, 64, [5,1],scope='Conv2d_0b_5x1')
                with tf.variable_scope('Branch_2'):
                    tower_conv2_0 = slim.conv2d(net, 64, [1,1], scope='Conv2d_0a_1x1')
                    tower_conv2_1 = slim.conv2d(tower_conv2_0, 96, [3,1],scope='Conv2d_0b_3x1')
                    tower_conv2_2 = slim.conv2d(tower_conv2_1, 96, [3,1],scope='Conv2d_0c_3x1')
                with tf.variable_scope('Branch_3'):
                    tower_pool = slim.avg_pool2d(net, [3,1], stride=[1,1], padding='SAME',scope='AvgPool_0a_3x1')
                    tower_pool_1 = slim.conv2d(tower_pool, 64, [1,1],scope='Conv2d_0b_1x1')
                net = tf.concat([tower_conv, tower_conv1_1, tower_conv2_2, tower_pool_1], 3)

            net = slim.repeat(net, 10, block35, scale=0.17)

                         #17 x 1 x 1088
            with tf.variable_scope('Mixed_6a'):
                with tf.variable_scope('Branch_0'):
                    tower_conv = slim.conv2d(net, 384, [3,1], stride= [2,1],padding=padding,scope='Conv2d_1a_3x1')
                with tf.variable_scope('Branch_1'):
                    tower_conv1_0 = slim.conv2d(net, 256, [1,1], scope='Conv2d_0a_1x1')
                    tower_conv1_1 = slim.conv2d(tower_conv1_0, 256, [3,1],scope='Conv2d_0b_3x1')
                    tower_conv1_2 = slim.conv2d(tower_conv1_1, 384, [3,1],stride=[2,1],
                                                padding=padding,scope='Conv2d_1a_3x1')
                with tf.variable_scope('Branch_2'):
                    tower_pool = slim.max_pool2d(net, [3,1], stride=[2,1],
                                                padding=padding,scope='MaxPool_1a_3x1')
                net = tf.concat([tower_conv, tower_conv1_2, tower_pool], 3)

            #8 x 1 x 2080
            with tf.variable_scope('Mixed_7a'):
                with tf.variable_scope('Branch_0'):
                    tower_conv = slim.conv2d(net, 256, [1,1], scope='Conv2d_0a_1x1')
                    tower_conv_1 = slim.conv2d(tower_conv, 384, [3,1], stride=[2,1],
                                            padding=padding,scope='Conv2d_1a_3x1')
                with tf.variable_scope('Branch_1'):
                    tower_conv1 = slim.conv2d(net, 256, [1,1], scope='Conv2d_0a_1x1')
                    tower_conv1_1 = slim.conv2d(tower_conv1, 288, [3,1], stride=[2,1],
                                            padding=padding,scope='Conv2d_1a_3x1')
                with tf.variable_scope('Branch_2'):
                    tower_conv2 = slim.conv2d(net, 256, [1,1], scope='Conv2d_0a_1x1')
                    tower_conv2_1 = slim.conv2d(tower_conv2, 288, [3,1],scope='Conv2d_0b_3x1')
                    tower_conv2_2 = slim.conv2d(tower_conv2_1, 320, [3,1], stride=[2,1],
                                            padding=padding,scope='Conv2d_1a_3x1')
                with tf.variable_scope('Branch_3'):
                    tower_pool = slim.max_pool2d(net, [3,1], stride=[2,1],padding=padding,scope='MaxPool_1a_3x1')
                net = tf.concat([tower_conv_1, tower_conv1_1, tower_conv2_2, tower_pool], 3)

            #4 x 1 x 2080
            net=slim.avg_pool2d(net, [2,1], stride=[2,1],padding=padding,scope='Conv2d_7b_1x1')

            with tf.variable_scope('Logits'):
                net = slim.avg_pool2d(net, [4,1],stride=[4,1], padding='VALID',
                            scope='AvgPool_1a_4x1')
                net = slim.flatten(net)
            #net = slim.dropout(net, dropout_keep_prob,scope='Dropout')
            #logits = slim.fully_connected(net, num_classes, activation_fn=None,scope='Logits')

        # Add dropout
        with tf.name_scope("dropout"):
            self.h_pool_flat=net
            self.h_drop = tf.nn.dropout(self.h_pool_flat, self.dropout_keep_prob)
        #添加一个"dropout"的模块,里面一个操作,输出为dropout过后的128*192的tensor

        # Final (unnormalized) scores and predictions
        with tf.name_scope("output"):#添加一个”output“的模块,多个operation
            W = tf.Variable(
                tf.random_uniform([2080, num_classes], -1.0, 1.0),
                name='WW')
            #operation1,系数tensor,如192*2,192个features分2类,名称为"W",注意这里用的是get_variables
            b = tf.Variable(tf.constant(0.1, shape=[num_classes]), name="b")
            #operation2,偏置tensor,如2,名称"b"
            l2_loss += tf.nn.l2_loss(W)
            #operation3,loss上加入w的l2正则
            l2_loss += tf.nn.l2_loss(b)
            #operation4,loss上加入b的l2正则
            self.scores = tf.nn.xw_plus_b(self.h_drop, W, b, name="scores")
            #operation5,scores计算全连接后的输出,如[0.2,0.7]名称”scores“
            self.predictions = tf.argmax(self.scores, 1, name="predictions")
            #operations,计算预测值,输出最大值的索引,0或者1,名称”predictions“

        # CalculateMean cross-entropy loss
        with tf.name_scope("loss"):#定义一个”loss“的模块
            losses = tf.nn.softmax_cross_entropy_with_logits(logits=self.scores, labels=self.input_y)
            #operation1,定义losses,交叉熵,如果是一个batch,那么是一个长度为batchsize1的tensor?
            self.loss = tf.reduce_mean(losses) + l2_reg_lambda * l2_loss
            #operation2,计算一个batch的平均交叉熵,加上全连接层参数的正则

        # Accuracy
        with tf.name_scope("accuracy"):#定义一个名称”accuracy“的模块
            correct_predictions = tf.equal(self.predictions, tf.argmax(self.input_y, 1))
            #operation1,根据input_y和predictions是否相同,得到一个矩阵batchsize大小的tensor
            self.accuracy = tf.reduce_mean(tf.cast(correct_predictions, "float"), name="accuracy")
            #operation2,计算均值即为准确率,名称”accuracy“
  • 说下关于name_scope和variable_scope的理解
    其实吧,首先大家都用过文件夹,理解文件夹的意思,拿某一行代码来看吧,这里类似于文件夹。

    一级目录为’Block’,二级目录为’Branch_0’,三级为’Conv2d_1*1’,因而那一层卷积层的参数和操作(operation)的名称为’Block/Branch_0/Conv2d_1*1”,所以这样方便变量命名和管理,这是形象化的解释,其他的细节作用请翻看官方文档和百度。

    with tf.variable_scope(scope,'Block',[net],reuse=reuse):
        with tf.variable_scope('Branch_0'):
            tower_conv=slim.conv2d(net,32,[1,1],scope='Conv2d_1x1')
        with tf.variable_scope('Branch_1'):
            tower_conv1_0 = slim.conv2d(net, 32, [1,1], scope='Conv2d_0a_1x1')
            tower_conv1_1 = slim.conv2d(tower_conv1_0, 32, [3,1], scope='Conv2d_0b_3x1')
        with tf.variable_scope('Branch_2'):
            tower_conv2_0 = slim.conv2d(net, 32, [1,1], scope='Conv2d_0a_1x1')
            tower_conv2_1 = slim.conv2d(tower_conv2_0, 48, [3,1], scope='Conv2d_0b_3x1')
            tower_conv2_2 = slim.conv2d(tower_conv2_1, 64, [3,1], scope='Conv2d_0c_3x1')

namescope就更加简单了,就像一个文件夹,文件夹里装着几个operation

        with tf.name_scope("loss"):#定义一个”loss“的模块
            losses = tf.nn.softmax_cross_entropy_with_logits(logits=self.scores, labels=self.input_y)
            #operation1,定义losses,交叉熵,如果是一个batch,那么是一个长度为batchsize1的tensor?
            self.loss = tf.reduce_mean(losses) + l2_reg_lambda * l2_loss
            #operation2,计算一个batch的平均交叉熵,加上全连接层参数的正则
  • 这里说一个遇到的小问题,直接看代码,最下面4行,在Python里,写一句“b=np.argmax(a)”,运行的时候会执行将a的最大值索引赋给b,在tensorflow不是,使用b=tf.argmax(a)只是定义了一个图(Graph),也就是一个关系,他需要在Session里run的时候才执行上述赋值的操作。
        def dev_step(x_batch, y_batch, writer=None):
            """
            Evaluates model on a dev set
            """
            #创建一个空字典用来查看各类别准确率和召回率,{key,[value1,value2,value3]}
            #每次送进来一组label和predictions,对应key的value1、value2分别+1,若两者相同,该key的value3+1
            acc_count={}
            for i in range(num_classes):
                acc_count[i]=[0,0,0]

            #验证集太大,会爆内存,采用batch的思想进行计算,下面生成多个子验证集
            num=20
            x_batch=x_batch.tolist()
            y_batch=y_batch.tolist()
            l=len(y_batch)
            l_20=int(l/num)
            x_set=[]
            y_set=[]
            for i in range(num-1):
                x_temp=x_batch[i*l_20:(i+1)*l_20]
                x_set.append(x_temp)
                y_temp=y_batch[i*l_20:(i+1)*l_20]
                y_set.append(y_temp)
            x_temp=x_batch[(num-1)*l_20:]
            x_set.append(x_temp)
            y_temp=y_batch[(num-1)*l_20:]
            y_set.append(y_temp)

            #每个batch验证集计算一下准确率,num个batch再平均
            lis_loss=[]
            lis_accu=[]
            for i in range(num):    
                feed_dict = {
                cnn.input_x: np.array(x_set[i]),
                cnn.input_y: np.array(y_set[i]),
                cnn.dropout_keep_prob: 1.0
                }
                step, summaries, loss, accuracy, predictions = sess.run(
                    [global_step, dev_summary_op, cnn.loss, cnn.accuracy, cnn.predictions],
                    feed_dict)
                lis_loss.append(loss)
                lis_accu.append(accuracy)
                time_str = datetime.datetime.now().isoformat()
                #给字典填坑
                #label_in=np.argmax(cnn.input_y, 1)
                label_in=np.argmax(np.array(y_set[i]), 1)
                #这里不能tf.argmax,因为tf.argmax是一个operation,是图里的一个结构,并没有执行
                #这里使用np.argmax,同理不能用cnn.input_y

4)图形分类和文本分类

这里基本都是猜想了,可能有错的与不合适的,欢迎讨论和验证。

  • 图像的基本元素是像素矩阵数值,目前中文本分类来说,主要是分词之后,以词为基本元素;大胆猜想一下,能不能以字为单位或更小的有意义单位,好比词根词缀这种东西;
  • 另一方面,从向量角度,举个例子来说,很著名的word2vec中king+women-man=queen案例,如果更大胆的深层次理解,这些向量有没有基向量元素,更细致更本源的划分方式存在么?

5)Gungun结语

目前就先写这么多了,后续填的坑有
(1)模型的continous learning、online learning及distributed xxx,因为只有这样这个模型采用了实际的意义,能落地才牛皮;
(2)接下来主要的搬砖是spark上数据处理的工作,其实这个砖我还蛮期待,为什么,因为我不会spark啊,新技术什么的好东西啊!
(3)xgboost来一点实际的干货体验下,有几个同学在做,那跟一下风,看看有啥花样,深度学习与统计机器学习都是工具,理论上我得都会啊
(4)GAN,我要生成滚滚100号的照片!!!
哟,好多坑,千金难买我乐意!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值