TensorFlow实战之TensorFlow入门

3.2 TensorFlow数据模型–张量

  • 一个张量最重要的三个属性:名字(name)、维度(shape)、类型(dtype)

3.3 TensorFlow运行模型–会话

  • ConfigProto最重要的参数有两个,第一个是allow_soft_placement。当它为True时,以下任意一个条件成立时,GPU的运算可以放到CPU上进行:
  1. 运算无法在GPU上运行。
  2. 没有GPU资源。
  3. 运算输入包括对CPU计算结果的引用。

另一个参数是log_device_placement,当它为True时日志将会记录每个节点被安排在哪个设备上方便调试。

import tensorflow.compat.v1 as tf
tf.disable_eager_execution()

a = tf.Variable(tf.constant([1.0]), name = 'a')
b = tf.Variable(tf.constant([2.0]), name = 'b')
result = a + b
config = tf.ConfigProto(allow_soft_placement=True,
						log_device_placement=True)			# 配置config			
with tf.Session(config = config) as sess:
    sess.run(tf.global_variables_initializer())
    print(sess.run(result))

3.4 TensorFlow实现神经网络

关于神经网络、前向后向传播的理论知识这里就不赘述了,主要注重TensorFlow的编程使用。

编程过程中常用函数

  1. Tensorflow随机数生成函数
函数名称 随机数分布 主要参数
tf.random_normal 正态分布 平均值、标准差、取值类型
tf.truncated_normal 正态分布,但如果随机出来的值偏离平均值超过2个标准差,那么这个数将会被重新随机 平均值、标准差、取值类型
tf.random_uniform 均匀分布 最小、最大取值、取值类型
tf.random_gamma Gamma分布 形状参数alpha、尺度参数beta、取值类型
  1. Tensorflow常数生成函数
函数名称 功能 样例
tf.Variable 产生全0的数组 tf.zeros([2,3], int32)->[[0,0,0],[0,0,0]]
tf.ones 产生全0的数组 tf.ones([2,3], int32)->[[1,1,1],[1,1,1]]
tf.fill 产生一个全部为给定数字的数组 tf.fill([2,3], 9)->[[9,9,9],[9,9,9]]
tf.constant 产生一个给定值的常量 tf.constant([1,2,3])->[1,2,3]
  1. Tensorflow变量生成函数
函数名称 功能 样例
tf.Variable 产生一个变量,可以用容器来初始化 tf.Variable(tf.constant([1.0]))
tf.placeholder 占位函数 tf.placeholder(shape=[None, 784], dtype=‘float’)
  1. Tensorflow运算函数
函数名称 功能 样例
tf.matmul 对张量进行乘积,张量维度满足的要求和矩阵乘法相同 tf.matmul(a,b)
tf.sigmoid sigmoid函数 tf.sigmoid(x)
  1. Tensorflow优化器
常用优化器
tf.train.GradientDescentOptimizer()
tf.train.AdamOptimizer()
tf.train.MomentumOptimizer()

编程实现简单的神经网络

简单说下流程,这个代码不完全是照着书上写的,有我自己改的地方,加入了简单的batch。

  1. 定义数据集的大小为10000,随机生成10000个两特征的样本,根据两个特征的和对样本进行分类。

  2. 定义好网络结构,这个网络比较简单,只有输入层、隐藏层、输出层。隐藏层的神经元个数定为20个,隐藏层采用relu激活函数,可有效防止梯度消失。同时输出层采用sigmoid激活函数,输出值的范围在[0,1]之间,表示分类为1的概率。

  3. 利用输出值和真实的分类结果来计算cross entropy交叉熵。
    l o s s = − ∑ 1 N ( p i l o g p i ′ + ( 1 − p i ) l o g ( 1 − p i ′ ) ) loss=-\sum_1^{N}(p_ilogp_i^{'}+(1-p_i)log(1-p_i^{'})) loss=1N(pilogpi+(1pi)log(1pi))其中 p i p_i pi是真实结果, p i ′ p_i^{'} pi是网络输出值,即分类概率。

  4. 利用Adam算法来优化损失函数。

  5. 一共进行20000次迭代,每次迭代训练batchSize个样本。程序设定的batchSize为2000,意味着每5次迭代取完整个训练集,然后继续重复。

代码

import tensorflow.compat.v1 as tf
import numpy as np
tf.disable_eager_execution()

dataNum = 10000         # 数据集大小为10000
batchSize = 2000        # 每次训练的batch为2000
trainData = np.random.randn(dataNum, 2)         # 产生有两个特征的数据集, shape为(10000, 2)
trainLabel = np.array([int(x+y>0) for (x,y) in trainData]).reshape(-1, 1)       # 若x+y>0归为1类, 否则归为0类

x = tf.placeholder(dtype='float', shape=[None, 2])          # 输入数据用占位函数,特征维度为2,None根据输入的batch自动判定
trueY = tf.placeholder(dtype='float', shape=[None, 1])      # 输出数据用占位函数

# 第一层全连接层
wFc1 = tf.Variable(tf.truncated_normal(shape=(2, 20), stddev=0.1))      # 初始化第一层的w,第一层神经元个数为20
bFc1 = tf.Variable(tf.constant(0.1, shape=[20]))            # 初始化第一层的b
hFc1 = tf.nn.relu(tf.matmul(x, wFc1) + bFc1)        # 激活函数选用relu函数

# 第二层全连接层
wFc2 = tf.Variable(tf.truncated_normal(shape=(20, 1), stddev=0.1))      # 初始化第二层的w,输出维度为1
bFc2 = tf.Variable(tf.constant(0.1, shape=[1]))         # 初始化第二层的的b
predY = tf.nn.sigmoid(tf.matmul(hFc1, wFc2) + bFc2)     # 输出选用sigmoid函数,把结果压缩到[0,1]区间,表示分类为1的概率值

# 定义损失函数,loss采用binary_cross_entropy(二值交叉熵)
# tf.clip_by_value(y, min, max)为剪枝函数,小于min取min,大于max取max,其余保持不变,防止log中出现0
loss = -tf.reduce_mean((trueY * tf.log(tf.clip_by_value(predY, 1e-10, 1))+ (1-trueY) * tf.log(tf.clip_by_value(1-predY, 1e-10, 1))))
trainStep = tf.train.AdamOptimizer(1e-3).minimize(loss)         # 定义优化器优化目标

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())     # 初始化所有变量
    iters = 20000   # 迭代次数为20000次
    for i in range(iters):
        x_ = trainData[(i % 5) * batchSize:((i % 5) + 1) * batchSize, :]        # 每次取batchSize个训练样本,每5次迭代重复整个训练集
        y_ = trainLabel[(i % 5) * batchSize:((i % 5) + 1) * batchSize, :]
        trainStep.run(feed_dict={
    
    x: x_, trueY: y_})     # 拿batchSize个样本进行训练
        if(i % 1000 == 0):
            crossEntropy = loss.eval(feed_dict={
    
    x: trainData, trueY: trainLabel})       # 每一千次迭代输出在整个训练集上的loss
            print('iter:%d, loss: %g' % (i, crossEntropy))

运行结果

iter0, loss: 0.669061
iter1000, loss: 0.0590102
iter2000, loss: 0.0314588
iter3000, loss: 0.0210427
iter4000, loss: 0.0154069
iter5000, loss: 0.0118919
iter6000, loss: 0.00953395
iter7000, loss: 0.00789001
iter8000, loss: 0.00671841
iter9000, loss: 0.00586595
iter10000, loss: 0.00523055
iter11000, loss: 0.00474468
iter12000, loss: 0.00436347
iter13000, loss: 0.00405675
iter14000, loss: 0.00380408
iter15000, loss: 0.00359156
iter16000, loss: 0.00340953
iter17000, loss: 0.00325123
iter18000, loss: 0.00311178
iter19000, loss: 0.0029876

从结果可以看出,随着迭代次数的增加,神经网络在训练集上的训练误差越来越小,说明程序设定正确。

总结

训练神经网络的过程可以分成以下三个步骤:

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

结语:以上内容和代码加入了自己的想法和验证,如有不当之处还请指正。
欢迎转载,标明出处。

猜你喜欢

转载自blog.csdn.net/qq_36583373/article/details/104997005
今日推荐