このシリーズでは、自然言語処理において主流であるTransformerを中心に、環境構築から学習の方法までまとめます。
今回の記事ではHuggingface Transformersによる日本語のテキスト分類の学習から推論までの実装を紹介します。
Google colabを使用して、簡単に最新の自然言語処理モデルを実装することができますので、ぜひ最後までご覧ください。
今回の内容
・テキスト分類モデルの学習
・テキスト分類モデルの評価
・ニュースサイトの記事を取得してニュースのカテゴリ分類を実装する
テキスト分類とは
自然言語処理におけるテキスト分類とは、特定のテキストにラベルまたはクラスを割り当てるタスクです。
主な使用例として、感情分析や自然言語推論、文法の正確性の評価などがあります。
今回の記事ではニュース記事にタイトルから、カテゴリに分類するモデルの作成を実装してみます。
Transformerとは
概要
「Transformer」は2017年にGoogleが「Attention is all you need」で発表した深層学習モデルです。
現在では、自然言語処理に利用する深層学習モデルの主流になっています。
これまでの自然言語処理分野で多く使われていた「RNN」(Recurrent Neural Network)や「CNN」(Convolutional Neural Network)を利用せず、Attentionのみを用いたEncoder-Decoder型のモデルとなっています。
「Transformer」が登場して以降、多くの自然言語処理モデルが再構築され、過去を上回る成果を上げています。
最近では自然言語処理だけでなく、ViTやDETRなどといった画像認識にも応用されています。
詳細は以下の記事をご覧ください。
Huggingface Transformersとは
概要
「Hugging Face」とは米国のHugging Face社が提供している、自然言語処理に特化したディープラーニングのフレームワークです。
「Huggingface Transformers」は、先ほど紹介したTransformerを実装するためのフレームワークであり、「自然言語理解」と「自然言語生成」の最先端の汎用アーキテクチャ(BERT、GPT-2など)と、何千もの事前学習済みモデルを提供しています。
ソースコードは全てGitHub上で公開されており、誰でも無料で使うことができます。
事前学習済みモデル
Hugging Faceではタスクに応じた様々な事前学習済みモデルが提供されています。
こちらからご確認ください。
Google colabによる導入
ここからはGoogle colabを使用して実装していきます。
今回紹介するコードは以下のボタンからコピーして使用していただくことも可能です。
まずはGoogleドライブをマウントして、作業フォルダを作成します。
from google.colab import drive
drive.mount('/content/drive')
!mkdir -p '/content/drive/My Drive/huggingface_transformers_demo/'
%cd '/content/drive/My Drive/huggingface_transformers_demo/'
次にtransformersをクローンします。
# !git clone https://github.com/huggingface/transformers
%cd transformers
テキスト分類モデルの学習
最後にニュース記事にタイトルから、カテゴリに分類するモデルの作成していきます。
データセットの取得
今回のこちらのサイトからニュース記事のデータセットを使用します。
(livedoor ニュースコーパス(https://www.rondhuit.com/download.html)より引用)
以下のコマンドを実行することで、データを取得することができます。
# livedoorニュースコーパスのダウンロード
!wget https://www.rondhuit.com/download/ldcc-20140209.tar.gz
!tar zxvf ldcc-20140209.tar.gz
サイトからニュース記事を取得する事ができました。
データは「huggingface_transformers_demo/transformers/text」に保存されます。
データセットの作成
取得したデータから、学習用のデータセットを作成します。
まずは各テキストファイルを読み込んで、タイトルのみを抽出する関数を定義します。
import os
import pandas as pd
# タイトルリストの取得
def get_title_list(path):
title_list = []
filenames = os.listdir(path)
for filename in filenames:
# ファイルの読み込み
with open(path+filename) as f:
title = f.readlines()[2].strip()
title_list.append(title)
return title_list
次にこの関数を、各ジャンルごとに分類されているニュース記事のフォルダに対して実行していきます。
以下の例では「it-life-hack(IT)」のタイトルを読み込み、ラベルとして「0」を割り当てています。
それ以降、「sports-watch(スポーツ)」、「dokujo-tsushin(独女)」、「smax(スマホ)」にも同様の処理を行います。
今回は4種類のジャンル分類モデルとしますが、さらに同様の処理を行うことで、さらに多くのジャンルの分類も可能となります。
# データセットの生成(各ニュース記事のタイトルを取得)
df = pd.DataFrame(columns=['label', 'sentence'])
title_list = get_title_list('text/it-life-hack/')
for title in title_list:
df = df.append({'label':0 , 'sentence':title}, ignore_index=True)
title_list = get_title_list('text/sports-watch/')
for title in title_list:
df = df.append({'label':1 , 'sentence':title}, ignore_index=True)
title_list = get_title_list('text/dokujo-tsushin/')
for title in title_list:
df = df.append({'label':2 , 'sentence':title}, ignore_index=True)
title_list = get_title_list('text/smax/')
for title in title_list:
df = df.append({'label':3 , 'sentence':title}, ignore_index=True)
すべてのタイトルの読み込みとラベルの付与が終わったら、データをシャッフルした後、学習用と検証用に分割します。
# データをシャッフルする
df = df.sample(frac=1)
# 上記で取得したデータを学習用と検証用に分割する
num = len(df)
df[:int(num*0.8)].to_csv('train.csv', sep=',', index=False)
df[int(num*0.8):].to_csv('val.csv', sep=',', index=False)
今回の学習で使用するデータセットが完成しました。
学習の実行
まずは必要なライブラリをインストールします。
# transformersのインストール
!pip install git+https://github.com/huggingface/transformers
!pip install -r ./examples/pytorch/text-classification/requirements.txt
# 日本語対応パッケージのインストール
!pip install ipadic
!pip install fugashi[unidic-lite]
# Huggingface Datasetsのインストール
!pip install datasets
!pip install sentencepiece
学習します。
%%time
# テキスト分類の学習
!python ./examples/pytorch/text-classification/run_glue.py \
--model_name_or_path=cl-tohoku/bert-base-japanese-whole-word-masking \
--do_train \
--do_eval \
--max_seq_length=128 \
--per_device_train_batch_size=32 \
--use_fast_tokenizer=False \
--learning_rate=2e-5 \
--num_train_epochs=50 \
--output_dir=text-classification_ja/ \
--overwrite_output_dir \
--train_file=./train.csv \
--validation_file=./val.csv
学習が終わると「./text-classification_ja」に結果が保存されます。
テキスト分類モデルの評価
さきほど作成したモデルでテストをしてみましょう。
「text = “30代おひとりさま“帰省やめたワケ”に波紋 親と子の価値観の違いに街の人は…”」というタイトルのカテゴリを判定します。
import torch
from transformers import BertJapaneseTokenizer, AutoModelForSequenceClassification
# 入力テキスト
text = "30代おひとりさま“帰省やめたワケ”に波紋 親と子の価値観の違いに街の人は…"
# モデルとトークナイザーの準備
model = AutoModelForSequenceClassification.from_pretrained('text-classification_ja/')
tokenizer = BertJapaneseTokenizer.from_pretrained('cl-tohoku/bert-base-japanese-whole-word-masking')
# テンソルに変換
tokenized_text = tokenizer.tokenize(text)
indexed_tokens = tokenizer.convert_tokens_to_ids(tokenized_text)
tokens_tensor = torch.tensor([indexed_tokens])
# 推論の実行
labels = ['IT', 'スポーツ', '独女','スマホ']
model.eval()
with torch.no_grad():
outputs = model(tokens_tensor)[0]
print(labels[torch.argmax(outputs)])
実行すると、以下のような結果が出力されます。
独女
正しい結果が得られました。
ニュースサイトの記事を分類してみる
ここからは実用的な活用例として、実際のニュースサイトの記事をジャンルごとに分類してみます。
先程学習したモデルでは4種類の判定しかできませんので、すべての記事を正しく分類できるわけではありませんが、活用のイメージはご理解いただけるかと思います。
スクレイピングとは
スクレイピングとは、WEBサイトから情報を自動的に取得し、必要に応じて情報の加工などを行うことです。
例えばニュースサイトからトップページに表示されている記事のタイトルを取得して、順番に表示することも可能です。
Pythonではスクレイピング用のライブラリが用意されていますので、簡単にスクレイピングを実装することができます。
今回はスクレイピングで取得した記事一覧に対して、先程作成したモデルにより、ニュースのジャンル分類を実装します。
スクレイピングよるニュース記事の取得
まずはスクレイピングに必要なライブラリをインストールします。
# スクレイピング関係のライブラリをインストール
!pip install requests
!pip install beautifulsoup4
次にニュース記事の一覧を取得して、出力します。
import requests
from bs4 import BeautifulSoup
import re
# ヤフーニュースのトップページ情報を取得
URL = "https://www.yahoo.co.jp/"
rest = requests.get(URL)
# BeautifulSoupにヤフーニュースのページ内容を読み込ませる
soup = BeautifulSoup(rest.text, "html.parser")
# ヤフーニュースの見出しを取得して出力する
data_list = soup.find_all(href=re.compile("news.yahoo.co.jp/pickup"))
for data in data_list:
print(data.span.string)
ニュース記事の一覧が出力されました。
ニュースサイトの記事を分類する
最後にここまでの内容をまとめます。
スクレイピングで取得した記事に対して、先ほど作成したモデルで推論を行います。
import requests
from bs4 import BeautifulSoup
import re
# ヤフーニュースのトップページ情報を取得する
URL = "https://www.yahoo.co.jp/"
rest = requests.get(URL)
# BeautifulSoupにヤフーニュースのページ内容を読み込ませる
soup = BeautifulSoup(rest.text, "html.parser")
# ヤフーニュースの見出しとURLの情報を取得して出力する
data_list = soup.find_all(href=re.compile("news.yahoo.co.jp/pickup"))
for data in data_list:
tokenized_text = tokenizer.tokenize(data.span.string)
indexed_tokens = tokenizer.convert_tokens_to_ids(tokenized_text)
tokens_tensor = torch.tensor([indexed_tokens])
with torch.no_grad():
outputs = model(tokens_tensor)[0]
print(labels[torch.argmax(outputs)],data.span.string)
出力結果の一部を抜粋しました。
分類結果と記事のタイトルを並べて出力しています。
スポーツ 日大 田中元理事長らを提訴へ
IT COCOA停止へ 全数把握見直しで
独身女性 自称サバサバ女漫画 NHKドラマ化
今回学習したカテゴリについてはおおよそ正しい答えが得られました。
さらに細分化したカテゴリで学習をすれば、実用的なモデルが作れそうですね。
まとめ
最後までご覧いただきありがとうございました。
今回の記事ではHuggingface Transformersによる日本語のテキスト分類の学習から推論までの実装を紹介しました。
このシリーズでは、自然言語処理全般に関するより詳細な実装や学習の方法を紹介しておりますので、是非ご覧ください。