Tensorflow简单神经网络
2020-07-09 本文已影响0人
策马踏清风
神经网络参数与Tensorflow变量
tf.Variable
作用是保存和更新神经网络中的参数
#声明2 X 3的矩阵变量,元素均值为0,标准差为2的随机数
weights = tf.Variable(tf.random_normal([2,3], stddev=2))
其它生成器
函数 | 随机数分布 | 主要参数 |
---|---|---|
tf.random_normal | 正太分布 | 平均值、标准差、取值类型 |
tf.truncated_normal | 正太分布,但如果随机出来的值偏离平均值超过2个标准差,那么值会重新随机 | 平均值、标准差、取值类型 |
tf.random_uniform | 拼接分布 | 最小、最大取值,取值类型 |
tf.random_gamma | Gamma分布 | 形状参数alpha、尺度参数beta、取值类型 |
使用常数初始化
函数名 | 功能 | 样例 |
---|---|---|
tf.zeros | 产生全0的数组 | tf.zeros([2,3], int32) -> [[0,0,0], [0,0,0]] |
tf.ones | 产生全1的数组 | 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] |
变量使用的例子
import tensorflow as tf
#初始化两个变量
w1 = tf.Variable(tf.random_normal((2,3), stddev=1, seed=1))
w2 = tf.Variable(tf.random_normal((3,1), stddev=1, seed=1))
#输入的特征向量
x = tf.constant([[0.7, 0.9]])
#前向传播
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)
sess = tf.Session()
#初始化变量
init_op = tf.global_variables_initializer()
sess.run(init_op)
print(sess.run(y))
sess.close()
#输出:[[3.957578]]
变量和张量的区别
-
tf.Variable
是一个运算,运算的结果也是一个张量,变量本质是特殊的张量 -
tf.Variable
里包含的就是一个张量 -
tf.constant
声明的是一个常量,tf.Variable
是变量,后续会进行模型参数调整
4.tf.Variable
会加入到GraphKeys.VARIABLES
中,trainable
参数可以区分优化参数(神经网络参数)和其它参数(迭代参数)
训练神经网络
import tensorflow as tf
# 声明两个参数,即神经网络的层
w1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1))
w2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))
# 给出维度可以降低出错率
# 声明占位符(入口)
x = tf.placeholder(tf.float32, shape=(1, 2), name='input')
# 使用全加,将层连接,形成网络
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)
sess = tf.Session()
# 调用初始化参数
init_go = tf.global_variables_initializer()
sess.run(init_go)
# 给入口占位符值,并运算
print(sess.run(y, feed_dict={x: [[0.7, 0.9]]})) #feed_dict是个字典
# 输出: [[3.957578]]
上面的是运行一个神经网络的代码,输入feed_dict根据神经网络运算得出结果。
神经网络可以通过大量样本调整变量的值,以提高预测结果准确性。
交叉熵和反向传播
- 交叉熵:用于表示预测值和实际值差距的值,通过特定公式得出
- 反向传播:根据交叉熵反向调整神经网络参数的过程
#使用sigmoid函数将y转换为0~1之间的数值,转换后y代表预测是正样本的概率
y = tf.sigmoid(y)
# 定义损失函数来刻画预测值与真实值得差距,交叉熵
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)))
# 上面操作中的这个方法是为了将值限定在一定范围内
# tf.clip_by_value(A,min,max)
# 学习率
learning_rate = 0.001
# 定义反向传播算法来优化神经网络参数
train_step = tf.train.AdamOptimizer(learning_rate).minimize(cross_entropy)
Tensorflow提供的优化算法有10种,常用的有:tf.train.GradientDescentOptimizer, tf.train.AdamOptimizer, tf.train.MomentumOptimizer。定义反向传播之后,通过运行sess.run(train_step)就可以对所有在GraphKeys.TRAINABLE_VARIABLES集合中的变量来进行优化,使当前batch下损失函数更小。
完整神经网络
import tensorflow as tf
from numpy.random import RandomState
#定义训练数据batch的大小
batch_size = 8
#定义神经网络参数
w1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1))
w2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))
#在shape的一个维度上使用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)
y = tf.matmul(a, w2)
#损失函数和反向传播
y = tf.sigmoid(y)
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)))
train_step = tf.train.AdamOptimizer(0.001).minimize(cross_entropy)
#随机生成一个模拟数据集
rdm = RandomState(1)
dataset_size = 128
X = rdm.rand(dataset_size, 2)
#定义规则来给出样本标签,x1+x2<1的样例都认为是正样本,其他为负,
Y = [[int(x1 + x2 < 1)] for (x1, x2) in X]
#创建一个会话来运行Tensorflow程序
with tf.Session() as sess:
init_go = tf.global_variables_initializer()
#初始化变量
sess.run(init_go)
#训练之前的参数
print('parameter w1 before train: ', sess.run(w1))
print('parameter w2 before train: ', sess.run(w2))
STEPS = 5000
for i in range(STEPS):
#每次迭代取batch_size个样本进行训练
start = (i * batch_size) % dataset_size
end = min(start+batch_size, dataset_size)
#通过训练样本训练神经网络并更新参数
sess.run(train_step, feed_dict={x: X[start:end], y_: Y[start:end]})
if i % 1000 == 0:
#每隔1000步计算所有数据集上的交叉熵并输出
total_cross_entropy = sess.run(cross_entropy, feed_dict={x: X, y_: Y})
print('After %d training_steps, cross entropy on all data is %g'%(i, total_cross_entropy))
print('parameter w1 after train: ', sess.run(w1))
print('parameter w2 after train: ', sess.run(w2))
parameter w1 before train: [[-0.8113182 1.4845988 0.06532937]
[-2.4427042 0.0992484 0.5912243 ]]
parameter w2 before train: [[-0.8113182 ]
[ 1.4845988 ]
[ 0.06532937]]
After 0 training_steps, cross entropy on all data is 1.89805
After 1000 training_steps, cross entropy on all data is 0.655075
After 2000 training_steps, cross entropy on all data is 0.626172
After 3000 training_steps, cross entropy on all data is 0.615096
After 4000 training_steps, cross entropy on all data is 0.610309
parameter w1 after train: [[ 0.02476983 0.56948674 1.6921941 ]
[-2.1977348 -0.23668921 1.1143895 ]]
parameter w2 after train: [[-0.45544702]
[ 0.49110925]
[-0.98110336]]
clip_by_value
- 可以将一个张量中的数值限制在一个范围之内。(可以避免一些运算错误:可以保证在进行log运算时,不会出现log0这样的错误或者大于1的概率)
tf.clip_by_value(1-y,1e-10,1.0)
交叉熵
主要有两个表达式
-
二分类(预测的结果只有两种,0/1)
image.png
-
yi
表示样本i的label,正类为1,负类为0 -
pi
表示样本i预测为正的概率
-
多分类
image.png
-
M
类别的数量 -
yic
指示变量(0或1),如果该类别和样本i的类别相同就是1,否则是0; -
pic
对于观测样本i属于类别c的预测概率。