MNIST神经网络

主要参考 : tensorflow 中文社区

简介

MNIST是一个入门级的计算机视觉数据集,它包含各种手写数字图片:

在此教程中,我们将训练一个机器学习模型用于预测图片里面的数字.

数据集

数据集的下载和安装本来可以用 tensorflow 社区提供的一份python代码来完成. 可惜链接是指向google 的网盘的, 我手上暂时也没可用的梯子, 只好百度了一份 input_data.py, 然而这份代码年代已经十分久远, 已经不适合现在版本的numpy了, 所以我又只能下载安装一份旧的numpy pip install numpy==1.16.0. But 又因为在国内连接pypi也十分的慢, socket会报 time out 错误, 我又只能换了下douban的镜像pip install redis -i https://pypi.douban.com/simple. 这下才算解决了数据集的问题(苦笑).

在使用中, 需要把input_data.pyimport进 python 的主程序中, 如果数据集没有被提前下载, 那么在运行时会调用input_data中的函数下载数据集. 建议先提前下载好数据集放置在固定的目录下, 可以避免运行时下载速度太慢的问题.

实际使用中的数据集会被分为两部分, 60000行的训练数据集(mnist.train)和10000行的测试数据集(mnist.test). 有了这个单独用来测试而不会用于训练的数据集会使模型更容易推广到其他数据集上(泛化).

而每一组数据单元包含一个手写图片和一个对应的标签的数据. 所有图片的数据可以由一个形状为[60000, 784]的张量来表示, 第一个维度当做图片的索引. 所有标签的数据用张量[60000,10]来表示. 且此处的10维向量是独热的, 代表 0 - 9 十种可能.

softmax回归

目标: 求得每个像素对于特定数字类的权值, 即得到一张给定图片属于某个特定数字类的证据(evidence), 证据值越大, 证明越有可能是这个数字类.

对于给定的输入图片 x 它代表的是数字 i 的证据可以表示为:
$$
evidence_i = \sum_j W_{i,j} + b_i
$$
其中$W_i$ 代表权重, $b_i$代表数字 i 类的偏置量, j 代表给定图片 x 的像素索引用于像素求和. 然后用softmax函数可以把这些证据转换成概率 y:
$$y = softmax(evidence)$$

可以看成是一个激励(activation)函数, 把我们定义的线性函数的输出转换成我们想要的格式, 也就是关于10个数字类的概率分布.

$$
\begin{aligned}
softmax(x) &= normalize(exp(x)) \
softmax(x)_i &= \cfrac{exp(x_i)}{\Sigma_jexp(x_j)}
\end{aligned}
$$

此处的normalize()为归一化, 归一化就是要把需要处理的数据经过处理后(通过某种算法)限制在你需要的一定范围内, 可以方便后面数据处理的方便, 其次是保证程序运行时的概率分布.

回归模型可以用下面的图解释:

第三张图的 W 矩阵即为权重值矩阵. 此处矩阵相乘的形式与下面 tf 的代码十分相似.

这里公式其实是单就一张图片而言. x1,x2,x3代表了 x 的第 1,2,3 个像素. 将矩阵乘法展开后就成了加权求和的形式. 不过在实际中, 图片是有 784 个像素的, 输出的向量元素个数也应该为10, 所以严格来说公式应该是这个样子.

目前为止这个模型的思想似乎很清晰了, 但是 softmax 回归 在这里究竟是什么作用还是有些不明朗, 不过我大致猜测其实 softmax 与模型参数 W 和 b 的确定并没有太大的关系, 它在这里主要的作用是将计算结果映射到 [0,1] 的区间上, 使结果作为概率值是有意义的. 在神经网络上, softmax 也是作用在最后一层. 综上, softmax 的作用是对模型输出的一层 “约束”.

模型设定

我所理解的模型设定这部分就是使用 tensorflow 的语言描述出数学模型的公式的过程. 这里所需要描述的公式如上图所示.

根据公式, 我们在代码中需要实现的有 tensorflow变量 x 和 y分别用来存储输入的数据和模型输出的数据, 并且还有 权重矩阵W 和 偏置量b.
还需要在程序中设定好使用的模型为 softmax 回归.

训练模型

交叉熵(cross-entropy)成本函数.
$$
H_{y’}(y) = -\sum_i y^{‘}_ilog(y_i)
$$
其中 y 是预测的概率分布, y’ 是实际的分布(输入的 one-hot vector, 这里输入为独热的向量也是为了和模型的输出的形式相同.).

