今さら聞けない自然言語処理(NLP)

こちらのイベントで説明した内容の抜粋です。

https://www.databricks.com/p/webinar/202204-apj-ve-fundamental-series-nlp

# 自然言語処理(Natural Language Processing: NLP)とは

我々が日常的に使っている自然言語をコンピューターで処理する技術です。

![Screen Shot 2022-09-11 at 15.59.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/9bbf42c0-1f20-ad4b-d569-c154e2a4b6cd.png)

そもそも、なぜ自然言語を処理する必要があるのでしょうか？

**世界は自然言語で溢れていますが分析が困難です**

2015年、HIMSS(医療情報管理システム協会)は、アメリカのヘルスケア業界において**12億の医療ドキュメント**が作成されたと推定しました。これ以降、毎年生成される医療テキストデータは増える一方です。電子フォーム、オンラインポータル、PDFレポート、メール、テキストメッセージ、チャットボット、これら全てが現在のヘルスケアコミュニケーションの中心となっていますが、あまりに量が多くて**人間による解釈、計測は不可能**となっています。

https://qiita.com/taka_yayoi/items/fcf396cf75418e87ec76

**しかし、重要な洞察は自然言語のデータからもたらされます**

患者の安全のモニタリングはより多くのデータを収集するにつれて複雑になっています。薬害イベントの5%以下が公式なチャネル経由で報告されており、それ以外の大部分は患者サポートセンターへのメール・電話や、ソーシャルメディアへの投稿、医師と医薬品セールスの会話、オンラインの患者フォーラムなどの**フリーテキストのチャネル経由**で報告されています。

https://qiita.com/taka_yayoi/items/35863e696c72f0d08909

このような背景から、ここ数年でNLPと機械学習を組み合わせる取り組みが増えています。

![Screen Shot 2022-09-11 at 16.01.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/3e03dc9f-9456-8652-f87a-dd0bccc3ba92.png)

機械学習では、コンピューターがタスクを実行する方法自体をデータから学び取ります。
![Screen Shot 2022-09-11 at 16.01.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/4a57399e-646d-4683-976b-460fba64719c.png)
機械学習とNLPを組み合わせることで、テキストに記載されている内容に基づいて特定の事象が発生している確率を導き出すことも可能となっています。
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f313136383838322f35636136343064362d656435372d333365342d613664342d6633613731633232373231372e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/347c74a2-5c43-4f8a-b0a5-48b35a26aed0.png)

このような技術の進展によって、テキストデータを分析することで様々な価値を生み出すことができるようになっています。
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f313136383838322f36383231626230382d653436362d303134362d366339312d3937323930336535316334322e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/19060200-d009-5971-1b2b-6e461ae164ec.png)


# 自然言語処理の要素技術

## 形態素解析

ある文章を入力とし、その文章に含まれる**意味をもつ表現要素の最小単位(形態素)** を特定します。これにより一連の文章を形態素に分解することができ、単語の数をカウントするなどコンピューターによる処理が容易になります。英語の場合、単語は空白で区切られていますが日本語はそうでないため、日本語の自然言語処理では形態素解析が重要な役割を担います。
![Screen Shot 2022-09-11 at 16.04.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/02d31fa5-3a10-debb-52c9-c9c232b8abea.png)

## 構文解析

ある文章を入力とし、文章に含まれる要素同士の関係性を解析します。係受け解析とも呼ばれます。
![Screen Shot 2022-09-11 at 16.05.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/7ac58f18-b355-dbaa-f55a-e8faded3eb3f.png)

## その他の技術

- **検索**
単語あるいは自然文を入力とし、単語を含む文書や関連する文書を返却します。
- **テキスト分類**
文書の類似性に基づいて文書をグルーピングします。
- **トピックモデリング**
テキストのグループからトピックを表すキーワードを特定します。
- **文章要約**
長い文章を数文に要約します。
- **機械翻訳**
ある言語で記述されている文章を別の言語に翻訳します。
- **文章生成**
複数の文章を学習するなどして、自動的に文章を生成します。

