コードを書けないけど「BERTによる自然言語処理」再トライ

コードを書けなくても自然言語処理はしたい

Pythonはよくわからないけど自然言語処理はしたい」と思い、昨年冬に試したのが以下サイトのコードです。

しかし、コピペしただけではうまく動かず、エラーメッセージが出て先に進めず終わってました。
ChatGPT」で解決。やはりPythonの基礎知識不足でつまづいていました。

余分な空白があります

Google Colaboratory」を使います。
動作環境はMacのM1チップ搭載機の「Chrome」です。
最初に試した日本語モデル予測ではまず、

形態素解析のためにJUMAN++をインストール

します。
ここでは、コピペの際に余分なスペースが入ったためか、エラーが出ました。
改行をエスケープするなどの対処が必要でした。
以下コードでインストールできました。

ChatGPT
ChatGPT

このエラーは、行末のバックスラッシュの後ろに余分な空白があるため、次の行がインデントされてしまい、コマンドの構文が壊れていることを示しています。

以下のように、各行の末尾の空白を削除することで、問題を解決できます。

!wget https://github.com/ku-nlp/jumanpp/releases/download/v2.0.0-rc2/jumanpp-2.0.0-rc2.tar.xz \
&& tar xJvf jumanpp-2.0.0-rc2.tar.xz \
&& rm jumanpp-2.0.0-rc2.tar.xz \
&& cd jumanpp-2.0.0-rc2/ \
&& mkdir bld \
&& cd bld \
&& cmake .. \
   -DCMAKE_BUILD_TYPE=Release \
   -DCMAKE_INSTALL_PREFIX=/usr/local \
&& make \
&& sudo make install

OSモジュールを使う必要があります

次にGoogle Driveをマウントし、作成したフォルダに学習モデルを格納するのですが、ルートに配置される状態が続きました。
これも「ChatGPT」で解決しました。

ChatGPT
ChatGPT

cd はシェルコマンドであり、Pythonのコマンドではありません。代わりにPythonでカレントディレクトリを変更するには、 os モジュールを使う必要があります。具体的には、次のように書くことができます。

import os

os.chdir('/content/drive/My Drive/bert/japan_test')

指定された比率でデータを分割します

コードの内容も整理して説明してくれます。
とりあえずコードを動かせるようにし、後から「ChatGPT」に説明してもらいながら、別のデータに流用しようと考えています。

train, valid_test = train_test_split(df, test_size=0.2, shuffle=True, random_state=123, stratify=df[categories])

はどういう処理でしょうか。

ChatGPT
ChatGPT

このコードは、与えられたデータフレーム(df)をトレーニング用と検証用に分割するためのコードです。具体的には、train_test_split関数を使用して、指定された比率でデータを分割しています。

train_test_split関数のパラメーターには、以下があります。

  • test_size:テスト用データの割合を指定します。デフォルトは0.25です。
  • shuffle:Trueに設定すると、データをシャッフルします。デフォルトはTrueです。
  • random_state:シード値を設定します。これにより、同じシード値を使用する場合、ランダムに選択されたサンプルが同じになります。
  • stratify:指定されたカテゴリ列に従って層化サンプリングします。これにより、サンプルがランダムに選択された場合と比較して、カテゴリごとに均等に分布するようになります。

train_test_split関数は、トレーニング用と検証用の2つのデータフレームを返します。このコードでは、トレーニング用と検証用のデータフレームを trainvalid_test にそれぞれ代入しています。ただし、valid_test に代入されるのは、元のデータフレームから取り出されたテスト用データです。

コードの実行結果です。

# JUMAN++によって品詞分解

text = "私は毎朝6時に起きて、*と散歩しています。"
result = jumanpp.analysis(text)
tokenized_text = [mrph.midasi for mrph in result.mrph_list()]
print(tokenized_text)

['私', 'は', '毎朝', '6', '時', 'に', '起きて', '、', '*', 'と', '散歩', 'して', 'い', 'ます', '。']
# 文章の区切れやマスクする部分をBERTに明示的に知らせるために、SEPやMASKを挿入

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

