機械学習

【入門】自然言語処理でできることをいくつかPythonで実装してみる!

自然言語処理
ウマたん
ウマたん
当サイト【スタビジ】の本記事では、自然言語処理についてPythonでの実装と合わせてまとめていきたいと思います。実際にテキスト情報を形態素解析で分解してテキスト類似度を計算したり、空欄を予測したりすることができるんです!

こんにちは!

消費財メーカーでデジタルマーケター・データサイエンティストを経験後、現在は独立して働いているウマたん(@statistics1012)です!

自然言語処理は、機械に人間の言葉を理解させる上で非常に重要な領域。

しかーし、あんまり自然言語処理の中身についてはブラックボックスでよく分かっていないという人が多いのではないでしょうか?

ロボたん
ロボたん
んー・・・概念だけは、なんとなーく分かっているけど・・・
ウマたん
ウマたん
そうだよね!完璧に理解する必要はないけど、ある程度自然言語処理について理解しておくことは重要だよ!

ということで、この記事では自然言語処理についてまとめていきたいと思います。

様々な自然言語処理領域に対してPython実装をおこなっていくので、気になるところからつまみ食い的にチェックしてみてください!

自然言語処理とは

自然言語処理

まず、自然言語処理とは何でしょうか?

自然言語処理とは、端的に言うと「人間の言葉を機械が理解するルール作り」です。

言葉は、人類が生み出した虚構であり文化によって全く違う構造を持ちます。

そんな言葉を機械が理解できるようにする領域が自然言語処理なのです。

機械が人間の言葉をしっかり理解するためには、文脈理解と単語理解が必要。

単語理解は、どのような言葉がどのような意味で使われているかをまとめた辞書(コーパスと呼ばれる)が必要になってきます。

そんな辞書と大量の文章をインプットさせて機会が文意を読み取ることができるようになるのです。

そのため、実は自然言語処理の分野では教師データがどれだけリッチかが非常に重要なんです。

その点では中国など個人情報の法規制に緩い国が有利。

なぜなら昨今のデジタル上でのコミュニケーションを仮にテキスト情報としてインプットすることが出来れば、各段に自然言語処理精度が上がるからです。

今のところ、コミュニケーションのテキスト情報をインプット情報として使える企業は少ないです。

日本でも、LINE社は日々の大量のコミュニケーション情報をテキストとして保持していながら個人情報保護の観点から解析に使えない状態になっています。

個人情報の取り扱いに関しては国によって全く方針が違うんですよねー。

ウマたん
ウマたん
データ保有に対しての国のスタンスの違いが、この分野の進化に大きな影響を及ぼすんだよねー!

Pythonで自然言語処理で出来ることを実装

PC

続いて、いくつかのトピックを紹介しながらPythonで実装をおこなっていきます。

MeCabで形態素解析をしてみよう!

Coding

まずは、形態素解析。

形態素解析とは、文章を単語単位で区切りそれぞれの単語に情報を付与する手法です。

形態素解析エンジンにはいくつかの種類がありますが、ここではMeCabを使用していきます。

Mecabは古くから有名で最も良く使われている形態素解析エンジン。

PythonだけでなくRやRubyなど他のプログラミング言語も使用することが可能です。

まずは、MeCabを使う環境を整えていきましょう!

MeCabを使う場合はGoogle colaboratoryを使うのがオススメです。

Google colaboratoryであれば、以下のように記述してあげることでMecabを利用することができます。

!apt install aptitude
!aptitude install mecab libmecab-dev mecab-ipadic-utf8 git make curl xz-utils file -y
!pip install mecab-python3==0.7

Google ColaboratoryとはGoogleが無料で提供してくれているクラウド実行型のJupyter notebook実行環境です。

Googleのアカウントを持ってさえいれば誰でも使用することができ、開発環境を整える必要もなくPythonによる機械学習実装が可能です。

