新手也可以学会TensorFlow

作者:caimouse

Tensorflow揭秘

 

 

https://medium.com/@gk_/tensorflow-demystified-80987184faf7

 

为了理解新的Tensorflow框架--Google的机器学习计算平台,通过一个玩具级的例子来学习它。

 

下面就是Google介绍这个框架的描述:

TensorFlow™ 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。它灵活的架构让你可以在多种平台上展开计算,例如台式计算机中的一个或多个CPU(或GPU),服务器,移动设备等等。TensorFlow 最初由Google大脑小组(隶属于Google机器智能研究机构)的研究员和工程师们开发出来,用于机器学习和深度神经网络方面的研究,但这个系统的通用性使其也可广泛用于其他计算领域。

 

What goes on within machine learning code is math, it helps to organize this in a way that simplifies and keeps the computative flow organized.

 

张量(Tensors)

首先遇到的第一个问题就是:张量是什么东西?它是怎么样流动呢?

一个向量(vector)是一串值的列表,一个矩阵(matrix)是一个数表(或者列表的列表)...,从而产生了一个数表的列表(或者列表的列表的列表),或者一个数表的数表(矩阵的矩阵),依次类推。所有数值使用张量表示,在机器学习里的任何等式都可以发现张量的存在。

 

现在让我们从一个已经学习过的例子来学习多层神经网络。

在这个例子里,我们使用数据特征值(‘x1’, ‘x2’, …)流过两层的神经网络、以及每个节点(神经元)、每个权重值(‘W’)和偏差值(‘b’),最后输出y值。

 

从上图可以看到,从输入值(‘X’)到输出值(‘Y’),经历了一系列(flow)数字流的计算(math),在数学计算上,使用了多维的矩阵(张量),常量和变量(比如b1)。定义和执行这些数字流的计算,这就是TensorFlow框架所做的事情。

 

 

由于通过这些数字流的计算,为了与预期的输出达到一致,必须不断地调整权重值和偏差值,从而让这个模型建立起来。TF框架平台提供了在GPU上加速计算的能力,这对于大规模数据训练时就特别有用。除此之外,TF框架也提供了很多数学公式的计算,这样对于开发和编写代码就特别方便了。这也就是为什么使用框架平台的原因。

 

TensorFlow的学习里,最经典的开始教程就是直接识别手写数字或鸢尾花卉数据集(classifying iris flowers)(或者在其它机器学习的框架也是如此)。当然使用这些实质性的数据来学习是比较有用的,但是这些数据对于一个机器学习新手来说,还是一个比较复杂的事情,所以这里采用一些玩具级别的数据来给新手学习。

 

For training data to achieve ‘toy’ status the data itself should be intuitive and easily grasped.

玩具级的数据集

让我们来构造一个只有5个元素的数组,让它当作输入。输出更简单,只有[0,1]或[1,0]两个,这两个输出的结果依赖于这个数组的第1位和最后1位是否为打开(也即是1):

[0, 1, 1, 1, 1], [0,1]

[1, 1, 1, 1, 0], [0,1]

[1, 1, 1, 0, 0], [0,1]

[1, 1, 0, 0, 0], [0,1]

[1, 0, 0, 0, 1], [1,0]

[1, 1, 0, 0, 1], [1,0]

[1, 1, 1, 0, 1], [1,0]

[1, 0, 0, 1, 1], [1,0]

 

仔细地看一下上面的数据集,就可以凭直感知道输入与输出的关系,从而建立一个模型。

 

如果我们使用这些数据来训练机器学习的模型,然后再使用它来预测5个元素的数组,是否可以呢?它是否预测正确吗?这就是一个机器学习的问题,具体的定义:软件学习模式。

 

代码

下面将要使用TensorFlow来建立一个模型,并且定义这些数据集,然后训练这个模型,再让它做一些预测。代码在这里:

https://github.com/ugik/notebooks/blob/master/Tensorflow%20ANN.ipynb

 

下面的代码就是基本的库导入,如下:

import numpy as np
import random
import tensorflow as tf

接着定义数据:

