AI for Engineer @Graspy 自然言語周りの備忘録

Graspyとは?公式ページのmeta dataを引用すると以下の通り。

Graspyは日本初のキャリア形成プラットフォームです。オンライン学習や著名人の勉強会を通してビジネススキルを高める「学びの場」と、企業やメンターとの交流を通した新たな価値観との「出会いの場」を提供することで「その先にある未来を掴む」ための機会を創ります。
プロフィール登録するだけで、最大20万円相当の学習カリキュラムを無料で学ぶことができます。 他にも各界の著名人が開催する勉強会に参加することができます。

具体的な登録方法は公式ページを見てもらうとして、普段から職務経歴書を更新し続けている人にとってはプロフィール登録にかかる手間はものの数分です。
実際に登録して500ポイント獲得し、今受けているAI for Engineerコースの内容は、入門としてとても良いと感じます。機械学習に纏わるPythonモジュールだけでなく、クラウド系の開発環境 IBM Watson や Microsoft Azure Machine Learningでの開発体験も網羅しており、やってて楽しい。
全てのプロフィール登録すると500ポイントもらえるのは、以下の受講可能コース5つ全て受けられますよ、という意味なんでしょうね。(100ポイント / コース 消費)

受講可能コース

AI for Engineer

AIエンジニアを目指す方や、より一層のスキルアップをしたいAIエンジニアの方におすすめです。

AI for Business

機械学習・ディープラーニングを学びます。 AIエンジニアを目指す方、AIに興味がある方におすすめ。

HTML/CSS

制作フロー&ポイントを学び、簡単なWEBサイトを作成できるようになります。

Javascript

WEBサイトに、様々な動きや機能を付加する方法を学びます。

Ruby on Rails

実践的なWebアプリケーション開発を学びます。 エンジニア志望の方、体系的に学び直したい方へ。

AI for Engineerコース受講にあたっての備忘録

受講中のAI for Engineerコースですが、内容を公開するわけにはいかないので、一般的な要素の備忘録をとっておきたいと思います。

N-gramは文章を分割する単位です。例えば、This is a penという文章があった場合、N-gramの値が2ではThis is、is a、a penのように前後の2つの単語で文章を区切って分割します。1では単語ごと、3ではThis is a、is a penのように区切るわけです。この方法をN-gram法といいます。特に2つの単語で区切った場合はバイグラム、1つではユニグラム、3つではトリグラムといいます。

英語のような単語区切りにスペースを使う言語とは異なり、日本語には使うことのできないN-gram。日本語にはMecabやJanomeのような形態素解析ツールを使用するのが一般的なんだそう。

形態素解析ツールのインストール

ということで試してみました。GraspyではJanomeのみ扱ってましたが、せっかく紹介があったのでMeCabも一緒に。

MeCab

公式サイトはこちら。以下引用。

MeCabは 京都大学情報学研究科−日本電信電話株式会社コミュニケーション科学基礎研究所 共同研究ユニットプロジェクトを通じて開発されたオープンソース 形態素解析エンジンです。 言語, 辞書,コーパスに依存しない汎用的な設計を 基本方針としています。 パラメータの推定に Conditional Random Fields (CRF) を用 いており, ChaSenが採用している 隠れマルコフモデルに比べ性能が向上しています。また、平均的に ChaSenJumanKAKASIより高速に動作します。 ちなみに和布蕪(めかぶ)は, 作者の好物です。

MeCabはシステムに入れる必要があるので、macOSならbrew、Linuxならaptとか使う。Windowsは知らない。最近だとSubsystem for Linuxでaptできるのかな。

$ brew search mecab mecab-ipadic
==> Formulae
mecab mecab-ko mecab-unidic-extended
mecab-ipadic mecab-ko-dic
mecab-jumandic mecab-unidic
$ brew install mecab
==> Downloading https://homebrew.bintray.com/bottles/mecab-0.996.high_sierra.bot
######################################################################## 100.0%
==> Pouring mecab-0.996.high_sierra.bottle.3.tar.gz
🍺  /usr/local/Cellar/mecab/0.996: 20 files, 4.2MB