ローカル環境でMecabを使う場合は以下のURLから「mecab-0.996-64.exe」をダウンロードしてセットアップする必要があります。

https://github.com/ikegami-yukino/mecab/releases/tag/v0.996

早速MeCabを利用して文章を単語区切りに分解していきます。

m=MeCab.Tagger()
m1=m.parse (text)

たったこれだけで、textを単語区切りにしてくれるんです。

試しにこのtext部分に
統計ラボはデータサイエンスとWebマーケティングをまとめたサイトです
と入れてみます。

※スタビジの旧サイト名は統計ラボでした

すると・・・

以下のような結果が返ってきます。素晴らしい!

統計	名詞,サ変接続,*,*,*,*,統計,トウケイ,トーケイ
ラボ	名詞,一般,*,*,*,*,ラボ,ラボ,ラボ
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
データ	名詞,一般,*,*,*,*,データ,データ,データ
サイエンス	名詞,一般,*,*,*,*,サイエンス,サイエンス,サイエンス
と	助詞,並立助詞,*,*,*,*,と,ト,ト
Web	名詞,固有名詞,組織,*,*,*,*
マーケティング	名詞,一般,*,*,*,*,マーケティング,マーケティング,マーケティング
を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
まとめ	動詞,自立,*,*,一段,連用形,まとめる,マトメ,マトメ
た	助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
サイト	名詞,一般,*,*,*,*,サイト,サイト,サイト
です	助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
EOS

返ってきた結果に対して名詞だけ取り出したいため、.splitを使い2つ目の要素が名詞だったら配列に格納するような処理を行っています。

for row in m1.split("n"):
        word =row.split("t")[0]#タブ区切りになっている1つ目を取り出す。ここには形態素が格納されている
        if word == "EOS":
            break
        else:
            pos = row.split("t")#タブ区切りになっている2つ目を取り出す。ここには品詞が格納されている
            slice = pos[:2]
            if slice == "名詞":
                word_list = word_list +" "+ word
    return word_list

これによりテキスト情報を単語に分解し、名詞だけ格納した配列が出来上がりました。

形態素解析×Light gbmで文章の著者を予測してみる

python

続いて、形態素解析したデータに対してLight gbmという強力な機械学習手法を使って文章の著者なのかを予測してみたいと思います。

データは、Nishikaというデータコンペの「AIは芥川龍之介を見分けられるのか?」というコンペのデータを使います。

Nishika_text Nishikaに会員登録をしてtrainデータをローカル環境にダウンロードしてください(※会員登録をしないとデータをダウンロードできません)。

データは、3,312個の文章とそれぞれに対して芥川龍之介が否かがラベルで付いているデータになっています。

こちらもMeCabを利用するのでGoogle colaboratory上で実装していきます。

以下のように記述してあげることでMecabが使えるようになります。

!apt install aptitude
!aptitude install mecab libmecab-dev mecab-ipadic-utf8 git make curl xz-utils file -y
!pip install mecab-python3==0.7

まずは必要なライブラリをインストールします。

import pandas as pd
import numpy as np
import collections
import MeCab
import lightgbm as lgb
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score

続いて必要なデータをデータフレームとして読み込みます。

df = pd.read_csv("/content/drive/MyDrive/Stabiz/python/data-science/nishika_text_data/train.csv")

続いてMeCabにより形態素解析を行い各文章ごとの単語を集計していきます。

m = MeCab.Tagger("")
text_list = []
length_list = []
# それぞれの文書を取り出して形態素解析
for sentence in df["body"]:
  ma = m.parse(sentence)
  word_list = []
  # 形態解析後の単語だけ抽出
  for text in ma.split("\n"):
    word_list.append(text.split("\t")[0])
  # 単語の数を集計
  length_list.append(len(word_list))
  # 単語の頻度を集計
  data = collections.Counter(word_list)
  text_data = pd.DataFrame.from_dict(data, orient='index')
  text_list.append(text_data)

