LoginSignup
3
1

More than 1 year has passed since last update.

chiVeの活用方法シリーズ

はじめに

2022年4月末に、WAP NLP Tech Talk#5 にて、「単語分散表現 chiVeの活用方法」というタイトルでお話しをしました。
そのQiita版として、スライド の内容を補足しながら4回に分けて紹介しています。
chiVe とは、日本語単語分散表現です。分散表現の基本事項や、chiVe の特長については、Part 1 で触れています。

さて、前回は公開済みの chiVe を使って文書分類をしました。今回は chiVe を追加学習し、前回と同じ分類タスクで結果を比較します。

追加学習

公開されている chiVe は汎用的なデータセットで学習済み1ですので、そのままでも利用できますが、手持ちのデータで追加学習させることによって、自分専用のドメイン(分野)に特化させることができます。
例えば、ニュースの分類タスクに専用で使う場合は、ニュースドメインのコーパスで追加学習させることで、より性能が高くなる可能性があります。

実験

今回も Livedoor ニュースコーパス でテキスト分類をします。

前回のコードの続きで進めます。

本記事から進めるには 前回の「データセットの準備 」節を適用してから次のコードを実行してください。
import gensim
import numpy as np
import sudachipy
import sudachidict_core
from sklearn.metrics import accuracy_score
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import make_pipeline, Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

tokenizer = sudachipy.Dictionary().create()

def tokenize(sent: str) -> list[str]:
    morphs = tokenizer.tokenize(sent.strip())
    norms = [m.normalized_form() for m in morphs]
    return norms

def text2vec(text: str, vectorizer):
    norms = tokenize(text)
    word_vecs = np.array([vectorizer[n] for n in norms if n in vectorizer])
    text_vec = np.average(vecs, axis=0)
    return vec

def classify(train_x, train_y, test_x, test_y):
    param_grid = {
        'svc__C': [1, 10, 100, 1000],
        'svc__gamma': [1e-4, 5e-4, 1e-3],
    }
    clf = make_pipeline(StandardScaler(), SVC(random_state=0))
    search = GridSearchCV(clf, param_grid, verbose=3)
    search.fit(train_x, train_y)
    best_model = search.best_estimator_
    predicted = best_model.predict(test_x)
    accuracy = accuracy_score(test_y, predicted)
    print('accuracy = {:.4f}'.format(accuracy))

フルモデルのダウンロード

chiVe の追加学習を行うには、フルモデルを使う必要があります。

console: フルモデルのダウンロードして展開
$ wget https://sudachi.s3-ap-northeast-1.amazonaws.com/chive/chive-1.2-mc90_gensim-full.tar.gz
$ tar xzf chive-1.2-mc90_gensim-full.tar.gz

chiVe の追加学習

chive の追加学習
from gensim.models import Word2Vec

# chiVe を追加学習するメソッド
def finetuning(output_chive_path: str, train_texts):
    chive_finetuned = Word2Vec.load("data/chive-1.2-mc90_gensim-full/chive-1.2-mc90.bin")

    # 実験の再現性のため(並列処理すると実験が再現できない)
    chive_finetuned.workers = 1

    # 語彙の再構築
    chive_finetuned.build_vocab(train_texts, update=True)

    # 追加学習で使用するデータセットは小規模なので、min_count を小さくしておく
    chive_finetuned.vocabulary.min_count = 0

    # 学習、保存
    chive_finetuned.train(train_texts, total_examples=chive_finetuned.corpus_count,
                          epochs=chive_finetuned.epochs)
    chive_finetuned.save(output_chive_path)

Livedoor ニュースコーパスの学習用データでchiVeを学習します。

# 学習用データを単語分割
train_toked = [tokenize(line) for article in train_df['article']
               for line in article.split('\n')]

# 追加学習した chiVe の保存先
output_chive_path='data/chive-1.2-mc90.livedoor.finetuned.bin'

# 追加学習
finetuning(output_chive_path, train_toked)

学習が終わると、次の3つのファイルが生成されているはずです。

$ ls
# >>> chive-1.2-mc90.livedoor.finetuned.bin
#     chive-1.2-mc90.livedoor.finetuned.bin.trainables.syn1neg.npy
#     chive-1.2-mc90.livedoor.finetuned.bin.wv.vectors.npy

これで、Livedoor ニュースコーパスに特化した chiVe が得られました。

追加学習した chiVe を使って分類

前回と同じデータセットで分類タスクの性能を確認します。

# 追加学習した chiVe の読み込み
chive_finetuned = Word2Vec.load('data/chive-1.2-mc90.livedoor.finetuned.bin')

# vectorizer=chive_finetuned.wv を指定して、ベクトル化
train_x = np.array([text2vec(article, vectorizer=chive_finetuned.wv)
                    for article in train_df["article"]])
train_y = np.array(train_df["label_id"])

test_x = np.array([text2vec(article, vectorizer=chive_finetuned.wv)
                   for article in test_df["article"]])
test_y = np.array(test_df["label_id"])

# 学習、評価
classify(train_x, train_y, test_x, test_y)
# >>> accuracy = 0.9227

前回の正解率 91.32% に比べて、改善できたようです。

他のデータセットで追加学習

chiVe の性能改善にはデータセットの選択が大切です。ニュース記事とは別のデータで chiVe を追加学習し、同じ分類タスク(ニュース分類)の性能が改善するか調べます。

別のデータセットとして、Twitter のツイート文を使ってみましょう。ツイート文は、ニュース記事に比べてカジュアルな表現が多く、同じ日本語ですが性質が全く異なります。

Twitterのデータセットとして、WRIMEを使います。

console: データセットのダウンロード
$ wget https://raw.githubusercontent.com/ids-cv/wrime/master/wrime-ver1.tsv
python: ツイート文で chiVe を追加学習してニュース記事を分類
import pandas as pd

# データを読み込んで、単語分割
wrime_df = pd.read_csv('data/wrime/wrime-ver1.tsv', delimiter='\t')
train_toked = [tokenize(line) for tweet in wrime_df['Sentence'] for line in tweet.split('\n')]

# chiVe の追加学習
finetuning('data/chive-1.2-mc90.wrime.finetuned.bin', train_toked)

chive_finetuned_wrime = Word2Vec.load('data/chive-1.2-mc90.wrime.finetuned.bin')

# ベクトル化
train_x = np.array([text2vec(article, vectorizer=chive_finetuned_wrime.wv)
                    for article in train_df["article"]])
train_y = np.array(train_df["label_id"])
test_x = np.array([text2vec(article, vectorizer=chive_finetuned_wrime.wv)
                   for article in test_df["article"]])
test_y = np.array(test_df["label_id"])

# 分類
classify(train_x, train_y, test_x, test_y)
# >>> accuracy = 0.9091

追加学習をしなかった場合の正解率 91.32% に比べて、性能が下がってしまったようです。
このように、追加学習を行う時には、適切なデータセットの選択が必要です。

まとめ

今回は chiVe の追加学習について触れました。
Livedoor ニュースコーパスの分類実験の結果は次の通りでした。

分類手法 正解率
chiVe(追加学習なし) + SVM 0.9132
chiVe(Livedoorで追加学習) + SVM 0.9227
chiVe(ツイート文で追加学習) + SVM 0.9091

同じドメインのデータセットで追加学習する手法(Livedoorで追加学習)が最も良い結果になりましたが、別のドメインのデータセットを使う手法(ツイート文で追加学習)は、改善が見られませんでした。
chiVe を追加学習する際には、応用先に合わせたデータセットをご検討ください。

さて、「単語分散表現 chiVe の活用方法」シリーズは今回が最後です。
ぜひ紹介した内容を応用して chiVe を使ってみてください。

  1. chiVe の学習の仕組みについてはこちらの記事を参照してください。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1