['[CLS]', '私', 'は', '毎朝', '6', '時', 'に', '起きて', '、', '[MASK]', 'と', '散歩', 'して', 'い', 'ます', '。', '[SEP]']
# 得られたテキストをBERT用に変換

tokens = bert_tokenizer.convert_tokens_to_ids(tokenized_text)
tokens_tensor = torch.tensor([tokens])
# マスクされた部分の予測を実施

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)

['私', '犬', 'あなた', '[UNK]', '君', '友人', '母', '彼', '僕', '人']

コードを書けなくても記事のカテゴリ分類をしたい

2つ目の記事では、公開データであるlivedoorニュースコーパスを用いて文章分類を行います。
9種類のカテゴリが割り振られており、この分類をBERTで行うモデルを構築します。
こちらも、「Python」の基本がわかっていればもっと早く解決できていました。

「ニュースデータの読み込み」、「学習データ、検証データ、評価データに分割」、「transformersライブラリのインストール」、「モデルの学習」と「評価に必要なライブラリのインポート」はエラーでずに実行できました。
データセットの定義では、エラーが表示され、「ChatGPT」に1行追加してもらうことで対処できました。

# Datasetの定義

class NewsDataset(Dataset):
def init(self, X, y, tokenizer, max_len):
self.X = X
self.y = y
(略)

以下メッセージが出ます。

NameError Traceback (most recent call last)
in ()
1 # Datasetの定義
—-> 2 class NewsDataset(Dataset):
3 def init(self, X, y, tokenizer, max_len):
4 self.X = X
5 self.y = y

NameError: name ‘Dataset’ is not defined

ChatGPT
ChatGPT

このエラーは、torch.utils.data.Datasetがインポートされていないことが原因です。 torch.utils.data.Datasetをインポートすることで、このエラーを修正できます。以下のように先頭に追加してみてください。

from torch.utils.data import Dataset

インポートすることで解決できます

tokenizerの取得のコードも同様に解決です。
「インポートの宣言」、という基本を知っていれば気づく設定でした。

tokenizerの取得

tokenizer = AutoTokenizer.from_pretrained(pretrained)

の部分で以下メッセージが出ました。

NameError Traceback (most recent call last)
in ()
3
4 # tokenizerの取得
—-> 5 tokenizer = AutoTokenizer.from_pretrained(pretrained)
6
7 # Datasetの作成

NameError: name ‘AutoTokenizer’ is not defined

ChatGPT
ChatGPT

AutoTokenizerが定義されていないためエラーが出ています。 transformers ライブラリから AutoTokenizer をインポートすることで解決できます。

from transformers import AutoTokenizer

# tokenizerの取得
tokenizer = AutoTokenizer.from_pretrained(pretrained)

同様の対処で次々と解決できました。

・・・をコードに追加する必要があります

以下のメッセージの意味がわかりますか。

(略)

—> 29 ‘ids’: torch.LongTensor(ids),
30 ‘mask’: torch.LongTensor(mask),
31 ‘labels’: torch.Tensor(self.y[index])

NameError: name ‘torch’ is not defined

ChatGPT
ChatGPT

torch ライブラリがインポートされていないため、エラーが発生しているようです。import torch を実行してから再度試してみてください。

以下のメッセージの意味もわかりますか。

(略)
3 def init(self, pretrained, drop_rate, otuput_size):
4 super().init()
—-> 5 self.bert = AutoModel.from_pretrained(pretrained)
6 self.drop = torch.nn.Dropout(drop_rate)
7 self.fc = torch.nn.Linear(768, otuput_size) # BERTの出力に合わせて768次元を指定


NameError: name ‘AutoModel’ is not defined

ChatGPT
ChatGPT

このエラーメッセージは、AutoModelが未定義であるため、BERTClassの定義が失敗したことを示しています。これは、transformersライブラリから必要なクラスをインポートすることができていないことを意味しています。AutoModelをインポートするために、from transformers import AutoModelをコードに追加する必要があります。

