使用前向传播和反向传播的神经网络代码

完整代码可从https://github.com/TimeIvyace/Basic-neural-network.git中下载

本代码使用监督学习的方法来更合理的设置参数取值,设置神经网络参数的过程就是神经网络的训练过程。使用监督学习的方式设置神经网络参数需要有一个标注好的训练数据集batch,监督学习最重要的思想就是,在已知答案的标注数据集上,模型给出的预测结果要尽量接近真实的答案。
在神经网络优化算法中,最常用的方法就是反向传播算法,基于当前神经网络模型的预测答案与正确答案之间的差距,反向传播算法会相应更新神经网络参数的取值,使差距越来越小。通常,在得到前向传播结果后,会需要定义一个损失函数(例如交叉熵)来刻画当前的预测值和真实答案之间的差距。目前Tensor支持7种反向传播的优化器,比较常用的优化方法有3种:tf.train.GradientDescentOptimizer、tf.train.AdamOptimizer和tf.train.MomentumOptimizer。在定义了反向传播算法之后,通过运行sess.run(train_step)就可以对神经网络中的参数进行优化,使得在当前batch下损失函数最小。

import tensorflow as tf
#Numpy是一个科学计算的工具包,通过randomstate生成模拟数据集
from numpy.random import RandomState

batch_size = 8 #神经网络训练集batch大小为8
#定义神经网络的结构,输入为2个参数,隐藏层为3个参数,输出为1个参数
#声明w1、w2两个变量,通过设定seed参数随机种子,随机种子相同,则每次使用此代码都生成相同的随机数
#stddev为标准差,没有mean设定均值,则均值默认为0
w1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1)) #w1为输入到隐藏层的权重,2*3的矩阵
w2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1)) #w2为隐藏层打输出的权重,3*1的矩阵

#维度中使用None,则可以不规定矩阵的行数,方便存储不同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) #a为隐藏层的输出,matmul为矩阵的相乘
y = tf.matmul(a, w2) #y为神经网络的输出

#定义损失函数和反向传播的算法
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))
#clip_by_value函数将y限制在1e-10和1.0的范围内,防止出现log0的错误
#*为矩阵元素之间的相乘
#y_为正确结果,y为预测结果
#cross_entropy定义了真实值与预测值之间的交叉熵,是一种损失函数
train_step = tf.train.AdamOptimizer(0.001).minimize((cross_entropy)) #反向传播算法

#通过随机数生成一个模拟数据集
rdm = RandomState(1) #rdm为伪随机数发生器,种子为1,只要种子相同,该发生器每次生成的随机数都是一样的
dataset_size = 128
X = rdm.rand(dataset_size, 2) #生成随机数,大小为128*2的矩阵
#Y属于样本的标签,所有x1+x2<1的都被认为是正样本,其余为负样本。
Y = [[int(x1+x2 <1)] for (x1, x2) in X]  #列表解析格式
#若x1+x2 <1为真,则int(x1+x2 <1)为1,若假,则输出为0

#创建会话
with tf.Session() as sess:
    init_op = tf.global_variables_initializer() #所有需要初始化的值
    sess.run(init_op) #初始化变量
    print(sess.run(w1))
    print(sess.run(w2))

    '''
    #在训练之前神经网络权重的值
    w1 = [[-0.81131822, 1.48459876, 0.06532937], [-2.44270396, 0.0992484, 0.59122431]]
    w2 = [[-0.81131822, 1.48459876, 0.06532937]]
    '''

    # 设定训练的轮数
    STEPS = 5000
    for i in range(STEPS):
        # 每次从数据集中选8个数据进行训练
        start = (i * batch_size) % dataset_size  # 训练集在数据集中的开始位置
        end = min(start + batch_size, dataset_size)  # 结束位置,若超过dataset_size,则设为dataset_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 steps(s), cross entropy on all data is %g" % (i, total_cross_entropy))

    # 在训练之后神经网络权重的值
    print(sess.run(w1))
    print(sess.run(w2))

>>[[-0.81131822  1.48459876  0.06532937]
 [-2.4427042   0.0992484   0.59122431]]
[[-0.81131822]
 [ 1.48459876]
 [ 0.06532937]]
 #训练之前神经网络参数的值
>>After 0 training steps(s), cross entropy on all data is 0.0674925
After 1000 training steps(s), cross entropy on all data is 0.0163385
After 2000 training steps(s), cross entropy on all data is 0.00907547
After 3000 training steps(s), cross entropy on all data is 0.00714436
After 4000 training steps(s), cross entropy on all data is 0.00578471
#这是每1000次训练之后的交叉熵,可以发现随着训练的运行,交叉熵是逐渐变小的,交叉熵越小说明预测的结果和真实的结果差距越小
>>[[-1.96182752  2.58235407  1.68203771]
 [-3.46817183  1.06982315  2.11788988]]
[[-1.82471502]
 [ 2.68546653]
 [ 1.41819501]]
#训练之后神经网络参数的值

可以得出训练神经网络的过程为以下3步:

  1. 定义神经网络的结构和前向传播的输出结果
  2. 定义损失函数以及选择反向传播优化的算法
  3. 生成会话并且在训练数据上反复运行反向传播优化算法
  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值