美文网首页
deeplearnjs 介绍 <一>

deeplearnjs 介绍 <一>

作者: Jeremy_young | 来源:发表于2018-02-27 22:31 被阅读633次

    闲来再做回搬运工,感觉和机器翻译比起来并没啥优势。。。

    deeplearn.js 是一个用于机器智能的开源 WebGL 加速的 JavaScript 库。deeplearn.js 为您的指尖带来高性能机器学习构建模块,允许您在浏览器中训练神经网络或在推理模式下运行预训练模型。

    让我们来看看 deeplearn.js 中的一些核心概念。

    Tensors

    在 deeplearn.js 中数据的核心单元便是 tensor,一个 Tensor 由一组任意维数的数值型数组构成。
    Tensors 由 shape 属性定义其形状。该库为低秩的张量(Tensors)提供了 sugar 般的子类:Scalar, Tensor1D, Tensor2D, Tensor3DTensor4D,以及一些用于构建它们的辅助函数。

    例如使用一个 2x3 维矩阵:

    let shape = [2, 3]; // 2 rows, 3 columns
    let a = dl.tensor2d([1.0, 2.0, 3.0, 10.0, 20.0, 30.0], shape);
    // deeplearn.js can also infer the shape
    let b = dl.tensor2d([[0.0, 2.0], [4.0, 6.0]]);  // 2 rows, 2 columns
    

    译者注:可见 shape 重新规定了前面数组的形状。

    Tensor 既可以用一个 WebGLTexture 将数据存到 GPU,或者以 JavaScript TypedArray 的形式存到 CPU 上。大多时候,用户都无需考虑存储问题,因为它是一个实现细节。

    有个地方你得好好想想其差异的,就是当从一个 Tensor 取出数据时,例如在调试时:

    let a = dl.tensor2d([[0.0, 2.0], [4.0, 6.0]]);
    a = a.square();
    
    // Async call to get the data from the tensor
    a.data().then(data => console.log('The data TypedArray', data));
    
    // Alternatively we can also call this synchronously
    let data = a.dataSync();
    console.log('The data TypedArray', data);
    

    在上例中,我们首先创建了一个 tensor,然后在其上调用了一个数学操作。这会将该 tensor 自动上传到 GPU。当我们想在 JavaScript 上下文使用它时(如打印出来),我们调用 data()dataSync() 将其下载到 CPU 内存中。请注意这是一个相对有代价的操作,所以你可能倾向于异步调用的版本。

    译者注:需要搞明白的是——数据从哪导到哪,怎样的过程有什么开销,以及哪些数据该在 GPU 运算更好

    Operations (Ops)

    Tensors 允许我们存储数据,同时 Ops 允许我们操纵数据。deeplearn.js 带有大量的适合于线性代数和机器学习的数学运算。它们有像square()的一元运算,像add()的二元运算以及mul()这样的对某个 tensors 进行变换并返回一个新的 tensors 结果的运算。

    let a = dl.tensor2d([[1.0, 2.0], [3.0, 4.0]]);  // tensor 
    let b = dl.tensor2d([[0.0, 2.0], [4.0, 6.0]]);  // tensor 
    
    // The library has a chainable API allowing you to call operations
    // directly as methods on Tensors.
    let average = a.sub(b).square().mean();
    
    // All operations are also exposed as functions in the main namespace
    // so we could also do.
    // 译者注:这些方法不仅每个 tensor 实例都有,而且在 dl 这个命名空间上能直接访问到
    let avg = dl.mean(dl.square(dl.sub(a, b)));
    

    Tidy Operations

    因为 deeplearn.js 使用了GPU加速数学运算,因此有必要管理GPU内存。在常规的 JavaScript 中,这部分工作由作用域(Scopes)处理,而在这里,我们提供了一个便捷的函数对 tensors
    执行操作时所产生的中间内存进行清理。

    我们把这个函数称作dl.tidy.

    let a = dl.tensor2d([1.0, 2.0, 3.0, 4.0]);
    
    // dl.tidy takes a function to tidy up after
    let average = dl.tidy(() => {
      // dl.tidy will clean up all the GPU memory used by tensors inside
      // this function, other than the tensor that is returned.
      //
      // Even in a short sequence of operations like the one below, a number
      // of intermediate tensors get created. So it is a good practice to
      // put your math ops in a tidy!
      return a.sub(b).square().mean();
    });
    

    运用dl.tidy()有助于防止应用程序的内存泄漏,并且能更谨慎地控制何时内存回收。

    手动方式清理 tensor 内存是dispose方法。

    let a = dl.tensor2d([[0.0, 2.0], [4.0, 6.0]]);
    a = a.square();
    a.dispose(); // Clean up GPU buffer
    

    相比,使用dl.tidy函数更方便些。

    Training

    许多机器学习的核心问题是实质上是训练机器完成一些任务的问题。在 deeplearn.js 中,这一过程被封装在Optimizers(优化器)中。优化器是逐步调整模型变量的策略,目的是减少模型预测的错误(或者按机器学习的说法是减少损失)。

    我们在教程中涵盖了训练和优化器,这里是 deeplearn.js 如何进行训练的一个大概轮廓:

    import * as dl from 'deeplearn';
    
    // 初始化模型变量
    const weights = dl.variable(dl.randomNormal([10, 64]));
    const biases = dl.variable(dl.zeros([64]));
    
    // 设置学习率和创建优化器.
    const LEARNING_RATE = .1;
    const optimizer = dl.train.sgd(LEARNING_RATE)
    
    /*
     * 进行推断并返回预测结果
     */
    function inference(input) { }
    
    /**
     * 通过比较预测值和真实值,计算模型损失
     *
     * 返回一个标量损失值 (如,单数值的张量)
     */
    function loss(predictions, labels) { }
    
    /**
     * 模型的单步训练
     */
    function trainStep(data, labels, returnCost = true) {
      // Calling optimizer.minimize will adjust the variables in the
      // model based on the loss value returned by your loss function.
      // It handles all the backpropogation and weight updates.
      const cost = optimizer.minimize(() => {
        // Any variables used in this inference function will be optimized
        // by the optimizer.
    
        // Make a prediction using the current state of the model
        const prediction = inference(data);
    
        // Compute loss of the current model and return it. Calculating this loss
        // should involve the variables we are trying to optimize.
        //
        // Once we return the less the optimizer will adjust the network
        // weights for our next iteration.
        return loss(prediction, labels);
      }, returnCost);
    
      // return the current loss/cost so that we can visualize it
      return cost;
    }
    
    /**
     * 训练模型.
     *
     * 通过循环调用上述单步训练 trainStep. 用 `await dl.nextFrame()` 避免阻塞浏览器
     *
     * 可在此加载、批处理、清洗你的数据
     */
    function train(data) { }
    

    Backends

    该库提供了一些后台来执行本库的核心数学运算,目前我们有一个 CPU 后台和一个 WebGL 后台,deeplearn.js 只要浏览器支持,是默认使用 WebGL 后台。WebGL 后台使用的是计算机的 GPU,旨在执行快速和高度优化的线性代数内核。

    若强制使用 CPU 后台,你可以程序开始处调用dl.setBackend('cpu')

    检查哪种后台正在被使用,可以调用dl.getBackend()

    WebGL 后台

    在使用WebGL后台时,数学运算如dl.add() 会推入着色器程序到GPU上执行。不像在CPU后台中那样,这些操作是不阻塞的(尽管将数据从主内存移动到GPU内存会有一些开销)。

    这些着色器程序从 WebGLTextures 读取和写入。在链接数学运算时,textures 可以留在GPU内存中,这对性能非常重要。

    你可以通过调用 tensor 的 data() 方法,定期从 gpu 下载数据,这样你就可以在你的主 Javascript 线程中读取这些数据。

    获取两个矩阵之间均方差的例子:

    const a = dl.tensor2d([[1.0, 2.0], [3.0, 4.0]]);
    const b = dl.tensor2d([[0.0, 2.0], [4.0, 6.0]]);
    
    // All these operations will execute on the GPU (if available)
    // without blocking the main thread.
    const diff = dl.sub(a, b);
    
    // Calling .data returns a promise that resolves to a TypedArray that holds
    // the tensor data downloaded from the GPU.
    diff.data().then(d => console.log('difference: ' + d));
    // We could also use dataSync to do this synchronously.
    console.log('difference: ' + diff.dataSync());
    

    TIP: Avoid calling data()/dataSync() between mathematical GPU operations unless you are debugging. This forces a texture download, and subsequent operation calls will have to re-upload the data to a new texture.

    CPU 后台

    在使用CPU实现时,这些数学运算会阻塞,然后立即在主 JavaScript 线程隐含的 TypedArray 上执行 。

    相同的操作在两种后台中都被实现,因此你的代码无需根据客户端上使用的后台进行更改。

    想了解更多?请阅读这些教程

    相关文章

      网友评论

          本文标题:deeplearnjs 介绍 <一>

          本文链接:https://www.haomeiwen.com/subject/lfbuxftx.html