Tensorflow(0)
总体认识:
- tensor,即张量,也就是高维数组;flow,即流,表示着张量的关系以及运算;tensorflow就是张量间的计算。
- 张量之间的计算是在图(graph)中实现的
图:
- 图是由几点与边组成的。
- 节点,即操作(operation);操作可以是加减乘除的运算,也可以是对常量、变量的初始化。
- 边连接着节点,表示着节点之间的数据传递以及控制依赖;并在图中以实线表示常规边,即相连节点只进行数据传递;以虚线表示特殊表,即相连节点存在前后执行的依赖关系。
-
node1 = tf.constant(3.0, tf.float32, name='node1') node2 = tf.constant(4.0, tf.float32, name='node1') node3 = tf.add(node1, node2)
建立如上的计算关系,将得到对应的graph;
-
注意直接打印node3,将不会显示7.0,而是 Tensor("Add:0", shape=(), dtype=float32);即返回一个Tensor值,其中包括节点名,形状以及类型;要想显示node3的具体值,需要在会话中进行,TF中只有执行Session时,才能提供数据与显示结果。
张量
- TF中所有数据均为张量;本质上张量是数组:零阶张量就是一个数、一阶张量就是一个向量一个一维数组、n阶张量就是n维数组;但是张量不是直接表保存一个数组,保存的是计算过程。
- Tensor("Add:0", shape=(), dtype=float32),其中:第一项为名字,冒号前表示具体名字,比如此处是加法的意思,冒号之后是序号,表示这是第几个加法计算;第二项是维度,默认为空,表示此时是一个标量;第三项是类型,类型极其重要,类型匹配是计算的前提。
- Tensor("Add:0", shape=(), dtype=float32)中的shape:一个张量有几维shape的括号里有几个数(通过数中括号对数确定),并逐内在每维度取元素数放在括号里;如: [1,2,3]->shape(3)一维且第一维有三个元素;[[1,2,3],[4,5,6]]->shape(2,3)二维且第一维两个元素第二维3个元素。
- tensor可以像数组一样的取值,如二阶tensor,可以用t[i,j]的形式获取元素,同样的下标是从0开始到。
- 张量的类型是可以缺省的,程序会根据所填入得值自行判断。若传入的值无小数点,则判断为int32;若传入的值有小数点,将判断为float32;由于缺省的存在,一定要注意计算时先确定类型匹配,否则程序很容易出现各种错误。
- 定义张量时虽然名字可以缺省,但是最好是带上,因为这样在Tensorboard上可以有更好的可读性。
操作
- 操作在计算图中表示为一个节点。
- 操作可以是加减乘除的运算,也可以是对常量、变量的初始化。
- 操作可以绑定于不同设备上,这为cpu结合gpu或者多gpu计算提供可能。
会话
- 会话用以整合TF程序运行的所用资源,TF所有的数据计算以及结果显示均在会话中实现,但是注意在程序结束后应及时关闭会话,防止内存泄漏。
-
引入会话可如上;但是上述代码存在问题,一旦在会话关闭语句之前产生异常,程序中途停止,会话将无法正常释放。tens0 = tf.constant([1,2.3]) sess = tf.Session() print(sess.run(tens0)) sess.close()
-
可利用python处理异常的语句改善会话引进的代码。上述代码在何种情况下均会执行会话关闭的操作。tens0 = tf.constant([1,2.3]) sess = tf.Session() try: print(sess.run(tens0)) except: print('Eception!') finally: sess.close()
-
更一般的可以用python的上下文管理器引入会话。此形势下,无论何种方式离开此区域,会话总会正常释放。tens0 = tf.constant([1,2.3]) with tf.Session() as sess: print(sess.run(tens0))
-
TF运行时会产生默认的graph,但是不会产生默认的Session;可以利用语句指定程序在默认会话下进行。在默认会话下,利用tensor.eval()计算张量的值,其效果与sess.run(tensor)一致,但是非默认会话下使用eval函数时错误的。sess = tf.Session() with sess.as_default(): print(tensor.eval())
-
在python中,引入默认会话可以用一个语句实现。sess = tf.InteractiveSession()
常量与变量
-
常量定义如上所示,定义时其名字最好与定义的常量名一致;常量一经定义不再改变,且无需进行额外的初始化操作;但是执行相关运算以及输出其值应在会话中进行。constant_name = tf.constant(value,nmae='constant_name')
-
与常量的定义无异,主要是注意首字母大写。所有变量使用前要进行初始化操作;并注意变量计算往往存在依赖关系,一定安排好先后计算的次序。var_name = tf.Variable(value,nmae='vart_name') init = tf.global_variables_initializer() sess.run(init)
-
神经网络中,权重是以变量的形式存在的,因为变量一经定义一般不会再人为传值,变量本身会随着训练的进行更新;对于不想更新的变量可以如上代码,将trainable参数置为False;特殊情况下需要对变量进行赋值,可以利用上文中的tf.assign进行更改,首参数为待改变的变量,次参数为要输入的值。epoch = tf.Variable(0, name='epoch', trainable=False) # 不更新 update_op = tf.assign(variable_to_be_upadated, newValue) # 人工输入值给变量
-
value = tf.Variable(0, name='value') one = tf.constant(1, name='one') new_value = tf.add(value, one, name='new_value') update_op = tf.assign(value, new_value) init = tf.global_variables_initializer() sess = tf.Session() with sess.as_default(): sess.run(init) for _ in range(10): sess.run(update_op) print(sess.run(value))
上述代码实现了利用tf.assign赋值,输出1到10
-
import tensorflow as tf tf.reset_default_graph() value = tf.Variable(0, name='value') one = tf.constant(1, name='one') new_value = tf.add(value, one, name='new_value') update_value = tf.assign(value, new_value) sum = tf.Variable(0, name='sum') new_sum = tf.add(sum, value, name='sum') update_sum = tf.assign(sum, new_sum) init = tf.global_variables_initializer() sess = tf.Session() with sess.as_default(): sess.run(init) for _ in range(10): sess.run(update_value) sess.run(update_sum) print("value: ", sess.run(value)) print("sum: ", sess.run(sum)) logdir = 'E:/log' writer = tf.summary.FileWriter(logdir, tf.get_default_graph()) writer.close()
上述代码实现了1+..+10,同样是利用了tf.assign对变量进行更新。
占位符
- 对于初未知的变量,用占位符表示;占位符本质上是一种变量,所以使用前也需要进行初始化;在神经网络中,输入数据常以占位符表示。
-
在定义占位符时,一般可选参数是类型、维度与名字;其中名字、维度是可缺省的,但是最好是将名字写作占位符名,来提高可读性;类型是不可缺省的。x = tf.placeholder(dtype, shape=none, name= none)
-
若操作依赖于占位符,在进行操作时,应利用feed_dict来对占位符对应传入初始值;传入时,是以字典的形式实现的。result = sess.run(operation, feed_dict={intput1:a,input2:b ...........})
Tensorboard
- tensorboard是基于tensorflow日志,进行信息提取的可视化工具;可与tensorflow在不同的进程里工作。
-
实现可视化主要为上述四步。1.tf.reset_defualt_garph() # 清除默认图中的计算 2.logdir = 'E:log' # 在指定路径下建立日志文件夹 3.定义各种计算...... 4.writer = tf.summary_FileWriter(logdir, tf.get_defualt_graph()) writer.close() ******************以上完成了对定义计算图,并生成日志************ ******************以下读取日志,并可视化*********************** 1. 在adacoinda的prompt中操作 2.首先切换到日志所在路径 3.使用 tensorboard --logdir==日志路径 4.命令执行后,会最终弹出一个地址,利用这个地址在浏览器进入