背景
这一周在学习某篇论文的代码,里面大量用到了TensorFlow
问题
主要问题是:断点调试程序时,我需要查看某一张量的值,这个张量存储在一个类的函数的一个局部变量里,而且其依赖的张量还使用了占位符,因此不能等到会话开启或占位符填充时,再查看这个局部张量的值,因为那时就访问不到了。
解决方法
1、启动会话。将会话启动提早到那个类的初始函数之前,并把会话对象做为参数传给类的初始函数,做为类的属性之一
之前这部分代码是这样
interaction_table, offset = get_interaction_table(train_data, n_entity)
interaction_table.init.run()
model = KGNN_LS(args, n_user, n_entity, n_relation,
adj_entity, adj_relation, interaction_table,
offset)
with tf.Session() as sess:
sess.run(init)
....
更改后变成了这样
with tf.Session() as sess:
sess.run(init)
interaction_table, offset = get_interaction_table(train_data, n_entity)
interaction_table.init.run()
model = KGNN_LS(args, n_user, n_entity, n_relation,
adj_entity, adj_relation, interaction_table,
offset, sess)
2、占位符填充。原来的代码里关于占位符填充的部分如下所示
while start + args.batch_size <= train_data.shape[0]:
_, loss = model.train(sess, get_feed_dict(model, train_data, start, start + args.batch_size))
start += args.batch_size
...
def get_feed_dict(model, data, start, end):
feed_dict = {model.user_indices: data[start:end, 0],
model.item_indices: data[start:end, 1],
model.labels: data[start:end, 2]}
return feed_dict
看来是分批次从训练集中取数据去训练,这样,我们先把训练集也保存到模型类里面,就像保存会话对象一样;而后可以把这个获取填充数据的函数稍加改动也封装到模型类里,为了避免测试集太大,我们可以固定只查看固定行数的样例,具体多少行可以根据一批处理样本的数量决定。相关代码如下所示
模型构造函数
model = KGNN_LS(args, n_user, n_entity, n_relation,
adj_entity, adj_relation, interaction_table,
offset, sess, train_data)
模型类构造函数的实现
def __init__(self, args, n_user, n_entity, n_relation,
adj_entity, adj_relation, interaction_table,
offset, session, train_data):
self.session = session
self.train_data = train_data
....
模型类内部获取填充数据的函数
def get_feed_dict_test(self):
start = 0
end = self.batch_size
data = self.train_data
feed_dict = {self.user_indices: data[start:end, 0],
self.item_indices: data[start:end, 1],
self.labels: data[start:end, 2]}
return feed_dict
然后把查看张量值的步骤封装成函数即可
def test_tensor(self, tensor):
return self.session.run([tensor], self.get_feed_dict_test())
这样就可以查看局部张量的值了
遇到的问题
在这个模型类的某部分,用到了XavierInitializer,我在用上面的方法查看被它初始化的张量时,报了如下错误
{FailedPreconditionError}Attempting to use uninitialized value XXX
解决方法
在XavierInitializer初始化的张量下面,再次初始化全局初始化器即可,代码如下
self.relation_emb_matrix = tf.get_variable(
shape=[n_relation, self.dim], initializer=self.initializer, name='relation_emb_matrix') # 被XavierInitializer初始化的张量之一
self.session.run(tf.global_variables_initializer())
然后查看XavierInitializer初始化的张量值就没问题了