IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [译]新手也可以学会TensorFlow

    caimouse发表于 2017-04-01 18:38:35
    love 0

    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++标准模板库从入门到精通 

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

    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





沪ICP备19023445号-2号
友情链接