1-1
# tensorflow 1.0 之后的版本实现 [tf1 对应 python 3.5 版本,尝试可用]
# tf1 版本的好处,网上有大量的资料;tf1在一些公司的使用还是比较多的;tf1是目前深度学习框架最难的
# 基于以上 3 点,所以推荐 tf1 版本
# warnings 用来屏蔽警告,因为 tf1 会出现很多警告,这些警告和代码运行时无关的
import warnings
warnings.filterwarnings("ignore")
import tensorflow as tf
1-2 简单的示例
ht = tf.constant('Hello,tf!',name="hello_tf")
print(ht)
# --> tf.Tensor(b'Hello,tf!', shape=(), dtype=string)
# 返回的内容意思是,返回一个 Tensor对象,名字是hello,tf,shape形状,这里是空的
# 类型是 string
1-2-1
# 想看 tensor 的值,只能建立对象,用run的方法才可以查看
# 所以需要先用 session() 创建对话
sess = tf.Session()         # 完成会话建立
ht_value = sess.run(ht)     # 将当前Tensor放进去,返回 ht_value
print(ht_value)
# -->
# b'Hello,tf!'
sess.close()                
# 当然,打开一个会话就要记得关闭;如果不关闭,会话流会一直存在,造成内存泄漏
1-2-2
# 在Python中,有开有关的东西,可以用 with 结构
# 注:with 结构的参考链接:https://blog.51cto.com/u_15149862/2799896
# 使用with结构,运行结束可以自动关闭session
with tf.Session() as sess:
    ht_value = sess.run(ht)
    print(ht_value)
# -->
# b'Hello,tf!'
# 需要注意,形状 shape 是一个非常重要的数据说明;庞大的数据肉眼是无法观看的
# 形状一般是指 矩阵的纬度
1-2-3
# [1,2,3]   (3,)  
# 说明是 一阶的 Tensor,里面有 3 个元素
# [[1,1],[2,2],[,3,3]]   (3,2)      
# 这是一个 3 行 2 列 的矩阵,这是 一个 2 阶的 Tensor 它的 Shape 是 3 行 2 列; (3,2)
# [[[11,11],[12,12]],[[22,22],[23,23]],[[33,33],[34,34]]]   (3,2,2)
# 第一个[]里有 3 个元素,第 2 3 个[] 有 2 个元素,所以是 (3,2,2); 这是一个 3 阶的 Tensor
# 彩色图片一般都是 3 个维度,长宽和通道数
# ......
1-3 标准模式
# 在 tf1(TensorFlow 1) 中,搭建模型和训练模型是分开的
# 搭建模型叫搭建计算图
# 执行模型叫运行计算图
# 类似于 设计电路板时,需要按照电路图把电路板刻出来,刻出来之后,需要通电,电路板才能用
# 这里也是如此,写模型时,先把模型写到一张计算图里;这时里面是没有数据的
# 只是先在计算图中进行定义
# 定义完成后,训练时需要运行计算图

# 所以需要 2 部分,先创建一个 TensorFlow 的图
# 创建一个 graph 对象
graph_t = tf.Graph()

# 将 graph 设置为默认的图
# 在with 结构下,作为默认的图
with graph_t.as_default():
    ht = tf.constant('Hello,tf!',name="hello_tf")
# 计算图写完后,如何运行这张图?
# 创建session运行计算图
# 使用 with 结构 定义 sess,在这里运行计算图的节点即可
with tf.Session(graph=graph_t) as sess:
    ht_value = sess.run(ht)
    print(ht_value)
# --> b'Hello,tf!'
# 这是 TensorFlow 1.0 的标准模式,也是一般模式;设计成这种结构的目的是为了加速训练
# 在后续的 TensorFlow 版本中,这种结构就不多了
1-4 简单计算
graph_t = tf.Graph()        # 定义一个 tf 计算图
# 以下就是一个计算
with graph_t.as_default():
    # 定义 2 个常量节点
    a = tf.constant(2,name="a")
    b = tf.constant(3,name="b")
    c = a + b
# 现在想看 c 的值,所以在 运行计算图里,查看 c 的值
with tf.Session(graph=graph_t) as sess:
    c_value = sess.run(c)
    print(c_value)
# --> 5
1-4-1 # 现在 a b c 的值都想看
# 用 sess.run,把 3 个值,放到 列表里面,接收的时候分别接收
# 看下a,b的值
with tf.Session(graph=graph_t) as sess:
    a_value,b_value,c_value = sess.run([a,b,c])
    print(a_value,b_value,c_value)
