所谓的模块化,就是将整个步骤分为三部分:生成数据集、前向传播、后向传播,分别对应三个文件
generated.py forward.py backward.py
目录
以上一个例子为例:
在generated.py文件中:
负责训练数据的生成(包括输入X和标签Y_)
#coding:utf-8
import numpy as np
import matplotlib.pyplot as plt
seed =2
def generated():
#基于seed产生随机数
rdm = np.random.RandomState (seed)
#随机数返回300行2列的矩阵,表示300组坐标点
X = rdm.randn(300,2)
#标记 ,作为输入数据集的标签(正确答案) 若<2则标记为1 ,否则为0
Y_ = [int (x0*x0+x1*x1<2) for (x0, x1) in X]
#1赋值为红色,其余赋值为蓝色
Y_c = [['red' if y else 'blue'] for y in Y_]
#对数据集X和标签Y进行shape整理,第一个元素为-1表示,随第二个元素计算得到,第二个元素表示列数
X = np.vstack(X).reshape(-1,2) #n行2列
Y_ = np.vstack(Y_).reshape(-1,1)#n行1列
#plt.scatter画出数据集X各行中0列元素和1列元素
plt.scatter(X[:,0], X[:,1] , c= np.squeeze (Y_c))
plt.show()
return X, Y_, Y_c
在forward.py文件中:
定义隐藏层权重和偏差:w和b,给出前向传播的过程
#coding:utf-8
#0. 导入模块
import tensorflow as tf
BATCH_SIZE = 30
#1.定义神经网络的输入、参数和输出,定义前向传播过程
def get_weight (shape, regularizer):
w = tf.Variable(tf.random_normal(shape), dtype = tf.float32)
tf.add_to_collection('losses',tf.contrib.layers.l2_regularizer(regularizer)(w))
return w
def get_bias(shape):
b = tf.Variable(tf.constant(0.01, shape = shape))
return b
def forward(x, regularizer):
#输入的x为n*2的维度, 所以w1的维度为2 ,有11个节点,所以后面的维度是11
w1 = get_weight ([2,11], regularizer)
b1 = get_bias([11])
y1 = tf.nn.relu(tf.matmul(x,w1) +b1) #得到的y1维度是n*11
#最后输出的是n*1维的y,所以 w2的维度是11*1
w2 = get_weight ([11,1], regularizer)
b2 = get_bias([1])
y = tf.matmul(y1,w2) +b2 #输出层不过激活函数
return y
在backward.py文件中
0. x和y_占位,生成数据,定义前向传播过程
1. 定义学习率
3. 损失函数、
4. 定义训练过程
5. 滑动平均
6.会话执行:
#coding:utf-8
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import tf6_generated
import tf6_forward
BATCH_SIZE = 30
LEARNING_RATE_BASE = 0.001 #初始学习率
LEARNING_RATE_DECAY = 0.999 #学习率衰减率
REGULARIZER = 0.01 #正则化权重
MOVINT_AVERAGE_DECAY = 0.99 #滑动平均
def backward():
x = tf.placeholder (tf.float32, shape = (None, 2))
y_ = tf.placeholder (tf.float32, shape = (None, 1))
X, Y_, Y_c = tf6_generated.generated() #数据集生成
y = tf6_forward.forward(x, REGULARIZER) #前向传播
#运行了几轮batchsize的计数器,初值为0,设置为不被训练
global_step = tf.Variable(0,trainable = False)
#定义指数下降学习率
learning_rate = tf.train.exponential_decay(
LEARNING_RATE_BASE,
global_step,
300/BATCH_SIZE,
LEARNING_RATE_DECAY,
staircase= True)
#定义损失函数
loss_mse = tf.reduce_mean(tf.square(y-y_))
loss_total = loss_mse + tf.add_n(tf.get_collection('losses'))
#定义反向传播方法:含正则化
train_step = tf.train.AdamOptimizer(learning_rate).minimize(loss_total)
#实现滑动平均
ema = tf.train.ExponentialMovingAverage(MOVINT_AVERAGE_DECAY, global_step)
# ema.apply后的括号里是更新列表,每次运行sess.fun(ema_op)时,对更新列表中的元素求滑动平均值
# 在实际应用中会使用tf.trainable_variable()自动将所有待训练的参数汇总为列表
# 这里因为只有一个参数,所以直接用apply([w1])也是可以的
# ema_op = ema.apply([w1])
ema_op = ema.apply(tf.trainable_variables())
# 反向传播更新参数之后,再更新每一个参数的滑动平均值,用下面的代码可以一次完成这两个操作
with tf.control_dependencies([train_step, ema_op]):
train_op = tf.no_op(name="train")
#设置完使用滑动平均模型之后,只需要在每次使用反向传播的时候改为使用run.(train_op)就可以正常执行了。
#会话执行
with tf.Session() as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)
STEPS = 4000
for i in range(STEPS):
start = (i*BATCH_SIZE) % 300
end = start + BATCH_SIZE
sess.run(train_op, feed_dict = {x:X[start:end], y_:Y_[start:end]})
if i%200==0:
loss_mse_v = sess.run(loss_total,feed_dict = {x:X, y_:Y_})
print('after' +str(i) + 'steps, loss is' +str(loss_mse_v))
#xx在-3和3之间,步长为0.01
xx,yy = np.mgrid[-3:3:0.01, -3:3:0.01]
#将xx和yy拉直,并合并成一个2列矩阵,得到一个网格
grid = np.c_[xx.ravel(), yy.ravel()]
#将网格坐标点喂入神经网络,probs为输出
probs = sess.run(y, feed_dict= {x:grid})
#probs 的shape调整成xx的样子
probs = probs.reshape(xx.shape)
plt.scatter(X[:,0], X[:,1], c= np.squeeze(Y_c))
plt.contour(xx,yy,probs,levels = [0.5])
plt.show()
if __name__ == "__main__":
backward()