NLP 实战 (1) | AI 编程也遵循软件工程的基本原理

记录结构化NLP服务之路,本文长期更新

管道(pipeline)

  • 从不同数据源(source)获取数据
  • 清洗数据
  • 构建数据集(dataset)
    • 数据集管理
  • 拆分训练集/验证集/测试集
  • 选择机器学习框架/算法(framework/algorithm)
  • 模型训练(train)/预训练/微调训练
  • 构建分类器(classifier)
  • 基于分类器提供 Rest 服务(server)
  • 输出结构化数据
    • 结构化数据提供给目标(dest)应用服务
  • 服务于应用层(application)

Python 环境

使用Python,一开始都会浪费很多时间在环境上,例如:

  • python 的不同版本
  • pip 的不同版本,每个python版本都对应一个pip,装python版本还需要装对应的pip
  • python 某个库在某个版本下可以装,但是它依赖的库在这个版本下的版本不能跑

手工方式(manual)

  • 安装目标 python 版本,例如 3.6的最高版本: python3.6.11
    • wget https://www.python.org/ftp/python/3.6.11/Python-3.6.11.tgz
    • tar xzf Python-3.6.11.tgz
    • cd Python-3.6.11
    • ./configure --enable-optimizations
    • make altinstall
  • 安装对应 pip版本
    • 下载 get-pip 脚本
    • 使用对应版本的 python 安装对应版本的 pip
      • python3.6 get-pip.py
  • 手工更改 /usr/local/bin 下 python 和 pip 的软连接映射
    • pip 软链接
      • ln -s -f /usr/local/bin/pip3 /usr/bin/pip
      • ln -s -f /usr/local/bin/pip3 /usr/bin/pip3
      • ln -s -f /usr/local/bin/pip3 /usr/bin/pip3.6
    • python 软链接
      • ln -s -f /usr/local/bin/python3.6 /usr/bin/python
      • ln -s -f /usr/local/bin/python3.6 /usr/bin/python3
      • ln -s -f /usr/local/bin/python3.6 /usr/bin/python3.6

使用 pyenv 管理

  • 使用 pyenv 管理python环境
  • 查看管理的 python 版本:pyenv versions ,带*号带是当前使用的版本
  • 验证当前python版本:python --version
  • 查看有哪些可用版本的python:pyenv install --list
  • 安装指定版本python:pyenv install 3.6.11
  • 切换版本:pyenv global 3.6.11
  • 如果是 Mac 系统,zsh 和 fish 两个shell 环境还需要为两个 shell 添加一些配置,参考 pyenv git 里的说明,请搜关键词 Zshfish

使用 conda 管理

  • 使用 conda 管理python环境
  • 安装 minicoda
  • 创建并安装指定版本的 python 环境:conda create -n py3.6 python=3.6.11
  • 切换环境:source activate py3.6
  • 查看当前生效的python和pip版本:python --version, pip --version

机器学习库

万变不离其宗,程序=数据结构+算法,每一种特定的库处理的是特定数据结构相关的算法,理解这点,保持目标问题导向的库选择和使用。

  • pandas,关于DataFrame的数据结构
  • numpy,处理多维数组
  • jieba,分词
  • sklearn,常见NLP任务
  • tensorflow,Google深度学习库
    • tensorflow-gpu
  • pytorch,更新和维护比tensorflow强
  • spacy
  • paddlepaddle 中文处理更友好

统一命令行接口

将整个管道的不同阶段操作统一到一致的命令行接口,不要让NLP任务变成一堆无序的项目和脚本,类似 git,将管道中的多任务统一到一致的接口里。

基本操作心智模型:python main.py -p {profile} -a action_name [sub options]

  • 操作说明
    • -p 指定配置环境,例如与携程阿波罗环境的划分:
      • dev 开发环境配置
      • fat 测试环境配置
      • pre 预发布环境配置
      • pro 线上环境配置
    • -a 指定action,例如:
      • -a build -d questions: 构建问题数据集
      • -a server -t answer: 启动答案服务

