Tensorflow 框架的一些细节
- session.run() 函数 https://blog.csdn.net/u014636245/article/details/101698300
run(self, fetches, feed_dict=None, options=None, run_metadata=None)
其中常用的fetches和feed_dict就是常用的传入参数。fetches主要指从计算图中取回计算结果进行放回的那些placeholder和变量,而feed_dict则是将对应的数据传入计算图中占位符,它是字典数据结构只在调用方法内有效。
DIEN 的代码在 model.train() 和 model.calculate() 中都用到了 session.run() 函数,
- model.train([self.loss, self.accuracy, self.optimizer], feed_dict={...})
- model.calculate([self.y_hat, self.loss, self.accuracy], feed_dict={...})
在这里,train() 要进行模型的优化,所以需要输出 self.optimizer, 保证 self.optimizer 这一变量进行了更新
calculate() 实际上是对应测试,需要输出 self.y_hat, 但并不需要进行模型的优化,迭代一个梯度步
-
tf.expand_dims() https://www.cnblogs.com/helloworld0604/p/9001703.html
-
tf.concat() https://blog.csdn.net/leviopku/article/details/82380118
-
tf.nn.embedding_lookup(embedding, id) 这个函数
-
tf.tile(input, multiples, name=None) # 将 input 作为一个整体,按照 multiples 铺下去 https://blog.csdn.net/tsyccnh/article/details/82459859
-
tf.layers.dense(inputs, units) # units 代表输出神经元的个数 (也即,输出的维度) https://blog.csdn.net/yangfengling1023/article/details/81774580
-
tf.shape() 能够work, 但 tensor.get_shape() 可能返回的是 None,不 work https://blog.csdn.net/u012436149/article/details/52905166
new_target_item_embedding = tf.tile(new_target_item_embedding, [1, tf.shape(self.item_history_embedding)[1], 1])
这里要输入维数,但这个维数是动态变化的。 -
tf.scope() https://www.cnblogs.com/MY0213/p/9208503.html
报错ValueError: Variable time4lstm/time4lstm_cell_target_item__v2/kernel already exists, disallowed
当多次使用同一个模块 _Linear 构建模型时,需要把设置一个变量名作用域,不然会以为是在同一个模块上反复传输,导致错误。 -
自己新写的一段代码
attention_output2 = attention_DIN(self.target_timepoint, self.item_history_timepoint, ATTENTION_SIZE, self.mask)
导致了如下错误:
ValueError: The last dimension of the inputs toDense
should be defined. FoundNone
.
似乎是必须要指定最后一维的维数,而先前 self.target_timepoint, self.item_history_timepoint 的维度无法被推测出来。因为 [128, 7], 128 是 batch size, 可能会变化,但是 tensorflow 静态图,必须先预先确定维数。
self.target_timepoint = tf.placeholder(tf.float32, [None, 7], name='target_timepoint') #[128, 7]
类似如下在 model 中的修改修改:
self.timeconsecutive_history.set_shape([None, None, 7])
self.timecurrent_history.set_shape([None, None, 7])
这两种修改似乎都可以成功。
-
tensorflow 由于静态图,同时出现的模块必须要使用不同的名字,否则会报错:
ValueError: Variable f1_attnull/kernel already exists, disallowed. Did you mean to set reuse=True or reuse=tf.AUTO_REUSE in VarScope? Originally defined at:
attention_output2 = attention_DIN(self.target_timepoint, self.item_history_timepoint, ATTENTION_SIZE, self.mask, stag='time_point'
使用 stag='time_point' 修改了此 bug。 -
numpy + tensorflow 很坑的 bug:
target_timepoint.append(inp[10][seqlen - maxlen:])
target_timepoint_np = np.zeros((n_samples, len(target_timepoint[0]))).astype('float32') # [128, 7]
for idx in range(128) :
target_timepoint_np[idx, :] = target_timepoint[idx]
这里其实 inp[10] 就是一个长为 7 的序列,当 seq_len 很大 [seqlen - maxlen:] 会导致 append 一个空的 list. 而下面,把一个空集可以很轻松地赋给一个 numpy array, 并且没有抛出错误。
最终导致如下错误:
ValueError: Cannot feed value of shape (128, 0) for Tensor u'Inputs/target_timepoint:0', which has shape '(?, 7)'
输出 print target_timepoint_np, 发现了最后面有一个空 [], 这才发现了这个错误。
- python2 似乎默认 单斜杠'/' 是整数除,这里又一个大问题,https://www.cnblogs.com/Dragon5/p/6368372.html
# from __future__ import absolute_import
# from __future__ import division
# from __future__ import print_function
需要使用这个。
或者 保证除法有一个数是浮点数,这样,就可以使得最终的数也是浮点数。我之前好像全部都弄错了?!
- linux 上运行 python 程序,如果 train_data 太大(47 G),可能会导致需要使用非常大的 cpu 内存。当 cpu 内存使用量大到一定程度,系统即将崩溃的时候,linux 内核会直接 kill 该进程,输出 “killed”。关于 cpu 内存的使用量监控,可以使用 top 命令,会看到某一个进程的 cpu 内存使用量会一直增长,直到 100%,然后内核程序会 kill 到该进程。http://www.45fan.com/article.php?aid=20020575243365012677632517
我的代码是使用了 GPU 的,GPU 显存的使用量不大,但不知为何 cpu 的内存炸了。而且似乎是在刚调用函数,还没有运行函数内部第一行命令(个人加的语句进行debug),就开始了预处理生成 tensorflow 的静态图。并在生成静态图的时候,cpu 内存一直增加,导致进程被 kill.
奇怪的是,当换用了小的 train data, 程序能够正常运行了。