交叉熵代表了模型计算结果中的损失(loss), 也就是说交叉熵越大, 那么计算结果的误差也就越大.

代码中要求TensorFlow用梯度下降算法以 0.01 的学习速率最小化交叉熵. 使用随机梯度的下降训练的意义在于, 在每一步训练时不使用所有的数据, 而是选取其中的子集来节省计算的开销. 在每一步的计算中, tensorflow 会自动使用反向传播算法(backpropagation algorithm)来不断降低 loss 的值. 我在网上找到了反向传播算法的介绍, 其原理大致为 : 当输入的数据集相同时, 损失函数的值 C 可以看做是关于 权重矩阵W 和 偏置量b 的二元函数. 也就是 $C = f(W,b)$, 当 C 的值最小时, 周围的函数是平滑的(也有不是的情况), 也就相当于偏导数为 0.
$$
\begin{aligned}
&\cfrac{\partial C}{\partial W} = 0 \
&\cfrac{\partial C}{\partial b} = 0
\end{aligned}
$$
经过多轮迭代使参数 W 和 b 达到接近这样的状态时, 梯度下降的一步就完成了. 但是具体每步的步长是多少要根据学习速率和步长来计算.

模型评估

模型评估的方法比较简单, 就是用 minst.test 中的数据, 将图片的数据输入到训练好的模型中, 然后调用 tf 中的函数与标签中的结果进行比对算出正确率. 这里的 test 数据应该与 train 中的数据不能有重合.

完整代码和我的注释

input_data.py 可以在百度上搜到, 就不贴在这里了.

MNIST.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import tensorflow as tf
import input_data

# 用 input_data.py 中的代码导入需要的数据集
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

### 模型构建 ####
x = tf.placeholder("float", [None, 784])
W = tf.Variable(tf.zeros([784,10])) # W 权重矩阵
b = tf.Variable(tf.zeros([10])) # b 偏置量
y = tf.nn.softmax(tf.matmul(x,W)+b) # y 输出值, 同时指出了模型为 softmax

### 训练模型以及评估 ####
y_ = tf.placeholder("float",[None,10]) # y_
cross_entropy = -tf.reduce_sum(y_*tf.log(y)) # 交叉熵, 符合上面的交叉熵公式
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy) # 使用随机梯度下降算法最小化交叉熵
init = tf.global_variables_initializer()
sess = tf.Session() # sess 为 session, tf 中一切 Variable 的操作都需要用session 来控制
sess.run(init) # 初始化后所有的 Variable 才能使用

for i in range(1000):
# 随机抓取 100 组数据作为一次训练的数据集. 再迭代训练 1000 次, 这样会利用上100_000组数据
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1)) # 返回一组boolean值代表正确的预测
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) # 将boolean值转为百分率
print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})) # 输出正确率

总结

这个 MNIST 的项目是 tensorflow中文社区 介绍的深度学习领域中的 “Hellowrold”, 用来练手应该是非常合适的, 这也是我第一次使用tensorflow. 被它的强大所震撼.(上面的代码样例实际运行时间不会超过 3 秒钟). 而且这个项目代表了机器学习中一个十分经典的问题 – 多分类问题.

当读懂了教程后, 会发现整个项目的构建思路其实是无比清晰的, 从问题的数据集的数学表示, 到设计数学模型描述实际问题中数据的关系, 再到将数学模型用代码实现已经选择训练模型的策略和评估方法, 在思路上十分顺畅. 这种设计思路我觉得对将来我自己的项目十分有借鉴意义. 只可惜我的数学底子在浩瀚的数学公式面前显得实在是微不足道, 无法深入的探究数学公式的原理. 在这里立个flag, 寒假在学习深度学习和tensorflow时也要尽最大努力补充数学和概率论的知识, 只有这样才能从更底层的角度深入的理解深度学习.

MINST卷积神经网络

上面的MINST例子有91%的正确率, 下面将使用卷积神经网络来改善效果.

卷积

卷积网络(也叫做卷积神经网络), 是指那些至少在网络的一层中使用卷积运算来代替一般的矩阵乘法运算的神经网络. 卷积是一种特殊的线性运算. 卷积网络是一种专门用来处理具有类似网络结构的数据的神经网络, 例如时间序列数据和二维的像素网络.

