澳门新浦京8455com但以此看似形参的花色,请在该项目中落到实处贰个力所能致得到栈最小元素的min函数

澳门新浦京8455com 9

澳门新浦京8455com 1

平台:
1.windows 10 64位
2.Anaconda3-4.2.0-Windows-x86_64.exe
(当时TF还不支持python3.6,又懒得在高版本的anaconda下配置多个Python环境,于是装了一个3-4.2.0(默认装python3.5),建议装anaconda3的最新版本,TF1.2.0版本已经支持python3.6!)
3.TensorFlow1.1.0

2.6 SVM 与 Softmax

这个比较很有意思,就像在用到分类算法的时候,就会想SVM还是logistic
regression呢一样。 
我们先用一张图来表示从输入端到分类结果,SVM和Softmax都做了啥: 

 澳门新浦京8455com 2

区别就是拿到原始像素数据映射得到的得分之后的处理,而正因为处理方式不同,我们定义不同的损失函数,有不同的优化方法。

18.二叉树的镜像

操作给定的二叉树,将其变换为源二叉树的镜像。
澳门新浦京8455com 3

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public void Mirror(TreeNode root) {
        if(root != null){
            TreeNode temp = root.left;
            root.left = root.right;
            root.right = temp;
            if(root.left!=null) Mirror(root.left);
            if(root.right!=null) Mirror(root.right);
        }
    }
}

我在尝试对一个基于tf版keras的深度学习训练网络进行损失函数改写的时候发现,在loss函数中,传递过来的输入图像,不是一个具体的值,而是一个类似形参的类型:因为我之后的处理是将输入图片转为一个矩阵,用opencv操作,但这个类似形参的类型,无法进行该操作。请问各位有没有什么办法,将loss中的输入图片变成能print出一个具体矩阵的类型?

函数总结(续上篇)

sess = tf.InteractiveSession() 将sess注册为默认的session
tf.placeholder() ,
Placeholder是输入数据的地方,也称为占位符,通俗的理解就是给输入数据(此例中的图片x)和真实标签(y_)提供一个入口,或者是存放地。(个人理解,可能不太正确,后期对TF有深入认识的话再回来改~~)
tf.Variable()
Variable是用来存储模型参数,与存储数据的tensor不同,tensor一旦使用掉就消失
tf.matmul() 矩阵相乘函数
tf.reduce_mean 和tf.reduce_sum
是缩减维度的计算均值,以及缩减维度的求和
tf.argmax() 是寻找tensor中值最大的元素的序号 ,此例中用来判断类别
tf.cast() 用于数据类型转换
————————————–我是分割线(一)———————————–
tf.random_uniform 生成均匀分布的随机数
tf.train.AdamOptimizer() 创建优化器,优化方法为Adam(adaptive moment
estimation,Adam优化方法根据损失函数对每个参数的梯度的一阶矩估计和二阶矩估计动态调整针对于每个参数的学习速率)
tf.placeholder
“占位符”,只要是对网络的输入,都需要用这个函数这个进行“初始化”
tf.random_normal 生成正态分布
tf.add 和 tf.matmul 数据的相加 、相乘
tf.reduce_sum 缩减维度的求和
tf.pow 求幂函数
tf.subtract 数据的相减
tf.global_variables_initializer 定义全局参数初始化
tf.Session 创建会话.
tf.Variable
创建变量,是用来存储模型参数的变量。是有别于模型的输入数据的
tf.train.AdamOptimizer (learning_rate = 0.001)
采用Adam进行优化,学习率为 0.001
————————————–我是分割线(二)———————————–

  1. hidden1_drop = tf.nn.dropout(hidden1, keep_prob) 给
    hindden1层增加Droput,返回新的层hidden1_drop,keep_prob是
    Droput的比例
  2. mnist.train.next_batch() 来详细讲讲
    这个函数。一句话概括就是,打乱样本顺序,然后按顺序读取batch_size 个样本
    进行返回。
    具体看代码及其注释,首先要找到函数定义,在tensorflowcontriblearnpythonlearndatasets
    下的mnist.py
    ————————————–我是分割线(三)———————————–
  3. tf.nn.conv2d(x, W, strides = [1, 1, 1, 1], padding
    =’SAME’)对于这个函数主要理解
    strides和padding,首先明确,x是输入,W是卷积核,并且它们的维数都是4(发现strides里有4个元素没,没错!就是一一对应的)
    先说一下卷积核W也是一个四维张量,各维度表示的信息是:[filter_height,
    filter_width, in_channels, out_channels]

