本来看到tensorflow是linux的比较崩溃,本人linux一窍不通
笔记本上经常遇到问题,一下解决一天。所以又是一些莫名的问题配置了两天,最后一怒之下换了台式。
目前,使用ubuntu麒麟1604的64位OS,感觉和自己相性很好,因为像win的界面化,个人比较喜欢
基本上,新系统上配置tensorflow很简单
1.安装annaconda,官网下就好了
2.使用下面命令安装tensorflow,一下就装好了
conda install -chttps://conda.anaconda.org/jjhelmus tensorflow
3.个人喜好安装ide,我喜欢用pycharm,不愿意用ipython,装完后就大功告成啦!
这里先不做udacity的第一个assgiment,因为本人也是小白一个,对tensorflow只有一句话的认识。
所以打算先看官方的tutorial
首先我们测试一下是否配置好了,
按照tensorflow官方的tutorial的第一段代码,跑一下看看:
可以看出是个线性回归哈~
那么配置没问题了,接下来我们就食用蓝色药丸(黑客帝国梗妥妥的):
进入mnist超新手教程,官网说的很清楚哈,不解释softmax了,之前好像也说过。
直接上代码看看吧:
from__future__ importabsolute_import
from__future__ importdivision
from__future__ importprint_function
# Import datafromtensorflow.examples.tutorials.mnist importinput_data
importtensorflow astf
flags = tf.app.flags
FLAGS = flags.FLAGS
flags.DEFINE_string('data_dir', '/tmp/data/', 'Directory for storing data')
这里值得提一句的是,他把data存放位置设置成了tmp下面的data文件夹,我们知道linux的/tmp重启后数据会不见。所以如果不想每次都重新下载,可以改一下存放路径,不过其实无所谓,这个数据集很小,网速可以的童鞋就别管啦。
mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True)
sess = tf.InteractiveSession()
mnist是函数读取出来的数据集并整合成的一个大的结构。具体包括了
mnist.train.images
mnist.train.labels
mnist.test.imagesmnist.test.labels
----------------------------------
实际上进一步学习tutorial发现,
mnist是一个轻量级的类,以Numpy数组的形式存储着训练、校验和测试数据集。同时提供了一个函数,用于在迭代中获得minibatch
----------------------------------
而这每一个,就是tensorflow中的tensor了,我个人理解,说白了张量就是样本矩阵合集
例如:
这就是一个张量。在我们这里,这个张量的大小是60000 X 784 ,784是每个样本(28X28的图片被扁平化后的数值,一共有六万个数据)
而[a,b]这样一个张量,第一个元素是样本的索引,第二个元素是图片中像素点的索引
而[a,b]对应一个值。比如[1,1]就是第一个样本第一个元素的像素值,是一个介于0-1的取值
而标签同样是一个张量。且一般像udacity课程中讲授的那样,使用one hot encoding。故,[1,1]表示第一个样本的第一个编码位是多少。这里看图应该是0/1取值,而第一个数据貌似是5,所以[1,1]=0
至于tf.InteractiveSession()我也不是很懂,我这里就认为是要与tensor交流的一种工具箱。下面开始是正式的模型构建,这里我说一下我通过一天的学习tensorflow的粗浅理解:
和传统coding不太一样,在定义测试集,训练集的时候就把data赋值给它。而tensorflow的感觉就像是先搭模型,等模型都搭建好了然后再往里面倒水,让水按照你搭建好的管道流通(所谓的flow)
----------------------------------
Tensorflow依赖于一个高效的C++后端来进行计算。与后端的这个连接叫做session。一般而言,使用TensorFlow程序的流程是先创建一个图,然后在session中启动它。
这里,我们使用更加方便的InteractiveSession类。通过它,你可以更加灵活地构建你的代码。它能让你在运行图的时候,插入一些计算图,这些计算图是由某些操作(operations)构成的。这对于工作在交互式环境中的人们来说非常便利,比如使用IPython。如果你没有使用InteractiveSession,那么你需要在启动session之前构建整个计算图,然后启动该计算图。什么意思呢,就是如果你不用InteractiveSession需要整个计算图构建好以后再run,那样就没法交互式地调试了,不便于设置断点查询中间值之类的。
而什么叫做计算图呢,就是我前一天理解的搭建的模型了,tf中需要你描述好这个模型是怎么一回事,然后具体的数据与计算是放在python外部完成的,这样速度就会快。
----------------------------------# Create the modelx = tf.placeholder(tf.float32, [None, 784])
首先我们看这个()里面:浮点数来表示这些图的具体值,这个张量的形状是[None,784 ]。(这里的None表示此张量的第一个维度可以是任何长度的。)
而placeholder是个占位符,所以很显然这像是个结构的声明,只不过这个结构按照统一的tensor形状来进行声明,可以调整的就只有数据类型以及维度
---------------------------
占位符是我们构建计算图的最重要的一部分,我们需要告诉这个进入计算图的数据是什么样子的
---------------------------
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
这是我们要学习的参数,
设置使用0初始化张量。矩阵乘法,只要第一个数字和x的第二个数字相同就可以。
为什么不像x一样先占位,我认为也是可以的,不过这里我们已经明确知道参数的size了,而tf中又给了我们variable这样的结构来快速运算可变量,可能会更快吧。注意这里写完依旧是没有赋值语句的,只是设置了要以0来初始化,只要记住,在tf中没看到run就没有赋值产生,始终还处于搭建管道阶段。
y = tf.nn.softmax(tf.matmul(x, W) + b)
matmul是tf为我们提供的矩阵运算,而tf中softmax模型也是写好了的,直接调用就可以了。注意以后我们用其他模型读文档也是很必要的。这里y的输出格式:
是[?,10]的形式的张量,类型是float32
个人认为这个形式是由之前我们设置的x以及变量所影响的,但具体没看源码,并不确定# Define loss and optimizery_ = tf.placeholder(tf.float32, [None, 10])
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
这一段先定义标准答案y_的张量,然后定义损失函数为交叉熵函数,外面那个求均值是因为交叉熵求出来是对单样本的,对于所有样本,我们需要求一个均值。这里实际上就做了一个批量梯度下降,而单样本同样适用,单个的均值就是自己。只需要把每次train的batchsize设置一下就好了。而tf中一旦我们提供损失函数,会给我们自动采用梯度下降的优化方法计算这一步的shift,我们这里学习率是0.5,输入函数是交叉熵损失函数。
---------------------------------
最后这一行代码实际上是用来往计算图上添加一个新操作,其中包括计算梯度,计算每个参数的步长变化,并且计算出新的参数值。
返回的train_step操作对象,在运行时会使用梯度下降来更新参数。因此,整个模型的训练可以通过反复地运行train_step来完成。
------------------------------------------
# Traintf.initialize_all_variables().run()
fori inrange(1000):
batch_xs, batch_ys = mnist.train.next_batch(100)
train_step.run({x: batch_xs, y_: batch_ys})
和前面的搭模型的代码不同,这里出现了run(),一旦tf开始run就说明有flow流过,此时variables全部有值了
而,mnist.train.next_batch的参数是batchsize。返回值是下一批输入值和标签值,这个返回值的类型感觉与前面x和y_占位符的声明有关系啊,但是并不清楚它们之间具体是怎么联系的,待解决
--------------------------------
mnist自身带有函数next_batch,返回值就是下一批的数据与标签,如果使用自定义数据集,可能需要重新写该类以及里面的函数,而不是直接按照其格式修改占位符那么简单--------------------------------
然后tran_step这样一个‘变量’居然也可以run,猜测是由于其定义中有
GradientDescentOptimizer(0.5).minimize()
而且run带的参数表明的意义似乎是把占位符对应的原本值替换再跑一遍
# Test trained modelcorrect_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
tf.argmax(y,1)表明的是对于y这个tensor,求其第一维最大值对应的索引
而tf.equal返回的是一个布尔数组转换成0,1后求均值就是正确率了
注意这里同样还没有开始run,只是设置了evaluation的形式
print(accuracy.eval_r({x: mnist.test.images, y_: mnist.test.labels}))这里eval函数其实就是一个把代码变成语句的函数,也就是run的意思,官方的tutorial里面这样也是可以的:
print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))
把accuracy这个tensor用feed_dict这样的数据去flow它并打印出来
----------------------------
这里feed_dict可以替换不只是占位符,他可以替换任何的张量
----------------------------