2.1 创建图,启动图的方法
2.1.1 Tensorflow基本概念:
-
使用图(graphs)来表示计算任务
-
在被称之为会话(Session)的上下文(context)中执行图
-
使用tensor表示数据
-
通过变量(Variable)维护状态
-
使用feed和fetch可以为任意的操作赋值或者从其中获取数据
Tensorlow是一个编程系统,使用图(graphs)来表示计算任务,图中的节点称之为op(operation),一个op获得0或多个Tensor,执行计算,产生多个0或多个Tensor。Tensor看作是一个n维的数组或列表。图必须在会话(Session)里被启动。
2.1.2 Tensorflow结构:
2.1.3 创建图,启动图代码演示:
import tensorflow as tf
# 创建一个常量节点op
m1 = tf.constant([[3,3]]) # 一行两列矩阵
m2 = tf.constant([[2],[3]]) # 第一个括号是行,第二个括号是列
# 创建一个矩阵乘法op,把m1和m2传入
product = tf.matmul(m1,m2)
print(product)
此处输出结果为:Tensor("MatMul_1:0", shape=(1, 1), dtype=int32)
因为这些计算全要在图里的会话中计算,而我们只是定义了op,但是未放在会话里,所以这里还全是Tensor。想要打印正确结果,方法如下:先定义一个会话,启动默认的图
# 定义一个会话,启动默认图
sess = tf.Session()
# 调用sess的run方法来执行矩阵乘法op
# run(product)触发了图中的3个op
result = sess.run(product)
print(result)
sess.close() # 关闭会话
输入结果:[[15]]
如上图定义会话的方式较麻烦,我可以采用如下方式定义会话最为常用:
with tf.Session() as sess:
# 调用sess的run方法来执行矩阵乘法op
# run(product)触发了图中的3个op
result = sess.run(product)
print(result)
此处定义会话的方式不需要执行关闭会话。
2.2 TensorFlow变量使用
import tensorflow as tf
x = tf.Variable([1,2])
a = tf.constant([3,3])
#增加一个减法op
sub = tf.subtract(x,a)
#增加一个加法op
add = tf.add(x,sub)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
print(sess.run(sub))
print(sess.run(add))
输出结果如下:
[-2 -1]
[-1 1]
此处需要注意:
-
在TensorFlow里使用变量的时候需要对变量进行初始化操作,因为Session不在Python环境下执行,对应上图中tf模块下的
tf.global_variables_initializer()
方法。 -
本处定义的是一个数组,与2-1中定义的矩阵不同,区分一下。
# 创建一个变量,初始化为0
state = tf.Variable(0,name='counter')
# 创建一个op,使state加1
new_value = tf.add(state,1)
# 赋值op
update = tf.assign(state,new_value)
# 变量初始化
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
print(sess.run(state))
for _ in range(5):
sess.run(update)
print(sess.run(state))
输出结果为:
0
1
2
3
4
5
需要注意的是:
-
此处赋值的时候需要创建一个赋值op
-
此处循环变量用_是一种编程习惯,表示循环内部不用到这个变量名
2.3 Fetch和Feed用法
Fetch表示在一个会话里可以同时执行多个op,得到它运行的结果
import tensorflow as tf
# Fetch
input1 = tf.constant(3.0)
input2 = tf.constant(2.0)
input3 = tf.constant(5.0)
add = tf.add(input1,input3)
mul = tf.multiply(input1,add) # 此处是数乘
with tf.Session() as sess:
result = sess.run([mul,add])
print(result)
输出结果如下:
[24.0, 8.0]
注意点:
-
这里数与数之间的乘法,使用的
tf.multiply()
,而前面的是矩阵或者数组的乘法,使用的tf.matmul()
-
此处的常量op必须赋值才能进行下面的运算,与下面的Feed区分开
Feed用法剖析如下:
# Feed
# 创建占位符
input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)
output = tf.multiply(input1,input2)
with tf.Session() as sess:
# feed的数据以字典的形式传入
print(sess.run(output,feed_dict={input1:[8.],input2:[2.]}))
输出结果如下:
[16.]
注意点:
-
此处使用Feed时可以在初始化常量时不赋值,先创建占位符,而在执行乘法op的时候再进行赋值即可,赋值方式对应Python里的字典方法
-
此处的键没有带单引号的原因是因为初始化的input已经是字符串类型
2.4 TensorFlow简单使用案例
import tensorflow as tf
import numpy as np
# 使用numpy生成100个随机点
x_data = np.random.rand(100)
y_data = x_data*0.1 + 0.2
#构造一个线性模型
b = tf.Variable(0.)
k = tf.Variable(0.)
y = k*x_data + b
# 二次代价函数
loss = tf.reduce_mean(tf.square(y_data - y))
# 定义一个梯度下降法来进行训练的优化器
optimizer = tf.train.GradientDescentOptimizer(0.2)
# 最小化代价函数
train = optimizer.minimize(loss)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
for step in range(201):
sess.run(train)
if step%20 == 0:
print(step,sess.run([k,b]))
输出结果如下:
0 [0.05260047, 0.09980422]
20 [0.102601565, 0.19862503]
40 [0.10155965, 0.19917576]
60 [0.10093498, 0.19950588]
80 [0.10056051, 0.19970378]
100 [0.10033602, 0.19982243]
120 [0.100201435, 0.19989355]
140 [0.100120746, 0.1999362]
160 [0.100072384, 0.19996175]
180 [0.1000434, 0.19997706]
200 [0.10002602, 0.19998625]
-
optimizer = tf.train.GradientDescentOptimizer(0.2)
,此处使用的是梯度下降法优化器,给定的学习率为0.2 -
此处使用梯度下降迭代201次之后,学习到的k和b都非常接近理想值
2.5 TensorFlow下非线性回归
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
x_data = np.linspace(-0.5,0.5,200)[:,np.newaxis]
noise = np.random.normal(0,0.02,x_data.shape)
y_data = np.square(x_data) + noise
# 定义两个placeholder,此处形状为行数不确定,列数为1
x = tf.placeholder(tf.float32,[None,1])
y = tf.placeholder(tf.float32,[None,1])
# 定义神经网络中间层,此处使用十个神经元作为中间层
Weight_L1 = tf.Variable(tf.random_normal([1,10]))
biases_L1 = tf.Variable(tf.zeros([1,10]))
Wx_plus_b_L1 = tf.matmul(x,Weight_L1) + biases_L1
L1 = tf.nn.tanh(Wx_plus_b_L1)
# 定义神经网络输出层
Weight_L2 = tf.Variable(tf.random_normal([10,1]))
biases_L2 = tf.Variable(tf.zeros([1,1]))
Wx_plus_b_L2 = tf.matmul(L1,Weight_L2) + biases_L2
prediction = tf.nn.tanh(Wx_plus_b_L2)
# 二次代价函数
loss = tf.reduce_mean(tf.square(y-prediction))
# 使用梯度下降法
train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
with tf.Session() as sess:
# 变量初始化
sess.run(tf.global_variables_initializer())
for _ in range(2000):
sess.run(train_step,feed_dict={x:x_data,y:y_data})
#获得预测值
prediction_value = sess.run(prediction,feed_dict={x:x_data})
#画图
plt.figure()
plt.scatter(x_data,y_data)
plt.plot(x_data,prediction_value,'-r',lw=3)
plt.show()
非线性回归学习结果如下:
Tips:
-
此处的
Weight_L1 = tf.Variable(tf.random_normal([1,10]))
表示给权值W赋予一个随机的初始值,此处W的维度是一行十列 -
L1 = tf.nn.tanh(Wx_plus_b_L1)
表示中间层的输出,此处使用双曲正切激活函数 -
使用占位符placeholder相当于占一个位置,下面操作和数据是分开的,如果以后拟合目标不是二次函数而是别的,也能够快速修改。