输入x,x是一个四维张量 ,各维度表示的信息是:[batch, in_height,
in_width, in_channels]

strides里的每个元素就是对应输入x的四个维度的步长,因为第2,3维是图像的长和宽,所以平时用的strides就在这里设置,而第1,4维一般不用到,所以是1

padding只有两种取值方式,一个是 padding=[‘VALID’]
一个是padding=[‘SAME’]
valid:采用丢弃的方式,只要移动一步时,最右边有超出,则这一步不移动,并且剩余的进行丢弃。如下图,图片长13,卷积核长6,步长是5,当移动一步之后,已经卷积核6-11,再移动一步,已经没有足够的像素点了,所以就不能移动,因此
12,13被丢弃。
same:顾名思义,就是保持输入的大小不变,方法是在图像边缘处填充全0的像素
————————————–我是分割线(四)———————————–
1.tf.nn.l2_loss()是对一个Tensor对象求L2 norm,这里用来求权值的L2范数
2.tf.add_to_collection(‘losses’, weight_loss), 把weight_loss
加到名为losses的loss中去
3.tf.nn.lrn,做局部相应归一化,来看看函数的定义

lrn(input, depth_radius=None, bias=None, alpha=None,
beta=None,name=None)

函数有6个输入,第一个自然是输入啦,2-5是LRN用到的参数,第一个是depth半径,bias
alpha beta是相应的参数,来看看伪代码就清楚了

sqr_sum[a, b, c, d] = sum(input[a, b, c, d – depth_radius : d +
depth_radius + 1] ** 2)
output = input / (bias + alpha * sqr_sum) ** beta
2-5的参数是有默认值的,分别是5,1,1,0.5

3.tf.nn.sparse_softmax_cross_entropy_with_logits()就是计算交叉熵的,但是如果是一个batch的,得出的是一个向量,还需要配合tf.reduce_mean()才能计算得出最终的loss(标量)

4.tf.get_collection(‘losses’),
从一个集合中取出全部变量,返回的是一个列表,这里是把losses的都取出来,在上面把
weight_loss和输出层的loss都加到losses中了,这个函数就是把losses中的loss取出来

5.tf.add_n:把一个列表的东西都依次加起来 (Adds all input tensors
element-wise.) 输入是一个list (inputs: A list of Tensor objects, each
with same shape and type.)
————————————–我是分割线(五)———————————–

1.t.get_shape().as_list() ,t是一个tensor,函数以list的形式返回
tensor的shape
2.tf.name_scope(‘conv1’) as scope
,tf.name_scope是用来命名Variable的,print(parameters)可以看到命名

  1. tf.Graph().as_default()能够在这个上下文里面覆盖默认的图,测试了一下
    不用这个也可以,但是用上好点,可能是避免冲突吧~
    ————————————–我是分割线(六)———————————–
  2. tensor.get_shape()[-1].value 获得 倒数第一个维度上的维数
  3. tf.get_variable(scope+’w’,
    shape = [kh, kw, n_in, n_out], dtype = tf.float32,
    initializer = tf.contrib.layers.xavier_initializer_conv2d())
    来看看函数定义:

    def get_variable(name,

                  shape=None,
                  dtype=None,
                  initializer=None,
                  regularizer=None,
                  trainable=True,
                  collections=None,
                  caching_device=None,
                  partitioner=None,
                  validate_shape=True,
                  use_resource=None,
                  custom_getter=None):
    

这下就清楚多了,除了第一个形参,其余都是带默认值的关键字参数,这样不根据参形参的顺序对参数赋值啦

3.tf.nn.relu_layer(input_op, kernel, biases, name = scope)
这个函数把 卷积操作,加偏置操作,relu操作
集成在一块儿了,不过这个仅限于全连接层这种一维的层,因为输入必须是2D的,具体如下:

def relu_layer(x, weights, biases, name=None):
Args:
x: a 2D tensor. Dimensions typically: batch, in_units
weights: a 2D tensor. Dimensions typically: in_units, out_units
biases: a 1D tensor. Dimensions: out_units
name: A name for the operation (optional). If not specified
“nn_relu_layer” is used.
Returns:
A 2-D Tensor computing relu(matmul(x, weights) + biases).
Dimensions typically: batch, out_units.

2.2.4 关于数据的预处理

插播一段,实际应用中,我们很多时候并不是把原始的像素矩阵作为输入,而是会预先做一些处理,比如说,有一个很重要的处理叫做『去均值』,他做的事情是对于训练集,我们求得所有图片像素矩阵的均值,作为中心,然后输入的图片先减掉这个均值,再做后续的操作。有时候我们甚至要对图片的幅度归一化/scaling。去均值是一个非常重要的步骤,原因我们在后续的梯度下降里会提到。