そして3312個の全文章の中で登場する単語の上位100個の頻出単語だけ特徴量とします。

feature = pd.concat(text_list, axis=1)
#Nanを0に置換
feature = feature.fillna(0)
#Arrayに変換
feature_temp = feature.values.sum(axis=1)
#上位k件
K = 100
#上位k件のインデックス
indices = np.argpartition(-feature_temp, K)[:K]

文章ごとに長さが違うので、長さのバイアスを取り除くために各特徴量を各文章の全単語数で割返して特徴量とします。

## 各文書に対して全体で頻出の上位k個の単語の出現数をその文書の単語出現数で割ったものを変数とする ##
modi_feature = []
for index, row in feature.iloc[indices].T.reset_index(drop=True).iterrows():
 modi_feature_temp = row/length_list[index]
 modi_feature.append(modi_feature_temp)
modi_feature = pd.concat(modi_feature, axis=1).T
# 各文書と作成した特徴量を結合
df = pd.concat([df, modi_feature], axis=1)

その上でやっとLight gbmの実装をしていきます!

## Light gbmと実装
df = df.drop(["writing_id", "body"], axis=1)
df_train, df_val = train_test_split(df, test_size=0.2)
col = "author"
train_y = df_train[col]
train_x = df_train.drop(col, axis=1)

val_y = df_val[col]
val_x = df_val.drop(col, axis=1)

trains = lgb.Dataset(train_x.values, train_y)
valids = lgb.Dataset(val_x.values, val_y)

params = {
    "objective": "binary",
    "metrics": "binary_logloss"
}

model = lgb.train(params, trains, valid_sets=valids, num_boost_round=1000, early_stopping_rounds=100)

最後に得られたモデルから予測値を算出し、その値に対してF-measureを算出しています。

## 予測:量的変数で返ってきているので0.5を閾値にして0,1に振り分ける
predict_list = []
for i in model.predict(val_x):
  if i > 0.5:
    predict = 1
  else:
    predict = 0
  predict_list.append(predict)

f1_score(val_y, predict_list)

 

この時予測値は連続値で返ってくるので、0.5を閾値にして0,1に振り分けています。

F-measureは分類問題でよく使われる指標で適合率と再現率の調和平均を取っています。

機械学習 評価指標
機械学習の予測・分類精度における評価指標を徹底解説!当サイト【スタビジ】の本記事では、機械学習を実装する上での評価指標について徹底的にまとめていきます!回帰タスクや分類タスクにおける評価指標について見ていきましょう。評価フェーズや評価における注意点についても解説していきます。...

結果的にF-measureの値は・・・0.851となりました!

以下が全コードになっています。

関数化していないので少し処理がわかりにくいですがご容赦を・・・

Mecabに関してより詳しくは以下の記事でまとめています。

Mecab 形態素解析
Pythonで文書類似度算出!MeCabで形態素解析後にTf-idfとCos類似度を使ってみよう当サイト【スタビジ】の本記事では、形態素解析器であるMeCabとPythonを用いて形態素解析を行いその後Tf-idfとCos類似度を使い最終的に文章の類似度を算出していきます。また、文章の著者が誰なのかをMeCabとLight gbmを用いて予測していきます。非常に簡単に実装できるかつ応用度が高いです!自然言語処理の世界に入るきっかけにしてくださいね!...

URLからスクレイピングでテキストを引っ張ってきて、それらをMecabで形態素解析し、テキスト類似度を測るプログラムを以下で公開していますのでぜひチェックしてみてください!

macとsurface
Flaskでできることを確認しながら簡単なWebアプリの実例を作ってみよう!当サイト【スタビジ】の本記事では、Pythonの軽量WebアプリケーションフレームワークであるFlaskを使って簡単なWebアプリケーションを作成していきたいと思います。Pythonを開発言語としても使えるようになると、幅が広がりますよー!...