def create_feature_sets_and_labels(test_size = 0.3):

    # known patterns (5 features) output of [1] of positions [0,4]==1
    features = []
    features.append([[0, 0, 0, 0, 0], [0,1]])
    features.append([[0, 0, 0, 0, 1], [0,1]])
    features.append([[0, 0, 0, 1, 1], [0,1]])
    features.append([[0, 0, 1, 1, 1], [0,1]])
    features.append([[0, 1, 1, 1, 1], [0,1]])
    features.append([[1, 1, 1, 1, 0], [0,1]])
    features.append([[1, 1, 1, 0, 0], [0,1]])
    features.append([[1, 1, 0, 0, 0], [0,1]])
    features.append([[1, 0, 0, 0, 0], [0,1]])
    features.append([[1, 0, 0, 1, 0], [0,1]])
    features.append([[1, 0, 1, 1, 0], [0,1]])
    features.append([[1, 1, 0, 1, 0], [0,1]])
    features.append([[0, 1, 0, 1, 1], [0,1]])
    features.append([[0, 0, 1, 0, 1], [0,1]])
    features.append([[1, 0, 1, 1, 1], [1,0]])
    features.append([[1, 1, 0, 1, 1], [1,0]])
    features.append([[1, 0, 1, 0, 1], [1,0]])
    features.append([[1, 0, 0, 0, 1], [1,0]])
    features.append([[1, 1, 0, 0, 1], [1,0]])
    features.append([[1, 1, 1, 0, 1], [1,0]])
    features.append([[1, 1, 1, 1, 1], [1,0]])
    features.append([[1, 0, 0, 1, 1], [1,0]])

    # shuffle out features and turn into np.array
    random.shuffle(features)
    features = np.array(features)

    # split a portion of the features into tests
    testing_size = int(test_size*len(features))

    # create train and test lists
    train_x = list(features[:,0][:-testing_size])
    train_y = list(features[:,1][:-testing_size])
    test_x = list(features[:,0][-testing_size:])
    test_y = list(features[:,1][-testing_size:])

    return train_x, train_y, test_x, test_y

在上面这段代码里,把三分之二的数据拿来训练模型,三分之一的数据拿来测试。这个比率的设置是通过变量test_size来定义的,并且通过随机函数shuffle来随机抽取一部分数据来执行,这样每次拿到的数据并不是一样的,通过这些数据不断实验和反复迭代。

 

现在可以使用TensorFlow来建立模型:

train_x, train_y, test_x, test_y = create_feature_sets_and_labels()

# hidden layers and their nodes
n_nodes_hl1 = 20
n_nodes_hl2 = 20

# classes in our output
n_classes = 2
# iterations and batch-size to build out model
hm_epochs = 1000
batch_size = 4
    
x = tf.placeholder('float')
y = tf.placeholder('float')

# random weights and bias for our layers
hidden_1_layer = {'f_fum':n_nodes_hl1,
                  'weight':tf.Variable(tf.random_normal([len(train_x[0]), n_nodes_hl1])),
                  'bias':tf.Variable(tf.random_normal([n_nodes_hl1]))}

hidden_2_layer = {'f_fum':n_nodes_hl2,
                  'weight':tf.Variable(tf.random_normal([n_nodes_hl1, n_nodes_hl2])),
                  'bias':tf.Variable(tf.random_normal([n_nodes_hl2]))}

output_layer = {'f_fum':None,
                'weight':tf.Variable(tf.random_normal([n_nodes_hl2, n_classes])),
                'bias':tf.Variable(tf.random_normal([n_classes])),}

上面建立了模型,共使用了20个节点和2层隐藏层,并使用随机值来初始化这些权重值和偏差值,同时也定义了输出层。

我们现在可以对这个模型来建立数学的等式关系了:

# our predictive model's definition
def neural_network_model(data):

    # hidden layer 1: (data * W) + b
    l1 = tf.add(tf.matmul(data,hidden_1_layer['weight']), hidden_1_layer['bias'])
    l1 = tf.sigmoid(l1)

    # hidden layer 2: (hidden_layer_1 * W) + b
    l2 = tf.add(tf.matmul(l1,hidden_2_layer['weight']), hidden_2_layer['bias'])
    l2 = tf.sigmoid(l2)

    # output: (hidden_layer_2 * W) + b
    output = tf.matmul(l2,output_layer['weight']) + output_layer['bias']

    return output

