zoukankan      html  css  js  c++  java
  • Matlab 中 Data-driven 风格的 API 设计

    设计

    所谓 data-driven API,指的是用户可以把“操作”作为参数,传入函数,像下面这种:

    stream = dataStream('load', 'example.csv');
    image = dataStream('get', stream, 1);
    newStream = processStream('map', @(im)(sobel(im)));
    

    这是我最近在写的图像数据库读取的工具函数,我把视频或图片文件夹抽象成一个 dataStream,并基于这个 dataStream 完成一系列读写以及图像处理操作(processStream)。

    代码中的 “load”(载入),“get”(读取),“map”(...就是你所知道的 map),都代表不同类型的操作,外层的 “dataStream”和 “processStream”仅起到一个入口的作用,它们的内部包含了每个操作的实现。设计 data-driven API 的方法很容易,例如上面的流处理函数:

    function varargout = processStream(action, varargin)
        varargout = repmat({[]}, [1 nargout]);
        [varargout{:}] = feval(action, varargin{:});
    end
    
    function newstream = map(stream, action, varargin)
        % ......map 的实现(略)
    end
    

    通过 varargin 和 varargout 传递可变的输入和输出参数,通过 feval 来调用对应的内部函数(例如map)即可。
    至于可变参数的用法,可以参考下面两个文档:

    1. Variable-length output argument list
    2. Variable-length input argument list

    优点

    Data-driven API 解决了 Matlab 的一个缺点,即一个文件仅能放一个主函数(以及几个用户无法访问的辅助函数)。它使相同功能的函数被良好的组织到了一起,许多图像处理库都采用这种风格的设计。

    脱离 Matlab 来看,Data-driven 使得开发者可以在不改变接口的情况下新增功能(例如,只要往 processStream.m 文件里加新的内部函数,就可以自动扩展 processStream 支持的操作);

    此外, data-driven 还可以让 API 支持某种程度的 DSL,因为操作的类型是通过字符串描述的,那么我们可以把这些字符串组织成一个文本文件,通过读取并执行这个文件,就能让 API 执行你想要的功能,或者我们可以把所需执行的操作保存到一个数组里,让 API 读取并执行这个数组。

    例如,基于 processStream,我设计了一个流水线操作的函数 pipeline.m:

    % 像流水线一样处理数据:
    % processStream('map',...) >>>> processStream('reduce',....)
    % 操作按照 schema 来执行,schema 就像下面这个,是个嵌套的 cell array
    % {
    %     { 'map'   , 'sobel', [3, 3] },  % 先在流中运行 3x3 的 sobel 算子
    %     { 'map'   , 'sharpen' }, % 在上一步的输出中运行锐化算子
    %     ..........
    % }
    % 这个 schema 相当于一个小的 DSL
    function result = pipeline(stream, schema)
        for i = 1 : numel(schema)
            args = makeArguments(stream, schema{i});
            result = processStream(args{:});
            stream = result;
        end
    end
    % 构造 processStream 的输入参数
    function args = makeArguments(stream, operations)
        args = {operations{1}, stream, operations{2:end}};
    end
    

    总结

    我认为 Data-driven API 是 Matlab 中最重要的“设计模式”(如果它有设计模式的话...),通过它,我把图像数据库抽象成数据流,并在数据流上实现了 map, foreach,flatmap,reduce 等等一系列 functional 风格的操作,基于这些操作,我把一个原本很冗长的机器学习训练脚本变得十分简洁。

  • 相关阅读:
    Go语言之深入剖析slice
    docker-compose 安装以及遇到的错误解决
    linux 简单记录9 --服务的访问控制列表(ssh,scp,screen)
    linux 简单记录8 --iptables 与 firewalld 防火墙
    linux 简单记录7--使用 RAID 与 LVM 磁盘阵列技术(使用LVM扩展磁盘空间)
    linux 简单记录6--存储结构与磁盘划分
    DNS 域名解析服务
    linux运用软链接解决目录空间不足
    linux 简单记录5--用户身份与文件权限
    ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper
  • 原文地址:https://www.cnblogs.com/heleifz/p/matlab-datadriven-api.html
Copyright © 2011-2022 走看看