また今回利用したLight gbm については以下の記事で詳しく解説しています!

Light GBM
LightGBMの仕組みとPythonでの実装を見ていこう!当サイト【スタビジ】の本記事では、最強の機械学習手法「LightGBM」についてまとめていきます。LightGBM の特徴とPythonにおける回帰タスクと分類タスクの実装をしていきます。LightGBMは決定木と勾配ブースティングを組み合わせた手法で、Xgboostよりも計算負荷が軽い手法であり非常によく使われています。...

RNNを使ってみる

AI

続いて、ディープラーニングの領域に足を踏み入れてみましょう!

RNNはリカレントニューラルネットワークの略で、ディープラーニングの層構造に再帰性を取り入れたもの。

通常のディープラーニングでは、時系列要素のあるデータを上手く扱えないという欠点があるんです。

【入門】ディープラーニング(深層学習)の仕組みとPython実装のやり方!当サイト【スタビジ】の本記事では、ディープラーニングの仕組みやPythonでの実装方法について解説していきます。ディープラーニングってなんとなくブラックボックスなイメージがあるかもしれませんが、実はシンプルなアルゴリズムなんですよー!...

そんなディープラーニングの構造に対して、時系列要素を加えて順番を考慮しようよというのがRNNの考え方。

時系列処理はテキストの文脈を読み取る上で非常に重要です。

例えば英語で、he said “I’m () ” という文章があった時、()の中身を当てるのは相当難しい。

しかし、その後ろにこんな文脈があったらどうでしょう?

Tom came home, and he said “I’m () “.

()の中にどのような文章が入るかほとんどの人が分かると思います。

おそらくTom came home, and he said “I’m home “でしょう。

このようにテキストの文脈からワードを推論するのは周りの文脈が非常に重要なんです。

それを実現できるのがRNNと考えてください。

今までのディープラーニングでは、それぞれのインプットがそれぞれの中間層に与えられていましたが、RNNでは同一の中間層を用いて再帰的にインプットが行われます。

再帰的という部分がReccurentと言われるゆえんです。

こんなイメージ

rnnの概念

同じレイヤーh1を用いているのがミソです。

これにより前のワードの情報をレイヤに記憶させ後続へとつなぐことができます。

自然言語処理ではないですが、RNNを使って時系列問題を解くことができるというところを見ていきましょう!

使うデータセットはKaggleのホームページが落とせる航空会社の乗客数データ!

1949年から1960年までの月別乗客数がデータとして入っています。

149行2列のシンプルなデータセット。

1変数の時系列データを基に過去のデータから未来の値を予測します。

この時、tflearnというライブラリを使ってRNN(正確にはLSTM)を実装していきます。tflearnはkerasと似たようなライブラリでディープラーニングの実装が感覚的に容易にできます。

実際にモデルを構築していきましょう!

最終的な評価はRMSE(Root Mean Square Error)で算出しています。

RMSEは0.10079201となりました。それなりに良い予測ができてる!

RNNについて詳しくは以下の記事でまとめています。

RNNとは
RNN(リカレントニューラルネットワーク)の概要とPython実装方法を分かりやすく解説!当サイト【スタビジ】の本記事では、ディープラーニングを時系列にも対応させたRNN(リカレントニューラルネットワーク)について解説していきます。RNNの仕組みや応用場面と一緒にPythonでの実装をしていきます。これからの応用が期待される領域なんですよー!...

Googleが公表したBERTを使ってみる

Server

最後にGoogleが2018年に公表し、2019年に検索アルゴリズム適応させたBERTについて見ていきましょう!

BERTとは「Bidirectional Encoder Representations from Transformers」の略であり、Googleが新たに開発した自然言語処理のロジックになります。

BERTの登場によりGoogleはより長く複雑な文章を理解できるようになり、文脈を読み取ることができるようになりました。

実際にGoogleのリリースにBERT導入前と導入後のGoogle検索の違いが記載されています。