そこそこ時間がかかるのでしばし待つ。

Janome

公式サイトはこちら。以下引用。

Janome (蛇の目) は,Pure Python で書かれた,辞書内包の形態素解析器です。
依存ライブラリなしで簡単にインストールでき,アプリケーションに組み込みやすいシンプルな API を備える形態素解析ライブラリを目指しています。
内包辞書として mecab-ipadic-2.7.0-20070801 を使っています。

実装は違えど、辞書は同じものを使用してるんですね。インストールは普通にpipを使います。

$ pip install janome

形態素解析ツールの使い方

Janome

Graspy等では「すもももももももものうち」を例題にしていたので、早口言葉をいくつか試してみました。引用元はこちらの早口言葉紹介サイト。難易度1の中から、個人的によく聞くものだけ抜き出してみました。

"生麦生米生卵",
"老若男女",
"赤パジャマ黄パジャマ茶パジャマ ",
"除雪車除雪作業中",
"隣の客はよく柿食う客だ",
"この釘はひきぬきにくい釘だ",
"かえるぴょこぴょこみぴょこぴょこあわせてぴょこぴょこむぴょこぴょこ",

お試しコードはこちら。

from janome.tokenizer import Tokenizer
import json
from pprint import PrettyPrinter
_sentences = [
  "生麦生米生卵",
  "老若男女",
  "赤パジャマ黄パジャマ茶パジャマ ",
  "除雪車除雪作業中",
  "隣の客はよく柿食う客だ",
  "この釘はひきぬきにくい釘だ",
  "かえるぴょこぴょこみぴょこぴょこあわせてぴょこぴょこむぴょこぴょこ",
]
def main():
  pp = PrettyPrinter(indent=2)
  results = []
  tokenizer = Tokenizer()
  for sentence in _sentences:
    tokens = tokenizer.tokenize(sentence)
    results.append({
      "sentence": sentence,
      "surfaces": [t.surface for t in tokens],
      "phonetics": [t.phonetic for t in tokens],
      "parts_of_speech": [t.part_of_speech for t in tokens],
    })
  pp.pprint(results)
if __name__ == '__main__':
  main()

結果は以下の通り。

