zoukankan      html  css  js  c++  java
  • 算法初探:Tensorflow及PAI平台的使用

    前言

    Tensorflow这个词由来已久,但是对它的理解一直就停留在“听过”的层面。之前做过一个无线图片适配问题智能识别的项目,基于Tensorflow实现了GoogLeNet - Inception V3网络(一种包含22层的深层卷积神经网络),但是基本上也属于“盲人摸象”、“照葫芦画瓢”的程度。作为当今机器学习乃至深度学习界出现频率最高的一个词,有必要去了解一下它到底是个什么东西。

    而PAI,作为一站式地机器学习和算法服务平台,它大大简化了模型构建、模型训练、调参、模型性能评估、服务化等一系列算法的工作,可以帮助我们更快捷地实现算法实验和应用。

    一、Tensorflow初探

    1. 安装和启动

    因为我自己的mac-pro安装了docker,所以安装Tensorflow的环境非常简单,只要拉取Tensorflow的官方镜像就可以完成Tensorflow的环境搭建。

    #拉取tensorflow镜像
    docker pull tensorflow/tensorflow
    
    #创建一个tensorflow的工作目录,挂载到容器内
    mkdir -p /Users/znifeng/docker-data/tensorflow/notebooks
    
    #启动容器
    docker run -it --rm --name myts -v /Users/znifeng/docker-data/tensorflow/notebooks:/notebooks -p 8888:8888 tensorflow/tensorflow
    

    启动成功后,将看到如下信息:

    复制链接http://127.0.0.1:8888/?token=487c52e0aa0cd2a7b231bf909c1d6666482f8ed03353e510到浏览器,就可以看到jupyter(支持在线编写和调试python的交互式笔记本)页面:

    接下来,你可以在jupyter上或者在docker容器内部编写和调试tensorflow的代码,容器内部已经包含了tensorflow的所有库。

    2. 基本使用

    2.1 核心概念

    • 使用图(graph)来表示计算任务
    • 使用张量(tensor)来表示数据。张量与矢量的区别:矢量相当于一阶的张量,张量可以从0阶到多阶(多维)
    • 图中的每一个节点称之为op(operation),每一个op有0或多个Tensor作为输入,执行计算后产出0或多个Tensor作为输出
    • 在被称之为会话Session的上下文(context)中执行图
    • 通过变量(variable)来维护状态
    • 使用feed和fetch可以为任意的操作赋值或者从其中获取数据
    • 使用placeholder来定义占位符,在运行时传入对应的参数值

    TensorFlow程序通常被组织成一个构建阶段和一个执行阶段。在构建阶段,op的执行步骤被描述成一个图,在执行阶段,使用会话执行图中的op。在Python中,返回的tensor是numpy.ndarray对象。;在C/C++中,返回的是tensorflow:Tensor实例。

    2.2 使用示例

    2.2.1 第一个helloworld程序:
    import tensorflow as tf
    
    #第一阶段: 构建图
    #定义一个1x2的矩阵,矩阵元素为[3 3]
    matrix1 = tf.constant([[3., 3.]])
    
    #定义一个2x1的矩阵,矩阵元素为[2
                               2]
    matrix2 = tf.constant([[2.],[2.]])
    
    # 创建一个矩阵乘法 matmul op , 把 'matrix1' 和 'matrix2' 作为输入.
    product = tf.matmul(matrix1, matrix2)
    
    #第二阶段: 执行图
    with tf.Session() as sess:
        print "matrix1: %s" % sess.run(matrix1)
        print "matrix2: %s" % sess.run(matrix2)
        print "result type: %s" % type(sess.run(product))
        print "result: %s" % sess.run(product)
    

    输出结果:

    matrix1: [[3. 3.]]
    matrix2: [[2.]
     [2.]]
    result type: <type 'numpy.ndarray'>
    result: [[12.]]
    

    如上图所示,在第一阶段(构建图)中,我们的每一行操作其实都是一个operation,包含两个constant操作和一个矩阵相乘的操作,每个operation的输出都是tensor,它的类型是num.ndarray。实际上,构建阶段我们只是定义op,并不会真正去执行;而在第二阶段中,通过定义了一个会话session,我们才会在会话中真正开始执行前面定义的各个operation,然后获得执行的结果。

    2.2.2 使用tensorflow实现识别手写数字(1~9)模型 —— Softmax Regression
    import input_data
    mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
    
    import tensorflow as tf
    
    ##Define input data format
    #input images, each image is represented by a tensor of 784 dimensions
    x = tf.placeholder("float", [None,784])
    #input labels, each label values one digit of [0,9], which is represented by a tensor of 10 dimensions
    y_ = tf.placeholder("float", [None, 10])
    
    ##Define Model and algorithm
    #weight array of each feature VS predicted result
    W = tf.Variable(tf.zeros([784, 10]))
    #bias of each digit
    b = tf.Variable(tf.zeros([10]))
    #predicted probability array of an image, which is of 10 dimensions. 
    #tf.matmul:矩阵相乘
    y = tf.nn.softmax(tf.matmul(x,W) + b)
    #cross-entropy or called loss function
    #tf.reduce_sum:压缩求和: tf.reduce_sum(x, 0)将x按行求和,tf.reduce_sum(x, 1)将x按列求和,tf.reduce_sum(x, [0, 1])按行列求和
    cross_entropy = -tf.reduce_sum(y_*tf.log(y))
    #gredient descent algorithm
    train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)
    
    ##Training model
    #initialize all variables
    init = tf.global_variables_initializer()
    with tf.Session() as sess:
        sess.run(init)
        for i in range(1000):
            batch_xs, batch_ys = mnist.train.next_batch(100)
            sess.run(train_step, feed_dict={x: batch_xs, y_:batch_ys})
    
        ##Evaluation 
        #tf.argmax(vector, 1):返回的是vector中的最大值的索引号。tf.argmax(vector, 0) 
        correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
        print sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})
    

    输出结果:

    0.904
    

    模型中使用的数据来自tensorflow/g3doc/tutorials/mnist/,总共包含7万张784(28x28)像素的1~9的数字图片,其中55000张用于模型训练作为训练集,5000张作为验证集,剩余10000张用作测试集。

    因此,每一张图片都可以用一个784维的向量来表示,向量里的每一个元素表示某个像素的强度值,介于0和1之间。使用x = tf.placeholder("float", [None,784])表示输入集x,其中placeholder为占位符,在实际使用时,我们再通过feed传入具体的行数来替换其中的None。y_则为对应的实际结果,因为结果集合为0~9,因此我们可以用[y0,y1,...,y9]的十维向量来表示结果,比如数字“1”可以表示为[0,1,0,0,0,0,0,0,0,0]。本例中,定义的模型为线性模型,先用wx+b得到初步结果z,再通过softmax函数将z折射得到0~9各个数字的概率值。

    在模型求解时,我们需要定义一个指标来评估模型是好的。而在机器学习中,通常是定义指标来表示模型是坏的,然后尽量最小化该指标得到最优解,该指标也称为成本(cost)或损失(loss)函数。本例中,我们用“交叉熵”来作为损失函数cross_entropy = -tf.reduce_sum(y_*tf.log(y)),然后用梯度下降的方式求解train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)。其中0.01为下降的速率。

    可以看到,经过1000次迭代,我们的模型的预测结果的准确率达到了90.4%。

    2.2.3 使用tensorflow实现识别手写数字(1~9)模型 —— DeepCNN

    上节中用softmax模型预测的准确率大概在90%,接下来尝试下用tensorflow实现一个卷积神经网络模型来识别手写数字。

    import input_data
    mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
    
    import tensorflow as tf
    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)
    
    def conv2d(x, W):
        return tf.nn.conv2d(x, W, strides=[1,1,1,1], padding="SAME")
    
    def max_pool_2x2(x):
        return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
    
    x = tf.placeholder("float", shape=[None, 784])
    y_ = tf.placeholder("float", shape=(None, 10))
    
    #第一层卷积
    W_conv1 = weight_variable([5, 5, 1, 32])
    b_conv1 = bias_variable([32])
    x_image = tf.reshape(x, [-1,28,28,1])
    h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
    h_pool1 = max_pool_2x2(h_conv1)
    
    #第二层卷积
    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)
    h_pool2 = max_pool_2x2(h_conv2)
    
    #密集连接层
    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)
    
    #Dropout防止过拟合
    keep_prob = tf.placeholder("float")
    h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
    
    #输出层: softmax
    W_fc2 = weight_variable([1024, 10])
    b_fc2 = bias_variable([10])
    y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
    
    #训练和评估模型
    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.global_variables_initializer())
        for i in range(2000):
            batch = mnist.train.next_batch(50)
            if i%200 == 0:
                train_accuracy = sess.run(accuracy, feed_dict={x:batch[0], y_: batch[1], keep_prob: 1.0})
                print "step %d, training accuracy %g"%(i, train_accuracy)
            train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})
        print "final training accuracy %g" % sess.run(accuracy, feed_dict={x:batch[0], y_: batch[1], keep_prob: 1.0})
    

    输出结果:

    step 0, training accuracy 0.14
    step 200, training accuracy 0.92
    step 400, training accuracy 0.96
    step 600, training accuracy 1
    step 800, training accuracy 0.9
    step 1000, training accuracy 0.96
    step 1200, training accuracy 0.94
    step 1400, training accuracy 0.94
    step 1600, training accuracy 0.98
    step 1800, training accuracy 1
    final training accuracy 0.99
    

    可以看到,2000次迭代后,deepccn的预测准确率达到了:99%。

    二、PAI平台的使用

    前面介绍了Tensorflow的基本概念和使用,下面简单介绍下使用PAI完成LR模型训练的基本过程。整个流程大概包含以下步骤:离线数据开发 -> PAI平台实验搭建 -> 模型服务化

    2.1 离线数据开发

    首先,算法的基础是数据,我们首先要通过对业务的分析,找出影响目标结果的特征,并对特征数据进行采集,得到各项特征的原始数据。这一部分,可以在odps完成。如“需求风险智能识别”中,涉及到多个表的join和指标的提取、计算等,对于一些缺省的值可以按照不同的策略来填充(如用0填充,或者该项的平均值)。最终得到如下的训练数据:

    2.2 PAI平台实验搭建

    进入PAI平台中,新建实验:smarttest,搭建如下的实验流程:

    流程中的每个组件可以从左侧“组件”导航栏中获取。具体流程如下:

    • 读数据表:输入odps表名
    • 类型转换:将特定的字段统一转化为double/int类型
    • 归一化:选取用于训练的特征,并进行归一化。归一化的逻辑为:y= (x-MinValue)/(MaxValue-MinValue)
    • 拆分:将数据集按照比例拆分为训练集和测试集
    • 逻辑回归二分类:使用LR模型对训练集的数据进行训练
    • 预测:将训练得到的模型对测试集的输入数据进行预测
    • 混淆矩阵:产出模型预测结果的混淆矩阵
    • 二分类评估:得到模型评估的AUC、KS、F1 Score等结果

    2.3 模型服务化

    训练好模型后,就可以将模型在线服务化。

  • 相关阅读:
    Autofac 依赖注入
    C#高级语法
    @helper
    Spiral Matrix -- LeetCode
    Best Time to Buy and Sell Stock with Cooldown -- LeetCode
    Kth Smallest Element in a Sorted Matrix -- LeetCode
    Number of Connected Components in an Undirected Graph -- LeetCode
    Super Ugly Number -- LeetCode
    Ugly Number II -- LeetCode
    Missing Ranges -- LeetCode
  • 原文地址:https://www.cnblogs.com/znicy/p/9981642.html
Copyright © 2011-2022 走看看