importtensorflowas tf
此时不报错说明tensorflow已经装好。
1、张量
张量是Tensorflow的中心单元,一个张量含有一系列原始的数据,这些数据可以变形为任意维度的数组,一个张量的rank代表的是这个张量的维度。
2、计算图
Tensorflow核心工程实际上有两个具体的部分
建立计算图
运行计算图
一个计算图是一系列TensorFlow对图节点的操作,首先我们可以建立两个浮点型节点:
node1=tf.constant(3.0,tf.float32) node2=tf.constant(4.0) print(node1,node2)
此时可以看到输出结果为:
Tensor("Const:0", shape=(), dtype=float32) Tensor("Const_1:0", shape=(), dtype=float32)
注意这里结果不会输出3.0,4.0.为了去评估每一个节点,我们需要在session内运行计算图。每一个session封装了对tensorflow的控制和状态
我们可以用以下的代码来建立一个session:
sess=tf.Session() print(sess.run([node1,node2]))
这里我们可以得到结果:
[3.0, 4.0]
当然我们可以通过对tensor的混合来建立更加复杂的计算,比如,我们可以使我们两个常量节点相加来生成一个新的计算图:
node3=tf.add(node1,node2) print("node3:",node3) print(sess.run(node3))
运行结果:
node3: Tensor("Add:0", shape=(), dtype=float32)
7.0
TensorFlow提供了一个名为TensorBoard的实用程序来展示一个图:
当然这个图还不够有趣,因为他仅仅会输出一个固定的结果,一个图应该被参数化为能接受外部的输入,这样变量被称为placeholders。
a=tf.placeholder(tf.float32) b=tf.placeholder(tf.float32) adder_hold=a+b
这里我们定义了两个输入参数a,b以及一个他们之间的运算。我们可以使用feed_dict参数来评估一个多输入图。
print(sess.run(adder_hold,{a:3,b:4.5})) print(sess.run(adder_hold,{a:[1,3],b:[4,6]}))
运行结果:
7.5
[ 5. 9.]
而在TensorBoard中,计算图如下:
当然,我们可以把计算图变得更复杂:
adder_hold_triple=adder_hold*3 print(sess.run(adder_hold_triple,{a:6,b:3}))
运行结果:
27.0
此时在TensorBoard中,计算图会变成这样:
在机器学习中,我们总是希望一个模型能够接受任意的输入。因此,为了使得这个模型可训练,我们需要修改这个图去得到新的输出。
Variable这个允许我们增加可训练的参数到原图中,这种变量需要初始化为一个类型和初始值:
W=tf.Variable([.3],tf.float32) b=tf.Variable([-.3],tf.float32) x=tf.placeholder(tf.float32) linear_model=W*x+b
tf.constants是一个固定的数,而对于Variable这种变量,我们需要对其进行初始化。
init=tf.global_variables_initializer() sess.run(init)
需要注意的是,直到我们调用sess之前,所有的变量Variable都是未初始化的。
由于x是一个placeholder,我们可以这样来同步评估线性模型:
print(sess.run(linear_model,{x:[1,2,3,4]}))
运行结果:
[ 0. 0.30000001 0.60000002 0.90000004]
我们已经建立了一个模型,但我们不知道这个模型的好坏,为了评估这个模型在训练集上的性能,我们需要一个placeholder来提供一个我们所需要的值。另外,我们需要写一个损失函数。
损失函数表征当前模型与提供数据的差异性。我们可以使用一个标准的损失模型来评估线性回归。也就是模型预测值与实际值的差的平方和
y=tf.placeholder(tf.float32) squared_deltas = tf.square(linear_model-y) loss = tf.reduce_sum(squared_deltas) print(sess.run(loss,{x:[1,2,3,4], y:[0,-1,-2,-3]}))
运行结果:
23.66
这个23.66实际上=(0-0)平方+(0.3-(-1))平方+(0.6-(-2))平方+(0.9-(-3))平方
我们可以通过重新设定W和b的值来尽可能来减少损失函数,我们可以看出W为-1且b为1时,这个函数的性能最好。
fixW = tf.assign(W,[-1.]) fixb = tf.assign(b,[1.]) sess.run([fixW, fixb]) print(sess.run(loss,{x:[1,2,3,4],y:[0,-1,-2,-3]}))
运行结果:
0.0
我们可以通过数学知识知晓W和b的最优值,而在真正大型的机器学习过程中,机器会自动的去寻找最优的W和b的值来适应模型。
3、训练API
tensorflow 提供了优化器optimizer来缓慢的改变每一个变量,由此达到最小化损失函数loss function的目的。
最简单的优化器叫做梯度下降,它会根据每个变量导数的大小对其进行修改。总而言之,手工计算倒数是乏味且容易出错的。因此tensorflow可以通过tf.gradient自动产生导数,而优化器就是做的这个工作。
optimizer = tf.train.GradientDescentOptimizer(0.01) train = optimizer.minimize(loss) sess.run(init) for i in range(1000): sess.run(train, {x:[1,2,3,4], y:[0,-1,-2,-3]}) print(sess.run([W,b]))
运行结果:
[array([-0.9999969], dtype=float32), array([ 0.99999082], dtype=float32)]
如果把输出W和b的函数放入到循环内部,则:
运行结果部分如下:
[array([-0.99999636], dtype=float32), array([ 0.99998927], dtype=float32)]
[array([-0.99999642], dtype=float32), array([ 0.99998939], dtype=float32)]
[array([-0.99999648], dtype=float32), array([ 0.99998951], dtype=float32)]
[array([-0.99999648], dtype=float32), array([ 0.99998963], dtype=float32)]
[array([-0.99999654], dtype=float32), array([ 0.99998975], dtype=float32)]
[array([-0.9999966], dtype=float32), array([ 0.99998987], dtype=float32)]
[array([-0.9999966], dtype=float32), array([ 0.99998999], dtype=float32)]
[array([-0.99999666], dtype=float32), array([ 0.99999011], dtype=float32)]
[array([-0.99999666], dtype=float32), array([ 0.99999022], dtype=float32)]
[array([-0.99999672], dtype=float32), array([ 0.99999034], dtype=float32)]
[array([-0.99999672], dtype=float32), array([ 0.99999046], dtype=float32)]
这就是一个简单的线性的机器学习样例,尽管做这个简单的线性回归不需要太多的TensorFlow核心代码,更复杂的模型和方法需要更多的核心代码,以及更高级的抽象模型。下面这个线性模型在TensorBoard中的计算图表示:
4、tf.contrib.learn
tf.contrib.learn是TensorFlow的一个高级库,他简化了机器学习的机制并定义了许多常用的模型。
同样还是线性模型的例子:
import tensorflow as tf import numpy as np features = [tf.contrib.layers.real_valued_column("x", dimension = 1)] estimator = tf.contrib.learn.LinearRegression(feature_columns=features) x= np.array([1,2,3,4]) y= np.array([0,-1,-2,-3]) input_fn = tf.contrib.learn.io.numpy_input_fn({"x":x}, y,batch_size=4,num_epochs=1000) estimator.fit(input_fn=input_fn, steps=1000) estimator.evaluate(input_fn=input_fn)
运行结果:
{'global_step': 1000, 'loss': 2.4252321e-08}
这段代码中,numpy这个库常用于对数据的加载、控制和预处理。之后使用features这个变量来传入一个实值特征。而这个estimator估计器是一个前端的,用来唤醒训练和评估功能,在库函数中,有许多预先定义好的函数,如线性回归,逻辑回归,线性分类,逻辑分类等。还有很多神经网络的分类器和回归器。本次代码中,我们仅用到了线性回归的估计器。Tensorflow给我们提供了很多方法去读和建立数据集合,这里我们使用了numpy_input_fn。我们需要写出每次训练批次数据的大小,训练的次数以及批次数。之后我们使用1000的次数调用fit函数来进行拟合。最后,我们调用evaluate函数来评估我们的模型,当然,在实际的训练中,我们会把训练集和测试集分开,来防止过拟合的发生。
5、经典模型
tf.contrib.learn这个函数并不限制我们对于模型的使用,如果我们想要建立一个常用的但是还没有存在于Tensorflow库中的模型,我们仍可以优化高抽象的数据集,并对其进行训练。
定义一个常用模型时,我们需要用到tf.contrib.learn.Estimator.实际上,tf.contrib.learn.LinearRegressor是tf.contrib.learn.Estimator的一个子类,我们可以使用model_fn来代替他,代码如下:
import numpy as np import tensorflow as tf def model(features, labels, mode): W = tf.get_variable("W", [1], dtype=tf.float64) b = tf.get_variable("b", [1], dtype=tf.float64) y = W*features['x'] + b loss = tf.reduce_sum(tf.square(y - labels)) global_step = tf.train.get_global_step() optimizer = tf.train.GradientDescentOptimizer(0.01) train = tf.group(optimizer.minimize(loss), tf.assign_add(global_step, 1)) return tf.contrib.learn.ModelFnOps( mode=mode, predictions=y, loss=loss, train_op=train) estimator = tf.contrib.learn.Estimator(model_fn=model) x = np.array([1., 2., 3., 4.]) y = np.array([0., -1., -2., -3.]) input_fn = tf.contrib.learn.io.numpy_input_fn({"x": x}, y, 4, num_epochs=1000) estimator.fit(input_fn=input_fn, steps=1000) print(estimator.evaluate(input_fn=input_fn, steps=10))
运行结果:
{'loss': 1.0118058e-10, 'global_step': 1000}
首先这里我们把原本的Variable函数换为了get_variable函数,在实际使用时,我们一般更常用get_variable这个函数,这个函数可以共享变量。而Variable一般用于较低版本中。之后我们采用了tf.contrib.learn.ModelFnOps来定义此模型,并通过input_fn来传入参数,最终得到训练结果。
以上就是tensorflow的一些最基础的知识,之后对tensorflow的学习可以从Mnist来入手。
注:本人python版本为3.5.2.在windows下使用pycharm来运行的,tensorflow采用的是windows下的CPU版本