tensorflow实现最基本的神经网络 + 对比GD、SGD、batch-GD的训练方法

# -*- coding:utf-8 -*-


# 将tensorflow 引入并命名tf
import tensorflow as tf
# 矩阵操作库numpy,命名为np
import numpy as np


'''
生成数据 
用python使用tensorflow时,输入到网络中的训练数据需要以np.array的类型
存在。并且要限制dtype为32bit以下。变量后跟着“.astype('float32')”总可以满足要求
'''
# X和Y是4个数据的矩阵,X[i]和Y[i]的值始终对应
X = [[0, 0], [0, 1], [1, 0], [1, 1]]
Y = [[0], [1], [1], [0]]
X = np.array(X).astype('int16')
Y = np.array(Y).astype('int16')


'''
定义变量
'''
# 网络结构:2维输入--> 2维隐含层 -->1维输出
# 学习速率(learing rate):0.0001


D_input = 2
D_hidden = 2
D_label = 1
lr = 0.0001
'''
容器
'''
# x为列向量 可变样本数*D_input; y为列向量 1*D_label 用GPU训练需要float32以下精度
x = tf.placeholder(tf.float32, [None, D_input], name=None)
t = tf.placeholder(tf.float32, [None, D_label], name=None)


'''
隐含层
'''
# 初始化权重W [D_input ,D_hidden ]
# truncated_normal 正对数函数,返回随机截短的正态分布,默认均值为0,区间为[-2.0,2.0]
W_h1 = tf.Variable(tf.truncated_normal([D_input, D_hidden], stddev=1.0), name="W_h")
# 初始化b D_hidden 一维
b_h1 = tf.Variable(tf.constant(0.1, shape=[D_hidden]), name="b_h")
# 计算Wx+b  可变样本数*D_hidden
pre_act_h1 = tf.matmul(x, W_h1) + b_h1
# 计算a(Wx+b) a代表激活函数,有tf.nn.relu()、tf.nn.tanh()、tf.nn.sigmoid()
act_h1 = tf.nn.relu(pre_act_h1, name=None)


'''
输出层
'''
W_o = tf.Variable(tf.truncated_normal([D_hidden, D_label],  stddev=1.0), name="W_o")
b_o = tf.Variable(tf.constant(0.1, shape=[D_label]), name="b_o")
pre_act_o = tf.matmul(act_h1, W_o) + b_o
y = tf.nn.relu(pre_act_o, name=None)


'''
损失函数和更新方法
'''
loss = tf.reduce_mean((y - t)**2)
train_step = tf.train.AdamOptimizer(lr).minimize(loss)
'''
训练
sess = tf.InteractiveSession()是比较方便的创建方法。也有sess =
tf.Session()方式,但该方式无法使用tensor.eval()快速取值等功能
'''
sess = tf.InteractiveSession()
# 初始化权重
# tf.tables_initializer(name="init_all_tables").run()调试时报错,可能是版本问题
# Add the variable initializer Op.
init = tf.global_variables_initializer()
sess.run(init)
# 训练网络
'''
GD(Gradient Descent):X和Y是4组不同的训练数据。上面将所有数据输入到网络,
算出平均梯度来更新一次网络的方法叫做GD。效率很低,也容易卡在局部极小值,但更新方向稳定
'''
 79 T = 100000  # 训练次数
for i in range(T):
    sess.run(train_step, feed_dict={x: X, t: Y})
 83 
'''
SGD(Gradient Descent):一次只输入一个训练数据到网络,算出梯度来更新一次网络的方法叫做SGD。
效率高,适合大规模学习任务,容易挣脱局部极小值(或鞍点),但更新方向不稳定。代码如下
'''
'''
T = 100000  # 训练几epoch
for i in range(T):
    for j in range(X.shape[0]):  # X.shape[0]表示样本个数 X.shape[0] 报错 'Placeholder:0', which has shape '(?, 2)
        sess.run(train_step, feed_dict={x: [X[j]], t: [Y[j]]})
'''
'''
batch-GD:这是上面两个方法的折中方式。每次计算部分数据的平均梯度来更新权重。
部分数据的数量大小叫做batch_size,对训练效果有影响。一般10个以下的也叫mini-batch-GD。代码如下:
'''
'''
T = 10000  # 训练几epoch
b_idx = 0  # batch计数
b_size = 2  # batch大小
for i in range(T):
    while b_idx <= X.shape[0]:
        sess.run(train_step, feed_dict={x: X[b_idx:b_idx+b_size], t: Y[b_idx:b_idx+b_size]})
        b_idx += b_size  # 更新batch计数
'''




'''
shuffle:SGD和batch-GD由于只用到了部分数据。若数据都以相同顺序进入网络会使得随后的epoch影响很小。
shuffle是用于打乱数据在矩阵中的排列顺序,提高后续epoch的训练效果。代码如下:
'''
'''
# shuffle
def shufflelists(lists):  # 多个序列以相同顺序打乱
    ri = np.random.permutation(len(lists[1]))
    out = []
    for l in lists:
        out.append(l[ri])
    return out


    # 训练网络
T = 100000  # 训练几epoch
b_idx = 0  # batch计数
b_size = 2  # batch大小
for i in range(T):  # 每次epoch都打乱顺
    X, Y = shufflelists([X, Y])
    while b_idx <= X.shape[0]:
        sess.run(train_step, feed_dict={x: X[b_idx:b_idx + b_size], t: Y[b_idx:b_idx + b_size]})
        b_idx += b_size  # 更新batch计数
'''
# 预测数据
print(sess.run(y, feed_dict={x: X}))
print(sess.run(act_h1, feed_dict={x: X}))
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值