BERT 検索結果(引用元:Google-”Understanding searches better than ever before”)

ブラジル人が米国へ渡航する際のビザの有無を知りたいのですが、BERT実装前は英文における”to”の意味を明確に捉えることができずアメリカ人がブラジルへ旅行する場合の結果を返していました(左側)。

BERT実装後は、しっかりアメリカ渡航の際の結果を返すことができています。

ロボたん
ロボたん
本当だ!確実に検索エンジンが賢くなっている!!
ウマたん
ウマたん
逆にこれまでは、この文脈を読み取れていなかったんだねー意外!

このように検索結果が、より検索者の検索意図を読み取れるように進化してきているのです。

それでは、そんなBERTを実際に実装してみましょう!

BERTを使って以下の日本語文章の空白を予測してみます。

※当サイト【スタビジ】は昔統計ラボというサイトでした

[‘統計’, ‘ラボ’, ‘は’, ‘*’, ‘を’, ‘発信’, ‘する’, ‘サイト’, ‘です’]

ロボたん
ロボたん
お!面白そう!
ウマたん
ウマたん
なんて予測されるかなー?

京都大学の黒橋・河原・村脇研究室の作成した強力な形態素解析器JUMAN++をインストールしていきます。

こちらは、先ほどのMeCabよりも口語に対応している形態素解析です。

BERTを実装するためには日本語における相当な量の事前学習が必要なのですが京都大学の黒橋・河原・村脇研究室が公開してくれています。

BERT日本語Pretrainedモデル 

非常にありがたいですね!

import urllib.request

kyoto_u_bert_url = "http://nlp.ist.i.kyoto-u.ac.jp/nl-resource/JapaneseBertPretrainedModel/Japanese_L-12_H-768_A-12_E-30_BPE.zip"
urllib.request.urlretrieve(kyoto_u_bert_url, "Japanese_L-12_H-768_A-12_E-30_BPE.zip")

続いてZIPファイルを解凍していきます。

!unzip Japanese_L-12_H-768_A-12_E-30_BPE.zip

これで、日本語モデルの準備は完了です。

config = BertConfig.from_json_file('/content/drive/My Drive/bert/japan_test/Japanese_L-12_H-768_A-12_E-30_BPE/bert_config.json')

model = BertForMaskedLM.from_pretrained('/content/drive/My Drive/bert/japan_test/Japanese_L-12_H-768_A-12_E-30_BPE/pytorch_model.bin', config=config)
bert_tokenizer = BertTokenizer('/content/drive/My Drive/bert/japan_test/Japanese_L-12_H-768_A-12_E-30_BPE/vocab.txt',
 do_lower_case=False, do_basic_tokenize=False)

必要なパラメータやモデル、BERTが扱いやすい形に加工するための変換処理などを先ほどダウンロードした日本語Pretrainedモデルから取得します。

text = "スタビジは*を発信するサイトです"
result = jumanpp.analysis(text)
tokenized_text = [mrph.midasi for mrph in result.mrph_list()]
print(tokenized_text)

続いて、JUMAN++によって品詞分解を行います。

[‘統計’, ‘ラボ’, ‘は’, ‘*’, ‘を’, ‘発信’, ‘する’, ‘サイト’, ‘です’]

tokenized_text.insert(0, '[CLS]')
tokenized_text.append('[SEP]')
masked_index = 4
tokenized_text[masked_index] = '[MASK]'
print(tokenized_text)

文章の区切れやマスクする部分をBERTに明示的に知らせるために、SEPやMASKを挿入していきます。

CLSは文章の頭に、SEPは文章の区切れに、MASKは隠したい部分に適用します。

[‘[CLS]’, ‘統計’, ‘ラボ’, ‘は’, ‘[MASK]’, ‘を’, ‘発信’, ‘する’, ‘サイト’, ‘です’, ‘[SEP]’]

