2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PyKNPの利用環境をDockerで建てる

Last updated at Posted at 2018-10-27

はじめに

PyKNPを利用して固有表現抽出をやってみたいなと思ってちょっと環境構築を調べてみました.メインで使用しているmacOSにはHomebrew経由で先人の用意したリポジトリuetchy/homebrew-nlp
を使わせてもらうことで準備できました.
ただ,この環境をDockerでイメージ化しておきたいなーという欲求が生まれたので,勉強がてら構築してみることにしました.

結論

忙しい方のためにTL;DR風に先に結論を書いておくことにします.

ファイル構成

開発用のディレクトリ(とはいえただのテスト)の構成は以下のような感じです.近年はrequirements.txtといったパッケージ関係をどう管理するかについて様々な流儀がありますがこのエントリでは触れないことにします.

  % tree
.
├── Dockerfile
├── docker-compose.yml
├── pyknp_test.py
└── requirements.txt

0 directories, 4 files

それぞれのファイルは以下のように用意しました.

Dockerfile
FROM python:3.6-slim

# create user as "app"
RUN useradd --user-group --create-home --shell /bin/false app

# set home directory
ENV HOME=/home/app

# copy source file
COPY . $HOME/pyknp_test

# install dependencies
RUN apt-get update && apt-get install -y \
  build-essential \
  curl \
  bzip2 \
  libjuman \
  libcdb-dev \
  zlib1g-dev
RUN pip3 install --requirement $HOME/pyknp_test/requirements.txt

# install juman and KNP and copy .jumanrc file
RUN mkdir $HOME/src && \
  cd $HOME/src && \
  curl -L -o juman-7.01.tar.bz2 http://nlp.ist.i.kyoto-u.ac.jp/nl-resource/juman/juman-7.01.tar.bz2 && \
  tar xf juman-7.01.tar.bz2 && \
  cd juman-7.01 && \
  ./configure && \
  make && \
  make install && \
  cp /usr/local/etc/jumanrc $HOME/.jumanrc
RUN cd $HOME/src && \
  curl -L -o knp-4.19.tar.bz2 http://nlp.ist.i.kyoto-u.ac.jp/nl-resource/knp/knp-4.19.tar.bz2 && \
  tar xf knp-4.19.tar.bz2 && \
  cd knp-4.19 && \
  ./configure && \
  make && \
  make install

# delete download cache
RUN rm -rf $HOME/src && \
  apt-get purge -y \
  build-essential \
  curl \
  bzip2

