赞
踩
在tensorflow中使用tf.variable定义变量,变量作用是保存和更新神经网络中的参数。并且要给变量初始化一个初始值:
weights=tf.Variable(tf.random_normal([2, 3], stddev=2))
这里定义了一个2x3的矩阵,矩阵中的元素是均值为0,标核差为2的随机数,这是因为tf.random_normal
函数通过参数mean来指定平均值,在没有指定时默认为0,而且通常是定义一个满足正态分布的随机数来初始化神经网络的参数,目前支持的有:
tensorflow还支持初始化一个常数变量。
示例:
import tensorflow as tf
#这里通过seed参数设定了随机种子,这样可以保证每次运行的结果是一样的
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]])
# 前向传播:1x2的输入->和隐层的2x3的权重矩阵相乘得到1x3矩阵->和输出层的3x1矩阵
# 相乘得到输出
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)
# 打开会话
sess = tf.Session()
# 这里是对变量为w1、w2的初始化
sess.run(w1.initializer)
sess.run(w2.initializer)
# 在通过以下进行y值的获取之前必须进行变量的初始化,而常量则不需要
print(sess.run(y))
sess.close()
结果:
[[3.957578]]
这里要注意的两点是:
w1.initializer
才被真正赋初值。tf.initialize_all_variable()
来初始化所有的变量,这样就不会有漏掉的变量忘了初始化,而且省了很大的力气。这里简单说下变量和张量的区别:
所有的数据都是通过张量的形式来组织的。而 tf.Variable
运算的结果就是一个张量,所以变量是一种特殊的张量。
- 在tensorflow中有一个集合的概念,就是所有的变量都会自动加入到graphKeys.VARIABLES
这个集合。这个集合主要是为了管理变量,可以通过tf.all_variables
函数拿到所有的当前计算图上的变量,这有助于持久化整个计算图的运行状态。
- 在构建机器学习模型时,可以通过变量声明函数中的trainable
参数来区分需要优化的参数(比如神经网络中的参数,很重要)和其他的以一些参数(比如迭代轮数),如果在声明变量时参数trainable为true,那么这个变量将会被加入graphKeys.TRAINABLE_VARIABLES
集合,然后通过tf.trainable_variables
函数得到所有需要优化的参数,而tensorflow也会把graphKeys.TRAINABLE_VARIABLES
集合中的变量作为默认的优化参数。
此外关于变量(维度、类型)还要注意:
validate_shape=False
w1= tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1))
w2= tf.Variable(tf.random_normal([2,2], stddev=1, seed=1))
# 会报错:维度不匹配
tf.assign(w1,w2)
# 改成这样就不会报错
tf.assign(w1,w2,validate_shape=False)
实际中其实用的很少。。。
w1.assign(w2)
这里首先说下在进行反向传播的过程中的第一步是使用tensorflow表达一个batch的数据,如果这时用普通的常量来定义,也就是说和普通编程一样,把输入数据定义为常量,这时会造成每来一个batch的数据,就需要定义一个batch的常量,而每生成一个常量,tensorflow都会在图中增加一个节点,这样的话在整个神经网络的训练过程中将产生很大的计算图,这样肯定是不行的,所以就有了placeholder机制,用于提供数据。placehlder其实相当于定义了一个位置,而这个位置的数据是在程序运行时再指定,这样就不用生成大量的常量来提供输入数据,而只需要将数据输入到placeholder来进行计算图的计算。
注意:placeholder在定义时,需要指定维度和数据类型,而数据类型是不能改变的,但是数据的维度可以根据提供的数据推导出来,所以不一定要给出。
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]])
x = tf.placeholder(tf.float32, shape=(1, 2), name="input")
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)) # 这里会报错,因为没有输入数据
# 下面这句是可以的
print(sess.run(y, feed_dict={x: [[0.7,0.9]]}))
这里需要注意的是在所有是初始化和输入都定义好了以后,在sess运行前向传播的时候需要提供一个feed_dict字典,也就是需要喂给模型数据才能跑起来,而且需要指定每一个placeholder的取值,否则会报错。
在得到前向传播的数值后,需要定义一个损失函数来刻画当前的预测值和真实值之间的差距,常用的就是交叉熵损失函数。
# 损失函数
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0))
# 反向传播优化神经网络参数
train_step = tf.train.AdamOptimizer(learning_rate).minimize(cross_entropy)
注意:目前tensorflow支持7种不同的优化器,比较常用的三种:
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_size = 8
w1= tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1)) # 这里是一个隐层,并且是3个节点
w2= tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))
x = tf.placeholder(tf.float32, shape=(None, 2), name="x-input") # 输入是个节点,即是每个样本2个特征
y_= tf.placeholder(tf.float32, shape=(None, 1), name='y-input') # 输出是2分类
# 定义前向传播过程,损失函数及反向传播算法
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)
y = tf.sigmoid(y) # 逻辑回归2分类
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)
X = rdm.rand(128,2)
Y = [[int(x1+x2 < 1)] for (x1, x2) in X]
print('Y:',Y)
# 创建一个会话来运行TensorFlow程序
with tf.Session() as sess:
# 初始化所有的变量
init_op = tf.global_variables_initializer()
sess.run(init_op)
# 输出目前(未经训练)的参数取值,这里是tensorflow中显示输出的方法
print(sess.run(w1))
print(sess.run(w2))
print("\n")
# 训练模型。
STEPS = 5000
for i in range(STEPS):
# 每次选择batch_size个样本进行训练
start = (i*batch_size) % 128
end = (i*batch_size) % 128 + batch_size
# 通过选取的batch_size训练样本训练网路并更新
sess.run([train_step, y, y_], 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 step(s), cross entropy on all data is %g" % (i, total_cross_entropy))
# 输出训练后的参数取值。
print("\n 训练结果:")
print(sess.run(w1))
print(sess.run(w2))
运行结果:
Y: [[0], [1], [1], [1], [1], [0], [0], [1], [1], [1], [0], [0], [0], [1], [0], [1], [0], [0], [0], [1], [0], [0], [1], [0], [1], [1], [1], [1], [1], [0], [1], [0], [1], [0], [0], [0], [1], [1], [0], [0], [0], [0], [0], [0], [0], [0], [0], [1], [0], [1], [1], [0], [0], [1], [0], [1], [0], [1], [0], [1], [1], [1], [0], [0], [1], [0], [1], [0], [0], [0], [1], [1], [1], [1], [1], [0], [1], [1], [1], [0], [1], [0], [1], [1], [0], [0], [1], [0], [1], [1], [1], [1], [0], [1], [0], [1], [0], [0], [1], [0], [0], [0], [1], [0], [0], [0], [1], [1], [1], [1], [1], [1], [0], [0], [0], [0], [0], [0], [1], [0], [0], [1], [0], [1], [0], [1], [0], [0]]
[[-0.8113182 1.4845988 0.06532937]
[-2.4427042 0.0992484 0.5912243 ]]
[[-0.8113182 ]
[ 1.4845988 ]
[ 0.06532937]]
After 0 training step(s), cross entropy on all data is 1.89805
After 1000 training step(s), cross entropy on all data is 0.655075
After 2000 training step(s), cross entropy on all data is 0.626172
After 3000 training step(s), cross entropy on all data is 0.615096
After 4000 training step(s), cross entropy on all data is 0.610309
训练结果:
[[ 0.02476983 0.56948674 1.6921941 ]
[-2.1977348 -0.23668921 1.1143895 ]]
[[-0.45544702]
[ 0.49110925]
[-0.98110336]]
这里要注意:
参考:《Tensorflow实战Google深度学习框架》
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。