tokens = bert_tokenizer.convert_tokens_to_ids(tokenized_text)
tokens_tensor = torch.tensor([tokens])

そして、得られたテキストをBERT用に変換します。

model.eval()
with torch.no_grad():
  outputs = model(tokens_tensor)
  predictions = outputs[0]
_,predicted_indexes = torch.topk(predictions[0, masked_index], k=10)
predicted_tokens = bert_tokenizer.convert_ids_to_tokens(predicted_indexes.tolist())
print(predicted_tokens)

そして、マスクされた部分の予測を行います。

結果は・・・

[‘統計’, ‘情報’, ‘データ’, ‘ニュース’, ‘それ’, ‘調査’, ‘分析’, ‘レポート’, ‘トレンド’, ‘ランキング’]

上手く予測できていることが分かります!

ところどころ省略しているので詳しくは以下の記事をチェックしてみてください!

BERTについて解説!日本語モデルを使って予測をしてみようー!当サイト【スタビジ】の本記事では、Googleが新たにリリースしたBERTについてSEO的観点とデータサイエンス的観点で解説し、日本語モデルを使って実際に文章の予測を行っていきます!BERTはPythonで簡単に実装できるんですよー!ぜひ試してみてくださいね!...

自然言語処理でできることをPythonで実装してみよう まとめ

自然言語処理についてまとめてきました!

自然言語処理は、機械が自然な会話を実現できるようになるために非常に重要な分野。

これからの研究が期待される領域なんですねー!

ロボたん
ロボたん
このまま何年か経てば人間と同レベルの会話は実現できるのー?
ウマたん
ウマたん
ある程度できることは間違いないんだけど、まだまだ課題は山積みなんだ!

例えば、複数人で会話をする時に人間であれば複数人の音声が重なっていても切り分けて処理することができますが、現状の機械ではそれは厳しいです。

音声分離の技術はまだまだこれからの研究課題になっています。

もしディープラーニングや機械学習、Pythonに興味があれば以下の記事で勉強法をまとめていますのでぜひチェックしてみてください!

【初心者向け】ディープラーニングの勉強ロードマップまとめ!当サイト【スタビジ】本記事では、ディープラーニングの学習方法について詳しくまとめていきます!ディープラーニングは難しいと思われがちですが、アルゴリズムは意外とシンプルで実装自体も非常に簡単なんです!Pythonでの実装もおこなっていきますよー!...
機械学習
【入門】機械学習のアルゴリズム・手法をPythonとRの実装と一緒に5分で解説!当サイト【スタビジ】の本記事では、入門者向けに機械学習についてカンタンにまとめていきます。最終的にはどのように機械学習を学んでいけばよいかも見ていきます。細かい手法の実装もPython/Rを用いておこなっていくので適宜参考にしてみてください。...
Python独学勉強法
【Python独学勉強法】初心者が3か月で習得できるロードマップ!当サイト【スタビジ】の本記事では、過去僕自身がPythonを独学を駆使しながら習得した経験をもとにPythonを効率よく勉強する方法を具体的なコード付き実装例と合わせてまとめていきます。Pythonはできることが幅広いので自分のやりたいことを明確にして勉強法を選ぶことが大事です。...
【5分で分かる】データサイエンティストに必要なスキルと独学勉強ロードマップ!当サイト【スタビジ】の本記事では、データサイエンティストに求められるスキルとそれを身に付けるための勉強法について徹底的にまとめていきます!入門者でも、しっかりデータサイエンティストについて理解しある程度独学で駆け出しの状態までいけることを目指します。...

 

スタビジアカデミーでデータサイエンスをさらに深く学ぼう!

スタアカサービスバナースタビジのコンテンツをさらに深堀りしたコンテンツが動画と一緒に学べるスクールです。

プレミアムプランでは私がマンツーマンで伴走させていただきます!ご受講お待ちしております!

スタビジアカデミーはこちら