深度学习笔记——全连接神经⽹络样例程序及详细注释
全连接神经⽹络(fully connected neural network),顾名思义,就是相邻两层之间任意两个节点之间都有连接。全连接神经⽹络是最为普通的⼀种模型(⽐如和CNN相⽐),由于是全连接,所以会有更多的权重值和连接,因此也意味着占⽤更多的内存和计算。
本⽂将分为两部分,第1部分介绍了⼀个完整的全连接神经⽹络的样例程序,并对程序中的函数进⾏了详细的注解。第2部分结合tensorflow 游乐场,利⽤全连接神经⽹络解决⼀个⼆分类问题。
1. 全连接神经⽹络样例程序bxcvzz
下⾯的代码定义了⼀个两层的全连接神经⽹络,如下图1所⽰。其⼯作原理如图2所⽰。
#coding:utf-8有道词典在线
uptting#由于python只接受ASCII character,那么在需要输⼊中⽂时,需要加⼊上⾯这⼀句,⽀持utf-8编码
#导⼊tensorflow
import tensorflow as tf
#这⾥是导⼊RandomState,后⾯利⽤其⽣成随机数,模拟⼀个数据集
from numpy.random import RandomState
#batch_size表⽰把输⼊数据分成若⼲组,每组数据为batch_size个,每次喂⼀组给NN
电大英语考试答案batch_size=8
#tf.random_normal原型为tf.random_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, ed=None, name=None)
#表⽰⽣成正态分布随机数,ed=1,表⽰种⼦初始化为1,对于同⼀个种⼦,每次⽣成的随机数相同
#这⾥到w1和w2对应图中的w1和w2
w1=tf.Variable(tf.random_normal([2,3],stddev=1,ed=1))
大学英语w2=tf.Variable(tf.random_normal([3,1],stddev=1,ed=1))
#TensorFlow provides a placeholder operation that must be fed with data on execution.
#原型:tf.placeholder(dtype,shape=None,name=None)
#placeholder进⾏占位(还没有具体的数据),因此在执⾏计算之前需要先喂⼊数据
#在ss.run()函数中⽤feed_dict喂数据
#在ss.run()函数中⽤feed_dict喂数据
#shape=(None,2),这⾥指定了shape为2列,但是⾏数没有指定,这样可以⽅便使⽤不同的batch_size
#x为输⼊数据,y_为输⼊数据的标签值
x=tf.placeholder(tf.float32,shape=(None,2),name='x-input')
y_=tf.placeholder(tf.float32,shape=(None,1),name='y-input')
#定义NN的前向传播过程
a=tf.matmul(x,w1)
y=tf.matmul(a,w2)
#定义激活函数,将y转换为0~1之间的数值,转换后y代表预测是正样本的概率,1-y代表是负样本的概率
y=tf.sigmoid(y)
#定义损失函数来刻画预测值与真实值的差距,这⾥选择的是交叉熵损失函数
#tf.clip_by_value()将y限定在1e-10~1.0之间,包含1e-10和1.0
#tf.reduce_mean()默认对括号中的所有值取平均值,其原型为tf.reduce_mean(input_tensor,reduction_indices=None,keep_dims=Fal,name=None)#当reduction_indices=1,则对括号中到张量以⾏为单位计算平均值,若等于0,则以裂为单位计算平均值
cross_entropy=-tf.reduce_mean(y_*tf.log(tf.clip_by_value(y,1e-10,1.0))+(1-y)*tf.log(tf.clip_by_value(1-y,1e-10,1.0)))
#定义反向传播算法来优化NN的参数,这⾥选择的是AdamOptimizer,其中learning_rate=0.001
train_ain.AdamOptimizer(0.001).minimize(cross_entropy)
#通过随机数⽣成⼀个模拟数据集
rdm=RandomState(1)
datat_size=128
#RandomState.rand():create an array of the given shape and populate it with
#random samples from a uniform distribution over [0, 1)
#X为模拟的输⼊数据集
X=rdm.rand(datat_size,2)
#定义规则来给出样本的标签。x1+x2<1的样例认为是正样本,否则为负样本
#这⾥0表⽰负样本,1表⽰正样本
Y=[[int(x1+x2<1)] for (x1,x2) in X]
#创建⼀个会话来运⾏TensorFlow
with tf.Session() as ss:
#利⽤global_variables_initializer汇总所有需要优化的变量,添加⽤于初始化变量的节点
init_op=tf.global_variables_initializer()
# 运⾏初始化操作
ss.run(init_op)
iack#输出w1和w2的值
print("w1:")
print(ss.run(w1))
print("w2:")
print(ss.run(w2))
#设定训练的轮数
STEPS=5000
for i in range(STEPS):
#每次选取batch_size个样本进⾏训练
start=(i*batch_size)%datat_size
end=min(start+batch_size,datat_size)
#通过选取的样本训练神经⽹络并更新数据
#通过feed_dict对x&y_进⾏赋值,其中x为样例内容,y_为x对应的标签
garbage
ss.run(train_step,feed_dict={x:X[start:end],y_:Y[start:end]})
#每隔1000轮计算在所有数据上的的交叉熵并输出
if i%1000==0:
june简写total_cross_entropy=ss.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))
2. 全连接神经⽹络求解⼆分类问题
在tensorflow playground中提供了⼏个⼆分类的例⼦,我们将⽤代码实现下⾯这个⼆分类问题。伦敦奥运会时间
假设根据零件的重量和长度来判断零件是否合格,也就是输⼊的x1,x2,⽤这两个数据作为⼀个点在
⼆维平⾯上的x, y坐标,那么零件就可以表⽰为⼆维平⾯上的⼀个点,图中蓝⾊表⽰合格,红⾊表⽰不合格。通过最后输出的数值和⼀个事先设定的阈值做⽐较就可以得到最后的分类结果。
#coding:utf-8
import tensorflow as tf
#导⼊numpy模块⽤于⽣成数据集
import numpy as np
#导⼊plt模块⽤于绘制图形
import matplotlib.pyplot as plt
#定义神经⽹络的输⼊、参数和输出,定义前向传播过程
>>>>>>>>>>>>>>>>>##def get_weight(shape, regularizer):
w = tf.Variable(tf.random_normal(shape), dtype=tf.float32)
#下⾯的代码有两个函数,tf.contrib.layers.l2_regularizer(regularizer)(w),其中第⼀个参数regularizer由形参传⼊,
#表⽰正则化的权重,第⼆个参赛为需要计算正则化损失的参数,这⾥选择的l2正则化,更多正则化的讲解请参考注解1
#tf.add_to_collection(name, value),将value加⼊name列表中
tf.add_to_collection('loss', tf.contrib.layers.l2_regularizer(regularizer)(w))
return w
def get_bias(shape):
b = tf.stant(0.01, shape=shape))
return b
def forward(x, regularizer):
w1 = get_weight([2,8], regularizer)
b1 = get_bias([8])
y1 = lu(tf.matmul(x, w1) + b1)bored的意思
w2 = get_weight([8,1], regularizer)
b2 = get_bias([1])
b2 = get_bias([1])
y = tf.matmul(y1, w2) + b2
return y
>>>>>>>>>>>>>>>>>###⽣成数据集
>>>>>>>>>>>>>>>>>##ed = 1
def generateds():
#基于ed产⽣随机数
rdm = np.random.RandomState(ed)
#随机数返回300⾏2列的矩阵,表⽰300组坐标点(x0,x1)作为输⼊数据集,randn()⽣成服从标准正态分布到数据(ave=0,stdev=1) X = rdm.randn(300,2)
#从X这个300⾏2列的矩阵中取出⼀⾏,判断如果两个坐标的平⽅和⼩于2,给Y赋值1,其余赋值0
#作为输⼊数据集的标签(正确答案)
Y_ = [int(x0*x0 + x1*x1 <2) for (x0,x1) in X]
#遍历Y中的每个元素,1赋值'red'其余赋值'blue',这样可视化显⽰时⼈可以直观区分
Y_c = [['red' if y el 'blue'] for y in Y_]
#对数据集X和标签Y进⾏形状整理,第⼀个元素为-1表⽰跟随第⼆列计算,第⼆个元素表⽰多少列,可见X为两列,Y为1列
#这⾥X可以不⽤整理形状,原因是它已经是n*2列
X = np.vstack(X).reshape(-1,2)
顺利英语Y_ = np.vstack(Y_).reshape(-1,1)
return X, Y_, Y_c
#print X
#print Y_
#print Y_c
#⽤plt.scatter画出数据集X各⾏中第0列元素和第1列元素的点即各⾏的(x0,x1),⽤各⾏Y_c对应的值表⽰颜⾊(c是color的缩写)#squeeze从数组的shape中将1的纬度删除
#plt.scatter(X[:,0], X[:,1], c=np.squeeze(Y_c))
#plt.show()
>>>>>>>>>>>>>>>>>###定义反向传播过程
>>>>>>>>>>>>>>>>>##STEPS = 40000 #训练轮数
BATCH_SIZE = 30
LEARNING_RATE_BASE = 0.001 #最初学习率
LEARNING_RATE_DECAY = 0.999 #学习率衰减率
REGULARIZER = 0.01 #正则化权重
def backward():
x = tf.placeholder(tf.float32, shape=(None, 2))
y_ = tf.placeholder(tf.float32, shape=(None, 1))
X, Y_, Y_c = generateds()
y = forward(x, REGULARIZER)
#global_step⽤来记录当前的训练轮数,下⾯到代码初始化global_step为0,并将其标记为超参数(不训练)
global_step = tf.Variable(0,trainable=Fal)
#通过exponential_decay函数⽣成学习率,其会指数级的减⼩学习率,参考注释3
learning_rate = ponential_decay(
LEARNING_RATE_BASE,
global_step,
300/BATCH_SIZE,
LEARNING_RATE_DECAY,
stairca=True)
stairca=True)
#定义损失函数,这⾥选择的是均⽅误差损失函数,并加上正则化项
#tf.add_n计算列表元素的和
loss_m = tf.reduce_mean(tf.square(y-y_))
loss_total = loss_m + tf.add__collection('loss'))
#定义反向传播⽅法:包含正则化
#这⾥选择AdampOptimizer
train_step = tf.train.AdamOptimizer(learning_rate).minimize(loss_total)
with tf.Session() as ss:
# 添加⽤于初始化变量的节点
init_op = tf.global_variables_initializer()
# 运⾏初始化操作
ss.run(init_op)
for i in range(STEPS):
start = (i*BATCH_SIZE) % 300
end = start + BATCH_SIZE
ss.run(train_step, feed_dict={x: X[start:end], y_:Y_[start:end]})
if i % 2000 == 0:
loss_v = ss.run(loss_total, feed_dict={x:X,y_:Y_})
print("After %d steps, loss is: %f" %(i, loss_v))
#这部分下⾯到代码为寻找分类的分界线
#xx, yy = np.mgrid[起:⽌:步长, 起:⽌:步长]
#xx,yy在-3到3之间以步长为0.01,⽣成⼆维⽹格坐标点
xx, yy = np.mgrid[-3:3:.01, -3:3:.01]
#np.c_收集规定区域内所有的⽹格坐标点
#np.ravel将多维数组降为⼀维
#这⾥是将xx,yy拉直,并合并成⼀个2列的矩阵,得到⼀个⽹格坐标点的集合
grid = np.c_[xx.ravel(), yy.ravel()]
#将⽹格坐标点喂⼊神经⽹络,probs为输出
probs = ss.run(y, feed_dict={x:grid})
#调整probs的形状
probs = shape(xx.shape)
#plt.scatter():利⽤指定颜⾊实现点(x,y)的可视化, plt.scatter (x 坐标, y 坐标, c=”颜⾊”)
plt.scatter(X[:,0], X[:,1], c=np.squeeze(Y_c))
#ur()函数:告知 x、y 坐标和各点⾼度,⽤ levels 指定⾼度的点描上颜⾊
#ur (x 轴坐标值, y 轴坐标值, 该点的⾼度, levels=[等⾼线的⾼度])
#这⾥是给所有probs=0.5的点上⾊,也就是寻找分界线
plt.show()
>>>>>>>>>>>>>>>>>##if __name__=='__main__':
backward()
输出结果如下: