Tensorflow——简单的二分类网络

写在前面

对于这个新的类别,我也不清楚到底能做到什么程度。首先,从自己的角度上来说,我更希望做一名开发者而非数据科学家来学习Tensorflow与其他深度学习框架。然后,目前主要学习资料是《Tensorflow深度学习框架》,依据这本书里的内容进行学习与注解。

基于模拟数据的二分类网络

下面是根据《Tensorflow深度学习框架》中的一个例子,纠正了一些版本上的Bug,具体可参考:Python——Print函数的Invalid syntax错误。网络代码如下所示:

# -*- coding: utf-8 -*-
"""
Created on Tue May 15 10:27:01 2018

@Description: Two Categories test by Tensorflow
@author: IdaZhang
"""

import tensorflow as tf

# 通过Numpy工具包生成模拟数据集
from numpy.random import RandomState

# 定义训练数据batch的大小
batch_size = 8

# 定义神经网络的参数
w1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1))
w2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))

# 在shape的维度上使用None可以方便的使用不大的batch大小。
# 在训练时需要把数据分成比较小的batch,但是在测试时,可以一次性使用全部的数据
# 当数据集比较小时,这样比较方便测试。但数据集比较大时,大量数据放入一个batch可能会
# 导致内存溢出
x = tf.placeholder(tf.float32, shape=(None, 2), name="x-input")
y_ = tf.placeholder(tf.float32, shape=(None, 1), name="y-input")

# 定义神经网络前向传播的过程
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)))
train_step = tf.train.AdamOptimizer(0.001).minimize(cross_entropy)

# 通过随机数生成一个模拟数据集
rdm = RandomState(1)
dateset_size = 128
X = rdm.rand(dateset_size, 2)

# 定义规则来给出样本的标签:x1+x2<1是正样本,否则是负样本。
# 这里用0和1表示负样本与正样本
Y = [[int(x1+x2 < 1)] for (x1, x2) in X]

# 创建一个会话来运行Tensorflow程序
with tf.Session() as sess:
     init_op = tf.initialize_all_variables()
     # 初始化变量
     sess.run(init_op)
     print (sess.run(w1))
     print (sess.run(w2))

     # 设定训练的轮数
     STEPS = 10000
     for i in range(STEPS):
          # 每次选取batch_size个样本进行训练
          start = (i * batch_size) % dateset_size
          end = min(start + batch_size, dateset_size)

          # 通过选取的样本训练神经网络并更新参数
          sess.run(train_step, feed_dict={x: X[start:end], y_: Y[start:end]})
          if i % 1000 == 0:
               # 每隔一段时间计算在所有数据上的交叉熵并输出
               total_cross_entropy = sess.run(
                         cross_entropy, feed_dict={x: X, y_: Y})
               print((("After %d training step(s), cross_entropy on all" 
                       "data is %g") % (i, total_cross_entropy)))

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

代码解读

由于代码主要注释都有,所以我主要从逻辑上说一下自己对这个网络的理解。

网络主要结果如下所示:
这里写图片描述

网络隐藏层部分有一层,权重参数由w1与w2表示,w1与w2由tf.Variable定义,分别是2*3与3*1的矩阵,权重参数是由满足标准差为1,均值为0的正态分布产生的随机值,并且设定了随机种子seed=1,这样能保证在后面的重复运行中,随机数产生的都是一样的。

placeholder叫占位符,是一个抽象的概念。用于表示输入输出数据的格式。告诉系统:这里有一个值/向量/矩阵,现在我没法给你具体数值,不过我正式运行的时候会补上的!这里让shape=[None, 2]或者[None, 1],其作用可以这样理解:需要输入一批[1,5]的数据的时候。比如我有一批共10个数据,那我可以表示成[10,5]的矩阵。如果是一批5个,那就是[5,5]的矩阵。tensorflow会自动进行批处理。

这里的x是输入,y_的实际含义就是真实值,后面的y是通过神经网络计算出来的预测值。

