GiNZA(7) - 係り受け解析

係り受け解析は、文章を文節または単語で分割した後、どの語がどの語を修飾しているかを判別する処理です。

構文解析と呼ばれることもあります。

文節の係り受け解析

文節の係り受け解析を行うソースコードは以下のようになります。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
import spacy
import ginza
nlp = spacy.load('ja_ginza')
doc = nlp('新橋で打ち合わせをしましょう。')

# 文節の係り受け解析
for span in ginza.bunsetu_spans(doc):
for token in span.lefts:
print(str(ginza.bunsetu_span(token))+' → '+str(span))

実行結果は以下の通りです。

[実行結果]

1
2
新橋で → しましょう。
打ち合わせを → しましょう。

各文節がどの文節に係っているかを確認できました。


7行目のbunsetu_spans()の代わりにbunsetu_phrase_spans()を使うと、主辞(文節で一番重要な単語)を抽出することができます。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
import spacy
import ginza
nlp = spacy.load('ja_ginza')
doc = nlp('新橋で打ち合わせをしましょう。')

# 文節の係り受け解析
for span in ginza.bunsetu_phrase_spans(doc):
for token in span.lefts:
print(str(ginza.bunsetu_span(token))+' → '+str(span))

実行結果は以下の通りです。

[実行結果]

1
2
新橋で → し
打ち合わせを → し

次回は、単語の係り受け解析を行います。

GiNZA(6) - 文節分割

文節分割は、文章を文節ごとに分解する処理です。

文節分割

日本語は、文節で分割した方が解析しやすくなることがよくあります。

文節分割を行うソースコードは以下のようになります。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
import spacy
import ginza
nlp = spacy.load('ja_ginza')
doc = nlp('新橋でランチをご一緒しましょう。次の火曜日はどうですか。')

# 文節分割
for sent in doc.sents:
for span in ginza.bunsetu_spans(sent):
print(span)

実行結果は以下の通りです。

[実行結果]

1
2
3
4
5
6
新橋で
ランチを
ご一緒しましょう。
次の
火曜日は
どうですか。

文節で分解することができました。


またspanをforでループすることにより、文節を分割したトークンを取得することができます。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
import spacy
import ginza
nlp = spacy.load('ja_ginza')
doc = nlp('新橋でランチをご一緒しましょう。次の火曜日はどうですか。')

# 文節分割+トークン化
for sent in doc.sents:
for span in ginza.bunsetu_spans(sent):
for token in span:
print(token)

実行結果は以下の通りです。

[実行結果]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
新橋

ランチ


一緒

ましょう



火曜日

どう
です


次回は、係り受け解析を行います。

GiNZA(5) - 文境界解析

文境界解析は、文章を文ごとに分解する処理です。

文の境界は「。」があるのでこれを検出すれば問題ないと思うかもしれませんが、「!」「?」で区切ることもあります。

また、「彼は『本当ですか。』とつぶやいた。」というように会話文が含まれていることもあり、文境界解析は意外と難しい処理になります。

文境界解析

文境界解析を行うソースコードは次のようになります。

[Google Colaboratory]

1
2
3
4
5
6
7
mport spacy
nlp = spacy.load('ja_ginza')
doc = nlp('新橋でランチをご一緒しましょう。次の火曜日はどうですか。')

# 文境界解析
for span in doc.sents:
print(span)

実行結果は以下の通りです。

[実行結果]

1
2
新橋でランチをご一緒しましょう。
次の火曜日はどうですか。

文ごとに分解することができました。


さらにspanをforでループすることにより、文を分割したトークンを取得することができます。

[Google Colaboratory]

1
2
3
4
5
6
7
8
import spacy
nlp = spacy.load('ja_ginza')
doc = nlp('新橋でランチをご一緒しましょう。次の火曜日はどうですか。')

# 文境界解析+トークン化
for span in doc.sents:
for token in span:
print(token)

実行結果は以下の通りです。

[実行結果]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
新橋

ランチ


一緒

ましょう



火曜日

どう
です



次回は、文節分割を行います。

GiNZA(4) - 形態素解析(レンマ化)

レンマ化は、トークンを辞書の見出し語に変換する処理です。

トークンを辞書の見出し語にそろえることで、異なる表記でも同じ単語であることを判別できるようになります。

レンマ化

レンマ化を行うソースコードは以下のようになります。

[Google Colaboratory]

1
2
3
4
5
6
7
8
import spacy
nlp = spacy.load('ja_ginza')
doc = nlp('新橋に行きます。')

for token in doc:
print(
token.text+', '+ # テキスト
token.lemma_) # レンマ化

実行結果は以下の通りです。

[実行結果]

1
2
3
4
5
新橋, 新橋
に, に
行き, 行く
ます, ます
。, 。

行きというトークンが、行くという見出し語に変換されています。

行くという単語であれば、辞書で確認できますね。


次回は、文境界解析を行います。

GiNZA(3) - 形態素解析(品詞タグ付け)

品詞タグ付けは、トークンの品詞を判別する処理です。

品詞タグ付け

トークンごとの品詞を確認するコードは以下の通りです。

品詞タグとして2種類表示します。

  • SudachiPyの品詞タグ
  • Universal Dependenciesの品詞タグ

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
import spacy
nlp = spacy.load('ja_ginza')
doc = nlp('新橋に行きます。')

for token in doc:
print(
token.text+', '+ # トークン
token.tag_+', '+ # SudachiPyの品詞タグ
token.pos_) # Universal Dependenciesの品詞タグ

実行結果は以下の通りです。

[実行結果]

1
2
3
4
5
新橋, 名詞-普通名詞-一般, NOUN
に, 助詞-格助詞, ADP
行き, 動詞-非自立可能, VERB
ます, 助動詞, AUX
。, 補助記号-句点, PUNCT

次回は、レンマ化を行います。

GiNZA(2) - 形態素解析(トークン化)

形態素解析

形態素解析とは、文章を形態素と呼ばれる言葉の最小単位に分割し形態素品詞見出し語を判定する処理です。

具体的には次のような処理に分けることができます。

  • トークン化
    文章を言葉の最小単位に分割する処理
  • 品詞タグ付け
    トークンの品詞を判別する処理
  • レンマ化
    トークンを辞書の見出し語に変換する処理

トークンの分割単位

GiNZAではトークン化の処理を行う場合、3種類の分割単位に切り替えて利用することができます。

分割単位を指定するためにはset_split_mode()を使います。


まずは分割単位Aでトークン化を行います。

[Google Colaboratory]

1
2
3
4
5
6
7
8
import spacy
import ginza
nlp = spacy.load('ja_ginza')
ginza.set_split_mode(nlp, 'A') # 分割単位A
doc = nlp('あの女性は国家公務員です')

for token in doc:
print(token)

[実行結果]

1
2
3
4
5
6
7
あの
女性

国家
公務

です

次に分割単位Bでトークン化を行います。

[Google Colaboratory]

1
2
3
4
5
6
7
8
import spacy
import ginza
nlp = spacy.load('ja_ginza')
ginza.set_split_mode(nlp, 'B') # 分割単位B
doc = nlp('あの女性は国家公務員です')

for token in doc:
print(token)

[実行結果]

1
2
3
4
5
6
あの
女性

国家
公務員
です

最後にに分割単位Cでトークン化を行います。

[Google Colaboratory]

1
2
3
4
5
6
7
8
import spacy
import ginza
nlp = spacy.load('ja_ginza')
ginza.set_split_mode(nlp, 'C') # 分割単位C
doc = nlp('あの女性は国家公務員です')

for token in doc:
print(token)

[実行結果]

1
2
3
4
5
あの
女性

国家公務員
です

分割単位によって「国家公務員」という単語の分け方が異なっていることが分かります。

  • 分割単位A
    国家/公務/員
  • 分割単位B
    国家/公務員
  • 分割単位C
    国家公務員

次回は、品詞のタグ付けを行います。

GiNZA(1) - インストール

自然言語処理を行うライブラリであるGiNZAを利用してみます。

GiNZAの概要

GiNZAは日本語の自然言語処理ライブラリで、次のような用途で使われます。

  • 情報抽出
    大量の自然言語の文章から、特定の条件に合致した情報を抽出します。
  • 自然言語理解
    発話文章から発話者がどんなタスクを要求しているのかを推測します。
  • 深層学習の前処理
    自然言語の文章を深層学習の入力データに変換します。
    自然言語処理の深層学習の推論で利用します。

インストール

GiNZAをインストールするには次のコマンドを実行します。

[Google Colaboratory]

1
2
# GiNZAのインストール
!pip install ginza==4.0.5

次のようなログが出力されていれば、インストールは成功しています。

[実行結果]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
Collecting ginza==4.0.5
Downloading ginza-4.0.5.tar.gz (20 kB)
Collecting spacy<3.0.0,>=2.3.2
Downloading spacy-2.3.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (10.4 MB)
|████████████████████████████████| 10.4 MB 5.5 MB/s
Collecting ja_ginza<4.1.0,>=4.0.0
Downloading ja_ginza-4.0.0.tar.gz (51.5 MB)
|████████████████████████████████| 51.5 MB 16 kB/s
Collecting SudachiPy>=0.4.9
Downloading SudachiPy-0.5.4.tar.gz (86 kB)
|████████████████████████████████| 86 kB 5.0 MB/s
Collecting SudachiDict-core>=20200330
Downloading SudachiDict-core-20210802.tar.gz (9.1 kB)
Collecting thinc<7.5.0,>=7.4.1
Downloading thinc-7.4.5-cp37-cp37m-manylinux2014_x86_64.whl (1.0 MB)
|████████████████████████████████| 1.0 MB 43.1 MB/s
Requirement already satisfied: blis<0.8.0,>=0.4.0 in /usr/local/lib/python3.7/dist-packages (from spacy<3.0.0,>=2.3.2->ginza==4.0.5) (0.4.1)
Requirement already satisfied: preshed<3.1.0,>=3.0.2 in /usr/local/lib/python3.7/dist-packages (from spacy<3.0.0,>=2.3.2->ginza==4.0.5) (3.0.5)
Requirement already satisfied: cymem<2.1.0,>=2.0.2 in /usr/local/lib/python3.7/dist-packages (from spacy<3.0.0,>=2.3.2->ginza==4.0.5) (2.0.5)
Requirement already satisfied: wasabi<1.1.0,>=0.4.0 in /usr/local/lib/python3.7/dist-packages (from spacy<3.0.0,>=2.3.2->ginza==4.0.5) (0.8.2)
Requirement already satisfied: srsly<1.1.0,>=1.0.2 in /usr/local/lib/python3.7/dist-packages (from spacy<3.0.0,>=2.3.2->ginza==4.0.5) (1.0.5)
Requirement already satisfied: numpy>=1.15.0 in /usr/local/lib/python3.7/dist-packages (from spacy<3.0.0,>=2.3.2->ginza==4.0.5) (1.19.5)
Requirement already satisfied: plac<1.2.0,>=0.9.6 in /usr/local/lib/python3.7/dist-packages (from spacy<3.0.0,>=2.3.2->ginza==4.0.5) (1.1.3)
Requirement already satisfied: requests<3.0.0,>=2.13.0 in /usr/local/lib/python3.7/dist-packages (from spacy<3.0.0,>=2.3.2->ginza==4.0.5) (2.23.0)
Requirement already satisfied: murmurhash<1.1.0,>=0.28.0 in /usr/local/lib/python3.7/dist-packages (from spacy<3.0.0,>=2.3.2->ginza==4.0.5) (1.0.5)
Requirement already satisfied: setuptools in /usr/local/lib/python3.7/dist-packages (from spacy<3.0.0,>=2.3.2->ginza==4.0.5) (57.4.0)
Requirement already satisfied: catalogue<1.1.0,>=0.0.7 in /usr/local/lib/python3.7/dist-packages (from spacy<3.0.0,>=2.3.2->ginza==4.0.5) (1.0.0)
Requirement already satisfied: tqdm<5.0.0,>=4.38.0 in /usr/local/lib/python3.7/dist-packages (from spacy<3.0.0,>=2.3.2->ginza==4.0.5) (4.62.3)
Requirement already satisfied: importlib-metadata>=0.20 in /usr/local/lib/python3.7/dist-packages (from catalogue<1.1.0,>=0.0.7->spacy<3.0.0,>=2.3.2->ginza==4.0.5) (4.8.1)
Requirement already satisfied: zipp>=0.5 in /usr/local/lib/python3.7/dist-packages (from importlib-metadata>=0.20->catalogue<1.1.0,>=0.0.7->spacy<3.0.0,>=2.3.2->ginza==4.0.5) (3.6.0)
Requirement already satisfied: typing-extensions>=3.6.4 in /usr/local/lib/python3.7/dist-packages (from importlib-metadata>=0.20->catalogue<1.1.0,>=0.0.7->spacy<3.0.0,>=2.3.2->ginza==4.0.5) (3.7.4.3)
Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.7/dist-packages (from requests<3.0.0,>=2.13.0->spacy<3.0.0,>=2.3.2->ginza==4.0.5) (3.0.4)
Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/lib/python3.7/dist-packages (from requests<3.0.0,>=2.13.0->spacy<3.0.0,>=2.3.2->ginza==4.0.5) (1.24.3)
Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.7/dist-packages (from requests<3.0.0,>=2.13.0->spacy<3.0.0,>=2.3.2->ginza==4.0.5) (2.10)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.7/dist-packages (from requests<3.0.0,>=2.13.0->spacy<3.0.0,>=2.3.2->ginza==4.0.5) (2021.5.30)
Collecting sortedcontainers~=2.1.0
Downloading sortedcontainers-2.1.0-py2.py3-none-any.whl (28 kB)
Collecting dartsclone~=0.9.0
Downloading dartsclone-0.9.0-cp37-cp37m-manylinux1_x86_64.whl (473 kB)
|████████████████████████████████| 473 kB 34.1 MB/s
Requirement already satisfied: Cython in /usr/local/lib/python3.7/dist-packages (from dartsclone~=0.9.0->SudachiPy>=0.4.9->ginza==4.0.5) (0.29.24)
Building wheels for collected packages: ginza, ja-ginza, SudachiDict-core, SudachiPy
Building wheel for ginza (setup.py) ... done
Created wheel for ginza: filename=ginza-4.0.5-py3-none-any.whl size=15895 sha256=05809609d54412282a3aca677bf262183e269cff4ea2eaa92b35fe485ed4104c
Stored in directory: /root/.cache/pip/wheels/ba/a9/a2/c1165c004f6dcb415b7a7d145aa4511b5024b5fb1f2eb0c0ea
Building wheel for ja-ginza (setup.py) ... done
Created wheel for ja-ginza: filename=ja_ginza-4.0.0-py3-none-any.whl size=51530813 sha256=f6d2a89bfa1850b356ef103dca344535c6472c5615cf8c7d3e0bf2f0bb964e42
Stored in directory: /root/.cache/pip/wheels/a8/f5/4a/5d4877342f912e0b7209d8a65e7ce39fe2c1a3c2511d59acfb
Building wheel for SudachiDict-core (setup.py) ... done
Created wheel for SudachiDict-core: filename=SudachiDict_core-20210802-py3-none-any.whl size=71418512 sha256=5d1f8362b682fef55a4ca03c8d4a590ed74a910a220d1d51947aac52c6d9a1c6
Stored in directory: /root/.cache/pip/wheels/91/e8/21/e80d212743835d87bb5e7eca81b6abef6d8cb67a294007a837
Building wheel for SudachiPy (setup.py) ... done
Created wheel for SudachiPy: filename=SudachiPy-0.5.4-cp37-cp37m-linux_x86_64.whl size=872116 sha256=de7e07689323107cc31919c53b64a7bad008113ae8e094daabcab14dbf5a8957
Stored in directory: /root/.cache/pip/wheels/6b/5b/8b/ce1f543c9e9af590fdc62e8344fda5a3950c60c0d21c83174e
Successfully built ginza ja-ginza SudachiDict-core SudachiPy
Installing collected packages: thinc, sortedcontainers, dartsclone, SudachiPy, spacy, SudachiDict-core, ja-ginza, ginza
Attempting uninstall: thinc
Found existing installation: thinc 7.4.0
Uninstalling thinc-7.4.0:
Successfully uninstalled thinc-7.4.0
Attempting uninstall: sortedcontainers
Found existing installation: sortedcontainers 2.4.0
Uninstalling sortedcontainers-2.4.0:
Successfully uninstalled sortedcontainers-2.4.0
Attempting uninstall: spacy
Found existing installation: spacy 2.2.4
Uninstalling spacy-2.2.4:
Successfully uninstalled spacy-2.2.4
Successfully installed SudachiDict-core-20210802 SudachiPy-0.5.4 dartsclone-0.9.0 ginza-4.0.5 ja-ginza-4.0.0 sortedcontainers-2.1.0 spacy-2.3.7 thinc-7.4.5

メニューから「ランタイム → ランタイムを再起動」を選択し、Google Colaboratoryを再起動しておきます。

トークン化

きちんとインストールできているかどうかを確認するために、トークン化を行ってみます。

[Google Colaboratory]

1
2
3
4
5
6
7
import spacy

nlp = spacy.load('ja_ginza')
doc = nlp('リモートワークできない職場なのでフリーランスになりました。')

for token in doc:
print(token)

実行結果は以下の通りです。

[実行結果]

1
2
3
4
5
6
7
8
9
10
11
12
13
リモートワーク
でき
ない
職場



フリーランス

なり
まし


きちんとトークン化できました。

次回からは、GiNZAを使って形態素解析を行います。

Transformers(16) - 要約④要約実行

学習したモデルを使って要約を行います。

要約

要約を行うコードは以下の通りです。

5行目で、日本語T5事前学習済みモデルのトークナイザーを読み込んでいます。

6行目では、前回ファインチューニングした要約モデルをoutputフォルダから読み込んでいます。

9行目に、要約対象の文章を設定しています。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import torch
from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM

# トークナイザーとモデルの準備
tokenizer = AutoTokenizer.from_pretrained('sonoisa/t5-base-japanese')
model = AutoModelForSeq2SeqLM.from_pretrained('output/')

# テキスト
text = "ぴちぴちのおねえさんが川でせんたくをしていると、ドンブラコ、ドンブラコと、大きな桃が流れてきました。おねえさんは大きな桃をひろいあげて、家に持ち帰りました。そして、ギャル男とおねえさんが桃を食べようと桃を切ってみると、なんと中から元気 の良いドランゴンの赤ちゃんが飛び出してきました。"

# テキストをテンソルに変換
input = tokenizer.encode(text, return_tensors='pt', max_length=512, truncation=True)

# 推論
model.eval()
with torch.no_grad():
summary_ids = model.generate(input)
print(tokenizer.decode(summary_ids[0]))

要約結果は以下の通りです。

[実行結果]

1
2
3
4
/usr/local/lib/python3.7/dist-packages/torch/_tensor.py:575: UserWarning: floor_divide is deprecated, and will be removed in a future version of pytorch. It currently rounds toward 0 (like the 'trunc' function NOT 'floor'). This results in incorrect rounding for negative values.
To keep the current behavior, use torch.div(a, b, rounding_mode='trunc'), or for actual floor division, use torch.div(a, b, rounding_mode='floor'). (Triggered internally at /pytorch/aten/src/ATen/native/BinaryOps.cpp:467.)
return torch.floor_divide(self, other)
<pad><extra_id_0>川でせんたくをしていると、ドンブラコ、ドンブラコと大きな桃が流れてきました。</s>

・・・要約と言えば要約されていますが、主語が全部とんでますし、中盤以降を全部省略とずいぶん大胆な要約となっています。

なんらかの改善が必要なのかもしれません。

Transformers(15) - 要約③ファインチューニング

学習データと検証データを使ってファインチューニングを行います。

ファインチューニング

次のコマンドを実行し、要約のファインチューニングを行います。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
%%time

# ファインチューニングの実行
!python ./transformers/examples/seq2seq/run_summarization.py \
--model_name_or_path=sonoisa/t5-base-japanese \
--do_train \
--do_eval \
--train_file=train.csv \
--validation_file=dev.csv \
--num_train_epochs=10 \
--per_device_train_batch_size=2 \
--per_device_eval_batch_size=2 \
--save_steps=5000 \
--save_total_limit=3 \
--output_dir=output/ \
--predict_with_generate \
--use_fast_tokenizer=False \
--logging_steps=100

実行結果は以下の通りです。

[実行結果]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
10/06/2021 11:45:03 - WARNING - __main__ -   Process rank: -1, device: cuda:0, n_gpu: 1distributed training: False, 16-bits training: False
10/06/2021 11:45:03 - INFO - __main__ - Training/evaluation parameters Seq2SeqTrainingArguments(output_dir='output/', overwrite_output_dir=False, do_train=True, do_eval=True, do_predict=False, evaluation_strategy=<IntervalStrategy.NO: 'no'>, prediction_loss_only=False, per_device_train_batch_size=2, per_device_eval_batch_size=2, per_gpu_train_batch_size=None, per_gpu_eval_batch_size=None, gradient_accumulation_steps=1, eval_accumulation_steps=None, learning_rate=5e-05, weight_decay=0.0, adam_beta1=0.9, adam_beta2=0.999, adam_epsilon=1e-08, max_grad_norm=1.0, num_train_epochs=10.0, max_steps=-1, lr_scheduler_type=<SchedulerType.LINEAR: 'linear'>, warmup_ratio=0.0, warmup_steps=0, logging_dir='runs/Oct06_11-45-03_2d9fb230d52a', logging_strategy=<IntervalStrategy.STEPS: 'steps'>, logging_first_step=False, logging_steps=100, save_strategy=<IntervalStrategy.STEPS: 'steps'>, save_steps=5000, save_total_limit=3, no_cuda=False, seed=42, fp16=False, fp16_opt_level='O1', fp16_backend='auto', fp16_full_eval=False, local_rank=-1, tpu_num_cores=None, tpu_metrics_debug=False, debug=False, dataloader_drop_last=False, eval_steps=100, dataloader_num_workers=0, past_index=-1, run_name='output/', disable_tqdm=False, remove_unused_columns=True, label_names=None, load_best_model_at_end=False, metric_for_best_model=None, greater_is_better=None, ignore_data_skip=False, sharded_ddp=[], deepspeed=None, label_smoothing_factor=0.0, adafactor=False, group_by_length=False, report_to=['tensorboard'], ddp_find_unused_parameters=None, dataloader_pin_memory=True, skip_memory_metrics=False, sortish_sampler=False, predict_with_generate=True)
Using custom data configuration default
Reusing dataset csv (/root/.cache/huggingface/datasets/csv/default-2359a64c962f9aac/0.0.0/2960f95a26e85d40ca41a230ac88787f715ee3003edaacb8b1f0891e9f04dda2)
loading configuration file https://huggingface.co/sonoisa/t5-base-japanese/resolve/main/config.json from cache at /root/.cache/huggingface/transformers/fb3cd498b86ea48d9c5290222d7a1b96e0acb4daa6d35a7fcb00168d59c356ee.82b38ae98529e44bc2af82ee82527f78e94856e2fb65b0ec6faecbb49d8ab639
Model config T5Config {
"_name_or_path": "/content/drive/MyDrive/T5_models/oscar_cc100_wikipedia_ja",
"architectures": [
"T5Model"
],
"bos_token_id": 0,
"d_ff": 3072,
"d_kv": 64,
"d_model": 768,
"decoder_start_token_id": 0,
"dropout_rate": 0.1,
"eos_token_id": 1,
"eos_token_ids": [
1
],
"feed_forward_proj": "relu",
"initializer_factor": 1.0,
"is_encoder_decoder": true,
"layer_norm_epsilon": 1e-06,
"max_length": 512,
"model_type": "t5",
"n_positions": 512,
"num_beams": 4,
"num_decoder_layers": 12,
"num_heads": 12,
"num_layers": 12,
"pad_token_id": 0,
"relative_attention_num_buckets": 32,
"transformers_version": "4.4.2",
"use_cache": true,
"vocab_size": 32128
}

loading configuration file https://huggingface.co/sonoisa/t5-base-japanese/resolve/main/config.json from cache at /root/.cache/huggingface/transformers/fb3cd498b86ea48d9c5290222d7a1b96e0acb4daa6d35a7fcb00168d59c356ee.82b38ae98529e44bc2af82ee82527f78e94856e2fb65b0ec6faecbb49d8ab639
Model config T5Config {
"_name_or_path": "/content/drive/MyDrive/T5_models/oscar_cc100_wikipedia_ja",
"architectures": [
"T5Model"
],
"bos_token_id": 0,
"d_ff": 3072,
"d_kv": 64,
"d_model": 768,
"decoder_start_token_id": 0,
"dropout_rate": 0.1,
"eos_token_id": 1,
"eos_token_ids": [
1
],
"feed_forward_proj": "relu",
"initializer_factor": 1.0,
"is_encoder_decoder": true,
"layer_norm_epsilon": 1e-06,
"max_length": 512,
"model_type": "t5",
"n_positions": 512,
"num_beams": 4,
"num_decoder_layers": 12,
"num_heads": 12,
"num_layers": 12,
"pad_token_id": 0,
"relative_attention_num_buckets": 32,
"transformers_version": "4.4.2",
"use_cache": true,
"vocab_size": 32128
}

loading file https://huggingface.co/sonoisa/t5-base-japanese/resolve/main/spiece.model from cache at /root/.cache/huggingface/transformers/a455eff173d5e851553673177dcb6876d5fcd0d39a4bdd7e9a75c50dfb2ab158.82c0f9a9b4ec152c1ca13afe226abd56b618ec9f9d395dc56fd3ad6ca14b4dcc
loading file https://huggingface.co/sonoisa/t5-base-japanese/resolve/main/added_tokens.json from cache at None
loading file https://huggingface.co/sonoisa/t5-base-japanese/resolve/main/special_tokens_map.json from cache at /root/.cache/huggingface/transformers/559eb952d008bbb60787ea4b89849e5a377f35e163651805b072f2fb1f4b28b9.c94798918c92ded6aeef2d2f0e666d2cc4145eca1aa6e1336fde07f2e13e2f46
loading file https://huggingface.co/sonoisa/t5-base-japanese/resolve/main/tokenizer_config.json from cache at /root/.cache/huggingface/transformers/175dd55a5be280f74e003b3b5efa1de2080efdc795da6dc013dd001d661fcb50.6de37cb3d7dbffde3a51667c5706471d3c6b2a3ff968f108c1429163c5860a5d
loading file https://huggingface.co/sonoisa/t5-base-japanese/resolve/main/tokenizer.json from cache at None
loading weights file https://huggingface.co/sonoisa/t5-base-japanese/resolve/main/pytorch_model.bin from cache at /root/.cache/huggingface/transformers/e6cfe18cc2661a1900624126a7fd3af005a942d9079fd828c4333b0f46617f58.f3773e9948a37df8ff8b19de7bdc64bbcc9fd2225fcdc41ed5a4a2be8a86f383
All model checkpoint weights were used when initializing T5ForConditionalGeneration.

All the weights of T5ForConditionalGeneration were initialized from the model checkpoint at sonoisa/t5-base-japanese.
If your task is similar to the task the model of the checkpoint was trained on, you can already use T5ForConditionalGeneration for predictions without further training.
Loading cached processed dataset at /root/.cache/huggingface/datasets/csv/default-2359a64c962f9aac/0.0.0/2960f95a26e85d40ca41a230ac88787f715ee3003edaacb8b1f0891e9f04dda2/cache-1b9264874e882057.arrow
Loading cached processed dataset at /root/.cache/huggingface/datasets/csv/default-2359a64c962f9aac/0.0.0/2960f95a26e85d40ca41a230ac88787f715ee3003edaacb8b1f0891e9f04dda2/cache-31c3668d81aead05.arrow
***** Running training *****
Num examples = 477
Num Epochs = 10
Instantaneous batch size per device = 2
Total train batch size (w. parallel, distributed & accumulation) = 2
Gradient Accumulation steps = 1
Total optimization steps = 2390
{'loss': 3.7109, 'learning_rate': 4.7907949790794984e-05, 'epoch': 0.42}
{'loss': 3.3028, 'learning_rate': 4.581589958158996e-05, 'epoch': 0.84}
{'loss': 2.9266, 'learning_rate': 4.372384937238494e-05, 'epoch': 1.26}
{'loss': 2.6457, 'learning_rate': 4.1631799163179915e-05, 'epoch': 1.67}
{'loss': 2.4916, 'learning_rate': 3.95397489539749e-05, 'epoch': 2.09}
{'loss': 2.2776, 'learning_rate': 3.744769874476988e-05, 'epoch': 2.51}
{'loss': 2.3356, 'learning_rate': 3.5355648535564854e-05, 'epoch': 2.93}
{'loss': 2.1054, 'learning_rate': 3.3263598326359835e-05, 'epoch': 3.35}
{'loss': 2.0186, 'learning_rate': 3.117154811715482e-05, 'epoch': 3.77}
{'loss': 1.9114, 'learning_rate': 2.9079497907949792e-05, 'epoch': 4.18}
{'loss': 1.8481, 'learning_rate': 2.6987447698744773e-05, 'epoch': 4.6}
{'loss': 1.7216, 'learning_rate': 2.489539748953975e-05, 'epoch': 5.02}
{'loss': 1.6217, 'learning_rate': 2.280334728033473e-05, 'epoch': 5.44}
{'loss': 1.6558, 'learning_rate': 2.0711297071129708e-05, 'epoch': 5.86}
{'loss': 1.5691, 'learning_rate': 1.8619246861924686e-05, 'epoch': 6.28}
{'loss': 1.5122, 'learning_rate': 1.6527196652719665e-05, 'epoch': 6.69}
{'loss': 1.3568, 'learning_rate': 1.4435146443514645e-05, 'epoch': 7.11}
{'loss': 1.4267, 'learning_rate': 1.2343096234309625e-05, 'epoch': 7.53}
{'loss': 1.3995, 'learning_rate': 1.0251046025104603e-05, 'epoch': 7.95}
{'loss': 1.3224, 'learning_rate': 8.158995815899583e-06, 'epoch': 8.37}
{'loss': 1.3677, 'learning_rate': 6.066945606694561e-06, 'epoch': 8.79}
{'loss': 1.3022, 'learning_rate': 3.97489539748954e-06, 'epoch': 9.21}
{'loss': 1.2621, 'learning_rate': 1.882845188284519e-06, 'epoch': 9.62}
100% 2390/2390 [33:01<00:00, 1.25it/s]

Training completed. Do not forget to share your model on huggingface.co/models =)


{'train_runtime': 1981.4145, 'train_samples_per_second': 1.206, 'epoch': 10.0}
100% 2390/2390 [33:01<00:00, 1.21it/s]
Saving model checkpoint to output/
Configuration saved in output/config.json
Model weights saved in output/pytorch_model.bin
tokenizer config file saved in output/tokenizer_config.json
Special tokens file saved in output/special_tokens_map.json
Copy vocab file to output/spiece.model
***** train metrics *****
epoch = 10.0
init_mem_cpu_alloc_delta = 1MB
init_mem_cpu_peaked_delta = 0MB
init_mem_gpu_alloc_delta = 850MB
init_mem_gpu_peaked_delta = 0MB
train_mem_cpu_alloc_delta = 0MB
train_mem_cpu_peaked_delta = 0MB
train_mem_gpu_alloc_delta = 2575MB
train_mem_gpu_peaked_delta = 5616MB
train_runtime = 1981.4145
train_samples = 477
train_samples_per_second = 1.206
10/06/2021 12:18:20 - INFO - __main__ - *** Evaluate ***
***** Running Evaluation *****
Num examples = 120
Batch size = 2
/usr/local/lib/python3.7/dist-packages/torch/_tensor.py:575: UserWarning: floor_divide is deprecated, and will be removed in a future version of pytorch. It currently rounds toward 0 (like the 'trunc' function NOT 'floor'). This results in incorrect rounding for negative values.
To keep the current behavior, use torch.div(a, b, rounding_mode='trunc'), or for actual floor division, use torch.div(a, b, rounding_mode='floor'). (Triggered internally at /pytorch/aten/src/ATen/native/BinaryOps.cpp:467.)
return torch.floor_divide(self, other)
100% 60/60 [01:37<00:00, 1.62s/it]
***** eval metrics *****
epoch = 10.0
eval_gen_len = 16.7333
eval_loss = 2.6638
eval_mem_cpu_alloc_delta = 2MB
eval_mem_cpu_peaked_delta = 0MB
eval_mem_gpu_alloc_delta = 0MB
eval_mem_gpu_peaked_delta = 1227MB
eval_rouge1 = 10.1667
eval_rouge2 = 6.3889
eval_rougeL = 10.2778
eval_rougeLsum = 10.5278
eval_runtime = 98.9901
eval_samples = 120
eval_samples_per_second = 1.212
CPU times: user 18 s, sys: 2.62 s, total: 20.7 s
Wall time: 35min 1s

35分ほどかかりました。

outputフォルダに学習結果となるモデルを表す複数ファイルが出力されています。

学習結果の確認

TensorBoardで学習結果を確認します。

[Google Colaboratory]

1
2
3
# 学習状況の確認
%load_ext tensorboard
%tensorboard --logdir runs

[実行結果]

損失(Loss)が0に収束・・・してはいないのですが、少しずづ減少し1.4以下になってはいるので、それなりに学習していることが分かります。

次回は、学習したモデルを使って要約を行います。

Transformers(14) - 要約②学習データと検証データの作成

前回ダウンロードしたニュース記事から学習データ検証データを作成します。

学習データ・検証データの作成

前回取得したニュース記事は、output.tsvに出力されています。

このファイルから、学習データ(8割)と検証データ(2割)を作成します。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import os
import pandas as pd

# データフレームの作成
df = pd.DataFrame(columns=['text', 'summary'])
with open('output.tsv') as f:
for line in f.readlines():
strs = line.split('\t')
df = df.append({'text':strs[3] , 'summary':strs[0]}, ignore_index=True)

# シャッフル
df = df.sample(frac=1)

# CSVファイルの保存
num = len(df)
df[:int(num*0.8)].to_csv('train.csv', sep=',', index=False)
df[int(num*0.8):].to_csv('dev.csv', sep=',', index=False)

処理が成功すると、以下のファイルが出力されます。

  • train.csv
    学習データ
  • dev.csv
    検証データ

必要ライブラリのインストール

次回ファインチューニングを行う前準備として、必要なライブラリをインストールしておきます。

[Google Colaboratory]

1
2
3
4
5
# ソースからのHuggingface Transformersのインストール
!git clone https://github.com/huggingface/transformers -b v4.4.2
!pip install -e transformers
!pip install fugashi[unidic-lite]
!pip install ipadic

メニューから「ランタイム → ランタイムを再起動」を選択し、Google Colaboratoryを再起動しておきます。

さらに以下のライブラリをインストールします。

[Google Colaboratory]

1
2
3
4
5
6
7
# Huggingface Datasetsのインストール
!pip install datasets==1.2.1

# 依存パッケージのインストール
!pip install rouge_score==0.0.4
!pip install sentencepiece==0.1.91

以上で、ライブラリのインストールが完了しました。

次回は、準備した学習データと検証データを使ってファインチューニングを行います。