如何迭代

开发/内部部署发布/测试/迭代/发布,其中内部部署发布 是首要重要的事情,遵循一些必要的原则有助于达成这点:

  • 内部发布优于第1版正确性,先把流程打通并发布一个版本,快速进入测试-开发迭代优先于1版正确性,最好能达成每周发布。
  • 第一性原理,NLP处理的数据是非结构化的,NLP的能力是通过对数据向量化,对数据进行分类和标注,提供数据背后的结构化信息。有了结构化信息,构建这些结构化信息的关系,进而可以对这些结构化的关系信息进行查询或推理。围绕这点带着要解决的目标问题去寻找工具,而不是先找工具,再找问题。
  • NLP任务也和其他所有软件开发一样,任务必须遵循SMART原则才能保持持续发版的能力。一个NLP任务可以是很模糊的,也可以是定向和明确的,例如标注和多分类相对明确的目标,聊天机器人是相对模糊的目标。一个模糊的目标不是一锤子买卖,它应该是基于一系列的有明确目标的子任务的基础之上来做。因此,要盯着那一个一个明确的子任务去做,再去合成一个大的任务。
  • 一个明确的具体的任务,一开始就可以做脚手架:部署后的接口先定下来,先提供一个fake版本。再通过一周一次的发布目标去反推改进。
  • 一个NLP任务,内部部署后要让标注对测试数据做仔细标注和统计,再分析用例的情况,这样去迭代。没有衡量,就没有改进的基准。

如何有效交付

NLP任务不纯粹只是算法问题,它也是一个产品,含有这些步骤:

  • 需求是什么?(Need)
  • 解决方式是什么?(Approach)
  • 好处是什么?(Benefit)
  • 跟什么竞争?(Competition)
  • 如何推广(Delivery)

一个不好的开发策略是:

  • 试图一下子开发一个大的功能:例如直接产出一个聊天机器人
  • 开发一个功能,但是一直在改进精确度,迟迟不上线获得真实的反馈

一个好的开发策略是使用NABCD模型来迭代:

[1] 分析痛点:例如用户在 blink.csdn.net/ 的#你问我答 活动里提问题,我们希望引导用户到 ask.csdn.net 上提问。用户的很多问题都是直接截图提问。blink 上 #你问我答 的截图提问,我们需要识别:

  • 用户提问的是什么编程语言的问题?这样我们可以给这个问题打上合适的编程语言标签。
  • 用户截图的代码文本能否提取出来,这样创建问题后回答者可以直接从文本里拷贝有用的关键字。

[2] 找到AI的解决方式:通过OCR识别文本,再对文本进行编程语言类型识别。这就是一个具体的算法解决方式。

[3] 好处是从 blink 上生成的问题获得了更好的结构化信息:编程语言标签和代码文本。这样回答者可以更好的回答该问题,从而解决提问者的需求。

[4] 跟什么竞争?问答网站很多,其他网站没有这个功能,那么 ask.csdn.net 的“截图提问” 会更有信息含量。一个功能的改进可能不起眼,10个功能的信息含量改进会获得整体信息含量的差距。另一个方面,跟自己以前的功能比,有了初步的“智能”。

[5] 如何推广?前面说了,在NLP开发中,一直该算法是无止境的,并且也会大致迟迟不交付的现象。因此,Delivery实际上就是为上线花时间:

  • 花时间把功能服务化,提供 Rest API
  • 花时间与标注做测试,统计 API 的精确度,定义好“足够好” 的指标,达到足够好就应该尽快与应用集成。
  • 花时间与应用开发集成,把功能集成到应用处理的流程里。

从这个分析过程中,我们在定NLP任务的时候,应该一开始就考虑好如何Delivery,避免一致忙于做算法模块,但是与团队其他人的迭代“延迟”很大。我们后面会基于这个原则来迭代所有其他NLP任务。

(未完待续…)

你可能感兴趣的:(NLP,In,Action,自然语言处理,机器学习,深度学习)