个人笔记,书已看完,剩余笔记都标书上了
import tensorflow as tf
tf.reset_default_graph()
defaultg1v1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1), name='defaultg1v1')
g1 = tf.Graph()
with g1.as_default():
g1v1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1), name='g1v1')
g1v2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1), name='g1v2')
g1x = tf.constant([[0.7, 0.9]], name='g1x')
# g1.get_collection(tf.GraphKeys.GLOBAL_VARIABLES) 做同样的事
with g1.as_default():
print(tf.global_variables())
g2 = tf.Graph()
with g2.as_default():
g2v1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1), name='g2v1')
g2v2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1), name='g2v2')
g2x = tf.constant([[0.7, 0.9]], name='g2x')
# g2.get_collection(tf.GraphKeys.GLOBAL_VARIABLES)
with g2.as_default():
print(tf.global_variables())
print(tf.global_variables())
with tf.Session(graph=g2) as sess:
sess.run(g2v2.initializer)
print(g2v2.eval())
# sess.run(g1v1.initializer)
# 报错,因为g2图中没有g2v2
上面三代码中一共有三个图,一个是默认的图,第二个是g1,最后一个是g2,三者互不共享
另外,只要在with外面定义变量,就会被丢进默认图中
并且同一个图中不可以有同名的tensor
g2.clear_collections(tf.GraphKeys.GLOBAL_VARIABLE)
清空某个图的全局变量
TF中图上的东西都是张量,只不过有些张量是值,有些张量是运算
import tensorflow as tf
#a和b就是两个值的张量
a = tf.constant([1.0, 2.0], name="a")
b = tf.constant([2.0, 3.0], name="b")
#result就是一个运算的张量
result=tf.add(a,b,'add')
sess = tf.InteractiveSession ()
print(a.eval())
print(b.eval())
print(result.eval())
sess.close()
sess = tf.Session ()
print(result.eval(session=sess))
print(sess.run(result))
sess.close()
a和b都是常量,在会话中可以直接取出他们的值
import tensorflow as tf
weights = tf.Variable(initial_value=[1,2])
print(sess.run(weights.initializer))
#None,初始化,做的事就是计算[1,2],然后赋给weights
print(weights.eval())
#数字,获取weights里的值
print(sess.run(weights.initial_value))
#重新计算initial_value,也就是[1,2]这个成员变量,这不是weights里的值,尽管他们大小相同,但这是不同的东西
import tensorflow as tf
#initial_value也可以是生成器
weights = tf.Variable(initial_value=tf.random_normal([2, 3], stddev=2))
print(sess.run(weights.initializer))
#None,初始化,做的事就是计算tf.random_normal([2, 3], stddev=2),然后把值赋给weights
print(weights.eval())
#数字,获取weights里的值
print(sess.run(weights.initial_value))
#计算initial_value,也就是tf.random_normal([2, 3], stddev=2)这个成员变量
#所以sess.run(weights.initial_value)就是sess.run(tf.random_normal([2, 3], stddev=2)),是运算tf.random_normal([2, 3], stddev=2)这个tensor,所以他产生的值和weights里其实没什么关系
再结合图3-7就能理解了
1.TF也是可以链式运算哦,还可以连着算哦
import tensorflow as tf
with tf.Session() as sess:
v1 = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
v2 = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
print(tf.clip_by_value(v, 2.5, 4.5).eval(session=sess))
print(tf.log(tf.clip_by_value(v, 2.5, 4.5)).eval(session=sess))
print(sess.run([v1,v2])
x=tf.placeholder(tf.float32,shape=(None,2),name='x-input')
y_=tf.placeholder(tf.float32,shape=(None,1),name='y-input')
w1=tf.Variable(tf.random_normal([2,1],stddev=1,seed=1))
y=tf.matmul(x,w1)
loss_less=10
loss_more=1
loss=tf.reduce_sum(tf.where(tf.greater(y,y_),(y-y_)*loss_more,(y_-y)*loss_less))
train_step=tf.train.AdamOptimizer(0.001).minimize(loss)
由于tf之中数据以张量形式存储,所以新定义的这个loss实际上并不是一个值,而是一个计算过程
Momentum意思是冲量,类似于惯性的一种东西, v t = γ v t − 1 + η Δ θ J ( θ ) v_t=\gamma v_{t-1}+\eta\Delta_\theta J(\theta) vt=γvt−1+ηΔθJ(θ),然后参数更新的时候用的是 θ = θ − v t \theta=\theta-v_t θ=θ−vt。举个例子,如果此时的梯度是 Δ θ J ( θ ) \Delta_\theta J(\theta) ΔθJ(θ), v t − 1 v_{t-1} vt−1代表着从开始到现在累积的梯度,可以理解为惯性。如果它方向是和梯度反着的,那么就看谁的力气大了,如果惯性的力气大,即使梯度反向了,惯性仍然能让下降方向不变,只不过下降的力气小了
Nesterov:用下一步的梯度和当前的惯性进行相比,往前多看一步,如果远远得看见未来的梯度和当前反向了,提前刹车,进一步降低震荡频次
惯性不是力,我懂的,就是这个意思
Adagrad:里面的 G t , i i G_{t,ii} Gt,ii说的不太对,应该是参数 θ i \theta_i θi的所有前 t t t次的平方和,就理解博主说的作用了
AdaDelta和RMSprop:感觉差不太多,没看出来差别
Adam:有着冲量性质和Adagrad的性质,其中 m m m就是那个惯性,然后 v t v_t vt的作用和Adagrad差不多,不怎么更新的参数尽量多更新,变化频繁的参数尽量少更新
优化方法总结:SGD,Momentum,AdaGrad,RMSProp,Adam解释的也很好
滑动平均模型有啥用的,它的应用场景是:我们先正常用BP算法优化损失函数 J J J,然后每次迭代都会得到一个权重矩阵 W t ( l ) W^{(l)}_t Wt(l)表示第 t t t次更新后 l l l层的权重矩阵,假如更新了 T T T次,每次的结果我们都记录下来,那么最后我们就有 W 1 ( l ) , . . . , W T ( l ) W^{(l)}_1,...,W^{(l)}_T W1(l),...,WT(l)个矩阵了(对于 l l l层),正常来讲 W T ( l ) W^{(l)}_T WT(l)就是我们的结果了
但滑动平均窗口告诉我们,这样取值不好,你得按 W ‾ T ( l ) = β W ‾ T − 1 ( l ) + ( 1 − β ) W T ( l ) \overline{W}^{(l)}_{T}=\beta \overline{W}^{(l)}_{T-1}+(1-\beta)W^{(l)}_{T} WT(l)=βWT−1(l)+(1−β)WT(l)这个式子来取最终结果,也就是最终模型的权重应该是这个 W ‾ T ( l ) \overline{W}^{(l)}_{T} WT(l)
也就是说滑动平均不参与优化过程,只参与结果修正
好处是什么呢,权重的变化比较平滑。
tf.reset_default_graph()
v1 = tf.get_variable('v', [1])
print(v1.name)
with tf.variable_scope('foo'):
v2 = tf.get_variable('v', [1])
print(v2.name)
with tf.variable_scope('foo'):
with tf.variable_scope('bar'):
v3 = tf.get_variable('v', [1])
print(v3.name)
v4 = tf.get_variable('v1', [1])
print(v4.name)
with tf.variable_scope('foo/bar1'):
v7 = tf.get_variable('v', [1])
print(v7.name)
with tf.variable_scope('', reuse=True):
v5 = tf.get_variable('foo/bar/v', [1])
print(v5 == v3)
v6 = tf.get_variable('foo/v1', [1])
print(v6 is v4)
print(tf.get_default_graph().get_collection(tf.GraphKeys.GLOBAL_VARIABLES))
# [, , , ]
print(tf.get_default_graph().get_collection(tf.GraphKeys.GLOBAL_VARIABLES, 'foo/bar'))
# []
print(tf.get_default_graph().get_tensor_by_name('foo/v1:0'))
# Tensor("foo/v1:0", shape=(1,), dtype=float32_ref)
print(tf.get_default_graph().get_tensor_by_name('v:0'))
# Tensor("v:0", shape=(1,), dtype=float32_ref)
看起来名称空间就像把一个graph拆成了好多份,但这些变量仍在同一个graph里的。并且做实验试了一下,发现不同变量空间是完全隔绝的,父子变量空间也不能穿插访问,并且可以一次性定义一个特别深的命名空间
注意,获取张量的时候,名字要按上面的格式:‘op_name:output_index’,而不仅仅是一个‘v’
import tensorflow as tf
tf.reset_default_graph()
v1=tf.get_variable('v1',[2],initializer=tf.zeros_initializer())
v2=tf.get_variable('v2',[2],initializer=tf.zeros_initializer())
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
tf.add_to_collection('temp',v1)
tf.add_to_collection('temp1',v1)
tf.add_to_collection('temp1',v2)
print(tf.get_default_graph().get_all_collection_keys())
#['variables', 'trainable_variables', 'temp', 'temp1']
print(tf.get_default_graph().get_collection(tf.GraphKeys.GLOBAL_VARIABLES))
#[, ]
print(tf.get_default_graph().get_collection('temp'))
#[]
请比较一些容器和命名空间的不同
容器就类似于软分块,仅仅就是打个标签,一个图里的一些张量可以存在不同的容器里
get_collection类似于获得图内某个容器内的张量
import tensorflow as tf
tf.reset_default_graph()
v1=tf.get_variable('v1',[2],initializer=tf.zeros_initializer())
v2=tf.get_variable('v2',[2],initializer=tf.ones_initializer())
result=v1/v2
saver=tf.train.Saver()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
saver.save(sess,'model.ckpt')
上面的代码是把模型保存起来
import tensorflow as tf
tf.reset_default_graph()
v1=tf.get_variable('v1',initializer=tf.constant([5,5],dtype=tf.float32))
v2=tf.get_variable('v2',initializer=tf.constant([5,5],dtype=tf.float32))
result=v1+v2
saver=tf.train.Saver()
#下面语句如果打开的话,重新读取的时候会报错
#v3=tf.Variable(tf.constant(2.0,shape=[1]),name='v3')
with tf.Session() as sess:
saver.restore(sess,'model.ckpt')
print(sess.run(result))
#[1. 1.]
print(tf.get_default_graph().get_collection(tf.GraphKeys.GLOBAL_VARIABLES))
#[, ]
上面的代码是只是重新读取这个模型的变量的值,没读到result,因此没有读取图结构,从结果可以看出,v1和v2的初始值都被换成了存储的值,并且读取的模型里的值必须与当前graph中的值一一对应,否则会报错的
import tensorflow as tf
tf.reset_default_graph()
v1=tf.Variable(tf.constant(1.0,shape=[1]),name='ov1')
v2=tf.Variable(tf.constant(2.0,shape=[1]),name='ov2')
result=v1/v2
init_op=tf.global_variables_initializer()
saver=tf.train.Saver()
with tf.Session() as sess:
sess.run(init_op)
saver.save(sess,'model.ckpt')
print(sess.run(result))
如果我们像上面那样存储
import tensorflow as tf
tf.reset_default_graph()
v1=tf.Variable(tf.constant(5.0,shape=[1]),name='v1')
v2=tf.Variable(tf.constant(2.0,shape=[1]),name='v2')
result=v1+v2
saver=tf.train.Saver({'ov1':v1,'ov2':v2})
with tf.Session() as sess:
saver.restore(sess,'model.ckpt')
print(sess.run(result))
print(tf.get_default_graph().get_collection(tf.GraphKeys.GLOBAL_VARIABLES))
读取的时候,Saver要传入一个字典,从而保证当前图的存储的图的变量名对应
import tensorflow as tf
reader=tf.train.NewCheckpointReader('model.ckpt')
global_variables=reader.get_variable_to_shape_map()
for variable_name in global_variables:
print(variable_name,global_variables[variable_name])
print(reader.get_tensor('v1'))
import tensorflow as tf
tf.reset_default_graph()
saver=tf.train.import_meta_graph('model.ckpt.meta')
with tf.Session() as sess:
saver.restore(sess,'model.ckpt')
print(sess.run(tf.get_default_graph().get_tensor_by_name('truediv:0')))
看,result被存在图结构里了,因为result并不是一个Variable,他是一个运算,要被存在meta文件里的,并且保留了这个运算的结果
fine-tuning的作用
机器学习总结(九):梯度消失(vanishing gradient)与梯度爆炸(exploding gradient)问题
『TensorFlow』使用集合collection控制variables
model_variable就是Key to collect model variables defined by layers. 进程内存储的模型参数的变量集合