请认真地查看这段代码,并且与前面神经网络图进行比较,在这里我们使用矩阵的乘法(tf.matmul),矩阵(张量)、权重值、偏差,并且定义激活函数tf.sigmoid,这些函数都是TF框架提供机器学习的内置API函数。

# hidden layer 1: (data * W) + b

l1 = tf.add(tf.matmul(data,hidden_1_layer[‘weight’]), hidden_1_layer[‘bias’]) l1 = tf.sigmoid(l1)

上面的代码跟前面学习过两层神经网络是一样的,但是现在使用TF框架来简化代码的编写,计算过程也被封装起来了。仔细地查看神经网络图,比较之前的代码和现在TF编写的代码,你应该发现它们其实是相等的。矩阵的乘法就更加简单了。

 

There’s no black-magic here: math is math.

现在开始来训练上面建立好的模型:

# training our model
def train_neural_network(x):
    # use the model definition
    prediction = neural_network_model(x)

    # formula for cost (error)
    cost = tf.reduce_mean( tf.nn.softmax_cross_entropy_with_logits(prediction,y) )
    # optimize for cost using GradientDescent
    optimizer = tf.train.GradientDescentOptimizer(1).minimize(cost)

    # Tensorflow session
    with tf.Session() as sess:
        # initialize our variables
        sess.run(tf.global_variables_initializer())

        # loop through specified number of iterations
        for epoch in range(hm_epochs):
            epoch_loss = 0
            i=0
            # handle batch sized chunks of training data
            while i < len(train_x):
                start = i
                end = i+batch_size
                batch_x = np.array(train_x[start:end])
                batch_y = np.array(train_y[start:end])

                _, c = sess.run([optimizer, cost], feed_dict={x: batch_x, y: batch_y})
                epoch_loss += c
                i+=batch_size
                last_cost = c

            # print cost updates along the way
            if (epoch% (hm_epochs/5)) == 0:
                print('Epoch', epoch, 'completed out of',hm_epochs,'cost:', last_cost)
        
        # print accuracy of our model
        correct = tf.equal(tf.argmax(prediction, 1), tf.argmax(y, 1))
        accuracy = tf.reduce_mean(tf.cast(correct, 'float'))
        print('Accuracy:',accuracy.eval({x:test_x, y:test_y}))

        # print predictions using our model
        for i,t in enumerate(test_x):
            print ('prediction for:', test_x[i])
            output = prediction.eval(feed_dict = {x: [test_x[i]]})
            # normalize the prediction values
            print(tf.sigmoid(output[0][0]).eval(), tf.sigmoid(output[0][1]).eval())
        
train_neural_network(x)

如果你把这段代码与之前没有使用框架的代码进行比较,发现它们竟然是相同的,训练的过程没有任何的变化。当我们通过周期地训练这个模型,让它的错误(损失函数)越来越来少,就把这个模型训练好了。

现在让我们查看一下它的输出和训练过程的信息:

Epoch   0 completed out of 1000 cost: 1.06944

Epoch 200 completed out of 1000 cost: 0.000669607

Epoch 400 completed out of 1000 cost: 0.00030982

Epoch 600 completed out of 1000 cost: 0.00019792

Epoch 800 completed out of 1000 cost: 0.00014411

Accuracy: 1.0

prediction for: [1, 1, 1, 1, 1]

0.998426 0.392255

prediction for: [1, 0, 1, 1, 1]

0.99867 0.364066

prediction for: [0, 0, 1, 1, 1]

0.028218 0.997783

prediction for: [0, 1, 0, 1, 1]

0.0528865 0.997093

prediction for: [1, 0, 0, 0, 1]

0.999507 0.413642

prediction for: [1, 0, 0, 1, 0]

0.0507428 0.998406

注意到这里,当训练超过1000次之后,它的错误将会减少。这里计算精度的数据是采用测试数据,而不是采用训练的数据。

接着下来,我们就可以使用它来预测测试数据了。当输入[1, _, _, _, 1]的形式时,它输出[1,0];当输入其它模式时,就输出[0,1]。每个值输出来时概率值:

