前言
什么是TensorFlow
什么是TensorFlow,Google的人是这样说的
TensorFlow™ 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。 它灵活的架构让你可以在多种平台上展开计算,例如台式计算机中的一个或多个CPU(或GPU),服务器,移动设备等等。TensorFlow 最初由Google大脑小组(隶属于Google机器智能研究机构)的研究员和工程师们开发出来,用于机器学习和深度神经网络方面的研究,但这个系统的通用性使其也可广泛用于其他计算领域。
TensorFlow是由Google brain team打造的一个神经网络的包,可以说他是以数据流图来进行数值计算的开源库,毕竟从名字来看Tensor Flow,张量 流动,代表着数据会流动。
为什么要用TensorFlow
TensorFlow出世以来被人们认为是最好的神经网络开源库之一,最大的优势就是可以让人们把它当成黑盒去构建我们的神经网络,使我们非常容易的构建出神经网络,降低了学习成本、开发成本、维护成本,而且由于开源,所以TensorFlow会进步的非常快。而且有着完整的移植性,那么什么是完整的移植性?TensorFlow可以跑在CPU上,GPU上;可以跑在Linux上、Mac上甚至Windows上;更激动的是移动平台也支持了Android、IOS;甚至目前物联网火热,连树莓派也支持了! 而且TensorFlow可以用C++开发,也可以用Python开发甚至JAVA、Go。
现在,让我们一起来学习TensorFlow吧!
hello TensorFlow
在码农的启蒙时代,我们学习新的语言的时候我们的第一行代码通常都是hello world,向世界招手。那我们先跟TensorFlow打个招呼吧正好测试下我们的TensorFlow环境有没有搭好(PS:本文使用的语言为Python2.7.13)
import tensorflow as tf
hello=tf.constant('hello TensorFlow')
sess=tf.Session()
print sess.run(hello)
输出:
hello TensorFlow
看到输出hello TensorFlow,那我们的环境没有问题了,进入基础的学习吧!
常量(constant)
在TensorFlow中,我们想要申请一个常量是非常简单的,直接使用constant去声明就好了,比如下面的一个加法小程序:
import tensorflow as tf
a=tf.constant(2)
b=tf.constant(3)
with tf.Session() as sess:
print sess.run(a)+sess.run(b)
输出:
5
变量(Variable)
在TensorFlow中,我们声明变量跟Python中直接声明变量有点不同,多了一个初始化的步骤,而且我们想要获取到值得时候需要用session.run()方法来获取。如下面的小程序,每次运行加一
import tensorflow as tf
state=tf.Variable(0,name='counter')
one=tf.constant(1)
new_value=tf.add(state,one)
update=tf.assign(state,new_value)
init=tf.global_variables_initializer()# 初始化非常重要!!!!!
with tf.Session() as sess:
sess.run(init)# 一定要运行这一句!!!!!!
for _ in range(3):
sess.run(update)
print sess.run(state)
输出:
1
2
3
会话(Session)
我对session的理解就是一个tf的执行代码块,代码块之间互不影响。在tf中运算、获取变量值、输出文件都需要用到session.run()
方法。
Session的写法有两种,一种是需要我们手动去关闭session的,另一种是借助Python的with,自身形成一个代码块,结束时自动关闭。代码如下:
import tensorflow as tf
import numpy as np
matrix1=tf.constant([[3,3]])
matrix2=tf.constant([[2],[2]])
product=tf.matmul(matrix1,matrix2)
sess=tf.Session()# 需要手动关闭session
print sess.run(product)
sess.close()
with tf.Session() as sess:# 类似for循环代码块,不许要手动关闭session
print sess.run(product)
[[12]]
[[12]]
占位符(placeholder)
在TensorFlow中,我们想要从外部传入数据到我们的神经网络中,我们需要先声明占位符变量,然后再运行时加入参数feed_dict={input1:[7.],input2:[2.]},代码如下:
import tensorflow as tf
input1=tf.placeholder(tf.float32)# 由于TensorFlow的常用数据格式是float32,所以我们这里定它为float32
input2=tf.placeholder(tf.float32)
output=tf.mul(input1,input2)
with tf.Session() as sess:
print sess.run(output,feed_dict={input1:[7.],input2:[2.]})
print sess.run(output,feed_dict={input1:[8.],input2:[2.]})
输出:
[ 14.]
[ 16.]
激励函数(activation function)
激励函数运行时激活神经网络中某一部分神经元,将激活信息向后传入下一层的神经系统。激励函数的实质是非线性方程。 Tensorflow 的神经网络里面处理较为复杂的问题时都会需要运用激励函数
TensorFlow当黑盒使用的话,提供了那么几种activation function:
- tf.nn.relu
- tf.nn.relu6
- tf.nn.crelu
- tf.nn.elu
- tf.nn.softplus
- tf.nn.softsign
- tf.nn.dropout
- tf.nn.bias_add
- tf.sigmoid
- tf.tanh
这里只列举TensorFlow内置的activation function列表,详情请看:https://www.tensorflow.org/api_docs/python/nn/activation_functions_
拟合直线
讲了那么多,我们用一个最基本的例子来拟合一条直线,看看效果吧。为了动态拟合,步数全显示,拟合效果要在本地运行
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
x_data=np.random.rand(100).astype(np.float32)
y_data=x_data*0.1+0.3
Weights=tf.Variable(tf.random_uniform([1],-1.0,1.0))
biases=tf.Variable(tf.zeros([1]))
y=Weights*x_data+biases
loss=tf.reduce_mean(tf.square(y-y_data))
optimizer=tf.train.GradientDescentOptimizer(0.5)
train=optimizer.minimize(loss)
init=tf.global_variables_initializer()
sess=tf.Session()
sess.run(init)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.scatter(x_data, y_data)
plt.ion()
plt.show()
for step in range(201):
try:
ax.lines.remove(lines[0])
except Exception:
pass
sess.run(train)
if step%20==0:
print(step,sess.run(Weights),sess.run(biases))
predition_value = sess.run(Weights)*x_data+sess.run(biases)
lines = ax.plot(x_data, predition_value, 'r-', lw=3)
plt.pause(0.1)
输出:
(0, array([-0.39641881], dtype=float32), array([ 0.86255205], dtype=float32))
(20, array([-0.07684354], dtype=float32), array([ 0.4014357], dtype=float32))
(40, array([ 0.04925749], dtype=float32), array([ 0.32910541], dtype=float32))
(60, array([ 0.08544023], dtype=float32), array([ 0.30835137], dtype=float32))
(80, array([ 0.09582227], dtype=float32), array([ 0.3023963], dtype=float32))
(100, array([ 0.09880129], dtype=float32), array([ 0.30068758], dtype=float32))
(120, array([ 0.09965606], dtype=float32), array([ 0.3001973], dtype=float32))
(140, array([ 0.09990131], dtype=float32), array([ 0.30005661], dtype=float32))
(160, array([ 0.09997168], dtype=float32), array([ 0.30001625], dtype=float32))
(180, array([ 0.09999187], dtype=float32), array([ 0.30000466], dtype=float32))
(200, array([ 0.09999766], dtype=float32), array([ 0.30000135], dtype=float32))
聪明的你应该会知道这是拟合一条y=Wx+b的直线,并通过不断减少loss得到最优解。
拟合曲线
拟合完直线之后我们来拟合曲线,咦代码好像有点不同,没错,他多了层的概念!
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
def add_layer(inputs,in_size,out_size,activatuib_funaction=None):
Weights=tf.Variable(tf.random_normal([in_size,out_size]))
biases=tf.Variable(tf.zeros([1,out_size]))+0.1
Wx_plus_b=tf.matmul(inputs,Weights)+biases
if activatuib_funaction is None:
outputs=Wx_plus_b
else :
outputs=activatuib_funaction(Wx_plus_b)
return outputs
x_data=np.linspace(-1,1,300)[:,np.newaxis]
noise=np.random.normal(0,0.05,x_data.shape)
y_data=np.square(x_data)-0.5+noise
xs=tf.placeholder(tf.float32,[None,1])
ys=tf.placeholder(tf.float32,[None,1])
l1=add_layer(xs,1,10,activatuib_funaction=tf.nn.relu)
predition=add_layer(l1,10,1,activatuib_funaction=None)
loss=tf.reduce_mean(tf.reduce_sum(tf.square(ys-predition),reduction_indices=[1]))
train_step=tf.train.GradientDescentOptimizer(0.1).minimize(loss)
init=tf.global_variables_initializer()
with tf.Session() as sess:
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
ax.scatter(x_data,y_data)
plt.show(block=False)
sess.run(init)
for train in range(1000):
sess.run(train_step,feed_dict={xs:x_data,ys:y_data})
if train%50==0:
try:
ax.lines.remove(lines[0])
except Exception:
pass
print train,sess.run(loss,feed_dict={xs:x_data,ys:y_data})
predition_value=sess.run(predition,feed_dict={xs:x_data})
lines=ax.plot(x_data,predition_value,'r-',lw=5)
plt.pause(0.1)
0 4.32185
50 0.0105035
100 0.00698409
150 0.00597143
200 0.00554833
250 0.00528405
300 0.00509511
350 0.00494532
400 0.00480955
450 0.00467035
500 0.00454288
550 0.00441678
600 0.00429541
650 0.00417984
700 0.00406591
750 0.00395388
800 0.00384926
850 0.00374607
900 0.00365008
950 0.00356661
添加层(add layer)
刚刚的拟合效果还是挺好的吧,可以注意到代码里有个add_layer方法,而且被调用2次,多了2个层,那么我们的add_layer方法怎么去定义的呢
def add_layer(inputs,in_size,out_size,activatuib_funaction=None):
Weights=tf.Variable(tf.random_normal([in_size,out_size]))
biases=tf.Variable(tf.zeros([1,out_size]))+0.1
Wx_plus_b=tf.matmul(inputs,Weights)+biases
if activatuib_funaction is None:
outputs=Wx_plus_b
else :
outputs=activatuib_funaction(Wx_plus_b)
return outputs
从函数定义来说起,我们调用这个函数的时候,需要给他的值有,输入值,输入值的数量,输出的数量,激活函数,这里给一个默认值,默认为空。
在神经网络的计算中,我们一般都会有权重(Weights)和偏差值(biases)两个变量,所以我们定义了Weights和biases,一般我们会给出初始值,Weights用随机函数生成,biases初始为0再加个0.1,为什么要+0.1呢,因为机器学习中推荐biases不为0,所以加上0.1。
然后定义了一个函数W*x+b
然后我们看有没有传入激活函数,如果没有激活函数的话就直接输出刚刚的算出来的值,如果有激活函数的话我们只需要把刚算出来的值传进去激活函数就行。
后记
TensorFlow的基本用法介绍到这里,下一节是对上面的拟合曲线进行讲解,更多高级的TensorFlow用法请继续关注~