# 自然言語処理における課題

自然言語処理には特有の難しさがあります。

**曖昧性の取り扱い**
自然言語には読み手の解釈によって意味が異なる曖昧性が含まれており、コンピューターでの取り扱いには課題があります。

> 「絶対値が上がる」は「**絶対値**が上がる」なのか「**絶対(に)値(段)** が上がる」なのか？

**新語への対応**
コンピューターは勝手に新語を学ばないので何かしらの手段で新語を学習させる必要があります。

**文脈の理解**
同じ単語であっても、文脈によって意味が異なるケースがあります。
![Screen Shot 2022-09-11 at 16.07.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/86f50976-8557-2f86-ba74-f67ddef2bf4e.png)

しかし、最近の技術の進歩によって、これらの課題にある程度対応できるようになってきています！

# 自然言語処理の適用事例

適切に自然言語を処理することで様々な価値を生み出すことができます。

**アストラゼネカ**
![Screen Shot 2022-09-11 at 16.08.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/3a16ffd6-983c-4037-1a70-16a6b6303c0d.png)
- 科学文献と膨大なデータソースに自然言語処理(NLP)を適用することで後段でのデータ分析に活用
- 研究者の意思決定に役立つ推薦モデルを構築

**RIOT GAMES**
![Screen Shot 2022-09-11 at 16.08.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/64eb83a9-0c5c-153c-be67-fe9a22d0ae52.png)
- ゲーム中の不正な言葉をリアルタイムで検出して防止することで、チャット上の誹謗中傷によるコミュニティの悪化を回避
- 特に、同じ単語でも文脈によって意味合いが異なる複数言語の解析が必要であり、このような要件に応えるモデルの精緻化を実現

**Medical University of South Carolina**
![Screen Shot 2022-09-11 at 16.08.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/0f0613cb-1e05-b162-82cc-14a0ee0f3a44.png)
- 患者のCOVID-19のリスクを特定するために600,000以上の遠隔医療レコードにNLPを適用
- 特定した高リスク患者に対して優先度を上げてCOVID-19の検査を実施

その他NLPでできることには、以下のようなものがあります。

**検知**
テキストの内容に基づいて、例えば、回避すべきイベントを検知し早期の対策を講じることができます。

**チャットbot**
製品・サービスに対する問い合わせに対する応答を自動化することができます。対象を音声にまで拡大すれば、Siriのような対話システムも構築することができます。

**感情分析**
製品・サービスに対するポジティブ・ネガティブな感情を分析することでフィードバックに活用することができます。

**レコメンデーション**
文書の内容に基づいて、関連する別の文書を提示することで、必要とする文書にクイックにアクセスすることができるようになります。

# NLPのウォークスルー

ウェビナーで使用したノートブックにはこちらからアクセスできます。

https://github.com/taka-yayoi/public_repo/tree/main/20220421_NLP_webinar

以下では、こちらのノートブックの流れを説明します。

https://github.com/taka-yayoi/public_repo/blob/main/20220421_NLP_webinar/1.%20%E5%BD%A2%E6%85%8B%E7%B4%A0%E8%A7%A3%E6%9E%90%E3%83%BB%E3%83%AF%E3%83%BC%E3%83%89%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89(spark).py

Sparkデータフレームを用いて形態素解析を行い、ワードクラウドで可視化するという内容となっています。

## 大量テキストデータに対する処理

Amazonの商品レビューのテキストデータを使用します。

