Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Python による日本語自然言語処理 〜系列ラベリングによる実世界テキスト分析〜 / PyC...

taishi-i
September 14, 2019

Python による日本語自然言語処理 〜系列ラベリングによる実世界テキスト分析〜 / PyCon JP 2019

PyCon JP 2019 での発表スライドです。
GitHub: https://github.com/taishi-i/nagisa-tutorial-pycon2019

taishi-i

September 14, 2019
Tweet

More Decks by taishi-i

Other Decks in Programming

Transcript

  1. 自己紹介 • 名前 ◦ 池田 大志(Taishi Ikeda) • 略歴 ◦

    2015 - 2017 : 奈良先端大 自然言語処理学研究室 出身 ◦ 2017 - 現在 : 企業にて自然言語処理に関する研究開発に従事 • これまでの取り組み ◦ WNUT@COLING2016 ◦ 形態素解析の今とこれから@言語処理学会2018 ◦ ポスターセッション@PyCon JP2018 ◦ 全国大会@人工知能学会2019 2
  2. WNUT@COLING2016 での発表 • Japanese Text Normalization with Encoder-Decoder Model •

    口語表現「すげえええ」を辞書表現「すごい」に正規化する研究 3
  3. 本発表について • 概要 ◦ Python による単語分割と品詞タグ付けの実装方法の説明 ◦ 日本語を対象とした固有表現抽出モデルの実装方法の説明 • 対象となる聞き手

    ◦ 自然言語処理に興味があり、テキストデータの分析を行いたい人 ◦ 一通り Python の基礎を勉強して、次に何か作ってみたい人 • ハンズオン形式による発表 ◦ 本発表を聞きつつ、手元で Python プログラムを動かしながら、 自然言語処理を体験してもらう内容 • 本スライドとサンプルコードは GitHub にて公開中 ◦ https://github.com/taishi-i/nagisa-tutorial-pycon2019 5
  4. 6 本発表の目的 コーパス • 自然言語処理を行うための一連の実装方法を理解してもらい、 開発現場で自然言語処理を活用するきっかけとなることが本発表の目的 ① 前処理 学習データ 開発データ

    評価データ ② 学習 学習済み モデル ③ 評価 実験結果 ④ 解析ミスへの対策 固有表現抽出モデルの実装にて説明 単語分割と品詞タグ付けの実装にて説明
  5. 目次 7 • 単語分割と品詞タグ付けについて ◦ nagisa とは? ◦ nagisa の利用事例

    ◦ Bidirectional LSTMs (BLSTMs) とは? ◦ BLSTMs による単語分割 ◦ BLSTMs による品詞タグ付け ◦ 「形態素解析器」ではないのか? • nagisa による単語分割と品詞タグ付けの 実装方法 ◦ インストール方法 ◦ シンプルな単語分割と品詞タグ付け機能を提供 ◦ 品詞による出力単語のフィルタリングが可能 ◦ ユーザー辞書の追加が容易 ◦ 顔文字やURLに対して頑健な解析が可能 ◦ 単語分割と品詞タグ付けの応用例 • Python による固有表現抽出モデ ルの実装方法 ◦ BLSTMs による固有表現抽出 ◦ 事前準備 ◦ 京都大学ウェブ文書リードコーパ スの前処理 ◦ 前処理スクリプトの実行 ◦ 固有表現抽出モデルの学習 ◦ 学習済みモデルの利用方法 ◦ 固有表現ごとの正解率の確認 ◦ 出力結果の確認によるエラー分析 ◦ 解析ミスへの対応方法 ◦ 系列ラベリングの応用例
  6. 本発表を通じて体験する自然言語処理 入力文: Pythonで簡単に使えるツールです Python で 簡単 に 使える ツール です

    Python で 簡単 に 使える ツール です 名詞 助詞 形状詞 助詞 動詞 名詞 助動詞 単語分割 品詞タグ付け 11
  7. 13

  8. nagisa とは? • 特徴 ◦ BLSTMs による単語分割と品詞タグ付けの機能を提供 ◦ 系列ラベリングモデルの学習が可能 ◦

    pip install nagisa でインストール可能 • 開発方針 ◦ シンプルで使いやすいツールを目指し、開発を行っている • 想定ユーザー ◦ これから自然言語処理を始めようと考えている Python ユーザー 14
  9. nagisa の利用事例 • NTT's Machine Translation Systems for WMT19 Robustness

    Task ◦ 口語表現を対象とした機械翻訳の研究にて nagisa を利用した事例 ◦ 入力文に含まれる顔文字を抽出する処理に利用している 18 https://www.aclweb.org/anthology/W19-5365
  10. Bidirectional LSTMs (BLSTMs) とは? • 前向き LSTM と後向き LSTM を計算することで、

    入力全体の情報を各時刻で考慮できるニューラルネットワーク Neural Networks, Types, and Functional Programming: http://colah.github.io/posts/2015-09-NN-Types-FP/ 20
  11. Bidirectional LSTMs (BLSTMs) とは? • 前向き LSTM と後向き LSTM を計算することで、

    入力全体の情報を各時刻で考慮できるニューラルネットワーク Neural Networks, Types, and Functional Programming: http://colah.github.io/posts/2015-09-NN-Types-FP/ 入力系列 出力系列 21
  12. BLSTMs による単語分割 入力文: Pythonで簡単に使えるツールです Python で 簡単 に 使える ツール

    です 各文字に対してタグを付与する BMMMME S BE S BME BME BE • 各文字に対して B・M・E・S の4つのタグを付与することで単語分割を行う ◦ Begin: 単語の開始文字とする ◦ Middel: 単語の途中文字とする ◦ End: 単語の終了文字とする ◦ Single: 一文字を単語とする 23
  13. BLSTMs による品詞タグ付け 入力文: Pythonで簡単に使えるツールです Python で 簡単 に 使える ツール

    です 各単語に対してタグを付与する 名詞 助詞 係詞 形状詞 動詞 名詞 助動詞 • 各単語に対して24個の品詞タグを付与する ◦ 名詞, 助詞, 接尾辞, 動詞, 連体詞, 助動詞, 形容詞 など ◦ 文字単位 BLSTMs のベクトルを単語ベクトルに結合することで、 未知語に対して頑健な品詞付与が可能となる 25
  14. インストール方法 29 $ pip install nagisa • pip によるインストールが可能 •

    サポートする OS と Python のバージョン ◦ Linux/macOS ▪ Python 2.7, 3.5, 3.6, 3.7 ◦ Windows (64bit) ▪ Python 3.5, 3.6, 3.7
  15. シンプルな単語分割と品詞タグ付け機能を提供 • nagisa.tagging(text) で単語分割と品詞タグ付けを実行する 30 >>> import nagisa >>> text

    = 'Pythonで簡単に使えるツールです' >>> tokens = nagisa.tagging(text) >>> print(tokens) Python/名詞 で/助詞 簡単/形状詞 に/助動詞 使える/動詞 ツール/ 名詞 です/助動詞 >>> print(tokens.words) ['Python', 'で', '簡単', 'に', '使える', 'ツール', 'です'] >>> print(tokens.postags) ['名詞', '助詞', '形状詞', '助動詞', '動詞', '名詞', '助動 詞']
  16. シンプルな単語分割と品詞タグ付け機能を提供 • nagisa.tagging(text) で単語分割と品詞タグ付けを実行する 31 >>> import nagisa >>> text

    = 'Pythonで簡単に使えるツールです' >>> tokens = nagisa.tagging(text) >>> print(tokens) Python/名詞 で/助詞 簡単/形状詞 に/助動詞 使える/動詞 ツール/ 名詞 です/助動詞 >>> print(tokens.words) ['Python', 'で', '簡単', 'に', '使える', 'ツール', 'です'] >>> print(tokens.postags) ['名詞', '助詞', '形状詞', '助動詞', '動詞', '名詞', '助動 詞'] インポート
  17. シンプルな単語分割と品詞タグ付け機能を提供 • nagisa.tagging(text) で単語分割と品詞タグ付けを実行する 32 >>> import nagisa >>> text

    = 'Pythonで簡単に使えるツールです' >>> tokens = nagisa.tagging(text) >>> print(tokens) Python/名詞 で/助詞 簡単/形状詞 に/助動詞 使える/動詞 ツール/ 名詞 です/助動詞 >>> print(tokens.words) ['Python', 'で', '簡単', 'に', '使える', 'ツール', 'です'] >>> print(tokens.postags) ['名詞', '助詞', '形状詞', '助動詞', '動詞', '名詞', '助動 詞'] 入力テキスト
  18. シンプルな単語分割と品詞タグ付け機能を提供 • nagisa.tagging(text) で単語分割と品詞タグ付けを実行する 33 >>> import nagisa >>> text

    = 'Pythonで簡単に使えるツールです' >>> tokens = nagisa.tagging(text) >>> print(tokens) Python/名詞 で/助詞 簡単/形状詞 に/助動詞 使える/動詞 ツール/ 名詞 です/助動詞 >>> print(tokens.words) ['Python', 'で', '簡単', 'に', '使える', 'ツール', 'です'] >>> print(tokens.postags) ['名詞', '助詞', '形状詞', '助動詞', '動詞', '名詞', '助動 詞'] 解析の実行
  19. シンプルな単語分割と品詞タグ付け機能を提供 • nagisa.tagging(text) で単語分割と品詞タグ付けを実行する 34 >>> import nagisa >>> text

    = 'Pythonで簡単に使えるツールです' >>> tokens = nagisa.tagging(text) >>> print(tokens) Python/名詞 で/助詞 簡単/形状詞 に/助動詞 使える/動詞 ツール/ 名詞 です/助動詞 >>> print(tokens.words) ['Python', 'で', '簡単', 'に', '使える', 'ツール', 'です'] >>> print(tokens.postags) ['名詞', '助詞', '形状詞', '助動詞', '動詞', '名詞', '助動 詞'] 結果の出力
  20. シンプルな単語分割と品詞タグ付け機能を提供 • nagisa.tagging(text) で単語分割と品詞タグ付けを実行する 35 >>> import nagisa >>> text

    = 'Pythonで簡単に使えるツールです' >>> tokens = nagisa.tagging(text) >>> print(tokens) Python/名詞 で/助詞 簡単/形状詞 に/助動詞 使える/動詞 ツール/ 名詞 です/助動詞 >>> print(tokens.words) ['Python', 'で', '簡単', 'に', '使える', 'ツール', 'です'] >>> print(tokens.postags) ['名詞', '助詞', '形状詞', '助動詞', '動詞', '名詞', '助動 詞'] 単語列リストの取得
  21. シンプルな単語分割と品詞タグ付け機能を提供 • nagisa.tagging(text) で単語分割と品詞タグ付けを実行する 36 >>> import nagisa >>> text

    = 'Pythonで簡単に使えるツールです' >>> tokens = nagisa.tagging(text) >>> print(tokens) Python/名詞 で/助詞 簡単/形状詞 に/助動詞 使える/動詞 ツール/ 名詞 です/助動詞 >>> print(tokens.words) ['Python', 'で', '簡単', 'に', '使える', 'ツール', 'です'] >>> print(tokens.postags) ['名詞', '助詞', '形状詞', '助動詞', '動詞', '名詞', '助動 詞'] 品詞列リストの取得
  22. 品詞による出力単語のフィルタリングが可能 • 引数に品詞を指定することで、出力単語のフィルタリングを行う 37 >>> import nagisa >>> text =

    'Pythonで簡単に使えるツールです' >>> tokens = nagisa.extract( text, extract_postags=['名詞'] ) >>> print(tokens) Python/名詞 ツール/名詞
  23. 品詞による出力単語のフィルタリングが可能 • 引数に品詞を指定することで、出力単語のフィルタリングを行う 38 >>> import nagisa >>> text =

    'Pythonで簡単に使えるツールです' >>> tokens = nagisa.extract( text, extract_postags=['名詞'] ) >>> print(tokens) Python/名詞 ツール/名詞 取得したい品詞を指定
  24. 品詞による出力単語のフィルタリングが可能 • 引数に品詞を指定することで、出力単語のフィルタリングを行う 39 >>> import nagisa >>> text =

    'Pythonで簡単に使えるツールです' >>> tokens = nagisa.extract( text, extract_postags=['名詞'] ) >>> print(tokens) Python/名詞 ツール/名詞 nagisa.extract の実行
  25. 品詞による出力単語のフィルタリングが可能 • 引数に品詞を指定することで、出力単語のフィルタリングを行う 40 >>> import nagisa >>> text =

    'Pythonで簡単に使えるツールです' >>> tokens = nagisa.extract( text, extract_postags=['名詞'] ) >>> print(tokens) Python/名詞 ツール/名詞 「名詞」のみを抽出
  26. 品詞による出力単語のフィルタリングが可能 • 引数に品詞を指定することで、出力単語のフィルタリングを行う 41 >>> import nagisa >>> text =

    'Pythonで簡単に使えるツールです' >>> tokens = nagisa.filter( text, filter_postags=['助詞', '助動詞'] ) >>> print(tokens) Python/名詞 簡単/形状詞 使える/動詞 ツール/名詞 除外したい品詞を指定
  27. 品詞による出力単語のフィルタリングが可能 • 引数に品詞を指定することで、出力単語のフィルタリングを行う 42 >>> import nagisa >>> text =

    'Pythonで簡単に使えるツールです' >>> tokens = nagisa.filter( text, filter_postags=['助詞', '助動詞'] ) >>> print(tokens) Python/名詞 簡単/形状詞 使える/動詞 ツール/名詞 nagisa.filter の実行
  28. 品詞による出力単語のフィルタリングが可能 • 引数に品詞を指定することで、出力単語のフィルタリングを行う 43 >>> import nagisa >>> text =

    'Pythonで簡単に使えるツールです' >>> tokens = nagisa.filter( text, filter_postags=['助詞', '助動詞'] ) >>> print(tokens) Python/名詞 簡単/形状詞 使える/動詞 ツール/名詞 「助詞」と「助動詞」以外を抽出
  29. ユーザー辞書の追加が容易 • single_word_list に追加した単語は、ひとつの単語として分割する 44 >>> import nagisa >>> text

    = "3月に見た「3月のライオン」" >>> print(nagisa.tagging(text)) 3/名詞 月/名詞 に/助詞 見/動詞 た/助動詞 「/補助記号 3/名詞 月/名詞 の/助詞 ライオン/名詞 」/補助記号 >>> new_tagger = nagisa.Tagger( single_word_list=['3月のライオン'] ) >>> print(new_tagger.tagging(text)) 3/名詞 月/名詞 に/助詞 見/動詞 た/助動詞 「/補助記号 3月のライオン/名詞 」/補助記号
  30. ユーザー辞書の追加が容易 • single_word_list に追加した単語は、ひとつの単語として分割する 45 >>> import nagisa >>> text

    = "3月に見た「3月のライオン」" >>> print(nagisa.tagging(text)) 3/名詞 月/名詞 に/助詞 見/動詞 た/助動詞 「/補助記号 3/名詞 月/名詞 の/助詞 ライオン/名詞 」/補助記号 >>> new_tagger = nagisa.Tagger( single_word_list=['3月のライオン'] ) >>> print(new_tagger.tagging(text)) 3/名詞 月/名詞 に/助詞 見/動詞 た/助動詞 「/補助記号 3月のライオン/名詞 」/補助記号 入力テキスト
  31. ユーザー辞書の追加が容易 • single_word_list に追加した単語は、ひとつの単語として分割する 46 >>> import nagisa >>> text

    = "3月に見た「3月のライオン」" >>> print(nagisa.tagging(text)) 3/名詞 月/名詞 に/助詞 見/動詞 た/助動詞 「/補助記号 3/名詞 月/名詞 の/助詞 ライオン/名詞 」/補助記号 >>> new_tagger = nagisa.Tagger( single_word_list=['3月のライオン'] ) >>> print(new_tagger.tagging(text)) 3/名詞 月/名詞 に/助詞 見/動詞 た/助動詞 「/補助記号 3月のライオン/名詞 」/補助記号 解析結果
  32. ユーザー辞書の追加が容易 • single_word_list に追加した単語は、ひとつの単語として分割する 47 >>> import nagisa >>> text

    = "3月に見た「3月のライオン」" >>> print(nagisa.tagging(text)) 3/名詞 月/名詞 に/助詞 見/動詞 た/助動詞 「/補助記号 3/名詞 月/名詞 の/助詞 ライオン/名詞 」/補助記号 >>> new_tagger = nagisa.Tagger( single_word_list=['3月のライオン'] ) >>> print(new_tagger.tagging(text)) 3/名詞 月/名詞 に/助詞 見/動詞 た/助動詞 「/補助記号 3月のライオン/名詞 」/補助記号 「3月のライオン」をリストに追加
  33. ユーザー辞書の追加が容易 • single_word_list に追加した単語は、ひとつの単語として分割する 48 >>> import nagisa >>> text

    = "3月に見た「3月のライオン」" >>> print(nagisa.tagging(text)) 3/名詞 月/名詞 に/助詞 見/動詞 た/助動詞 「/補助記号 3/名詞 月/名詞 の/助詞 ライオン/名詞 」/補助記号 >>> new_tagger = nagisa.Tagger( single_word_list=['3月のライオン'] ) >>> print(new_tagger.tagging(text)) 3/名詞 月/名詞 に/助詞 見/動詞 た/助動詞 「/補助記号 3月のライオン/名詞 」/補助記号 new_tagger を定義
  34. ユーザー辞書の追加が容易 • single_word_list に追加した単語は、ひとつの単語として分割する 49 >>> import nagisa >>> text

    = "3月に見た「3月のライオン」" >>> print(nagisa.tagging(text)) 3/名詞 月/名詞 に/助詞 見/動詞 た/助動詞 「/補助記号 3/名詞 月/名詞 の/助詞 ライオン/名詞 」/補助記号 >>> new_tagger = nagisa.Tagger( single_word_list=['3月のライオン'] ) >>> print(new_tagger.tagging(text)) 3/名詞 月/名詞 に/助詞 見/動詞 た/助動詞 「/補助記号 3月のライオン/名詞 」/補助記号 解析の実行
  35. ユーザー辞書の追加が容易 • single_word_list に追加した単語は、ひとつの単語として分割する 50 >>> import nagisa >>> text

    = "3月に見た「3月のライオン」" >>> print(nagisa.tagging(text)) 3/名詞 月/名詞 に/助詞 見/動詞 た/助動詞 「/補助記号 3/名詞 月/名詞 の/助詞 ライオン/名詞 」/補助記号 >>> new_tagger = nagisa.Tagger( single_word_list=['3月のライオン'] ) >>> print(new_tagger.tagging(text)) 3/名詞 月/名詞 に/助詞 見/動詞 た/助動詞 「/補助記号 3月のライオン/名詞 」/補助記号 解析結果
  36. 顔文字やURLに対して頑健な解析が可能 • 文字単位の BLSTMs による解析で顔文字をひとつの単語として分割する 51 >>> import nagisa >>>

    text = 'https://github.com/taishi-i/nagisaでコードを公 開中(๑¯ω¯๑)' >>> tokens = nagisa.tagging(text) >>> print(tokens) https://github.com/taishi-i/nagisa/URL で/助詞 コード/名詞 を/助詞 公開/名詞 中/接尾辞 (๑¯ω¯๑)/補助記号
  37. 顔文字やURLに対して頑健な解析が可能 • 文字単位の BLSTMs による解析で顔文字をひとつの単語として分割する 52 >>> import nagisa >>>

    text = 'https://github.com/taishi-i/nagisaでコードを公 開中(๑¯ω¯๑)' >>> tokens = tagger.tagging(text) >>> print(tokens) https://github.com/taishi-i/nagisa/URL で/助詞 コード/名詞 を/助詞 公開/名詞 中/接尾辞 (๑¯ω¯๑)/補助記号 入力テキスト
  38. 53 https 名詞,固有名詞,組織,*,*,*,https,*,* :// 名詞,サ変接続,*,*,*,*,://,*,* github 名詞,一般,*,*,*,*,github,*,* . 名詞,サ変接続,*,*,*,*,.,*,* com

    名詞,一般,*,*,*,*,com,*,* / 名詞,サ変接続,*,*,*,*,/,*,* taishi 名詞,一般,*,*,*,*,taishi,*,* - 名詞,サ変接続,*,*,*,*,-,*,* i 名詞,一般,*,*,*,*,i,*,* / 名詞,サ変接続,*,*,*,*,/,*,* nagisa 名詞,一般,*,*,*,*,nagisa,*,* で 助詞,格助詞,一般,*,*,*,で,デ,デ コード 名詞,一般,*,*,*,*,コード,コード,コード を 助詞,格助詞,一般,*,*,*,を,ヲ,ヲ 公開 名詞,サ変接続,*,*,*,*,公開,コウカイ,コーカイ 中 名詞,接尾,副詞可能,*,*,*,中,チュウ,チュー ( 名詞,サ変接続,*,*,*,*,(,*,* ๑ 記号,一般,*,*,*,*,๑,*,* 記号,空白,*,*,*,*, ,*,* ̄ 記号,一般,*,*,*,*,̄,*,* ω 記号,アルファベット,*,*,*,*,ω,オメガ,オメガ 記号,空白,*,*,*,*, ,*,* ̄๑ 記号,一般,*,*,*,*,̄๑,*,* ) 名詞,サ変接続,*,*,*,*,),*,* Janome による形態素解析 過剰な分割結果
  39. 顔文字やURLに対して頑健な解析が可能 • 文字単位の BLSTMs による解析で顔文字をひとつの単語として分割する 54 >>> import nagisa >>>

    text = 'https://github.com/taishi-i/nagisaでコードを公 開中(๑¯ω¯๑)' >>> tokens = nagisa.tagging(text) >>> print(tokens) https://github.com/taishi-i/nagisa/URL で/助詞 コード/名詞 を/助詞 公開/名詞 中/接尾辞 (๑¯ω¯๑)/補助記号 解析結果
  40. 顔文字やURLに対して頑健な解析が可能 • 文字単位の BLSTMs による解析で顔文字をひとつの単語として分割する 55 >>> import nagisa >>>

    text = 'https://github.com/taishi-i/nagisaでコードを公 開中(๑¯ω¯๑)' >>> tokens = nagisa.tagging(text) >>> print(tokens) https://github.com/taishi-i/nagisa/URL で/助詞 コード/名詞 を/助詞 公開/名詞 中/接尾辞 (๑¯ω¯๑)/補助記号 解析結果
  41. 56 ツール名 初期 リリース 最新 リリース 解析手法 分割基準 解析 速度

    対応言語 pip Star 特徴 JUMAN 1992 2014 ラティス/人手に よるコスト設定 JUMAN基準 ◯ perl, Python △ - 豊富な意味表現の付与 が可能 ChaSen 1996 2011 ラティス/HMM ipadic, UniDic, NAIST-dic △ コマンド ラインのみ ✕ - 統計処理により 形態素解析を可能とした MeCab 2006 2013 ラティス/CRF ipadic, UniDic, JUMAN基準, NEologd ◎ C++, Python, その他 ラッパー多数 ◯ 469 日本語NLPの デファクトスタンダード KyTea 2011 2014 点推定/SVM UniDic ◯ C++, Python △ 156 読み推定が可能 Rakuten MA 2014 2015 系列ラベリング /SCW UniDic ◯ JavaScript ✕ 403 100% JavaScript による 実装 JUMAN++ 2016 2019 ラティス/ニュー ラルLM JUMAN基準 ◯ Python △ 173 ニューラルLMを用いるこ とで高精度 Sudachi 2017 2019 ラティス/CRF 長・中・短の 3種類 ◯ Java, Python ◯ 368 分割単位のコントロール が可能 nagisa 2018 2019 系列ラベリング /BLSTMs UniDic △ Python ◯ 135 Pythonで簡単に使える Stanford NLP 2019 2019 系列ラベリング /BLSTMs Universal Depndency ✕ Python ◯ 2377 多言語に対応 GiNZA 2019 2019 ラティス/CRF Universal Depndency ✕ Python ◯ 233 係り受け解析も可能 SentencePiece 2017 2019 UnigramLM Subword ◎ C++, Python ◯ 2977 ニューラル言語処理向け のトークナイザ 2019年度版 形態素解析器比較表 2019年9月4日時点の情報
  42. 本発表を通じて体験する自然言語処理 入力文: カナダのモントリオール大学教授ヨシュア・ベンジオ氏 単語分割 カナダ の モントリ オール 大学 教授

    ヨシュア ・ ベンジオ 氏 固有表現抽出 カナダ の モントリ オール 大学 教授 ヨシュア ・ ベンジオ 氏 B-LOC O B-ORG E-ORG O B-PSN M-PSN E-PSN O 61
  43. 本発表を通じて体験する自然言語処理 入力文: カナダのモントリオール大学教授ヨシュア・ベンジオ氏 単語分割 カナダ の モントリ オール 大学 教授

    ヨシュア ・ ベンジオ 氏 固有表現抽出 カナダ の モントリ オール 大学 教授 ヨシュア ・ ベンジオ 氏 B-LOC O B-ORG E-ORG O B-PSN M-PSN E-PSN O • 場所:カナダ • 組織:モントリオール大学 • 人名:ヨシュア・ベンジオ 62
  44. BLSTMs による固有表現抽出 • 固有表現の箇所に対応する、抽出すべきテキスト中の箇所をあらかじめ タグづけした学習データを用意し、そのデータを機械学習アルゴリズムに 与え、そのデータから抽出規則を自動的に学習する (コロナ社「自然言語処理の基礎」より) • 固有表現タグの一覧 ◦

    TIME, DATE, LOCATION, PERSON, MONEY, ARTIFACT PERCENT, ORGANIZATION, OPTIONAL • BMEO によるチャンキング ◦ Begin: 固有表現の開始単語とする (e.g. B-PSN) ◦ Middel: 固有表現の途中単語とする (e.g. M-PSN) ◦ End: 固有表現の終了単語とする (e.g. E-PSN) ◦ O: 固有表現でないことを示すタグ 65
  45. 京都大学ウェブ文書リードコーパス • 各文書は KNP フォーマットで保存されている ◦ KWDLC-1.0/dat/rel/w201106-00021201106-0002100303.KNP 67 # S-ID:w201106-0002100303-1

    (Revision.8ce44af on 2014-08-14) JUMAN:8.0 (Revision.06f73dd on 2015-01-07) KNP:4.2-93fadae DATE:2015/07/04 SCORE:-11.27431 MOD:2015/11/02 MEMO: * 0 3D + 0 4D <ne type="DATE" target="1981年"/> 1981 せんきゅうひゃくはちじゅういち * 名詞 数詞 * * 年 ねん * 接尾辞 名詞性名詞助数辞 * * に に * 助詞 格助詞 * * * 1 2D + 1 2D <ne type="LOCATION" target="ワシントン州"/> ワシントン わしんとん * 名詞 地名 * * 州 しゅう * 接尾辞 名詞性特殊接尾辞 * * + 2 3D <rel type="ノ?" target="ワシントン州" sid="w201106-0002100303-1" tag="1"/>
  46. 京都大学ウェブ文書リードコーパスの前処理 • モデル学習のため、KNP フォーマットをタブ区切りのファイルに変換する 68 カナダ B-LOCATION の O モントリオール

    B-ORGANIZATION 大学 E-ORGANIZATION 教授 O ヨシュア B-PERSON ・ M-PERSON ベンジオ E-PERSON 氏 O EOS サンプルデータへのリンクは ←ここをクリック
  47. 前処理スクリプトの実行 1. 前処理スクリプトのダウンロードと作業ディレクトリへの移動 2. 解凍した京大ウェブ文書リードコーパス(KWDLC-1.0)を引数に指定し、 preprocess_kwdlc.py の実行(タブ区切りのファイルへの変換と学習・ 開発・評価データの分割)を行う 3. 出力ファイルの確認を行う

    73 $ git clone https://github.com/taishi-i/nagisa-tutorial-pycon2019 $ cd nagisa-tutorial-pycon2019/kwdlc_ner_tutorial $ python preprocess_kwdlc.py KWDLC-1.0 $ ls data kwdlc.txt kwdlc.train kwdlc.dev kwdlc.test Python コードへのリンクは ←ここをクリック
  48. 固有表現抽出モデルの学習 • 学習スクリプトの実行 • train_kwdlc_model.py  74 $ python train_kwdlc_model.py import

    nagisa nagisa.fit( train_file="data/kwdlc.train", dev_file="data/kwdlc.dev", test_file="data/kwdlc.test", model_name="data/kwdlc_ner_model" ) Python コードへのリンクは ←ここをクリック
  49. 固有表現抽出モデルの学習 • 学習スクリプトの実行 • train_kwdlc_model.py  75 $ python train_kwdlc_model.py import

    nagisa nagisa.fit( train_file="data/kwdlc.train", dev_file="data/kwdlc.dev", test_file="data/kwdlc.test", model_name="data/kwdlc_ner_model" ) インポート
  50. 固有表現抽出モデルの学習 • 学習スクリプトの実行 • train_kwdlc_model.py 76 $ python train_kwdlc_model.py import

    nagisa nagisa.fit( train_file="data/kwdlc.train", dev_file="data/kwdlc.dev", test_file="data/kwdlc.test", model_name="data/kwdlc_ner_model" ) 入力ファイルの指定
  51. 固有表現抽出モデルの学習 • 学習スクリプトの実行 • train_kwdlc_model.py 77 $ python train_kwdlc_model.py import

    nagisa nagisa.fit( train_file="data/kwdlc.train", dev_file="data/kwdlc.dev", test_file="data/kwdlc.test", model_name="data/kwdlc_ner_model" )  出力モデル名の指定
  52. 固有表現抽出モデルの学習 • 学習スクリプトの実行 • train_kwdlc_model.py 78 $ python train_kwdlc_model.py import

    nagisa nagisa.fit( train_file="data/kwdlc.train", dev_file="data/kwdlc.dev", test_file="data/kwdlc.test", model_name="data/kwdlc_ner_model" )  学習の実行
  53. 学習過程のログ 79 [dynet] random seed: 1234 [dynet] allocating memory: 32MB

    [dynet] memory allocation done. [nagisa] LAYERS: 1 [nagisa] THRESHOLD: 3 [nagisa] DECAY: 1 [nagisa] EPOCH: 10 ... Epoch LR Loss Time_m DevWS_f1 DevPOS_f1 TestWS_f1 TestPOS_f1 1 0.100 15.09 0.632 92.41 83.14 91.70 82.63 2 0.100 8.818 0.637 93.59 85.59 93.21 85.28 3 0.100 6.850 0.637 93.98 85.60 93.75 86.01 4 0.100 5.751 0.634 94.44 87.29 94.01 86.99 5 0.050 5.028 0.614 94.35 87.02 94.01 86.99 6 0.050 3.727 0.647 94.84 87.52 94.79 87.91 7 0.025 3.268 0.613 94.52 87.45 94.79 87.91 8 0.012 2.761 0.610 94.75 87.58 94.79 87.91 9 0.012 2.447 0.634 94.95 87.79 95.00 88.28 10 0.006 2.333 0.624 94.73 87.41 95.00 88.28
  54. 学習過程のログ 80 [dynet] random seed: 1234 [dynet] allocating memory: 32MB

    [dynet] memory allocation done. [nagisa] LAYERS: 1 [nagisa] THRESHOLD: 3 [nagisa] DECAY: 1 [nagisa] EPOCH: 10 ... Epoch LR Loss Time_m DevWS_f1 DevPOS_f1 TestWS_f1 TestPOS_f1 1 0.100 15.09 0.632 92.41 83.14 91.70 82.63 2 0.100 8.818 0.637 93.59 85.59 93.21 85.28 3 0.100 6.850 0.637 93.98 85.60 93.75 86.01 4 0.100 5.751 0.634 94.44 87.29 94.01 86.99 5 0.050 5.028 0.614 94.35 87.02 94.01 86.99 6 0.050 3.727 0.647 94.84 87.52 94.79 87.91 7 0.025 3.268 0.613 94.52 87.45 94.79 87.91 8 0.012 2.761 0.610 94.75 87.58 94.79 87.91 9 0.012 2.447 0.634 94.95 87.79 95.00 88.28 10 0.006 2.333 0.624 94.73 87.41 95.00 88.28  ハイパーパラメータの一覧
  55. 学習過程のログ 81 [dynet] random seed: 1234 [dynet] allocating memory: 32MB

    [dynet] memory allocation done. [nagisa] LAYERS: 1 [nagisa] THRESHOLD: 3 [nagisa] DECAY: 1 [nagisa] EPOCH: 10 ... Epoch LR Loss Time_m DevWS_f1 DevPOS_f1 TestWS_f1 TestPOS_f1 1 0.100 15.09 0.632 92.41 83.14 91.70 82.63 2 0.100 8.818 0.637 93.59 85.59 93.21 85.28 3 0.100 6.850 0.637 93.98 85.60 93.75 86.01 4 0.100 5.751 0.634 94.44 87.29 94.01 86.99 5 0.050 5.028 0.614 94.35 87.02 94.01 86.99 6 0.050 3.727 0.647 94.84 87.52 94.79 87.91 7 0.025 3.268 0.613 94.52 87.45 94.79 87.91 8 0.012 2.761 0.610 94.75 87.58 94.79 87.91 9 0.012 2.447 0.634 94.95 87.79 95.00 88.28 10 0.006 2.333 0.624 94.73 87.41 95.00 88.28 開発データに対する 単語分割のF1値とタグ付けのF1値
  56. 学習過程のログ 82 [dynet] random seed: 1234 [dynet] allocating memory: 32MB

    [dynet] memory allocation done. [nagisa] LAYERS: 1 [nagisa] THRESHOLD: 3 [nagisa] DECAY: 1 [nagisa] EPOCH: 10 ... Epoch LR Loss Time_m DevWS_f1 DevPOS_f1 TestWS_f1 TestPOS_f1 1 0.100 15.09 0.632 92.41 83.14 91.70 82.63 2 0.100 8.818 0.637 93.59 85.59 93.21 85.28 3 0.100 6.850 0.637 93.98 85.60 93.75 86.01 4 0.100 5.751 0.634 94.44 87.29 94.01 86.99 5 0.050 5.028 0.614 94.35 87.02 94.01 86.99 6 0.050 3.727 0.647 94.84 87.52 94.79 87.91 7 0.025 3.268 0.613 94.52 87.45 94.79 87.91 8 0.012 2.761 0.610 94.75 87.58 94.79 87.91 9 0.012 2.447 0.634 94.95 87.79 95.00 88.28 10 0.006 2.333 0.624 94.73 87.41 95.00 88.28 評価データに対する 単語分割のF1値とタグ付けのF1値
  57. 学習済みモデルの利用方法 • モデルファイルをロードし、固有表現抽出モデルを利用する 83 >>> import nagisa >>> ner_tagger =

    nagisa.Tagger( vocabs="data/kwdlc_ner_model.vocabs", params="data/kwdlc_ner_model.params", hp="data/kwdlc_ner_model.hp" ) >>> text = "FacebookのAIラボ所長でもあるヤン・ルカン博士" >>> tokens = ner_tagger.tagging(text) >>> print(tokens) Facebook/B-ORGANIZATION の/O AI/O ラボ/O 所長/O で/O も/O ある/O ヤン/B-PERSON ・/M-PERSON ルカン/E-PERSON 博士/O Python コードへのリンクは ←ここをクリック
  58. 学習済みモデルの利用方法 • モデルファイルをロードし、固有表現抽出モデルを利用する 84 >>> import nagisa >>> ner_tagger =

    nagisa.Tagger( vocabs="data/kwdlc_ner_model.vocabs", params="data/kwdlc_ner_model.params", hp="data/kwdlc_ner_model.hp" ) >>> text = "FacebookのAIラボ所長でもあるヤン・ルカン博士" >>> tokens = ner_tagger.tagging(text) >>> print(tokens) Facebook/B-ORGANIZATION の/O AI/O ラボ/O 所長/O で/O も/O ある/O ヤン/B-PERSON ・/M-PERSON ルカン/E-PERSON 博士/O モデルファイルの指定
  59. 学習済みモデルの利用方法 • モデルファイルをロードし、固有表現抽出モデルを利用する 85 >>> import nagisa >>> ner_tagger =

    nagisa.Tagger( vocabs="data/kwdlc_ner_model.vocabs", params="data/kwdlc_ner_model.params", hp="data/kwdlc_ner_model.hp" ) >>> text = "FacebookのAIラボ所長でもあるヤン・ルカン博士" >>> tokens = ner_tagger.tagging(text) >>> print(tokens) Facebook/B-ORGANIZATION の/O AI/O ラボ/O 所長/O で/O も/O ある/O ヤン/B-PERSON ・/M-PERSON ルカン/E-PERSON 博士/O ner_tagger の定義
  60. 学習済みモデルの利用方法 • モデルファイルをロードし、固有表現抽出モデルを利用する 86 >>> import nagisa >>> ner_tagger =

    nagisa.Tagger( vocabs="data/kwdlc_ner_model.vocabs", params="data/kwdlc_ner_model.params", hp="data/kwdlc_ner_model.hp" ) >>> text = "FacebookのAIラボ所長でもあるヤン・ルカン博士" >>> tokens = ner_tagger.tagging(text) >>> print(tokens) Facebook/B-ORGANIZATION の/O AI/O ラボ/O 所長/O で/O も/O ある/O ヤン/B-PERSON ・/M-PERSON ルカン/E-PERSON 博士/O 入力テキスト
  61. 学習済みモデルの利用方法 • モデルファイルをロードし、固有表現抽出モデルを利用する 87 >>> import nagisa >>> ner_tagger =

    nagisa.Tagger( vocabs="data/kwdlc_ner_model.vocabs", params="data/kwdlc_ner_model.params", hp="data/kwdlc_ner_model.hp" ) >>> text = "FacebookのAIラボ所長でもあるヤン・ルカン博士" >>> tokens = ner_tagger.tagging(text) >>> print(tokens) Facebook/B-ORGANIZATION の/O AI/O ラボ/O 所長/O で/O も/O ある/O ヤン/B-PERSON ・/M-PERSON ルカン/E-PERSON 博士/O 解析の実行
  62. 学習済みモデルの利用方法 • モデルファイルをロードし、固有表現抽出モデルを利用する 88 >>> import nagisa >>> ner_tagger =

    nagisa.Tagger( vocabs="data/kwdlc_ner_model.vocabs", params="data/kwdlc_ner_model.params", hp="data/kwdlc_ner_model.hp" ) >>> text = "FacebookのAIラボ所長でもあるヤン・ルカン博士" >>> tokens = ner_tagger.tagging(text) >>> print(tokens) Facebook/B-ORGANIZATION の/O AI/O ラボ/O 所長/O で/O も/O ある/O ヤン/B-PERSON ・/M-PERSON ルカン/E-PERSON 博士/O 解析結果の出力
  63. 固有表現ごとの正解率の確認 • タグ単位の正解率ではなく、固有表現単位の正解率も確認する 89 precision recall f1-score support LOCATION 0.64

    0.67 0.66 127 DATE 0.84 0.88 0.86 78 ORGANIZATION 0.40 0.41 0.40 46 ARTIFACT 0.42 0.41 0.41 44 OPTIONAL 0.29 0.11 0.15 19 PERSON 0.59 0.75 0.66 51 MONEY 1.00 1.00 1.00 5 TIME 0.50 0.40 0.44 5 PERCENT 1.00 1.00 1.00 3 micro avg 0.62 0.64 0.63 378 macro avg 0.61 0.64 0.62 378 Python コードへのリンクは ←ここをクリック
  64. 出力結果の確認によるエラー分析 • 正解率だけではなく、目視による出力結果の確認を 90 >>> text = "米Googleのエンジニアリングフェローも務めるジェフリー・ ヒントン博士" >>>

    tokens = ner_tagger.tagging(text) >>> print(tokens) 米/B-LOCATION Google/B-LOCATION の/O エンジニアリング/O フェ ロー/O も/O 務める/O ジェ/O フリー/O ・/O ヒントン/B-PERSON 博士 /O
  65. 出力結果の確認によるエラー分析 • 正解率だけではなく、目視による出力結果の確認を 91 >>> text = "米Googleのエンジニアリングフェローも務めるジェフリー・ ヒントン博士" >>>

    tokens = ner_tagger.tagging(text) >>> print(tokens) 米/B-LOCATION Google/B-LOCATION の/O エンジニアリング/O フェ ロー/O も/O 務める/O ジェ/O フリー/O ・/O ヒントン/B-PERSON 博士 /O 入力テキスト
  66. 出力結果の確認によるエラー分析 • 正解率だけではなく、目視による出力結果の確認を 92 >>> text = "米Googleのエンジニアリングフェローも務めるジェフリー・ ヒントン博士" >>>

    tokens = ner_tagger.tagging(text) >>> print(tokens) 米/B-LOCATION Google/B-LOCATION の/O エンジニアリング/O フェ ロー/O も/O 務める/O ジェ/O フリー/O ・/O ヒントン/B-PERSON 博士 /O 解析結果の出力
  67. 出力結果の確認によるエラー分析 • 正解率だけではなく、目視による出力結果の確認を 93 >>> text = "米Googleのエンジニアリングフェローも務めるジェフリー・ ヒントン博士" >>>

    tokens = ner_tagger.tagging(text) >>> print(tokens) 米/B-LOCATION Google/B-LOCATION の/O エンジニアリング/O フェ ロー/O も/O 務める/O ジェ/O フリー/O ・/O ヒントン/B-PERSON 博士 /O タグ付け部分の解析ミス Google が LOCATION に
  68. 出力結果の確認によるエラー分析 • 正解率だけではなく、目視による出力結果の確認を 94 >>> text = "米Googleのエンジニアリングフェローも務めるジェフリー・ ヒントン博士" >>>

    tokens = ner_tagger.tagging(text) >>> print(tokens) 米/B-LOCATION Google/B-LOCATION の/O エンジニアリング/O フェ ロー/O も/O 務める/O ジェ/O フリー/O ・/O ヒントン/B-PERSON 博士 /O 単語分割部分の解析ミス 「ジェ」と「フリー」 に
  69. 解析ミスへの対応方法 • 解析ミスを修正したデータを学習データに追加し、再学習を行う 95 米 B-LOCATION Google B-LOCATION の O

    エンジニアリング O フェロー O も O 務める O ジェ O フリー O ・ O ヒントン E-PERSON 博士 O EOS 米 B-LOCATION Google B-ORGANIZATION の O エンジニアリング O フェロー O も O 務める O ジェフリー B-PERSON ・ M-PERSON ヒントン E-PERSON 博士 O EOS 修正 修正 修正 学習データに 追加
  70. 系列ラベリングの応用例 • 系列ラベリングの利点 ◦ 辞書に存在しないパターンを抽出することができる ◦ 文脈によって判断することができる • サービス名抽出 ◦

    系列ラベリングは、新しいサービス名の抽出等に応用可能 96 入力文: 「Apple TV+」は日本でも月額600円で11月開始。 系列ラベリング • サービス名:Apple TV+ • 料金: 月額600円 • 提供日: 11月開始
  71. おわりに • nagisa を有効活用できる場面 ◦ 小規模なテキストデータ(~2万文)をサクッと分析したいとき ◦ Colaboratory や heroku

    (無料枠) で自然言語処理をやりたいとき ◦ 文書分類等の応用タスクで、品詞のフィルタリングや ユーザー辞書追加による精度の影響を確認したいとき ◦ 日本語を対象とした系列ラベリングのベースラインとして • 本発表の内容や nagisa に関する質問等は GitHub で全て対応します ◦ issues お待ちしております ◦ https://github.com/taishi-i/nagisa-tutorial-pycon2019 97
  72. 参考リンク • GitHub ◦ https://github.com/taishi-i/nagisa • nagisa: RNNによる日本語単語分割・品詞タグ付けツール ◦ https://qiita.com/taishi-i/items/5b9275a606b392f7f58e

    • Pythonで動く形態素解析ツール「nagisa」を使ってみた ◦ https://upura.hatenablog.com/entry/2018/09/18/203540 • 形態素解析ツールのnagisa(なぎさ)を知っていますか? ◦ https://yolo.love/nlp/nagisa/ 98