基于TensorFlow的深度学习入门,TensorFlow基本函数和用法

前言:

  思索了很久,我觉得需要一篇这样的文章,帮助大家边熟悉TensorFlow边复习深度学习。

一、TensorFlow

  TensorFlow是一张计算的图,图上标满了计算节点和向量,跟着这些矢量一步一步往下计算就成了一个计算的流;如下图所示。而整张计算图并不是,随着一行Python代码计算而一步一步往下走,实际上,Python代码并不会切实计算,所有的参数只是真实值得一个引用,也就是说,Python代码只是在描绘这张计算图,并没有切实参与计算。只有当这张计算图“启动”之后,才会开始计算。


  Python代码是什么,举一个简单的例子,如何描述这张图:

import tensorflow as tf
a = tf.constant([1,2],name="a")
b = tf.constant([2,3],name="b")
result = a + b

描述完之后如何启动这张计算图?

#创建一个会话session
with tf.Session() as sess:
  sess.run(result)

通过这样,就可以知道,TensorFlow的运行确实有些许不同,但是往下使用,就会发现,除了这些区别,没有什么特别难理解的复杂操作。

二、深度学习

深度学习的“hello world”就是MNIST,但是我偏偏不拿它来做第一个例子,不是任性,而是换一种新鲜的血液,且多一个对比。假设要用深度学习来区分蓝点和黄点:


  影响黄色和蓝色的因素,我们假设为温度和湿度,OK,这样的话,我们就要引入第一个概念:特征向量。“在机器学习中,所有用于描述实体的数字的组合就是一个实体的特征向量。”用这个做例子,特征向量就是(温度,湿度),两维,记作(X1,X2)。这个例子很简单,我们肉眼都能看到两者对结果的影响就是象限--但是机器不知道,怎么让机器更明确知道内在的关系与逻辑?--深度学习。于是我们想通过三层简单的网络,使得机器理解这个逻辑:


    第一层就是输入层,就是我们的特征向量;第二层是隐藏层,第三层是输出层。

  隐藏层的向前传播

    输入层和输出层之间的都是隐藏层,一个隐藏层对应一个矩阵,这个矩阵记录这一些参数,层与层之间的运算就是就是矩阵相乘。


上面每一个点就是一个节点、或者说神经元,然后蓝色的节点功能就是对各个上一层节点乘以W参数之后的求和,等到输出值。利用矩阵的思想,上述式子就是:

   [X][W]=[A]

这就是向前传播;

损失函数:

  损失函数利用的是交叉熵;

假设现在有一个样本集中两个概率分布p,q,其中p为真实分布,q为非真实分布。假如,按照真实分布p来衡量识别一个样本所需要的编码长度的期望为:

但是,如果采用错误的分布q来表示来自真实分布p的平均编码长度,则应该是:

TensorFlow中的用法表达:
cross_entropy = -tf.reduce_mean(y_*tf.log(y))

    如果是回归预测问题,我们一般用mse:


   如果是归类问题,我们一般用SoftMax:

                                                                                       \sigma (\mathbf {z} )_{j}={\frac {e^{z_{j}}}{\sum _{k=1}^{K}e^{z_{k}}}}    

回到刚刚的图形,蓝色节点算出来的值,是一个数学结果,怎么用来判断是图一数据中的蓝还是黄呢?这时候,我们需要的不是一个数字,而是一个概率,此时,我们就可以想到:分类问题:就用softmax函数,该函数可以吧数值变换成概率,有了概率,我们就知道,在温度和湿度的影响下,该产品最后呈现是黄的概率和蓝的概率,因此,就可以设置阈值,来加以表达~e.g.大于0.5的话我们就去确信是蓝色,这样,我们的深度学习模型就做好了。

反向传播:

深度学习模型做好了,反向传播用于优化,反向传播目的是让上述的损失函数最小化。


一般在TensorFlow中的用法是:

train_step = tf.train.AdamOptimizer(learning_rate).minimize(loss)

初始化参数:

TensorFlow提供一个非常简单的一键初始化参数的用法:

init_op = tf.initialize_all_variable()
sess.run(init_op)

有了上述的种种基础,我们可以开始训练这个模型,看看效果:我们甚至可以设置不一样的数据来在线看到每一步的过程:


三、一些提醒:

深度学习的概念:两个重要特性:非线性和多层。