[https://s3\.amazonaws\.com/amazon\-reviews\-pds/tsv/index\.txt](https://s3.amazonaws.com/amazon-reviews-pds/tsv/index.txt)

### データ準備

初回のみ実行します。

```py:Python
file_path = "/FileStore/shared_uploads/takaaki.yayoi@databricks.com/amazon_reviews_multilingual_JP_v1_00.tsv.gz"

sdf = spark.read.format("csv").option("delimiter", "\t") \
                              .option("header", True) \
                              .load(file_path)
#display(sdf)

# データフレームをDeltaに保存します
path = f"/tmp/takaaki.yayoi@databricks.com/nlp/amazon_review.delta"
sdf.repartition(288).write.format('delta').mode("overwrite").option("path", path).saveAsTable("20210712_demo_takaakiyayoi.amazon_review")
```

### ライブラリのインポート

```py:Python
import pandas as pd

from janome.tokenizer import Tokenizer
import matplotlib.pyplot as plt
from wordcloud import WordCloud

import string
```

```py:Python
sdf = spark.table("20210712_demo_takaakiyayoi.amazon_review")
```

### データ前処理

データには英語テキストも含まれているので、日本語のレビューに限定します。

```py:Python
from pyspark.sql.types import ArrayType, StringType, IntegerType, DoubleType
from pyspark.sql.functions import col
from pyspark.sql.functions import pandas_udf
from pyspark.sql.functions import udf
```

Apache Sparkを用いることで処理を並列分散することができます。Sparkのpandas UDF(User-defined Function:ユーザー定義関数)を活用して大量データに対する形態素解析処理を高速に処理します。

[DatabricksにおけるSpark pandasユーザー定義関数 \- Qiita](https://qiita.com/taka_yayoi/items/b65197128ee698d87910)

```py:Python
@pandas_udf(IntegerType())
def filter_by_ascii_rate(texts: pd.Series) -> pd.Series:
  threshold = 0.9 # テキストの9割が英数字の場合は除外
  ascii_letters = set(string.printable)
    
  filtered = []
  
  for text in texts:
      if text is None:
        filtered.append(0)
      else:
        rate = sum(c in ascii_letters for c in text) / len(text)
        filtered.append(int(rate <= threshold))
      
  return pd.Series(filtered)
```

```py:Python
# is_jpカラムの追加
filtered_sdf = sdf.withColumn("is_jp", filter_by_ascii_rate(col("review_body"))).filter("is_jp == 1")
filtered_sdf.write.format("noop").mode("append").save()
```

```py:Python
display(filtered_sdf)
```
![Screen Shot 2022-09-11 at 16.16.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/8c45875b-d7a9-a9fb-ab07-56c9a460f1c2.png)

### 形態素解析

[Word Cloudが作りたくなったら。 \- Qiita](https://qiita.com/kyoro1/items/59216cc09b56d5b5f760)

janomeを使って形態素解析を行い、分かち書きを行います。

```py:Python
@pandas_udf(ArrayType(StringType()))
def tokenize_base_form(texts: pd.Series) -> pd.Series:  
  from janome.tokenizer import Tokenizer
  t = Tokenizer()
  tokenized = []
  
  for text in texts:
  
    # 全てのトークンを抽出
    #tokens = [token.base_form for token in t.tokenize(text)]
    #tokenized.append(tokens)
  
    # 一般名詞のみを抽出
    noun_list = []
    for token in t.tokenize(text):
      split_token = token.part_of_speech.split(',')

      #and split_token[1] == '一般'
      if split_token[0] == '名詞' and len(token.surface) > 1:
        noun_list.append(token.surface)
  
    tokenized.append(noun_list)
  
  return pd.Series(tokenized)
```

```py:Python
tokenized_sdf = filtered_sdf.withColumn("tokens", tokenize_base_form(col("review_body")))
tokenized_sdf.write.format("noop").mode("append").save()
```

```py:Python
display(tokenized_sdf)
```
![Screen Shot 2022-09-11 at 16.17.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/7a0dd8ec-bae8-83e7-b056-951b6eba88ec.png)

## 可視化

ワードクラウドで可視化します。

```py:Python
def depict_word_cloud(noun_list):
    ## 名詞リストの要素を空白区切りにする(word_cloudの仕様)
    noun_space = ' '.join(map(str, noun_list))
    ## word cloudの設定(フォントの設定)
    wc = WordCloud(background_color="white", font_path=r"/usr/share/fonts/truetype/fonts-japanese-gothic.ttf", width=300,height=300)
    wc.generate(noun_space)
    ## 出力画像の大きさの指定
    plt.figure(figsize=(5,5))
    ## 目盛りの削除
    plt.tick_params(labelbottom=False,
                    labelleft=False,
                    labelright=False,
                    labeltop=False,
                   length=0)
    ## word cloudの表示
    plt.imshow(wc)
    plt.show()
```

```py:Python
noun_list = tokenized_sdf.take(10)
display(noun_list)
```
![Screen Shot 2022-09-11 at 16.20.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/24efdf55-3e72-aaa5-f655-ffe0fa691b02.png)

```py:Python
for i in range(len(noun_list)):
  depict_word_cloud(noun_list[i]['tokens'])
```
![Screen Shot 2022-09-11 at 16.20.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/41910f84-b6be-945e-723e-67a7ad4933bc.png)

# NLPの最新技術動向

これは一部ですが日々新たな技術が生まれています。

**scikit-learn**
最新技術ではないですが、最初に使い始めるのには適していると思います。

**Word2vec**
Word2vecは、2013年にGoogleの研究者トマス・ミコロフ氏によって提案された手法です。単語の意味ベクトルを得ることで、単語の意味を考慮した処理が可能となります。

**BERT(Bidirectional Encoder Representations from Transformers)**
2018年にGoogleから発表されたニューラル言語モデルです。事前学習済みモデルをファインチューニングすることで様々な自然言語処理タスクで高い精度を発揮しています。日本語向けのモデルも公開されています。

[**Spark NLP**](https://nlp.johnsnowlabs.com/)
Spark向けNLPライブラリです。John Snow Labsによって提供されています。日本語にも対応しています。

[**BigARTM**](https://github.com/bigartm/bigartm)
新たなトピックモデリングの手法です。

# さいごに

ウェビナーで参照した、あるいは関連する記事を以下に示します。DatabricksでのNLPに興味がある方はこちらの記事もご覧になってください。

- [Databricks SparkでMeCabを動かしてみる](https://qiita.com/taka_yayoi/items/3b5836853eac8ac248c1)
- [無料のDatabricks Community EditionでSpark NLPを使って自然言語処理をやってみる](https://qiita.com/taka_yayoi/items/ebec25578a7cfe2f50b0)
- [Databricksで日本語ワードクラウドを作成する](https://qiita.com/taka_yayoi/items/91c8c4cf40b1b8b63075)
- [日本語に対してSpark NLPを使う](https://qiita.com/taka_yayoi/items/f34a5accaa8f7cad603a)
- [LDAの先へ：BigARTMによる最先端のトピックモデル](https://qiita.com/taka_yayoi/items/622bedee5231ebadb8d8)
- [Spark NLPとSpark MLLib\(LDA\)を用いた分散トピックモデリング](https://qiita.com/taka_yayoi/items/d639ec54a3fd751aad0a)
- [DatabricksでSparkNLPとMLLibを使って分散トピックモデリングをやってみる](https://qiita.com/taka_yayoi/items/15d384b2497631dc97bc)
- [DatabricksでSparkNLPとMLLibを使って分散トピックモデリングをやってみる\(日本語編\)](https://qiita.com/taka_yayoi/items/dc96cfcfa275adf5ce8a)
- [Apache Spark向け自然言語処理ライブラリのご紹介](https://qiita.com/taka_yayoi/items/fd7d099dfd8b25486499)
- [NLPを用いた薬害イベント検知による薬品安全性の改善](https://qiita.com/taka_yayoi/items/35863e696c72f0d08909)
- [ヘルスケアにおける大規模テキストデータへの自然言語処理の適用](https://qiita.com/taka_yayoi/items/fcf396cf75418e87ec76)
- [自然言語処理によるリアルワールド診療データからのオンコロジー\(腫瘍学\)に関する洞察の抽出](https://qiita.com/taka_yayoi/items/7bebfa4bc107b0638eab)

# その他の「今さら聞けない」シリーズ

https://qiita.com/taka_yayoi/items/51583a581ce5a6ba6558

https://qiita.com/taka_yayoi/items/2e652c2796a8738acac8


### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)