假设 x(t) 是某传感器传来的测量结果.
采用一个有效的概率密度函数(也算是一种加权函数)$W(a)$, a 表示距离某个特定自变量的距离大小, 对自变量的定义域的任意值均采用这种加权平均的操作, 就有
$$s(t) = \int x(a)w(t-a)da$$
这里 a 是当前时刻t之前的某个时刻. x 是输入(input), 第二个参数 w 叫做核函数. 输出有时被称作特征映射. 这种运算就叫做卷积. 用星号表示:
$$s(t) = (x * w)(t)$$
对于离散数据的二维卷积运算, 上述积分可以简化为
$$S(i,j)=(I * K)(i,j)=\sum_m \sum_nI(m,n)K(i-m,j-n)$$
因为卷积是可交换(翻转)的, 所以等价于
$$S(i,j)=(K * I)(i,j)=\sum_m \sum_nI(i-m,j-n)K(m,n)$$
许多神经网络库会实现一个相关的函数, 称为互相关函数, 和卷积运算一样但是没有对核翻转.
$$S(i,j)=(I*K)(i,j)=\sum_m\sum_nI(i+m,j+n)K(m,n)$$
下面是个 2 维卷积的例子.

池化

如何理解CNN中的池化?.
我的通俗的理解: 池化用来提取一个张量中的最具有特征的值, 可能是最大值, 也可能是最小值或者平均值. 池化的意义在于可以在保持数据较少损失的同时减少数据规模, 降低运算成本.

卷积神经网络

下面要构建整个项目的网络结构. 总的来说分为 5 层, 分别是 第一层卷积运算, 第二层卷积运算, 第三层为全连接层, 第四层为 Dropout 层,最后一层为 softmax 输出层. 因为包含了卷积运算, 所以这个神经网络也是卷积神经网络. 这四层网络都有各自的作用.

第一层卷积层.

第一层卷积=层直接对图片的原始数据进行处理, 作用是要对图片特征进行初步的提取. 在这层卷积中, 设定 filter(核) 的大小为 $5\times5$, 并每次提取出一个长度为 32 的向量.

为了符合tensorflow中卷积运算函数的格式要求, 将图片的张量形状设定为$x = [-1,28,28,1]$, 这里的 -1 代表未设定(因为图片数量不固定), 第二三个维度代表图片的长和宽, 第四个维度代表了颜色通道数, 因为数据集是灰度图, 所以只有一个维度, 如果是rgb图像那么就有三个维度. 可以把这个输入的 x 张量想象为 一摞叠起来的照片(具有厚度). 同时将 filter1 的张量形状设定为$[5,5,1,32]$, 这里第三个维度的 1 与图书数据的通道数对应. 我将其理解为长度为 1 的输入向量, 计算结果为长度为 32 的输出向量. 那么偏置量显然也要设定为长度为 32 的向量.

根据卷积运算的定义, 可以确定这里的 $result_1 = (x*filter1) + b$ 的结果是个形状为 $[28,28,32]$ 的张量.

但是这层卷积中还包括了池化. 这个项目中使用的是 max_pool, 直观的理解应该就是提取最明显的特征作为下一层的输入数据. 这里定义池化的模板大小为$2\times2$, 步长为 1, 边距为 0, 并且下面几层的池化均为这个设定. 这样每次池化会将相邻且不重叠的 $2\times2$ 个元素作为一个 padding, 提取出其中最”大”的数据保留, 其余数据删掉. 这里何为最大我不清楚, 有可能是向量的模长, 也可能是别的, 但是一定是最能反映图像特征的. 总之经过这样一层处理, 我们的数据先是被”挖掘”出更多的特征(卷积后的结果让数据长度由1变为32), 然后又经过”提炼”让数据量大幅变小(池化让图片每4个像素缩为一个, 最后成了$14\times14$的大小.)

$$[28,28,1] \underrightarrow{ 第一层卷积层 }[14,14,32]$$

没有图不好理解, 有空在网上找几个图补上.

第二层卷积层

为了构建一个更深的网络, 将图片中的数据进一步提炼, 舍掉无用的数据, 这里再加入一层卷积层. 这一次要将32位的向量扩充到64位, 也就是计算出64个特征.

同样还是先卷积运算, 定义 filter2 的张量形式为 $[5,5,32,64]$, 显然偏置量就为一个64位的向量.

$result_2 = (result_1*filter2)$.

类似第一层, 还要在加上池化. 模板大小也为$2\times2$, 这样输出的图片就是$7\times7$了.

$$[14,14,32] \underrightarrow{ 第一层卷积层 }[7,7,64]$$

第三层全连接层(密集连接层)

