上一篇文章用了一个简单的例子说明了一下机器学习的基本实现方式。我们可以看到,机器学习过程中,会用到很多矩阵运算,还会用到一些数学算法和公式,例如梯度下降算法、激励函数等。如果这些算法让我们自己去实现,将会十分困难。还好,Google意识到了这是一个有难度但是重复性的劳动。推出了一款开源的机器学习开发框架tensorflow
(类似的框架还有Theano、Lasagne、Blocks、MXNet...,没用过),它跟python
是一对完美的搭档(虽然它也支持C++)。python
就不多讲了,它是当前很流行的一款主流语言。这篇文章稍微聊聊tensorflow
。看看它提供了那些常用的功能。tensorflow
的详细使用方法介绍见官网http://www.tensorfly.cn/。
tensorflow
的几个概念:
tensor
graph
seesion
tensorflow
的几个特点:
- 使用图 (graph) 来表示计算任务.
- 在被称之为 会话 (Session) 的上下文 (context) 中执行图.
- 使用 tensor 表示数据.
- 通过 变量 (Variable) 维护状态.
- 使用 feed 和 fetch 可以为任意的操作(arbitrary operation) 赋值或者从其中获取数据。
代码示例(实现向量相减):
import tensorflow as tf
# 变量(同时也是一个tensor)
x = tf.Variable([1.0, 2.0])
# 常量(同时也是一个tensor)
a = tf.constant([3.0, 3.0])
# 定义初始化变量的一个操作(OP)
init = tf.initialize_all_variables()
# 定义一个减法的操作(OP)
sub = tf.sub(x, a)
上面就是利用tensor
和OP
定义了一个计算图Graph
,这个计算图类似于C语言等中的变量和函数的声明和定义,没有真正的执行。
通过下面这段代码,在会话(Session)中,才能真正的执行上面的计算图。
# 在Session中启动计算图(Graph).
sess = tf.Session()
# 执行计算图中的操作(OP),限制性初始化变量的init,在执行减法sub
sess.run(init)
sess.run(sub)
# 任务完成, 关闭Session.
sess.close()
执行结果:
[-2. -1.]
上面这段是很简单的一个程序,旨在说明tensorflow
的基本组成要素和运行方法。真正机器学习中,用到的计算图要远远比上面的程序复杂。
下面给出一段使用了神经网络的程序,有兴趣的可以看看。
# 从文件中读入训练数据集
import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
# 定义将要输入的x和期望输出的y,这里只是两个占位符,这类似与两个变量,需要在训练的时候输入真实的值。
x = tf.placeholder("float", shape=[None, 784])
y_ = tf.placeholder("float", shape=[None, 10])
# 我们定义两个函数用于变量初始化
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)
# 定义卷积OP
def conv2d(x, W):
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
# 定义池化OP
def max_pool_2x2(x):
return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
strides=[1, 2, 2, 1], padding='SAME')
# 定义第一层卷积的权值和偏置
W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])
# 对长度为784的一维的x做个变形,这里是变成28x28的矩阵,这个是原始图像的尺寸。
x_image = tf.reshape(x, [-1,28,28,1])
# 经过Relu激活函数,然后进行池化。
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
# 经过这个池化后,图像尺寸变为原来的一半,即14×14
h_pool1 = max_pool_2x2(h_conv1)
# 将Relu函数的输出,再经过一层卷积神经网络,用法与第一层卷积神经网络类似。
W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
# 经过这个赤化后,图像尺寸再减小一半,即7×7
h_pool2 = max_pool_2x2(h_conv2)
# 现在,图片尺寸减小到7x7,我们加入一个有1024个神经元的全连接层,用于处理整个图片。我们把池化层输出的张量reshape成一维向量,乘上权重矩阵,加上偏置,然后对其使用ReLU。
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
# 最后加入一个softmax层
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
y_conv=tf.nn.softmax(tf.matmul(h_fc1, W_fc2) + b_fc2)
# 创建Session,开始训练
cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
with tf.Session() as sess:
sess.run(tf.initialize_all_variables())
for i in range(20000):
batch = mnist.train.next_batch(50)
if i%100 == 0:
train_accuracy = accuracy.eval(feed_dict={
x:batch[0], y_: batch[1]})
print "step %d, training accuracy %g"%(i, train_accuracy)
train_step.run(feed_dict={x: batch[0], y_: batch[1]})
print "test accuracy %g"%accuracy.eval(feed_dict={
x: mnist.test.images, y_: mnist.test.labels})
sweet tip: 上面这段程序是经典的手写数字识别,tensorflow官网上有相应的程序和介绍。代码实现见https://github.com/goinghlf/mnist-with-tensorflow