首页 > 代码库 > TensorFlow实战——入门与实现前馈神经网络

TensorFlow实战——入门与实现前馈神经网络

入门

我们先来理解一下TensorFlow字面上的意思:

  • Tensor,张量,其实我们可以简单的理解为是多维数组,这也是TensorFlow中的基本数据结构。
  • Flow,流,很直观的表达了,Tensor之间的转化是一种类似于流的方式。

ex.

import tensorflow as tf
a = tf.constant([1.0,2.0],name="a")
b = tf.constant([2.0,3.0],name="b")
result = a+b
sess = tf.Session()
sess.run(result)

解析

tf.constant是用来创建常量Tensor的。在运行到result = a+b时,TensorFlow并没有真的把两个Tensor相加。tf.Session()返回的是和TensorFlow的会话,该会话我们可以调用其的run方法。如sess.run(result),这时TensorFlow才会去回溯帮我们,类似于流水一样,从上面流下来,真正的帮计算出result。结果:

array([ 3.,  5.], dtype=float32)

实现前馈神经网络

import tensorflow as tf
from numpy.random import RandomState

# 每次我们训练的时候 只喂8条数据进去
batch_size = 8

"""
random_normal 生成随机多维数组
def random_normal(shape,
                  mean=0.0,
                  stddev=1.0,
                  dtype=dtypes.float32,
                  seed=None,
                  name=None):
如 w1 就生成了 2×3 的随机数组,数值发布为平均数为0,标准差为1

这里,我们准备构建的神经网络为:
输入层为 2个节点
隐藏层(只有一层)为 3个节点

w1 和 w2 
"""
w1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1))
w2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))

"""
这里的 placeholder 可以看成一个入口,
我们不希望把如此巨大的数据量全都一下子装进TensorFlow里,这极大的增加了开销。
我们更希望是,每次喂一部分的数据,然后每次更新优化优化权值。
x 是特征数据的入口,就2维
y_ 是label数据的入口
None 代表行数任意
"""
x = tf.placeholder(tf.float32, shape=(None, 2), name=‘x-input‘)
y_ = tf.placeholder(tf.float32, shape=(None, 1), name=‘y-input‘)


# 矩阵相乘,得到预测结果 y
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)

# 损失函数,后面会讲
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))


"""
 创建优化器,
 0.001 是学习率
 优化目标三 最小化 cross_entropy
"""
train_step = tf.train.AdamOptimizer(0.001).minimize(cross_entropy)

# 随机生成数据
rdm = RandomState(1)
dataset_size = 128
X = rdm.rand(dataset_size, 2)
Y = [[int(x1 + x2 < 1)] for (x1, x2) in X]

"""
TF的会话需要关闭,
但若我们使用

with tf.Session() as sess:
    .....
    .....

的编码写法,就不用担心忘记关闭会话了。
"""
with tf.Session() as sess:
    #  创建变量初始化的操作,并run它
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    """
    于是便执行了 tf.Variable ,w1 w2 被初始化了。我们来看下打印结果:
    [[-0.81131822  1.48459876  0.06532937]
     [-2.44270396  0.0992484   0.59122431]]
 [[-0.81131822]
 [ 1.48459876]
 [ 0.06532937]]
    """
    print sess.run(w1)
    print sess.run(w2)

    # 迭代次数
    STEPS = 5000

    for i in range(STEPS):
        # 截取数据
        start = (i * batch_size) % dataset_size
        end = min(start + batch_size, dataset_size)

       # 喂数据给 x 和 y_,并 run 训练
        sess.run(train_step, feed_dict={x: X[start:end], y_: Y[start:end]})

      """
      每训练 1000 次
      我们打印出整个数据集的 cross_entropy

     Atter 0 training step(s),cross entropy on all data is 0.0674925 
Atter 1000 training step(s),cross entropy on all data is 0.0163385 
Atter 2000 training step(s),cross entropy on all data is 0.00907547 
Atter 3000 training step(s),cross entropy on all data is 0.00714436 
Atter 4000 training step(s),cross entropy on all data is 0.00578471 

    我们可以看到随着优化,cross entropy越来越低

      """
        if i % 1000 == 0:
            total_cross_entropy = sess.run(cross_entropy,feed_dict={x: X, y_: Y})
            print("Atter %d training step(s),cross entropy on all data ""is %g " % (i, total_cross_entropy))

    """
    最后 看一下 w1 w2 优化调整后的结果:

    [[-1.9618274   2.58235407  1.68203783]
     [-3.4681716   1.06982327  2.11788988]]
[[-1.8247149 ]
 [ 2.68546653]
 [ 1.41819501]]

    """
    print sess.run(w1)
    print sess.run(w2)

损失函数

接下来我们看看上述代码中的损失函数:

cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))

cross_entropy,交叉熵,用于计算两个概率分布之间的距离:

H(p,q)=?xp(x)logq(x)<script type="math/tex" id="MathJax-Element-168">\large H(p,q) = -\sum_{x}p(x)logq(x) </script>

这里我们之所以可以使用它作为损失函数,是因为我们这里把二分类label简单的看作值是1的概率。
这里的p(x)就是y_,label数据。这里的 logq(x)就是tf.log(tf.clip_by_value(y, 1e-10, 1.0)),预测的结果。tf.clip_by_value(y, 1e-10, 1.0)是为了将y中的取值限制在[1e-10, 1.0]。最后我们再使用tf.reduce_mean对其求一个平均值,并取负数,便得到了损失函数。

<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

    TensorFlow实战——入门与实现前馈神经网络