全连接层的优点是每个输出的神经元都会受到输入数据的作用, 可以把输入数据的所有特征进行综合, 但是明显需要计算量也很大, 需要的参数也非常多. 所以之前两层也可以看做是为这层做准备, 一是要提前提取特征, 二是减少数据规模.

经过前两层的处理, 数据规模已经足够小了, 且计算出了 64 个特征值. 全连接的输出应该为一个向量. 这里设定向量的长度为 1024, 所以权重张量设定为$[7,7,64,1024]$ 也就是说需要 1024 个结点(神经元)来计算. 那么可以算出实际全连接时需要的参数有$7\times7\times64\times1024$个, 已经是个很大的数字了, 如果之前数据规模没降下来, 那数字又会大的惊人.

同理偏置量也是1024位的向量.

$$result_3 = matmul(result_2, W) + b $$

$$[7,7,64] \underrightarrow{ 第三层全连接层 }[1024]$$

第四层 Dropout 层

这一层的目的是为了防止过拟合.

深度学习中Dropout原理解析

Dropout说的简单一点就是:我们在前向传播的时候,让某个神经元的激活值以一定的概率p停止工作,这样可以使模型泛化性更强,因为它不会太依赖某些局部的特征,如图所示。

$$[1024] \underrightarrow{ 第四层Dropout层 }[1024]$$

第五层输出层

这一层和之前的基础教程没啥区别, 主要的作用还是通过softmax使神经网络的输出规范化为有意义的概率值. 也就是限定了网络输出的值域为[0,1], 同理输出为10位的向量, 代表了这个图像被分类到十个数字的概率.
$$[1024] \underrightarrow{ 第五层输出层 }[10]$$

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import tensorflow as tf
import tensorflow.examples.tutorials.mnist.input_data as input_data

def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)

def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)

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')

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
sess = tf.InteractiveSession()

x = tf.placeholder('float', shape=[None, 784])
y_hat = tf.placeholder('float', shape=[None, 10])
x_image = tf.reshape(x, [-1, 28, 28, 1])
# 第一层卷积
W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)
# 第二层卷积
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)
# 全连接层
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)
# Dropout
keep_prob = tf.placeholder('float')
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
# 输出层
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
# softmax
y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
# 训练评估模型
cross_entropy = -tf.reduce_sum(y_hat*tf.log(y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_hat, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, 'float'))
sess.run(tf.global_variables_initializer())
for i in range(2000):
batch = mnist.train.next_batch(50)
if i % 100 == 0:
train_accuracy = accuracy.eval(feed_dict={x: batch[0], y_hat: batch[1], keep_prob: 1.0})
print("step %d, training accuracy %g" % (i, train_accuracy))
train_step.run(feed_dict={x: batch[0], y_hat: batch[1], keep_prob: 0.5})

print("test accuracy %g" % accuracy.eval(feed_dict={
x: mnist.test.images, y_hat: mnist.test.labels, keep_prob: 1.0
}))

tensorflow 常用 API

package: tf [version 1.x 2.x]

TensorFlow root package. 此包为 tensorflow 的根package.
下文记录那些 tf root package 中的变量或method.

  • 函数原型: tf.placeholder(dtype, shape=None, name=None)

method: placeholder [version 1.x]

Inserts a placeholder for a tensor that will be always fed.
为一个将总被填充数据的张量插入占位符.

method: trainable_variables [version 1.x]

Returns all variables created with trainable=True.
使用方法: tvars = tf.trainable_variables()
tvars 中将会包含此程序中建立的所有可训练的参数.

method: ones_like [version 1.x 2.x]

  • 函数原型: tf.ones_like(tensor, dtype=None, name=None, optimize=True)
  • 参数:
    • tensor: A Tensor.
    • dtype: A type for the returned Tensor. Must be float32, float64, int8, uint8, int16, uint16, int32, int64, complex64, complex128 or bool.
    • name: A name for the operation (optional).
    • optimize: if true, attempt to statically determine the shape of ‘tensor’ and encode it as a constant.
  • 举例:
    tensor = tf.constant([[1, 2, 3], [4, 5, 6]])
    tf.ones_like(tensor) # [[1, 1, 1], [1, 1, 1]]

method: zero_like [version 1.x 2.x]

类似 tf.ones_like, 具体略.

method: reduce_mean [version 1.x]:

tf.reduce_mean 函数用于计算张量tensor沿着指定的数轴(tensor的某一维度)上的平均值,主要用作降维或者计算tensor(图像)的平均值。

  • 函数原型: reduce_mean(input_tensor, axis=None, keep_dims=False, name=None, reduction_indices=None)
  • 函数参数:
    • input_tensor: 输入的待降维的tensor;
    • axis: 指定的轴,如果不指定,则计算所有元素的均值
    • keep_dims:是否降维度,设置为True,输出的结果保持输入tensor的形状,设置为False,输出结果会降低维度;
    • name: 操作的名称
    • reduction_indices:在以前版本中用来指定轴,已弃用;

method: get_variable [version 1.x]

Gets an existing variable with these parameters or create a new one.
获取或新建一个拥有这些参数的变量. 被调用时, 此方法会以当前变量作用域名作为前缀, 并执行reuse检查.

  • 函数原型: tf.get_variable(name,shape=None,dtype=None,initializer=None, regularizer=None, trainable=None, collections=None, caching_device=None, partitioner=None, validate_shape=True, use_resource=None, custom_getter=None, constraint=None, synchronization=tf.VariableSynchronization.AUTO, aggregation=tf.VariableAggregation.NONE)

  • 使用样例:

    1
    2
    3
    4
    5
    6
    7
    8
    def foo():
    with tf.variable_scope("foo", reuse=tf.AUTO_REUSE):
    v = tf.get_variable("v", [1])
    return v

    v1 = foo() # Creates v.
    v2 = foo() # Gets the same, existing v.
    assert v1 == v2

class: Session [version 1.x]

A Session object encapsulates the environment in which Operation objects are executed, and Tensor objects are evaluated.
Session对象封装了执行操作对象和计算张量对象的环境.

  • method:

    • run(fetches, feed_dict=None, options=None, run_metadata=None):
      运行”一步”session中的操作并计算参数fetches中的张量, 或者将feed_dict中的数据替换session中的占位符.
      例如:

      • 使用 fetches 训练:

        1
        2
        3
        4
        5
        intermed = tf.add(tf.constant(2.0, tf.constant(5.0)))
        mul = tf.mul(tf.constant(3.0), intermed)

        with tf.Session():
        print(sess.run([mul, intermed]))
      • 使用 feed_dict 训练:

        1
        2
        3
        4
        5
        6
        input1 = tf.placeholder(tf.types.float32)
        input2 = tf.placeholder(tf.types.float32)
        output = tf.mul(input1, input2)

        with tf.Session() as sess:
        print sess.run([output], feed_dict={input1:[7.], input2:[2.]})

method: argmax [version 1.x]

返回张量中参数最大的值的下标.

  • 函数原型: tf.argmax(input, dimension, name=None).
    dimension: 维度, 当dimension=0时按列查找, 当dimension=1时按行查找.

method: equal [version 1.x]

比较两个张量是否相同, return a==b

method: cast [version 1.x]

强制类型转换.

  • 函数原型: tf.cast(x, dtype, name=None)
  • 举例: accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")):
    通过对一个boolean数组强制转为float类型, 然后求平均值计算出相应的正确率.

method: matmul [version 1.x]

张量乘法.

class: global_variable_initializer [version 1.x]:

Returns an Op that initializes global variables

module: tf.nn [version 1.x 2.x]

Wrappers for primitive Neural Net (NN) Operations.
用于提供对底层神经网络操作的支持.

method: conv2d [version 1.x]

卷积运算.

  • 函数原型:
    tf.nn.conv2d(input, filter=None, strides=None, padding=None, use_cudnn_on_gpu=True, data_format='NHWC', dilations=[1, 1, 1, 1], name=None, filters=None)

method: avg_pool [version 1.x, version 2.x]

