AI Challenger 2018:细粒度用户评论情感分类冠军 - 程惠阁

关注了一些 ai 相关的。原文查看机器之心:https://www.jiqizhixin.com/articles/2019-01-28-16

2018年8月-12月,由美团点评、创新工场、搜狗、美图联合主办的“AI Challenger 2018全球AI挑战赛”历经三个多月的激烈角逐,冠军团队从来自全球81个国家、1000多所大学和公司的过万支参赛团队中脱颖而出。其中“后厂村静静”团队-由毕业于北京大学的程惠阁(现已入职美团点评)单人组队,勇夺“细粒度用户评论情感分类”赛道的冠军。本文系程惠阁对于本次参赛的思路总结和经验分享,希望对大家能够有所帮助和启发。

img

背景

在2018全球AI挑战赛中,美团点评主要负责了其中两个颇具挑战的主赛道赛题:细粒度用户评论情感分析和无人驾驶视觉感知。其中NLP中心负责的细粒度用户评论情感分析赛道,最受欢迎,参赛队伍报名数量最多,约占整个报名团队的五分之一。

细粒度用户评论情感分析赛道提供了6大类、20个细分类的中文情感评论数据,标注规模难度之大,在NLP语料特别是文本分类相关语料中都属于相当罕见,这份数据有着极其重要的科研学术以及工业应用价值(目前在大众点评App已经可以看到20个类别的情感标签了)。

1. 工具介绍

在本次比赛中,采用了自己开发的一个训练框架,来统一处理TensorFlow和PyTorch的模型。在模型代码应用方面,主要基于香港科技大学开源的RNetMnemonicReader做了相应修改。在比赛后期,还加入了一个基于BERT的模型,从而提升了一些集成的效果。

2. 整体思路

整体将该问题看作20个Aspect的情感多分类问题,采用了传统的文本分类方法,基于LSTM建模文本,End2End多Aspect统一训练。

文本分类是业界一个较为成熟的问题,在2018年2月份,我参加了Kaggle的“作弊文本分类”比赛,当时的冠军团队主要依靠基于翻译的数据增强方法获得了成功。2018年反作弊工作中的一些实践经验,让我意识到,数据是提升文本分类效果的第一关键。因此,我第一时间在网络上寻找到了较大规模的大众点评评论语料,在Kaggle比赛的时候,NLP的语言模型预训练还没有出现,而随着ELMo之类模型的成功,也很期待尝试一下预训练语言模型在这个数据集合上的整体效果。


kubernetes 的编译、打包和发布(v1.10)

这是一篇 kubernetes 编译的简单备忘,以1.10.11为例。

编译主要参考文档为官方文档:https://github.com/kubernetes/kubernetes/blob/master/build/README.md

下载源码

下载v1.10.11源码

git clone -b v1.10.11 https://github.com/kubernetes/kubernetes.git
cd kubernetes

# 或者自由切换到其它分支
git branch
git tag | grep v1.10
git checkout v1.10.11

源码有100多万文件、将近700M,下载比较慢,需要一些耐心。

1571366044132

修改源码

这一块就各显神通了。

运行编译环境

使用容器运行一个编译环境,将代码文件映射到目的文件夹

docker run -it --rm -v $(pwd):/usr/lib/go/src/k8s.io/kubernetes kelvinblood/go-kube-build:v1.11 sh

单模块编译

以kubeadm为例,进入cmd文件夹进行编译即可。

cd /usr/lib/go/src/k8s.io/kubernetes/cmd/kubeadm
go build 

参考资料


使用容器编译 golang 项目

一直推崇开发环境容器化,对于我这种多台电脑同时办公的开发者是十分必要的。最近换了一台工作机器,想起按照原来的方式再走一遍环境配置,不禁恼火。于是还是搞起了容器化编译。下面记录一下过程。

启动环境

编辑 boot.sh 脚本,运行 golang 容器。

#!/usr/bin/env bash

docker run -d -t --name=go --net=host -v /root/golang/go:/go -v /root/golang/code:/code --privileged docker.io/golang bash

其中我把go的依赖文件映射到本地 /root/golang/go,代码仓库映射到 /root/golang/code。至于为什么直接使用host的网络,还是为了编译测试的方便。

进入容器

编辑 exec.sh 脚本,方便进入容器里

docker exec -it go /bin/bash

拉取依赖

这里以gin为例:

go get -u github.com/gin-gonic/gin

编译

以下面这个helloworld为例:

# gohello.go

package main

import (
"github.com/gin-gonic/gin"
"net/http"
)

func main(){
   router := gin.Default()
   router.GET("/", func(c *gin.Context) {
      c.String(http.StatusOK, "Hello World")
   })
   router.Run(":8000")
}

运行命令:

go build gohello.go

生成 gohello 文件。

运行这个文件,在浏览器中访问:

http://{ip}:8000/

可以看到浏览器中显示 hello world 字样。

另外,很多go项目对go的版本是有要求的,所以需要注意下运行的golang的版本号。


又一个 webdav 服务器

背景

前几天记录了一篇关于 webdav 的文章,但那个 webdav 我始终无法解决写数据的问题。于是又找到了这个 webdav,虽然也有瑕疵, 不过总算满足了目前写文件的需求。

搭建 WebDAV

编辑 docker-compose.yml 文件:

version: '3.2'

  webdav-zotero:
    image: morrisjobke/webdav
    container_name: webdav-zotero
    environment:
      USERNAME: kelu
      PASSWORD: kelu
    volumes:
      - zotero:/var/webdav/zotero
    restart: always
    ports:
      - "8080:80"

用户名密码均为 kelu, 运行即可。

docker-compose up -d

使用 http://ip:8080/webdav 即可访问到服务。


一个电商需求分析demo - LaravelChina

一篇清晰简约的需求分析的文章。原文:https://laravel-china.org/courses/laravel-shop/5.7/module-division/2738

用例分析

Laravel Shop 是我们整套课程将要构建的项目名称,是一个单商户的电商系统。本章节将简单地从产品用例的角度上来分析 Laravel Shop 的需求,好让大家对我们即将开发的项目有个基础的概念。我们主要从以下三种元素入手:

  1. 角色
  2. 信息
  3. 动作

接下来做单独分解。

1. 角色

在我们的 Laravel Shop 里,将会出现以下角色:

  • 游客 —— 没有登录的用户;
  • 用户 —— 注册用户, 可以购买商品;
  • 运营 —— 可以上架、下架商品,处理订单;
  • 管理员 —— 权限最高的用户角色,可以管理运营。

2. 信息结构

主要信息有:

  • 用户 —— 模型名称 User;
  • 收货地址 —— 模型名称 UserAddress,包含地址和收货人姓名、电话;
  • 商品 —— 模型名称 Product,比如 iPhone X 就是一个商品;
  • 商品 SKU —— 模型名称 ProductSKU,同一商品下有个别属性可能有不同的值,比如 iPhone X 256G 和 iPhone X 64G 就是同一个商品的不同 SKU,每个 SKU 都有各自独立的库存;
  • 订单 —— 模型名称 Order;
  • 订单项 —— 模型名称 OrderItem,一个订单会包含一个或多个订单项,每个订单项都会与一个商品 SKU 关联;
  • 优惠券 —— 模型名称 CouponCode,订单可以使用优惠券来扣减最终需要支付的金额;
  • 运营人员 —— 模型名称 Operator,管理员也属于运营人员。

3. 动作

角色和信息之间的互动称之为『动作』,动作主要有以下几个:

  • 创建 Create
  • 查看 Read
  • 编辑 Update
  • 删除 Delete

用例

1.游客

  • 游客可以查看商品列表;
  • 游客可以查看单个商品内容。

2. 用户

  • 用户可以查看自己的收货地址列表;
  • 用户可以新增收货地址;
  • 用户可以修改自己的收货地址;
  • 用户可以删除自己的收货地址;
  • 用户可以收藏商品;
  • 用户可以将商品加入购物车;
  • 用户可以将购物车中的商品打包下单;
  • 用户可以在下单时使用优惠券;
  • 用户可以通过微信、支付宝支付订单;
  • 用户可以查看自己的订单信息;
  • 用户可以对已支付的订单申请退款;
  • 用户可以将已发货的订单标记为确认收货;
  • 用户可以对已购买的商品发布评价。

3. 运营

  • 运营可以看到所有的用户列表;
  • 运营可以发布商品;
  • 运营可以编辑商品内容;
  • 运营可以编辑商品 SKU 及其库存;
  • 运营可以下架商品;
  • 运营可以将用户已支付的订单标记为已发货;
  • 运营可以对申请退款的订单执行退款;
  • 运营可以创建、编辑、删除优惠券。

4. 管理员

  • 管理员可以查看运营人员列表;
  • 管理员可以新增运营人员;
  • 管理员可以编辑运营人员;
  • 管理员可以删除运营人员。

file

很多时候,当开发团队开始启动一个项目时,区分功能模块的优先顺序尤其重要,否则你都不知道从哪里下手。这里我们使用一个简单的分析框架,来决策功能模块的开发优先级。你也可以使用其对大部分的 Web 项目进行模块开发的优先级分析。

模块清单

首先,基于我们的需求分析,我们将系统拆分成如下几大模块:

  • 用户模块
  • 商品模块
  • 订单模块
  • 支付模块
  • 优惠券模块
  • 管理模块

依赖关系

有了模块清单,接下来我们需要思考,他们之间的依赖关系是怎样的。在上面的功能清单中,『订单模块』依赖于『用户模块』和『商品模块』,『支付模块』和『优惠券模块』又依赖于『订单模块』。各个模块之间的依赖关系可以用下图来表示:

file

上层的模块依赖于下层的模块,因此在开发过程中我们会优先构建下层的模块。

开发顺序

所以我们各个模块开发的顺序如下:

  1. 用户模块
  2. 商品模块
  3. 订单模块
  4. 支付模块
  5. 优惠券模块

『管理模块』是一个特殊的模块,既包含本身的逻辑(管理后台的权限控制等),又与其他业务模块都有关联,因此在开发过程中会与其他模块穿插开发。

MVP 产品

是的,作为工程师,我们不需要了解产品的方方面面,那是产品经理的工作。但是作为一位优秀的开发者,在开发项目时,对将要完成的产品 MVP 要了然于胸,MVP 是 Minimum Viable Prodcut (最小化可行性产品)的简称。如何得出产品的 MVP 产品呢?可以先问这样的问题:

对于这个产品来讲,哪些功能是必不可缺的?

电商产品是一个用户购买商品的地方,产品存在的核心价值是『用户购买商品』,那首先需要用户、然后需要商品、购买需要付款。所以在我们的电商项目里,用户、商品、订单和支付模块都是必不可少的。

优惠券功能并不是购物流程中必备的一环,属于附加的功能,锦上添花的东西。我们在设计和开发项目时,应优先完成基础的功能,让流程能尽快跑起来,尽早交付,快速迭代。

Web 开发是个速度至上的领域,最小产品功能先上,测试的工作量也不会太大。不能憋大招,一个上线就是一大堆功能,复杂度增加的是无限的开发和调错时间,项目上线期限无尽延长。另一方面,用户能在最短时间内接触到产品,产品经理也可以尽快听到用户的反馈,及时调整产品战略,产品离成功会更进一步,这是一个多赢的方案。

这个思路也与敏捷开发的思路不谋而合:

敏捷开发即是以用户的需求进化为核心,采用迭代、循序渐进的方法进行软件开发。

结语

功能模块的开发优先级,我们已经有了,接下来就是要动手开始写代码了。