# --> 2 3 5
1-5 placeholder
# placeholder 可以认为是一种占位符类型的变量
# 之所以存在是因为比如线性回归中  x 和 y 应该先传到网络图中
# 所以在网络图里,就应该有变量去接收 X 和 Y,这种变量就被称作 placeholder 变量
a = tf.placeholder(tf.float32)  # 里面需要告诉传入值的类型
print(a)
# --> Tensor("Placeholder:0", dtype=float32)
# 结果说明,名字是 Placeholder,类型是 float32
# 定义placeholder时,如果传入的数据不是这个类型,会强制转换成需要的类型
1-5-1 # 那么 placeholder 怎么用?
# 以后写 TensorFlow 程序时,如果是 1.0 版本,基本都是需要这样写的
# 不要脱离 with 结构,这样容易出现问题
graph_t = tf.Graph()
with graph_t.as_default():
    a = tf.placeholder(tf.float32)
with tf.Session(graph=graph_t) as sess:
    a_value = sess.run(a)
    print(a_value)
# --> 
# InvalidArgumentError (see above for traceback): 
# You must feed a value for placeholder tensor 'Placeholder' with dtype float
# 这时 print(a_value) 会报错,TensorFlow 报错会很长,因为它的调用关系比较多
# 一般就是看最下端
# 必须给 Tensor placeholder 一个值,才能看他的具体值
1-5-2 # 那么 placeholder 应该怎样赋值呢?
graph_t = tf.Graph()
with graph_t.as_default():
    a = tf.placeholder(tf.float32)
with tf.Session(graph=graph_t) as sess:
    a_value = sess.run(a,{a:1.0})       
    # {a:1.0} 参数名称 叫 feed dict;其实传 1 也可以,会转换成 float
    print(a_value)
# --> 1.0
1-5-3 # 现在把 1-4 中的常量计算用 placeholder 替代
graph_t = tf.Graph()
with graph_t.as_default():
    a = tf.placeholder(tf.float32)
    b = tf.placeholder(tf.float32)
    c = a + b
# 这里 a 和 b 只是起到了 定义的作用,定义 外部要传进来的值的类型
# 其实也是可以定义形状的
# 传入的值,必须要和定义的形状保持一致

# 现在想看 c 的值,就必须给 a b 传值;用到谁,就需要给谁传值
with tf.Session(graph=graph_t) as sess:
    c_value = sess.run(c,{a:2.0,b:3.0})
    print(c_value)
# --> 5.0
2-1 # 建立一个c= (a+2b)*b 计算图,传入任意a、b的值,输出c的结果
import warnings
warnings.filterwarnings("ignore")

import tensorflow as tf

graph_t = tf.Graph()
with graph_t.as_default():
    a = tf.placeholder(tf.float32)
    b = tf.placeholder(tf.float32)
    c = (a + 2*b)*b

with tf.Session(graph=graph_t) as sess:
    c_value = sess.run(c,{a:2.0,b:5.0})
    print(c_value)
# --> 60.0
3-1 Variable
# Variable 是 线性回归中的 w 和 b;是神经网络里,真实定义的不断变化的变量
a = tf.Variable(2.0, dtype=tf.float32)      # Variable 必须给 初始值
print(a)
# --> Tensor("Variable/read:0", shape=(), dtype=float32)
# 结果显示是一个 Variable 
3-1-1
graph_t = tf.Graph()
with graph_t.as_default():
    a = tf.Variable(2.0, dtype=tf.float32)
    b = tf.Variable(3.0, dtype=tf.float32)
    c = a + b

# 现在看 c 的值
with tf.Session(graph=graph_t) as sess:
    c_value = sess.run(c)
    print(c_value)
# FailedPreconditionError (see above for traceback): 
# Attempting to use uninitialized value Variable_1
# 结果报错了,为什么会这样?
# 因为在计算图里,写的东西都算是定义;前面的 placeholder 和 常量 constant 也都算是定义
# 只是定义了 有一个 Variable 向量,初始化是 3.0 和 2.0
# session run 时 没有赋值操作
3-1-2 # 什么叫赋值操作?
graph_t = tf.Graph()
with graph_t.as_default():
    a = tf.Variable(2.0, dtype=tf.float32)
    b = tf.Variable(3.0, dtype=tf.float32)
    c = a + b
# 就是使用 tf 的全局向量初始化,session run 一下 init
with tf.Session(graph=graph_t) as sess:
    init = tf.global_variables_initializer()    
    # 这一行代码的作用是,将初始化定义的变量的值,放到变量里面
    # 第一次训练,必须初始化
    sess.run(init)
    c_value = sess.run(c)
    print(c_value)
# --> 5.0