对输入信号执行平均池化操作.

  • 函数原型:
    tf.nn.avg_pool(value, ksize, strides, padding, data_format='NHWC', name=None, input=None)
  • 参数:
    • value: A 4-D Tensor of shape [batch, height, width, channels] and type float32, float64, qint8, quint8, or qint32.
    • ksize: An int or list of ints that has length 1, 2 or 4. The size of the window for each dimension of the input tensor.
    • strides: An int or list of ints that has length 1, 2 or 4. The stride of + the sliding window for each dimension of the input tensor.
    • padding: A string, either ‘VALID’ or ‘SAME’. The padding algorithm. See + the “returns” section of tf.nn.convolution for details.
    • data_format: A string. ‘NHWC’ and ‘NCHW’ are supported.
    • name: Optional name for the operation.
    • input: Alias for value.
  • 使用例子:
    d1 = tf.nn.avg_pool(d1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

method: relu [version 1.x]

relu, 全名为 rectified linear unit, 线性整流单元. 是一种常用的激励函数. 函数基本相当于: lambda x: max(0, x).

  • 函数原型: tf.nn.relu(features, name=None)

method: sigmoid_cross_entropy_with_logits[version 1.x 2.x]

Computes sigmoid cross entropy given logits
基于给定的参数计算 sigmoid 交叉熵.

  • 函数原型: tf.nn.sigmoid_cross_entropy_with_logits(_sentinel=None, labels=None, logits=None, name=None)
  • 函数参数:
    • _sentinel: Used to prevent positional parameters. Internal, do not use. (用于避免传递位置参数, 不可使用)
    • labels: A Tensor of the same type and shape as logits.
    • logits: A Tensor of type float32 or float64.
    • name: A name for the operation (optional).
  • 例子:
    • tf.nn.sigmoid_cross_entropy_with_logits(logits = Dx, labels = tf.ones_like(Dx))
    • tf.nn.sigmoid_cross_entropy_with_logits(logits = Dg, labels = tf.zeros_like(Dg))

module: tf.train [version 1.x]

class: GradientDescentOptimizer [version 1.x]

能实现随机梯度下降算法的优化器.

  • 数据域:
    • learning_rate: A Tensor or a floating point value. The learning rate to use.
    • use_locking: If True use locks for update operations.
    • name: Optional name prefix for the operations created when applying gradients. Defaults to “GradientDescent”.
  • method:
    • __init__(learning_rate, use_locking=False, name='GradientDescent')
    • minimize(loss, global_step=None, var_list=None, gate_gradients=GATE_OP, aggregation_method=None, colocate_gradients_with_ops=False, name=None, grad_loss=None):
      以loss的学习率更新var_list中的参数以最小化loss.
    • 使用样例:
      train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

class: AdamOptimizer [version 1.x]

Optimizer that implements the Adam algorithm.
Adam优化器, 能按照 Adam 算法更新参数.

  • 数据域:

    • loss: A Tensor containing the value to minimize.
    • global_step: Optional Variable to increment by one after the variables have been updated.
    • var_list: Optional list or tuple of Variable objects to update to minimize loss. Defaults to the list of variables collected in the graph under the key GraphKeys.TRAINABLE_VARIABLES.
    • gate_gradients: How to gate the computation of gradients. Can be GATE_NONE, GATE_OP, or GATE_GRAPH.
    • aggregation_method: Specifies the method used to combine gradient terms. Valid values are defined in the class AggregationMethod.
    • colocate_gradients_with_ops: If True, try colocating gradients with the corresponding op.
    • name: Optional name for the returned operation.
    • grad_loss: Optional. A Tensor holding the gradient computed for loss.
  • method:

    • __init__:
      __init__(learning_rate=0.001, beta1=0.9, beta2=0.999, epsilon=1e-08, use_locking=False, name='Adam')
    • minimize:
      minimize(loss, global_step=None, var_list=None gate_gradients=GATE_OP, aggregation_method=None, colocate_gradients_with_ops=False, name=None, grad_loss=None)
  • 使用举例:
    d_trainer_fake = tf.train.AdamOptimizer(0.0003).minimize(d_loss_fake, var_list=d_vars)
    d_trainer_real = tf.train.AdamOptimizer(0.0003).minimize(d_loss_real, var_list=d_vars)

tf.summary []

scalar

GAN入门

基本原理

一个 GAN 中包含两个模型: 生成模型 (Generator Model) 和一个判别模型(Discriminative Model)组成.
判别模型会接收两个输入, 分别为真实数据和假数据. 判别模型需要判断输入数据究竟是否为真. 生成模型通过反卷积神经网络将随机输入值转化为图像.
在训练过程中, 判别器学习从一堆生成器生成的假数字图像中, 找出真正的数字图像, 同时生成器通过判别器的反馈学习如何生成具有欺骗性的图片, 放着被判别器识别出来.
上述过程可以用公式描述:
$$
\underset{G}{min} \underset{D}{max}V(D,G) = E_{x\sim p_{data}(x)}[logD(x)] + E_{z\sim p_z(z)}[log(1-D(G(z)))]
$$

  • 其中 x 代表真实数据. 那么D(x)就是判别模型对真实数据的判别(认为真则为1, 否则为0).
  • z 代表外部输入的一个随机的噪声. 那么G(z)就是生成模型输出的伪造数据.
  • 训练过程中, G总是试图让表达式右侧最小化, D总是试图让表达式右侧最大化, 由此两个网络产生对抗.