[ { 'parts_of_speech': [ '名詞,固有名詞,人名,姓',
                         '接頭詞,名詞接続,*,*',
                         '名詞,固有名詞,地域,国',
                         '名詞,接尾,一般,*',
                         '名詞,一般,*,*'],
    'phonetics': ['ナマムギ', 'ナマ', 'ベイ', 'セイ', 'タマゴ'],
    'sentence': '生麦生米生卵',
    'surfaces': ['生麦', '生', '米', '生', '卵']},
  { 'parts_of_speech': ['名詞,一般,*,*'],
    'phonetics': ['ローニャクナンニョ'],
    'sentence': '老若男女',
    'surfaces': ['老若男女']},
  { 'parts_of_speech': [ '名詞,一般,*,*',
                         '名詞,一般,*,*',
                         '名詞,一般,*,*',
                         '名詞,一般,*,*',
                         '名詞,一般,*,*',
                         '名詞,一般,*,*'],
    'phonetics': ['アカ', 'パジャマ', 'キ', 'パジャマ', 'チャ', 'パジャマ'],
    'sentence': '赤パジャマ黄パジャマ茶パジャマ ',
    'surfaces': ['赤', 'パジャマ', '黄', 'パジャマ', '茶', 'パジャマ']},
  { 'parts_of_speech': [ '名詞,サ変接続,*,*',
                         '名詞,接尾,一般,*',
                         '名詞,サ変接続,*,*',
                         '名詞,サ変接続,*,*',
                         '名詞,接尾,副詞可能,*'],
    'phonetics': ['ジョセツ', 'シャ', 'ジョセツ', 'サギョー', 'チュー'],
    'sentence': '除雪車除雪作業中',
    'surfaces': ['除雪', '車', '除雪', '作業', '中']},
  { 'parts_of_speech': [ '名詞,一般,*,*',
                         '助詞,連体化,*,*',
                         '名詞,一般,*,*',
                         '助詞,係助詞,*,*',
                         '副詞,一般,*,*',
                         '名詞,一般,*,*',
                         '動詞,自立,*,*',
                         '名詞,一般,*,*',
                         '助動詞,*,*,*'],
    'phonetics': ['トナリ', 'ノ', 'キャク', 'ワ', 'ヨク', 'カキ', 'クウ', 'キャク', 'ダ'],
    'sentence': '隣の客はよく柿食う客だ',
    'surfaces': ['隣', 'の', '客', 'は', 'よく', '柿', '食う', '客', 'だ']},
  { 'parts_of_speech': [ '連体詞,*,*,*',
                         '名詞,一般,*,*',
                         '助詞,係助詞,*,*',
                         '動詞,自立,*,*',
                         '形容詞,非自立,*,*',
                         '名詞,一般,*,*',
                         '助動詞,*,*,*'],
    'phonetics': ['コノ', 'クギ', 'ワ', 'ヒキヌキ', 'ニクイ', 'クギ', 'ダ'],
    'sentence': 'この釘はひきぬきにくい釘だ',
    'surfaces': ['この', '釘', 'は', 'ひきぬき', 'にくい', '釘', 'だ']},
  { 'parts_of_speech': [ '動詞,自立,*,*',
                         '副詞,一般,*,*',
                         '動詞,自立,*,*',
                         '副詞,一般,*,*',
                         '動詞,自立,*,*',
                         '助詞,接続助詞,*,*',
                         '副詞,一般,*,*',
                         '名詞,一般,*,*'],
    'phonetics': ['カエル', 'ピョコピョコ', 'ミ', 'ピョコピョコ', 'アワセ', 'テ', 'ピョコピョコ', '*'],
    'sentence': 'かえるぴょこぴょこみぴょこぴょこあわせてぴょこぴょこむぴょこぴょこ',
    'surfaces': [ 'かえる',
                  'ぴょこぴょこ',
                  'み',
                  'ぴょこぴょこ',
                  'あわせ',
                  'て',
                  'ぴょこぴょこ',
                  'むぴょこぴょこ']}]

「かえるぴょこぴょこ...」「生麦生米生卵」のように、単語区切りが判定しづらい文は苦手そうですね。Tokenizerクラスのコンストラクタにユーザ辞書を指定できるので、精度をあげるには辞書を自作すべしってことですかね。

Mecab

mecabは標準入力から文を入力できるので、以下のようなスクリプトを書いてみました。

#!/usr/bin/env bash
SENTENCES=(
  '生麦生米生卵'
  '老若男女'
  '赤パジャマ黄パジャマ茶パジャマ '
  '除雪車除雪作業中'
  '隣の客はよく柿食う客だ'
  'この釘はひきぬきにくい釘だ'
  'かえるぴょこぴょこみぴょこぴょこあわせてぴょこぴょこむぴょこぴょこ'
)
for S in ${SENTENCES[@]}
do
    echo $S:
    echo -en "$(echo $S | mecab)\n\n"
done

結果はこちら。