20 包含min函数的栈

定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。

import java.util.Stack;

public class Solution {

    Stack<Integer> stack = new Stack<Integer>();
    Stack<Integer> minStack = new Stack<Integer>();
    int min;
    public void push(int node) {
        stack.push(node);
        if(minStack.empty())
            min = node;
        else
            min = Math.min(minStack.peek(),node);
        minStack.push(min);
    }

    public int pop() {
        minStack.pop();
        return stack.pop();
    }

    public int top() {
        return stack.peek();
    }

    public int min() {
        return minStack.peek();
    }
}

牛津大学计算机视觉组(Visual Geometry Group)出产的VGGnet是 ILSVRC
2014年
分类第二名,定位项目第一名,其VGG-16VGG-19广泛应用于图像领域!
论文《very deep convolutional networks for large-scale image
recognition》
特点就是多个小卷积核(3*3)的堆叠来替代大卷积核(5*5,7*7),减少参数的同时增加了特征提取的能力。

2.5.1 信息论角度的理解

对于两个概率分布p(“真实的概率分布”)和估测的概率分布q(估测的属于每个类的概率),它们的互熵定义为如下形式:

 澳门新浦京8455com 4

而Softmax分类器要做的事情,就是要最小化预测类别的概率分布(之前看到了,是澳门新浦京8455com 5与『实际类别概率分布』(p=[0,…1,…,0],只在结果类目上是1,其余都为0)两个概率分布的交叉熵

另外,因为互熵可以用熵加上KL距离/Kullback-Leibler
Divergence(也叫相对熵/Relative
Entropy)来表示,即澳门新浦京8455com 6,而p的熵为0(这是一个确定事件,无随机性),所以互熵最小化,等同于最小化两个分布之间的KL距离。换句话说,交叉熵想要从给定的分布q上预测结果分布p

==19.顺时针打印矩阵(这道题有难度)==

==见书P161==

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

# -*- coding: utf-8 -*-
"""
Created on Mon Jun 12 16:36:43 2017

@author: ASUS
"""
from datetime import datetime
import math
import time
import tensorflow as tf

# 定义函数对卷积层进行初始化
# input_op : 输入数据 
# name : 该卷积层的名字,用tf.name_scope()来命名
# kh,kw : 分别是卷积核的高和宽
# n_out : 输出通道数
# dh,dw : 步长的高和宽
# p : 是参数列表,存储VGG所用到的参数
# 采用xavier方法对卷积核权值进行初始化
def conv_op(input_op, name, kh, kw, n_out, dh, dw, p):
    n_in = input_op.get_shape()[-1].value # 获得输入图像的通道数
    with tf.name_scope(name) as scope:
        kernel = tf.get_variable(scope+'w',
            shape = [kh, kw, n_in, n_out], dtype = tf.float32,
            initializer = tf.contrib.layers.xavier_initializer_conv2d())
        #  卷积层计算
        conv = tf.nn.conv2d(input_op, kernel, (1, dh, dw, 1), padding = 'SAME')
        bias_init_val = tf.constant(0.0, shape = [n_out], dtype = tf.float32)
        biases = tf.Variable(bias_init_val, trainable = True, name = 'b')
        z = tf.nn.bias_add(conv, biases)
        activation = tf.nn.relu(z, name = scope)
        p += [kernel, biases]
        return activation

# 定义函数对全连接层进行初始化
# input_op : 输入数据
# name : 该全连接层的名字
# n_out : 输出的通道数
# p : 参数列表 
# 初始化方法用 xavier方法
def fc_op(input_op, name, n_out, p):
    n_in = input_op.get_shape()[-1].value

    with tf.name_scope(name) as scope:
        kernel = tf.get_variable(scope+'w',
            shape = [n_in, n_out], dtype = tf.float32,
            initializer = tf.contrib.layers.xavier_initializer())
        biases = tf.Variable(tf.constant(0.1, shape = [n_out],
            dtype = tf.float32), name = 'b')
        activation = tf.nn.relu_layer(input_op, kernel,  #  ???????????????
            biases, name = scope)
        p += [kernel, biases]
        return activation 

# 定义函数 创建 maxpool层
# input_op : 输入数据 
# name : 该卷积层的名字,用tf.name_scope()来命名
# kh,kw : 分别是卷积核的高和宽
# dh,dw : 步长的高和宽
def mpool_op(input_op, name, kh, kw, dh, dw):
    return tf.nn.max_pool(input_op, ksize = [1,kh,kw,1],
        strides = [1, dh, dw, 1], padding = 'SAME', name = name)

#---------------创建 VGG-16------------------

def inference_op(input_op, keep_prob):
    p = []
    # 第一块 conv1_1-conv1_2-pool1
    conv1_1 = conv_op(input_op, name='conv1_1', kh=3, kw=3,
                n_out = 64, dh = 1, dw = 1, p = p)
    conv1_2 = conv_op(conv1_1, name='conv1_2', kh=3, kw=3,
                n_out = 64, dh = 1, dw = 1, p = p)
    pool1 = mpool_op(conv1_2, name = 'pool1', kh = 2, kw = 2,
                dw = 2, dh = 2)
    # 第二块 conv2_1-conv2_2-pool2
    conv2_1 = conv_op(pool1, name='conv2_1', kh=3, kw=3,
                n_out = 128, dh = 1, dw = 1, p = p)
    conv2_2 = conv_op(conv2_1, name='conv2_2', kh=3, kw=3,
                n_out = 128, dh = 1, dw = 1, p = p)
    pool2 = mpool_op(conv2_2, name = 'pool2', kh = 2, kw = 2,
                dw = 2, dh = 2)
    # 第三块 conv3_1-conv3_2-conv3_3-pool3
    conv3_1 = conv_op(pool2, name='conv3_1', kh=3, kw=3,
                n_out = 256, dh = 1, dw = 1, p = p)
    conv3_2 = conv_op(conv3_1, name='conv3_2', kh=3, kw=3,
                n_out = 256, dh = 1, dw = 1, p = p)
    conv3_3 = conv_op(conv3_2, name='conv3_3', kh=3, kw=3,
                n_out = 256, dh = 1, dw = 1, p = p)
    pool3 = mpool_op(conv3_3, name = 'pool3', kh = 2, kw = 2,
                dw = 2, dh = 2)
    # 第四块 conv4_1-conv4_2-conv4_3-pool4
    conv4_1 = conv_op(pool3, name='conv4_1', kh=3, kw=3,
                n_out = 512, dh = 1, dw = 1, p = p)
    conv4_2 = conv_op(conv4_1, name='conv4_2', kh=3, kw=3,
                n_out = 512, dh = 1, dw = 1, p = p)
    conv4_3 = conv_op(conv4_2, name='conv4_3', kh=3, kw=3,
                n_out = 512, dh = 1, dw = 1, p = p)
    pool4 = mpool_op(conv4_3, name = 'pool4', kh = 2, kw = 2,
                dw = 2, dh = 2)
    # 第五块 conv5_1-conv5_2-conv5_3-pool5
    conv5_1 = conv_op(pool4, name='conv5_1', kh=3, kw=3,
                n_out = 512, dh = 1, dw = 1, p = p)
    conv5_2 = conv_op(conv5_1, name='conv5_2', kh=3, kw=3,
                n_out = 512, dh = 1, dw = 1, p = p)
    conv5_3 = conv_op(conv5_2, name='conv5_3', kh=3, kw=3,
                n_out = 512, dh = 1, dw = 1, p = p)
    pool5 = mpool_op(conv5_3, name = 'pool5', kh = 2, kw = 2,
                dw = 2, dh = 2)
    # 把pool5 ( [7, 7, 512] )  拉成向量
    shp  = pool5.get_shape()
    flattened_shape = shp[1].value * shp[2].value * shp[3].value
    resh1 = tf.reshape(pool5, [-1, flattened_shape], name = 'resh1')

    # 全连接层1 添加了 Droput来防止过拟合    
    fc1 = fc_op(resh1, name = 'fc1', n_out = 2048, p = p)
    fc1_drop = tf.nn.dropout(fc1, keep_prob, name = 'fc1_drop')

    # 全连接层2 添加了 Droput来防止过拟合    
    fc2 = fc_op(fc1_drop, name = 'fc2', n_out = 2048, p = p)
    fc2_drop = tf.nn.dropout(fc2, keep_prob, name = 'fc2_drop')

    # 全连接层3 加一个softmax求给类别的概率
    fc3 = fc_op(fc2_drop, name = 'fc3', n_out = 1000, p = p)
    softmax = tf.nn.softmax(fc3)
    predictions = tf.argmax(softmax, 1)
    return predictions, softmax, fc3, p

# 定义评测函数

def time_tensorflow_run(session, target, feed, info_string):
    num_steps_burn_in = 10
    total_duration = 0.0
    total_duration_squared = 0.0

    for i in range(num_batches + num_steps_burn_in):
        start_time = time.time()
        _ = session.run(target, feed_dict = feed)
        duration = time.time() - start_time
        if i >= num_steps_burn_in:
            if not i  % 10: 
                print('%s: step %d, duration = %.3f' % 
                    (datetime.now(), i-num_steps_burn_in, duration))
            total_duration += duration
            total_duration_squared += duration * duration
    mean_dur = total_duration / num_batches 
    var_dur = total_duration_squared / num_batches - mean_dur * mean_dur
    std_dur = math.sqrt(var_dur)
    print('%s: %s across %d steps, %.3f +/- %.3f sec / batch' %(datetime.now(), info_string, num_batches, mean_dur, std_dur))

# 定义函数 运行网络
def run_benchmark():
    with tf.Graph().as_default():
        image_size = 224
        images = tf.Variable(tf.random_normal(
            [batch_size, image_size, image_size, 3],
            dtype = tf.float32, stddev = 1e-1))

        keep_prob = tf.placeholder(tf.float32)
        predictions, softmax, fc3, p = inference_op(images, keep_prob)

        # 创建session ,初始化参数
        init = tf.global_variables_initializer()
        sess = tf.Session()
        sess.run(init)

        # 评测  forward的耗时
        time_tensorflow_run(sess, predictions, {keep_prob: 1.0}, 'Forward')
        # 评测 forward 和 backward 
        objective = tf.nn.l2_loss(fc3)
        gard = tf.gradients(objective, p)
        time_tensorflow_run(sess,gard,predictions, {keep_prob: 0.5}, 'Forward-backward')

batch_size = 16
num_batches = 100
run_benchmark() 

2.4 一些现实的考虑点

知识点:

关于值传递和引用传递可以得出这样的结论:

  1. 基本数据类型传值,对形参的修改不会影响实参;
  2. 引用类型传引用,形参和实参指向同一个内存地址(同一个对象),所以对参数的修改会影响到实际的对象;
  3. String, Integer,
    Double等immutable的类型特殊处理,可以理解为传值,最后的操作不会修改实参对象。

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printMatrix(int [][] matrix) {
        if(matrix == null) return null;
        ArrayList<Integer> result = new ArrayList<>();
        int start = 0;
        while(start*2<matrix.length&&start*2<matrix[0].length){
            printMatrixCircle(matrix,start,result);
            start++;
        }
       return result;
    }
    public void printMatrixCircle(int [][] matrix,int start,ArrayList<Integer> result){
        int endX = matrix[0].length - 1 - start;
        int endY = matrix.length - 1 - start;
        for(int i = start;i <= endX;i++){
            result.add(matrix[start][i]);
        }
        if(start < endY){
            for(int i = start +1;i <= endY;i++)
                result.add(matrix[i][endX]);
        }
        if(start<endX&&start<endY)
            for(int i = endX -1;i>=start;i--)
                result.add(matrix[endY][i]);
        if(start<endX&&start<endY-1)
            for(int i = endY -1;i>start;i--)
                result.add(matrix[i][start]);
    }
}