matmul就是将括号内的两个矩阵相乘,输入的特征矩阵乘以第一个参数矩阵,得到隐藏层的值,然后隐藏层的值构成的矩阵乘以第二个参数矩阵就得到了输出值。也就是程序中的y。很显然,这里的y是经过神经网络计算之后的预测值。

程序定义损失函数的时候,调用了tf.reduce_mean()函数,该函数的作用是:求平均值,具体可参考:tensorflow学习之常用函数总结:tensorflow官方例子中的诸如tf.reduce_mean()这类函数

tf.clip_by_value()函数是设置值域范围的函数:输入一个张量A,把A中的每一个元素的值都压缩在min和max之间。小于min的让它等于min,大于max的元素的值等于max。在这里,使用该函数就是将输出值y限定在1e-10与1.0之间。这样可以避免一些运算错误(如:log0是无效的,或者大于1的概率)。

然后赋值给log函数,这个函数依次完成了对张量中所有元素一次求对数的功能,并乘以y_,这里完成了对张量的所有元素相乘的功能,注意这里不是求矩阵乘法,Tensorflow中矩阵乘法需要通过tf.matmul()函数完成。求平均,将该结果即是交叉熵损失函数。

tf.train.AdamOptimizer()是Adam优化算法,是一个寻找全局最优点的优化算法,引入了二次方梯度校正,具体的算法说明可以参考:Adam:一种随机优化方法

后面就是循环训练网络了。注意这里使用了with语句,即上下文管理器,使用with后不管with中的代码出现什么错误,都会进行对当前对象进行清理工作。

例如file的file.close()方法,无论with中出现任何错误,都会执行file.close()方法,还有这里的sess.close()方法。避免我们在网络复杂之后,还要时刻记得关闭sess的情况。

循环过程中要注意sess.run()的两处使用:

sess.run(train_step, feed_dict={x: X[start:end], y_: Y[start:end]})

与:

total_cross_entropy = sess.run(cross_entropy, feed_dict={x: X, y_: Y})

注意这里的feed_dict与之前设置的placeholder相对应,前面在神经网络中设定了占位的地方,后面运行的时候就要向其中“喂数据”。

基于Tensorflow的神经网络训练全过程

  1. 定义神经网络的结构和前向传播的输出结果;
  2. 定义损失函数以及选择反向传播优化的算法;
  3. 生成会话(Session)并在训练数据上反复运行反向传播优化的算法。

程序运行结果

[[-0.8113182   1.4845988   0.06532937]
 [-2.4427042   0.0992484   0.5912243 ]]
[[-0.8113182 ]
 [ 1.4845988 ]
 [ 0.06532937]]
After 0 training step(s), cross_entropy on alldata is 0.0674925
After 1000 training step(s), cross_entropy on alldata is 0.0163385
After 2000 training step(s), cross_entropy on alldata is 0.00907547
After 3000 training step(s), cross_entropy on alldata is 0.00714436
After 4000 training step(s), cross_entropy on alldata is 0.00578471
After 5000 training step(s), cross_entropy on alldata is 0.00430222
After 6000 training step(s), cross_entropy on alldata is 0.00280812
After 7000 training step(s), cross_entropy on alldata is 0.00137464
After 8000 training step(s), cross_entropy on alldata is 2.11566e-05
After 9000 training step(s), cross_entropy on alldata is -0
[[-2.5939224  3.1860275  2.3882565]
 [-4.11018    1.6826365  2.8342733]]
[[-2.4300373]
 [ 3.3341115]
 [ 2.1006744]]

写在后面

这一篇博客讲道理,写的不咋地,原因是有很多地方我自己也还没有完全搞明白。万事开头难嘛,现在这里写一下,后面有所新的领悟也好回过头来进行修改。

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zy2317878/article/details/80321868
文章标签: Tensorflow
个人分类: Tensorflow
上一篇Python——Print函数的Invalid syntax错误
下一篇LeetCode-16. 3Sum Closest
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