生麦生米生卵:
生麦	名詞,固有名詞,人名,姓,*,*,生麦,ナマムギ,ナマムギ
生	接頭詞,名詞接続,*,*,*,*,生,ナマ,ナマ
米	名詞,固有名詞,地域,国,*,*,米,ベイ,ベイ
生	名詞,接尾,一般,*,*,*,生,セイ,セイ
卵	名詞,一般,*,*,*,*,卵,タマゴ,タマゴ
EOS
老若男女:
老若男女	名詞,一般,*,*,*,*,老若男女,ロウニャクナンニョ,ローニャクナンニョ
EOS
赤パジャマ黄パジャマ茶パジャマ:
赤	名詞,一般,*,*,*,*,赤,アカ,アカ
パジャマ	名詞,一般,*,*,*,*,パジャマ,パジャマ,パジャマ
黄	名詞,一般,*,*,*,*,黄,キ,キ
パジャマ	名詞,一般,*,*,*,*,パジャマ,パジャマ,パジャマ
茶	名詞,一般,*,*,*,*,茶,チャ,チャ
パジャマ	名詞,一般,*,*,*,*,パジャマ,パジャマ,パジャマ
EOS
除雪車除雪作業中:
除雪	名詞,サ変接続,*,*,*,*,除雪,ジョセツ,ジョセツ
車	名詞,接尾,一般,*,*,*,車,シャ,シャ
除雪	名詞,サ変接続,*,*,*,*,除雪,ジョセツ,ジョセツ
作業	名詞,サ変接続,*,*,*,*,作業,サギョウ,サギョー
中	名詞,接尾,副詞可能,*,*,*,中,チュウ,チュー
EOS
隣の客はよく柿食う客だ:
隣	名詞,一般,*,*,*,*,隣,トナリ,トナリ
の	助詞,連体化,*,*,*,*,の,ノ,ノ
客	名詞,一般,*,*,*,*,客,キャク,キャク
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
よく	副詞,一般,*,*,*,*,よく,ヨク,ヨク
柿	名詞,一般,*,*,*,*,柿,カキ,カキ
食う	動詞,自立,*,*,五段・ワ行促音便,基本形,食う,クウ,クウ
客	名詞,一般,*,*,*,*,客,キャク,キャク
だ	助動詞,*,*,*,特殊・ダ,基本形,だ,ダ,ダ
EOS
この釘はひきぬきにくい釘だ:
この	連体詞,*,*,*,*,*,この,コノ,コノ
釘	名詞,一般,*,*,*,*,釘,クギ,クギ
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
ひきぬき	動詞,自立,*,*,五段・カ行イ音便,連用形,ひきぬく,ヒキヌキ,ヒキヌキ
にくい	形容詞,非自立,*,*,形容詞・アウオ段,基本形,にくい,ニクイ,ニクイ
釘	名詞,一般,*,*,*,*,釘,クギ,クギ
だ	助動詞,*,*,*,特殊・ダ,基本形,だ,ダ,ダ
EOS
かえるぴょこぴょこみぴょこぴょこあわせてぴょこぴょこむぴょこぴょこ:
かえる	動詞,自立,*,*,一段,基本形,かえる,カエル,カエル
ぴょこぴょこ	副詞,一般,*,*,*,*,ぴょこぴょこ,ピョコピョコ,ピョコピョコ
み	動詞,自立,*,*,一段,連用形,みる,ミ,ミ
ぴょこぴょこ	副詞,一般,*,*,*,*,ぴょこぴょこ,ピョコピョコ,ピョコピョコ
あわせ	動詞,自立,*,*,一段,連用形,あわせる,アワセ,アワセ
て	助詞,接続助詞,*,*,*,*,て,テ,テ
ぴょこぴょこ	副詞,一般,*,*,*,*,ぴょこぴょこ,ピョコピョコ,ピョコピョコ
むぴょこぴょこ	名詞,一般,*,*,*,*,*
EOS

同じ辞書を使ってるだけあって、同じ結果になりました。

感想

精度が必要ならそれなりの辞書を用意した上で、助詞/助動詞を除いたtokenを説明変数として使用すれば、いい感じの精度が期待できる…のかな?機械学習を勉強するのはいいけど、まだ実用的な実装未経験なので、応用についてはそのうちまた別途ということで。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

Close Bitnami banner
Bitnami