主要内容:
1.CNN之VGG-net的测试
2.该实现中的函数总结

2.2 理解线性分类器

我们想想,其实线性分类器在做的事情,是对每个像素点的三个颜色通道,做计算。咱们拟人化一下,帮助我们理解,可以认为设定的参数/权重不同会影响分类器的『性格』,从而使得分类器对特定位置的颜色会有自己的喜好

举个例子,假如说我们的分类器要识别『船只』,那么它可能会喜欢图片的四周都是蓝色(通常船只是在水里海里吧…)。

我们用一个实际的例子来表示这个得分映射的过程,大概就是下图这个样子:

澳门新浦京8455com 7

原始像素点向量xi经过W和b映射为对应结果类别的得分澳门新浦京8455com 8。不过上面这组参数其实给的是不太恰当的,因为我们看到在这组参数下,图片属于狗狗的得分最高
-_-||

来看看论文中给了5个模型的基本情况:
澳门新浦京8455com 9

2.5.4 关于softmax这个名字的一点说明

准确地说,SVM分类器使用hinge loss(有时候也叫max-margin
loss)。而Softmax分类器使用交叉熵损失/cross-entropy
loss
。Softmax分类器从softmax函数(恩,其实做的事情就是把一列原始的类别得分归一化到一列和为1的正数表示概率)得到,softmax函数使得交叉熵损失可以用起来。而实际上,我们并没有softmax
loss
这个概念,因为softmax实质上就是一个函数,有时候我们图方便,就随口称呼softmax
loss。

You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图