为什么要非线性:我们先补充多层是很重要的,它可以解决异或问题,深度取决于层数。有了这个,我们可以开始证明:我们前面说过,每一层对应一个参数矩阵,这些矩阵数目代表层数,每一个矩阵用W表示则会有:W1,W2,W3...我们前面也说过,每一层就是输入乘以参数矩阵得到的输出,因此,假设输入X,输出Y,则有:

       ((  [X]*[W1] )*[W2] )*[W3] = [Y]

如果是线性的,那么:必然存在,矩阵乘法性质:[X]*[Q] = [Y]   [Q]是W1,W2,W3的合并;

这样,一个矩阵Q代表一层,无论神经网络多少层,就只是一层的效果。。。白忙活!

这时候,我们需要引入一种让层与层之间隔绝的东西,使他不可以合并,实现非线性:激活函数。

也就是在每一层之间加入激活函数:


1、Sigmiod函数:


2、Tanh函数:

         

3、ReLU函数:

         


四、躲不过去的例子:

MNIST代码如下:

import tensorflow as tf

from tensorflow.examples.tutorials.mnist import input_data


# 在变量的构建时,通过truncated_normal 函数初始化权重变量,shape 是一个二维的tensor,从截断的正太分布中输出随机值。
def weight_varible(shape):
    initial = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initial)


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


def conv2d(x, w):
    # x 输入,是一个tensor,w 为filter,strides卷积时每一维的步长,padding 参数是string类型的值,为same,或valid,use_cudnn_on_gpu: bool类型,默认是true
    return tf.nn.conv2d(x, w, strides=[1, 1, 1, 1], padding='SAME')


def max_pool_2x2(x):
    # x 为池化的输入,ksize 为窗口的大小,四维向量,一般为【1,height,width,1】, 因为不在channel上做池化,stride 和卷积类型,窗口在每一维上滑动的步长,【1,stride,stride,1】
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')


# tensorflow 中已经写好了加载mnist 数据集的脚本,minist是一个轻量级的类文件,存储了Numpy格式的训练集,验证集。。同时提供了数据中mini-batch迭代的功能
mnist = input_data.read_data_sets('MNIST_data/', one_hot=True)

# 输入数据参数
x = tf.placeholder(tf.float32, [None, 784])
# 当某轴为-1 时,根据数组元素的个数自动计算此轴的长度
x_image = tf.reshape(x, [-1, 28, 28, 1])
y = tf.placeholder(tf.float32, [None, 10])

# 后台C++,通过session与后台连接, 在session中运行创建的图,
# 使用InteractiveSession 更方便,允许交互操作,如果不用InteractiveSession, 在启动一个回话和运行图之前,要创建整个流图
sess = tf.InteractiveSession()

# 第一个卷积层
w_conv1 = weight_varible([5, 5, 1, 32])
b_conv1 = bias_varible([32])
h_conv1 = tf.nn.relu(conv2d(x_image, w_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

# 第二个卷积层
w_conv2 = weight_varible([5, 5, 32, 64])
b_conv2 = bias_varible([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, w_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

# 全连接层
# 经过两次pool 之后大小变为7*7
w_fc1 = weight_varible([7 * 7 * 64, 1024])
b_fc1 = bias_varible([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(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

# output softmax

w_fc2 = weight_varible([1024, 10])
b_fc2 = bias_varible([10])
y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, w_fc2) + b_fc2)

# 定义loss 函数,和最优化函数
cross_entropy = -tf.reduce_sum(y * tf.log(y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

# 定义eval
correct_prediction = tf.equal(tf.arg_max(y_conv, 1), tf.arg_max(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))  # cast 为类型转换函数,将类型转换为tf.float32

sess.run(tf.initialize_all_variables())

# 开始正式的训练
for i in range(20000):
    batch = mnist.train.next_batch(50)
    # mnist 类中提供了取batch的函数
    if i % 100 == 0:
        # train_accuracy=accuracy.eval()
        print(
        "step %d, training accuracy %g" % (i, sess.run(accuracy, feed_dict={x: batch[0], y: batch[1], keep_prob: 1.0})))

    sess.run(train_step, feed_dict={x: batch[0], y: batch[1], keep_prob: 0.5})
    # train_step.run()

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

5、TensorFlow一些常用的函数:

函数参考:https://www.cnblogs.com/wuzhitj/p/6298004.html

更多深度学习基础:http://blog.csdn.net/errors_in_life/article/details/65950699

猜你喜欢

转载自blog.csdn.net/Errors_In_Life/article/details/79581350