prediction for: [1, 0, 0, 1, 0]

0.0507428 0.998406

这里就意味着模型已经认为输入的模式与[1, _, _, _, 1]模式有严重的不同。

在这里采用玩具级的数据来解释,可以让你的精力主要放在代码上面,而不数据集。这个两层的神经网络ANN的工作方式,你立即可以借鉴它,使用它去对鸢尾花分类,或者去预测股票的市场走势了。

 

训练代码详细介绍

让我们再回过头来看一下训练代码,我们定义了变量prediction等于训练的模型:

# use the model definition

 prediction = neural_network_model(x)

接着告诉TF框架怎么样来优化这个模型:

c = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(prediction,y))

 optimizer = tf.train.GradientDescentOptimizer(1).minimize(c)

当然我们也可以使用TF框架其它的优化方法来建立这个模型。

接着下来,通过周期地迭代这个模型:

with tf.Session() as sess:

 sess.run(tf.global_variables_initializer())

for epoch in range(hm_epochs):

 _, c = sess.run([optimizer, cost], feed_dict={x: batch_x, y: batch_y})

通过每一小批次数据的训练,这个模型每一次就调整它的权重值和偏差值(朝它减少错误的方向进行)。

这个模型的精度计算是采用测试数据来评估的:

correct = tf.equal(tf.argmax(prediction, 1), tf.argmax(y, 1))

accuracy = tf.reduce_mean(tf.cast(correct, ‘float’))

print(‘Accuracy:’,accuracy.eval({x:test_x, y:test_y}))

最后使用这个模型来处理一些新数据的结果,就非常简单了,它直接使用激活函数来计算输出值0和1:

print (‘prediction for:’, test_x)

output = prediction.eval(feed_dict = {x: [test_x]})

print(tf.sigmoid(output[0][0]).eval(), tf.sigmoid(output[0][1]).eval())

 

整个过程是怎么样呢

我们通过机器学习算法来实现识别5个数字数组的预测模式,它是通过训练数据来实现的:

提供[1, _, _, _, 1] 和其它数据。它是通过查看这些数据来学习,并没有人为地告诉它怎么样预测这些数组。与传统的编程模式进行比较,就是像下面这样:

def identify_pattern(data):

    if data[0]==1 and data[-1]==1:

        return [1,0]

    else:

        return [0,1]

    

print(test_x[0], identify_pattern(test_x[0]))

显然上面这个过程就不是机器学习了,它是采用人为制定的规则来进行解决问题。如果我们采用写规则这种方式来编写程序处理图像识别的问题,就会遇到非常大的困难。到这里,我们应该理解这些预测模型,其实就是通过一些数据,或者说数字流的方式来通过这些计算等式来形成的。

现在,你可以有经验来学习处理更真实的问题了,比如手写数字的识别。

1. TensorFlow API攻略

http://edu.csdn.net/course/detail/4495
2. TensorFlow入门基本教程
http://edu.csdn.net/course/detail/4369

3. C++标准模板库从入门到精通 

4.跟老菜鸟学C++

http://edu.csdn.net/course/detail/2901

5. 跟老菜鸟学python

http://edu.csdn.net/course/detail/2592

6. 在VC2015里学会使用tinyxml库

http://edu.csdn.net/course/detail/2590

7. 在Windows下SVN的版本管理与实战 

 http://edu.csdn.net/course/detail/2579

8.Visual Studio 2015开发C++程序的基本使用 

http://edu.csdn.net/course/detail/2570

9.在VC2015里使用protobuf协议

http://edu.csdn.net/course/detail/2582

10.在VC2015里学会使用MySQL数据库

http://edu.csdn.net/course/detail/2672



发表评论

0个评论

我要留言×

技术领域:

我要留言×

留言成功,我们将在审核后加至投票列表中!

提示x

人工智能开发框架知识库已成功保存至我的图谱现在你可以用它来管理自己的知识内容了

删除图谱提示×

你保存在该图谱下的知识内容也会被删除,建议你先将内容移到其他图谱中。你确定要删除知识图谱及其内容吗?

删除节点提示×

无法删除该知识节点,因该节点下仍保存有相关知识内容!

删除节点提示×

你确定要删除该知识节点吗?