# change user
RUN chown -R app:app $HOME/*
WORKDIR $HOME/pyknp_test
USER app

# set CMD
CMD ["python3", "pyknp_test.py"]
docker-compose.yml
version: '3'
services:
  pyknp:
    build: .
    volumes:
      - .:/home/app/pyknp_test
pyknp_test.py
# coding: utf-8
import pyknp
import re

# KNP prepairing
knp = pyknp.KNP(option="-tab -dpnd", jumanpp=False)

def make_np_tagged_text(src_text: str):
    tagged_text = src_text # copy
    result = knp.parse(src_text) # tagging

    for tag in result.tag_list():
        if "NE:" in tag.fstring: # if fstring has NE phrase
            # extract NE phrase
            tagged_ne_phrase = re.search("<NE:(.*):(.*)>", tag.fstring).group(0)
            ne_phrase = re.search("<NE:(.*):(.*)>", tag.fstring).group(2)

            # overwrite to src text
            tagged_text = tagged_text.replace(ne_phrase, tagged_ne_phrase)

    return tagged_text

def main():
    line = "太郎は5月18日の朝9時に花子に会いに行った."

    print(line)
    print(make_np_tagged_text(line))

if __name__ == "__main__":
    main()
requirements.txt
pyknp

実行

docker-composeを介して実行してみます.

  % docker-compose build
(ガガッとビルドされる)

  % docker-compose up
Starting pyknp_test_pyknp_1 ... done
Attaching to pyknp_test_pyknp_1
pyknp_1  | 太郎は5月18日の朝9時に花子に会いに行った.
pyknp_1  | <NE:PERSON:太郎>は5月18日の朝9時に<NE:LOCATION:花子>に会いに行った.
pyknp_test_pyknp_1 exited with code 0

pyknp_test.pyの変数lineを変えて再び実行してみましょう.

pyknp_test.py(抜粋)
    line = "ほげほげ〜"
  % docker-compose up
Starting pyknp_test_pyknp_1 ... done
Attaching to pyknp_test_pyknp_1
pyknp_1  | ほげほげ〜
pyknp_1  | ほげほげ〜
pyknp_test_pyknp_1 exited with code 0

いい感じですね:thumbsup:

構成の説明

環境

ざっくり以下のような環境でテストしています.

OS macOS 10.13.6
Docker 18.06.1-ce-mac73

Dockerfile

いくつかの手順に分解してDockerfileを読み解いていきます.筆者は,主に個人でのツールやサービス開発でDockerを利用しているのでそのあたりのtipsが入っていると感じる方もいるかも知れません.

元イメージの設定,ユーザ設定

Dockerfile(抜粋)
FROM python:3.6-slim

# create user as "app"
RUN useradd --user-group --create-home --shell /bin/false app

# set home directory
ENV HOME=/home/app

# copy source file
COPY . $HOME/pyknp_test

この部分は,構築するイメージの元イメージの設定,実行ユーザの設定,開発ディレクトリのコピーをおこなっています.
最終的に実行するのはappユーザとなるようこのあと準備していきます.

JUMAN, KNPのインストール

最近だとJUMANの代わりにJUMAN++を使用することが多いのでしょうか?解析器に強くないので分かりませんが・・・
その話は置いて,JUMAN, KNPをインストールします.どちらも黒橋・河原研究室から発表されているものです.公開に感謝しながら使っていきます.

では,JUMAN, KNPのインストールを抜粋しながら見ていきます.

ビルド環境・ライブラリ等の準備

Dockerfile(抜粋)
# install dependencies
RUN apt-get update && apt-get install -y \
  build-essential \
  curl \
  bzip2 \
  libjuman \
  libcdb-dev \
  zlib1g-dev

この部分は,ビルド環境(build-essential)とライブラリ等を準備します.
今回は構築するイメージのもととしてpython:3.6-slimを使用しているので,このあと使用するファイルダウンロードと展開のためcurlbzip2も同時にインストールしています.

pipからのインストール

Dockerfile(抜粋)
RUN pip3 install --requirement $HOME/pyknp_test/requirements.txt

この部分は,開発ディレクトリのrequirements.txtを元にpipからパッケージをインストールしています.Dockerfileの記述を見ればわかりますが,最初に開発ディレクトリの内容をイメージにコピーしているため実行できます.

JUMAN, KNPのインストール

Dockerfile(抜粋)
# install juman and KNP and copy .jumanrc file
RUN mkdir $HOME/src && \
  cd $HOME/src && \
  curl -L -o juman-7.01.tar.bz2 http://nlp.ist.i.kyoto-u.ac.jp/nl-resource/juman/juman-7.01.tar.bz2 && \
  tar xf juman-7.01.tar.bz2 && \
  cd juman-7.01 && \
  ./configure && \
  make && \
  make install && \
  cp /usr/local/etc/jumanrc $HOME/.jumanrc
RUN cd $HOME/src && \
  curl -L -o knp-4.19.tar.bz2 http://nlp.ist.i.kyoto-u.ac.jp/nl-resource/knp/knp-4.19.tar.bz2 && \
  tar xf knp-4.19.tar.bz2 && \
  cd knp-4.19 && \
  ./configure && \
  make && \
  make install

この部分は,JUMAN, KNPのソースをダウンロードして展開,make,make installしている部分です.
特徴は,.jumanrcファイルをホームディレクトリにコピーしているところです.この処理は現在rootで実行しているのでこの処理をやっておきます.

ちなみに,Dockerの公式ドキュメントを読む感じだとそれぞれのソースはcurlからファイルに保存せずに直接tarに渡して実行するほうが一般的なのかもしれません.

JUMAN++を利用したいと考えている方は,ダウンロードするソースをJUMAN++に変えて実行してください.

ビルド環境等の削除

Dockerfile(抜粋)
# delete download cache
RUN rm -rf $HOME/src && \
  apt-get purge -y \
  build-essential \
  curl \
  bzip2

この部分は,インストール済みのJUMAN, KNPのソースの削除,ビルド環境等の削除をおこなっています.
イメージを軽くしたいのでcurl等も削除しています.

ユーザ変更と実行コマンドの指定

Dockerfile(抜粋)
# change user
RUN chown -R app:app $HOME/*
WORKDIR $HOME/pyknp_test
USER app

# set CMD
CMD ["python3", "pyknp_test.py"]

この部分で,ホームディレクトリの中身の権限をappユーザに変更しています.これにより,コマンドの実行をappユーザとしておこなえるようにしています.
また,ワーキングディレクトリをコピーした開発ディレクトリにしています.docker-compose.yml側でイメージ内のパス指定をしなくて済むようこうしておくと良いでしょう.

docker-compose.yml

docker-compose.yml
version: '3'
services:
  pyknp:
    build: .
    volumes:
      - .:/home/app/pyknp_test

docker-compose.ymlは結構シンプルです.pyknpというサービス名で先程のDockerfileをビルドして実行させています.
また,先程設定したワーキングディレクトリ直下に開発ディレクトリの中身をバインドします.これで開発ディレクトリの中身を変更しても再度ビルドすること無く実行できます.

おわりに

何となくいい感じに開発環境ができたのではないでしょうか.
ディレクトリの構成が簡単なのでイメージ公開やらリポジトリ公開までやらなくてもいいかな〜と勝手に思っています.要望あれば挑戦してみようと思いますのでコメントください.

他にも,何か良いプラクティス等あればコメント頂けると幸いです.

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?