以下のメッセージはどうですか。

(略)
—> 20 device = ‘cuda’ if cuda.is_available() else ‘cpu’
21
22 # モデルの学習

NameError: name ‘cuda’ is not defined

ChatGPT
ChatGPT

このエラーメッセージは、cuda が定義されていないため、cuda.is_available() を呼び出すことができないという意味です。cuda は、NVIDIA GPUを使った計算を行うためのライブラリです。可能であれば、PyTorchのTensorやモデルパラメータをGPU上で計算することで、演算速度を向上させることができます。cuda が使用できるかどうかを確認するためには、PyTorchの torch.cuda.is_available() 関数を使用します。エラーメッセージが表示された場合は、import torch の行の下に import torch.cuda as cuda を追加することで、cuda.is_available() 関数を使用できるようになります。

以下はどうですか。

—> 36 dataloader_train = DataLoader(dataset_train, batch_size=batch_size, shuffle=True)
37 dataloader_valid = DataLoader(dataset_valid, batch_size=len(dataset_valid), shuffle=False)
38

NameError: name ‘DataLoader’ is not defined

ChatGPT
ChatGPT

NameErrorは、指定された名前が現在のスコープ内で定義されていないことを示します。この場合、DataLoaderという名前が定義されていないことを示しています。このエラーが発生する可能性がある原因は、torch.utils.data.DataLoaderがインポートされていないことが挙げられます。DataLoaderを使用するためには、from torch.utils.data import DataLoaderを追加する必要があります

以下も教えてくれますか。

—> 44 s_time = time.time()

NameError: name ‘time’ is not defined

ChatGPT
ChatGPT

このエラーメッセージは、コードの中で time モジュールがインポートされていないために生じています。import time をコードの冒頭に追加して、問題を解決してください。

今度は以下のメッセージが出ました。

—-> 3 fig, ax = plt.subplots(1, 2, figsize=(15, 5))
4 ax[0].plot(x_axis, np.array(log[‘train’]).T[0], label=’train’)
5 ax[0].plot(x_axis, np.array(log[‘valid’]).T[0], label=’valid’)


NameError: name ‘plt’ is not defined

ChatGPT
ChatGPT

このエラーは、pltが定義されていないことを示しています。pltmatplotlibのライブラリで、データの可視化に使われます。解決するには、以下のようにコードの先頭にimport matplotlib.pyplot as pltを追加してください。

以下のメッセージも出ました。

—-> 7 ax[0].plot(x_axis, np.array(log[‘train’]).T[0], label=’train’)
8 ax[0].plot(x_axis, np.array(log[‘valid’]).T[0], label=’valid’)
9 ax[0].set_xlabel(‘epoch’)

NameError: name ‘np’ is not defined

ChatGPT
ChatGPT

このエラーメッセージは、NumPyライブラリが読み込まれていないため、npという名前が定義されていないことを示しています。NumPyを読み込む必要があるので、次のようにコードを追加してください。

import numpy as np


これにより、NumPyライブラリが読み込まれ、npが定義されるようになります。

結果、参考にした記事同様に、評価データで約90%の精度を得ることができました。

# 正解率の算出
dataloader_train = DataLoader(dataset_train, batch_size=1, shuffle=False)
dataloader_valid = DataLoader(dataset_valid, batch_size=1, shuffle=False)
dataloader_test = DataLoader(dataset_test, batch_size=1, shuffle=False)

print(f'正解率(学習データ):{calculate_loss_and_accuracy(model, dataloader_train, device)[1]:.3f}')
print(f'正解率(検証データ):{calculate_loss_and_accuracy(model, dataloader_valid, device)[1]:.3f}')
print(f'正解率(評価データ):{calculate_loss_and_accuracy(model, dataloader_test, device)[1]:.3f}')

正解率(学習データ):0.989
正解率(検証データ):0.898
正解率(評価データ):0.898
タイトルとURLをコピーしました