Universal Dependencies と BERT/RoBERTa/DeBERTa モデルによる多言語情報処理安岡孝一

rootparataxis
obj
advmodobj
nmod

advmod

nmod

ADV

VERB

NOUN

NOUN

ADV

VERB

NOUN

NOUN

v,副詞,否定,無界

v,動詞,行為,移動

n,名詞,主体,動物

n,名詞,固定物,地形

v,副詞,否定,無界

v,動詞,行為,得失

n,名詞,主体,動物

n,名詞,人,関係

不

入

虎

穴

不

得

虎

子

root
advcl
punct
advmodadvmod

obj

punct
obj
aux

nmod

ADV

VERB

NOUN

PUNCT

ADV

AUX

VERB

PART

NOUN

PUNCT

RB

VV

NN

,

RB

MD

VV

PFA

NN

.

，

怎么

能

抓到

小

老虎

。

不

进入 虎穴

root
advcl
obl

mark

case

obj

aux

punct

case

aux

NOUN

ADP

VERB

AUX

SCONJ

NOUN

ADP

VERB

AUX

PUNCT

名詞-普通名詞-一般

助詞-格助詞

動詞-一般

助動詞

助詞-接続助詞

名詞-普通名詞-一般

助詞-格助詞

動詞-非自立可能

助動詞

補助記号-句点

虎穴

に

ば

虎子

を

得

ず

。

obj

nmod

入ら ざれ

root
advcl
aux
advmodobj

nmod

advmod

PART

VERB

NOUN

NOUN

AUX

PART

VERB

NOUN

NEG

VACT

NCMN

NCMN

XVBM

NEG

VSTA

NCMN

ไม่

เข้า

ถ้า

เสือ

ย่อม

ไม่

2024 年 8 月版

ได้

ลูก

NOUN
NCMN

เสือ

Universal Dependencies と BERT/RoBERTa/DeBERTa モデル
による多言語情報処理 (2024 年 8 月版)
安岡孝一 (京都大学人文科学研究所附属人文情報学創新センター)

1

概説編
1.1 Universal Dependencies と CoNLL-U . . . . . . . . . . . . . . . . . . . . .
1.2 依存文法理論と Universal Dependencies . . . . . . . . . . . . . . . . . . .
1.3 BERT/RoBERTa/DeBERTa モデルと穴埋めゲーム . . . . . . . . . . . . .
1.4 Universal Dependencies における係り受け解析 . . . . . . . . . . . . . . .

5
5
9
14
16

2

古典中国語 (漢文) 編
2.1 古典中国語 UD における品詞付与と文切り . . . . . . . . . . . . . . . . .
2.2 古典中国語 UD における係り受け解析 . . . . . . . . . . . . . . . . . . .
2.3 古典中国語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . . . .

20
20
23
25

3

日本語編
3.1 国語研短単位にもとづく品詞付与と係り受け解析 . . . . . . . . . . . . .
3.2 国語研短単位ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . .
3.3 国語研長単位にもとづく品詞付与と係り受け解析 . . . . . . . . . . . . .
3.4 国語研長単位ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . .
3.5 文節にもとづく係り受け解析 . . . . . . . . . . . . . . . . . . . . . . . .

29
29
31
33
35
36

4

英語編
4.1 英語 UD における品詞付与と係り受け解析 . . . . . . . . . . . . . . . . .
4.2 英語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . . . . . . .
4.3 英語 UD による構成素解析 . . . . . . . . . . . . . . . . . . . . . . . . . .

37
37
38
40

5

フランス語編5.1 フランス語 UD における品詞付与と係り受け解析 . . . . . . . . . . . . .
5.2 フランス語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . . . .

42
42
43

6

ドイツ語編
6.1 ドイツ語 UD における品詞付与と係り受け解析 . . . . . . . . . . . . . . .
6.2 ドイツ語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . . . . .

46
46
47

7

オランダ語編
7.1 オランダ語 UD における品詞付与と係り受け解析 . . . . . . . . . . . . .
7.2 オランダ語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . . . .

50
50
50

8

タイ語編
8.1 タイ語 UD における品詞付与 . . . . . . . . . . . . . . . . . . . . . . . .
8.2 タイ語 UD における係り受け解析 . . . . . . . . . . . . . . . . . . . . . .
8.3 タイ語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . . . . . .

53
53
54
54

ベトナム語編
9.1 ベトナム語 UD における品詞付与 . . . . . . . . . . . . . . . . . . . . . .
9.2 ベトナム語 UD における係り受け解析 . . . . . . . . . . . . . . . . . . .
9.3 ベトナム語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . . . .

58
58
59
59

10 ロシア語編
10.1 ロシア語 UD における品詞付与と係り受け解析 . . . . . . . . . . . . . . .
10.2 ロシア語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . . . . .

62
62
62

11 ウクライナ語編
11.1 ウクライナ語 UD における品詞付与と係り受け解析 . . . . . . . . . . . .
11.2 ウクライナ語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . .

65
65
65

12 ベラルーシ語編
12.1 ベラルーシ語 UD における品詞付与と係り受け解析 . . . . . . . . . . . .
12.2 ベラルーシ語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . .

68
68
69

13 セルビア語編
13.1 セルビア語 UD における品詞付与と係り受け解析 . . . . . . . . . . . . .
13.2 セルビア語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . . . .

72
72
73

14 クロアチア語編
14.1 クロアチア語 UD における品詞付与と係り受け解析 . . . . . . . . . . . .
14.2 クロアチア語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . .

77
77
77

15 コプト語編
15.1 コプト語 UD における品詞付与 . . . . . . . . . . . . . . . . . . . . . . .
15.2 コプト語 UD における係り受け解析 . . . . . . . . . . . . . . . . . . . . .
15.3 コプト語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . . . . .

80
80
81
81

16 スペイン語編
16.1 スペイン語 UD における品詞付与と係り受け解析 . . . . . . . . . . . . .
16.2 スペイン語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . . . .

84
84
85

17 カタルーニャ語編
17.1 カタルーニャ語 UD における品詞付与と係り受け解析 . . . . . . . . . . .
17.2 カタルーニャ語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . .

88
88
89

18 ガリシア語編
18.1 ガリシア語 UD における品詞付与と係り受け解析 . . . . . . . . . . . . .
18.2 ガリシア語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . . . .

92
92
92

19 ポルトガル語編
19.1 ポルトガル語 UD における品詞付与と係り受け解析 . . . . . . . . . . . .
19.2 ポルトガル語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . .

95
95
96

9

20 イタリア語編
20.1 イタリア語 UD における品詞付与と係り受け解析 . . . . . . . . . . . . .
20.2 イタリア語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . . . .

98
98
99

21 ラテン語編
101
21.1 ラテン語 UD における品詞付与と係り受け解析 . . . . . . . . . . . . . . . 101
21.2 ラテン語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . . . . . 101
22 バスク語編
10422.1 バスク語 UD における品詞付与と係り受け解析 . . . . . . . . . . . . . . . 104
22.2 バスク語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . . . . . 105
23 韓国語編
23.1 韓国語 UD における品詞付与と係り受け解析 . . . . . . . . . . . . . . . .
23.2 韓国語の形態素にもとづく品詞付与と係り受け解析 . . . . . . . . . . . .
23.3 韓国語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . . . . . .

107
107
108
109

24 アイヌ語編
112
24.1 アイヌ語 UD における品詞付与と係り受け解析 . . . . . . . . . . . . . . . 112
24.2 アイヌ語ミニ DeBERTa モデルの製作 . . . . . . . . . . . . . . . . . . . . 113

1 概説編
本書では、Universal Dependencies (UD)[1] と呼ばれる多言語係り受けコーパス[2] を用いて、自然言語処理のうち、特に、品詞付与と係り受け解析に関して解説します。これらの解析手法の背後には、現実にはヤヤコシイ数式が横たわっているのですが、本書では、できる限り数式を使わずに、これらの解析手法を解説します。一方で、現代の自然言語
処理は、その多くを BERT[3]・RoBERTa[4]・DeBERTa[5] などの事前学習モデルに拠っていることから、これら事前学習モデルについても概要を紹介します。また、各手法を読者が実際に試せるよう、Google Colaboratory[6] でのプログラミング例も、同時に示しています。プログラミング例は、理解しやすいよう、また「写経」しやすいよう、長くても 25行程度に収めることを心がけました。python 等の基本知識が無くとも、とりあえずは動かしてみることが出来るでしょう。
本書の構成は、第 1 章が言語横断的な「概説編」となっており、第 2 章以降で各言語ごとの手法を解説しています。どの章から読み始めても大丈夫ですが、疑問が起こった
ら、必ず第 1 章に戻ってみることをオススメします。なお、それぞれの解析手法に関しては、できるだけ原論文や URL を示すようにしました。また、本書で書き切れなかった
諸言語についても、deplacy[7] のサポートページ[8] に、Google Colaboratory での使用例を示しました (表 1)。応用を検討する際の一助となれば幸いです。

1.1

Universal Dependencies と CoNLL-U

UD は、書写言語における品詞・形態素属性・依存構造 (係り受け関係) を、言語に関わらず記述する手法です。句構造を考慮せずに係り受け関係を記述することで、言語横断性を高めていて、全ての文法構造を単語間のリンクで記述するのが特徴です。
依存構造解析それ自体は、Tesnière の構造的統語論[9] に源を発し、Мельчук の有向グラ
フ記述[10] によって、一応の完成を見た手法です。その最大の特長は、いわゆる動詞中心主義によって言語横断的な記述が可能だという点にあり、Мельчук 依存文法をコンピュー
タ向けに洗練した UD においても、言語に関わらない記述、という特長が前面に押し出されています。UD における文法構造記述は、句構造を考慮せず、全てを単語間のリンクとして表現します。これにより、言語横断的な文法構造記述を可能としているのです。
[1]

Marie-Catherine de Marneffe, Christopher D. Manning, Joakim Nivre, Daniel Zeman: Universal Dependencies, Computational Linguistics, Vol.47, No.2 (June 2021), pp.255-308.
[2]https://universaldependencies.org において、カレル大学の LINDAT/CLARIN を中心とした 100以上のグループが、世界中の言語に対して開発中。
[3]
Jacob Devlin, Ming-Wei Chang, Kenton Lee, Kristina Toutanova: BERT: Pre-training of Deep Bidirectional
Transformers for Language, Proceedings of the 2019 Conference of the North American Chapter of the Association for Computational Linguistics (June 2019), Human Language Technologies, Vol.1, pp.4171-4186.
[4]
https://arxiv.org/abs/1907.11692[5]
Pencheng He, Xiaodong Liu, Jianfeng Gao, Weizhu Chen: DeBERTa: Decoding-enhanced Bert With Disentangled Attention, 9th International Conference on Learning Representations (May 2021), Poster 03-2562.
[6]
https://colab.research.google.com[7]
安岡孝一: Universal Dependencies にもとづく多言語係り受け可視化ツール deplacy, 人文科学とコン
ピュータシンポジウム「じんもんこん 2020」論文集 (2020 年 12 月), pp.95-100.
[8]https://koichiyasuoka.github.io/deplacy/#templates-for-google-colaboratory[9]
Lucien Tesnière: Éléments de Syntaxe Structurale, Paris: C. Klincksieck (1959).
[10]
Igor A. Mel’čuk: Dependency Syntax: Theory and Practice, New York: State University of New York Press(1988).

–5–

表 1: deplacy に接続可能な各言語の係り受け解析ツール (2024 年 8 月 30 日現在)
アフリカーンス語
アイヌ語
アラビア語
ベラルーシ語
ブルガリア語
カタルーニャ語
コプト語
チェコ語
ウェールズ語
デンマーク語
ドイツ語
ギリシア語
英語
スペイン語
エストニア語
バスク語
ペルシア語
スオミ語
フェロー語
フランス語
ゲール語 (アイルランド)
ゲール語 (スコットランド)
ガリシア語
古典ギリシア語
ヘブライ語
ヒンディー語
クロアチア語
ハンガリー語
アルメニア語
インドネシア語
アイスランド語
イタリア語
日本語
カザフ語
韓国語
ラテン語
リトアニア語
ラトビア語
古典中国語
マケドニア語
マルタ語
ノルウェー語 (ブークモール)
ノルウェー語 (ニーノルスク)
オランダ語
ポーランド語
ポルトガル語
ルーマニア語
ロシア語
スロバキア語
スロベニア語
セルビア語 (キリル)セルビア語 (ラテン)スウェーデン語
タミル語
タイ語
タガログ語
トルコ語
ウクライナ語
ベトナム語
ウォロフ語
中国語 (簡化字)
中国語 (繁體字)Camphr-Udify, UDPipe 2, Trankit, spaCy-jPTDP, Stanza, spacy-udpipe
esuparTrankit, UDPipe 2, spacy-udpipe, Stanza, spaCy-jPTDP
Camphr-Udify, Stanza, Trankit, UDPipe 2
Trankit, Camphr-Udify, UDPipe 2, CLASSLA, Stanza, spaCy-jPTDP, spacy-udpipe
Camphr-Udify, Stanza, spacy-udpipe, Trankit, UDPipe 2, spaCy, spaCy-jPTDP
esupar, spaCy-Coptic, UDPipe 2, StanzaCamphr-Udify, spaCy-jPTDP, Trankit, UDPipe 2, spacy-udpipe, Stanza
UDPipe 2, Stanza, Camphr-Udify
Camphr-Udify, UDPipe 2, Stanza, Trankit, spaCy, spacy-udpipe, spaCy-jPTDP
Camphr-Udify, Stanza, UDPipe 2, spaCy-jPTDP, NLP-Cube, spacy-udpipe, Trankit, spaCy など
Stanza, UDPipe 2, Trankit, spacy-udpipe, NLP-Cube, spaCy-jPTDP, Camphr-Udify, spaCy など
Camphr-Udify, Stanza, UDPipe 2, NLP-Cube, Trankit, spacy-udpipe, spaCy-jPTDP
Stanza, UDPipe 2, NLP-Cube, spaCy, spacy-udpipe, Trankit, Camphr-Udify, spaCy-jPTDP など
Stanza, spacy-udpipe, EstMalt, spaCy-jPTDP, UDPipe 2, Trankit, Camphr-Udify
Trankit, Stanza, spacy-udpipe, Camphr-Udify, spaCy-jPTDP, UDPipe 2
Stanza, spaCy-jPTDP, spacy-udpipe, Trankit, Camphr-Udify, UDPipe 2 など
Stanza, UDPipe 2, spacy-udpipe, spacy-fi, Trankit, Camphr-Udify, spaCy-jPTDP
UDPipe 2, Stanza
spaCy, Stanza, UDPipe 2, Trankit, spacy-udpipe, Camphr-Udify, NLP-Cube, spaCy-jPTDP など
Stanza, UDPipe 2, Trankit, spacy-udpipe, spaCy-jPTDP, Camphr-Udify
Stanza, UDPipe 2, Trankit
Camphr-Udify, Stanza, spaCy-jPTDP, Trankit, UDPipe 2
Camphr-Udify, UDPipe 2, spaCy-jPTDP, Stanza, Trankit, spacy-udpipe
Trankit, HebPipe, Stanza, spaCy-jPTDP, UDPipe 2, spacy-udpipe
UDPipe 2, Trankit, Stanza, spaCy-jPTDP, spacy-udpipe, Camphr-Udify
UDPipe 2, Trankit, Camphr-Udify, Stanza, CLASSLA, spaCy, spaCy-jPTDP, spacy-udpipe
Trankit, UDPipe 2, Camphr-Udify, HuSpacy, spacy-udpipe, Stanza, spaCy-jPTDP, NLP-Cube
Stanza, Camphr-Udify, Trankit, UDPipe 2, spacy-udpipe
Stanza, Trankit, spacy-udpipe, Camphr-Udify, UDPipe 2, spaCy-jPTDP
Stanza, UDPipe 2, is ud is pud
NLP-Cube, Trankit, Camphr-Udify, Stanza, spaCy, UDPipe 2, spaCy-jPTDP など
spaCy-SynCha, spaCy-ChaPAS, UniDic-COMBO, spaCy, GiNZA, UDPipe 2, Stanza, UniDic2UD など
Camphr-Udify, Trankit, Stanza, NLP-Cube, kazdet
Camphr-Udify, Stanza, UDPipe 2, Trankit, spaCy-jPTDP, spacy-udpipe, Stanza
Trankit, Stanza, UDPipe 2, spacy-udpipe, Camphr-Udify, spaCy-jPTDP
spaCy, Trankit, Stanza, Camphr-Udify, UDPipe 2, spacy-udpipe
Camphr-Udify, Trankit, UDPipe 2, Stanza, spacy-udpipe, spaCy-jPTDP
SuPar-Kanbun, UD-Kanbun, GuwenCOMBO, UD-Chinese, Trankit, esupar, Stanza, UDPipe 2 など
bert-base-slavic-cyrillic-upos, Camphr-Udify, spaCy
Stanza, UDPipe 2, Camphr-Udify
Stanza, Camphr-Udify, UDPipe 2, Trankit, spaCy-jPTDP, spaCy
Stanza, spacy-udpipe, spaCy-jPTDP, UDPipe 2, Trankit
spaCy-Alpino, Camphr-Udify, Stanza, UDPipe 2, Trankit, spacy-udpipe, spaCy, spaCy-jPTDP など
spaCy, Camphr-Udify, Stanza, UDPipe 2, spacy-udpipe, Trankit, COMBO-NLP, spaCy-jPTDP など
spaCy, Camphr-Udify, Stanza, spaCy-jPTDP, UDPipe 2, spacy-udpipe, Trankit
UDPipe 2, Trankit, NLP-Cube, Camphr-Udify, spaCy, Stanza, spaCy-jPTDP, spacy-udpipe
Stanza, Trankit, Camphr-Udify, UDPipe 2, NLP-Cube, spaCy, spacy-udpipe, spaCy-jPTDP など
Camphr-Udify, UDPipe 2, Trankit, spacy-udpipe, NLP-Cube, Stanza, spaCy-jPTDP
CLASSLA, UDPipe 2, spacy-udpipe, Camphr-Udify, Trankit, spaCy-jPTDP, Stanza
esupar, Camphr-Udify
CLASSLA, UDPipe 2, Trankit, Camphr-Udify, esupar, Stanza, spacy-udpipe, spaCy-jPTDP
Camphr-Udify, Trankit, Stanza, UDPipe 2, spacy-udpipe, spaCy-jPTDP
Camphr-Udify, Trankit, UDPipe 2, spacy-udpipe, Stanza
esupar, spaCy-Thai
Camphr-Udify, ud-tagalog-spacy
Stanza, spaCy-jPTDP, tr core news trf, Camphr-Udify, UDPipe 2, spacy-udpipe, Trankit
Stanza, NLP-Cube, Camphr-Udify, UDPipe 2, Trankit, spacy-udpipe, spaCy-jPTDP など
Trankit, Stanza, esupar, spaCy-jPTDP, UDPipe 2, spacy-udpipe など
UDPipe 2, Stanza
Trankit, Stanza, UDPipe 2, NLP-Cube, esupar, spacy-udpipe, UD-Chinese, spaCy
Trankit, Stanza, UDPipe 2, esupar, NLP-Cube, spacy-udpipe, UD-Chinese, spaCy–6–表 2: CoNLL-U の各フィールド

1. ID: 単語ごとに付与されたインデックスで、文ごとに 1 から始まる整数。縮約語に対しては、単語の範囲を示すのも可。
2. FORM: 語、または、句読記号。
3. LEMMA: 基底形、語幹。
4. UPOS: UD で規定された言語普遍な品詞タグ (表 3)。
5. XPOS: 言語固有の品詞タグ。
6. FEATS: UD で規定された言語普遍な形態素属性のリスト。言語固有の拡張も可。
7. HEAD: 当該の単語の係り受け元 ID。係り受け元が無い場合は 0 とする。
8. DEPREL: UD で規定された言語普遍な係り受けタグ (表 4)。HEAD が 0 の場合はroot とする。言語固有の拡張も可。
9. DEPS: 複数の係り受け元を持つ場合、全ての HEAD:DEPREL ペア。
10. MISC: その他のアノテーション。

表 3: UD 品詞タグ (UPOS)
Open class words
ADJ 形容詞
ADV 副詞INTJ 感嘆詞
NOUN 名詞PROPN 固有名詞
VERB 動詞Closed class words
ADP 側置詞
AUX 助動詞CCONJ 並列接続詞
DET 限定詞
NUM 数詞PART 接辞
PRON 代名詞SCONJ 従属接続詞

Other
PUNCT 句読点
SYM 記号
X その他

表 4: UD 係り受けタグ (DEPREL)

Core
arguments
Non-coredependents

Modifier
Words

Function
Words

advcl 連用修飾節

advmod 連用修飾語
discourse 談話要素

aux 動詞補助成分
cop 繫辞mark 標識

NominalsClausesnsubj 主語
obj 目的語
iobj 間接目的語
obl 斜格補語
vocative 呼称語
expl 形式語
dislocated 外置語

csubj 節主語
ccomp 節目的語
xcomp 節補語

Nominaldependents

nmod 体言による連体修飾語
appos 同格
nummod 数量による修飾語

acl 連体修飾節

amod 用言による連体修飾語

det 決定語
clf 類別語
case 格表示

Coordination

MWE

Loose

SpecialOther

conj 接続
cc 接続語

fixed 固着
flat 並列compound 複合

list 細目
parataxis 隣接表現

orphan 親なし
goeswith 泣き別れ
reparandum 言い損じ

punct 句読点
root 親dep 未定義–7–

# text = 人莫知其子之惡
1
人
人
NOUN
2
莫
莫
ADV
3
知
知
VERB
4
其
其
PRON
5
子
子
NOUN
6
之
之
SCONJ
7
惡
惡
NOUN

n,名詞,人,人
v,副詞,否定,禁止
v,動詞,行為,動作n,代名詞,人称,起格
n,名詞,人,関係
p,助詞,接続,属格
n,名詞,描写,態度

_
_
_
_
_
_
_

3
3
0
5
7
5
3

nsubj
advmod
root
det
nmod
case
obj

_
_
_
_
_
_
_

SpaceAfter=NoSpaceAfter=NoSpaceAfter=NoSpaceAfter=NoSpaceAfter=NoSpaceAfter=NoSpaceAfter=No# text = 人は其の子の悪しきを知らない
1
人
人
NOUN
名詞-普通名詞-一般
2
は
は
ADP
助詞-係助詞
3
其の
其の
DET
連体詞
4
子
子
NOUN
名詞-普通名詞-一般
5
の
の
ADP
助詞-格助詞
6
悪しき悪しい ADJ
形容詞-一般7ををADP
助詞-格助詞
8
知ら
知る
VERB
動詞-一般
9
ない
ない
AUX
助動詞

_
_
_
_
_
_
_
_
_

8
1
4
6
4
8
6
0
8

nsubj
case
det
nsubj
case
ccomp
case
root
aux

_
_
_
_
_
_
_
_
_

SpaceAfter=NoSpaceAfter=NoSpaceAfter=NoSpaceAfter=NoSpaceAfter=NoSpaceAfter=NoSpaceAfter=NoSpaceAfter=NoSpaceAfter=No# text = A man doesn’t know the evil of his son
1
A
a
DET
DT
_
2
man
man
NOUN
NN
_
3-4 doesn’t _
_
_
_
3
does
do
AUX
VBZ
_
4
n’t
not
PART
RB
_
5
know
know
VERB
VB
_
6
the
the
DET
DT
_
7
evil
evil
NOUN
NN
_
8
of
of
ADP
IN
_
9
his
he
PRON
PRP$
_
10
son
son
NOUN
NN
_

2
5
_
5
5
0
7
5
10
10
7

det
nsubj
_
aux
advmod
root
det
obj
case
det
nmod

_
_
_
_
_
_
_
_
_
_
_

_
_
_
SpaceAfter=No
_
_
_
_
_
_
SpaceAfter=No

root
obj
nsubj
advmod

nmod
case

det

NOUN

ADV

VERB

PRON

NOUN

SCONJ

NOUN

n,名詞,人,人

v,副詞,否定,禁止

v,動詞,行為,動作n,代名詞,人称,起格

n,名詞,人,関係

p,助詞,接続,属格

n,名詞,描写,態度

人

莫

知

其

子

之

惡
root

nsubj
case

nsubj
case

det

ccomp
case

aux

NOUN

ADP

DET

NOUN

ADP

ADJ

ADP

VERB

AUX

名詞-普通名詞-一般

助詞-係助詞

連体詞

名詞-普通名詞-一般

助詞-格助詞

形容詞-一般

助詞-格助詞

動詞-一般

助動詞

人

は

其の

子

の

悪しき を

知ら ない

root
nsubj
aux
det

nmod
case

obj
advmod

det

det

DET

NOUN

AUX

PART

VERB

DET

NOUN

ADP

PRON

NOUN

DT

NN

VBZ

RB

VB

DT

NN

IN

PRP$

NN

evil

of

his

son

A

man doesn’t know the図 1: 漢日英 CoNLL-U と deplacy による可視化–8–

UD 係り受けコーパスの交換用フォーマットとして、CoNLL-U と呼ばれるタブ区切りテ
キスト (文字コードは UTF-8[11] ) が規定されています。CoNLL-U の各行は各単語に対応していて、表 2 に示す 10 個のタブ区切りフィールドで構成されます。ID・FORM・LEMMA
は、単語そのものに関するフィールドです。UPOS・XPOS・FEATS は、単語の品詞と形態素属性に関するフィールドです。HEAD・DEPREL・DEPS は、単語の係り受けに関す
るフィールドです。
UD における係り受け関係は、単語間の有向グラフを HEAD と DEPREL で記述します。
HEAD は、その単語に入る有向枝のリンク元 ID を示していて、DEPREL は、その有向枝における係り受けタグです。ただし、HEAD が 0 の場合、その枝に入るリンク元は存在しません。リンクの本数は単語の個数に等しく、各リンクのリンク先は、全て互いに異なっています。すなわち、各単語から出るリンクは複数の可能性がありますが、各単語に入るリンクは 1 つだけなのです。なお、リンクはループしません。
UD の係り受けリンクは、Мельчук 依存文法の後裔にあたり、いわゆる動詞中心主義です。動詞をリンク元として、主語や目的語へとリンクします。修飾関係においては、被修飾語から修飾語へとリンクします。ただし、側置詞 (前置詞や後置詞) を体言の修飾語だとみなす点[12] が、Мельчук とは異なっています。また、コピュラ文においては動詞中心主義を採らず、補語をリンク元として、主語や繫辞へとリンクします。
UD の言語横断性を示す実際例として、古典中国語 (漢文)「人莫知其子之惡」と日本語
文「人は其の子の悪しきを知らない」と英文「A man doesn’t know the evil of his son」のCoNLL-U を、図 1 で比較してみましょう。これらの CoNLL-U は、各言語 UD を横目に手作業で書いたもので、FEATS・DEPS は使用していません。可視化には deplacy を用いています。漢日英で語順は異なっているものの、nsubj (主語) と nmod(体言による連体修飾語)、obj (目的語) と ccomp(節目的語) のリンクが、それぞれに対応していると言えます。
また、コピュラ文に対する UD の例として、露文「Это ручка」と仏文「C’est un stylo」と日本語文「これはペンです」の CoNLL-U を、図 2 で比較してみましょう。露仏日のいずれにおいても、補語から主語へ nsubj が繫がれていて、それぞれに対応していると言えます。なお、仏日においては、繫辞が cop で繫がれています。

1.2 依存文法理論と Universal Dependencies
UD の係り受け構造は、Мельчук の有向グラフ記述を理論的支柱としながらも、実践面では Reed-Kellogg の文法構造[13] を取り入れています。このあたりについて、簡単に紹介
しておきましょう。
述語
目的語 という構造を基本に、英文を視
Reed-Kellogg 文法構造図は、 主語
覚化します。主文 (main sentence) を太線で、それ以外の節 (clause) を細線で視覚化した
上に、修飾語を斜線に載せて示します。たとえば英文「Those who labour with their minds[11]

ISO/IEC 10646-1:1993/Amd.2:1996 Information Technology — Universal Multiple-Octet Coded Character
Set (UCS) — Part 1: Architecture and Basic Multilingual Plane, Amendment 2: UCS Transformation Format 8(UTF-8), International Organization for Standardization, Genève (October 15, 1996).
[12]
Joakim Nivre: Towards a Universal Grammar for Natural Language Processing, CICLing 2015: 16th International Conference on Intelligent Text Processing and Computational Linguistics (April 2015), pp.3-16.
[13]
Alonzo Reed and Brainerd Kellogg: Higher Lessons in English: A Work on English Grammar and Composition, New York: Clark & Maynard (1877).

–9–

# text = to ruqka
1
to
to
2
ruqka
ruqka

PRON
NOUN

_
_

_
_

2
0

nsubj
root

_
_

_
SpaceAfter=No# text = C’est un stylo
1
C’
ce
PRON
2
est
e
^tre
AUX
3
un
un
DET
4
stylo
stylo
NOUN

_
_
_
_

_
_
_
_

4
4
4
0

nsubj
cop
det
root

_
_
_
_

SpaceAfter=No__SpaceAfter=No# text = これはペンです
1
これ
此れ
PRON
2
は
は
ADP
3
ペン
ペン
NOUN
4
です
です
AUX

代名詞
助詞-係助詞
名詞-普通名詞-一般
助動詞

_
_
_
_

3
1
0
3

nsubj
case
root
cop

_
_
_
_

SpaceAfter=NoSpaceAfter=NoSpaceAfter=NoSpaceAfter=No

root
nsubj
PRON

NOUN

Это ручка
root
nsubj
cop
det
PRON

AUX

DET

NOUN

C’

est

un

stylo

root
nsubj
case

cop

PRON

ADP

NOUN

AUX

代名詞

助詞-係助詞

名詞-普通名詞-一般

助動詞

これ

は

ペン です

図 2: コピュラ文の CoNLL-U と deplacy による可視化

Those

rule

who

labourothers

h
wit

minds
ir
the

図 3: Reed-Kellogg 文法構造図– 10 –

rule others」に対しては、「Those rule others」という主文の「Those」を、「who labour」という節が修飾していて、その「labour」を「with minds」が修飾し、「minds」を「their」
が修飾していることから、図 3 のようになります。Reed-Kellogg 文法構造図は、英語に特化して設計されているので、必ずしも他の言語には適用できません。
Tesnière は、スラブ諸語の研究を通して、のちに依存文法と呼ばれる言語横断的な記述手法を発案しました。文に現れる語は互いに依存関係にある、というのが、依存文法の基本的な考え方です。語と語の間の依存関係においては、上位項 (régissant) が下位項
(subordonné) を支配し、下位項が上位項に依存します。たとえば英文「Those who labour
with their minds rule others」であれば、rule が Those と others を支配し、Those と others
が rule に依存します。ただし、転用がおこなわれている場合は、それらの語の間には依存関係は無く、並置する形で表現します。たとえば図 4 左では、名詞 minds が with によって E 転用 (連用修飾語に転用) されており、あるいは動詞 labour が who によって A 転用
(連体修飾語に転用) されています。
Tesnière の依存文法は、文における語の順序に関わらず、語の依存関係を記述するので、たとえば古典中国語にも応用可能です。すなわち「勞心者治人」であれば、「心」が「勞」に依存し、「勞」が「者」によって O 転用 (体言に転用) され「治」に依存します。
これを図 4 右のように図示すれば、「Those who labour with their minds rule others」との間で、言語をまたいだ比較も可能となるのです。
rule
治
Those

othersOA勞

who labour
E

者

人

心

with minds
their

図 4: Tesnière 依存文法図

Tesnière の依存文法は、その後、Robinson[14] や Hudson[15] らにより、Chomsky 句構造文
法[16] との融合が試みられました。一方Мельчук は、語の依存関係の有向グラフ記述によって依存文法の形式化をおこない、Chomsky 句構造文法と決別しました。
Мельчук の依存文法は、文中の語 X と Y に対し、依存関係 X→Y によって文を記述します。X→Y は、X は Y を支配する、あるいは、Y は X に依存する、と読みます。各矢印には、依存関係に関する適切なタグが付与されます。各語が依存する語は高々1 つであり、依存関係はループしません。依存関係は、あくまで語と語の間の記述で、それがたとえ節(clause) や句 (phrase) に係るものであっても、割り切って語と語の関係として記述します。
この「割り切り」の結果として、Мельчук の依存文法は、言語横断的な文法構造記述と[14]

Jane J. Robinson: Dependency Structures and Transformational Rules, Language, Vol.46, No.2 (June 1970),
pp.259-285.
[15]
Richard Hudson: Word Grammar, New York: Basil Blackwell (1984).
[16]
Noam Chomsky: Aspects of the Theory of Syntax, Cambridge: MIT Press (1965).

– 11 –

RULE act,pressubjectival

direct-objectival

THAT plOTHER plmodificative

治める

LABOUR act,pressubjectival

WHO nom

adverbial

WITH
prepositional

MIND pldeterminative

THEY poss治

subjectival

direct-objectival

者+は

人+を

modificative

subjectival

direct-objectival者人

modificative

労する勞

direct-objectival

direct-objectival

心+を心

図 5: Мельчук の依存文法による文法構造記述
なっています。英文「Those who labour with their minds rule others」と、日本語文「心を労する者は人を治める」と、古典中国語 (漢文)「勞心者治人」に対して、Мельчук の依存文法による文法構造記述を、図 5 に示します。ただし、タグのうち subjectival と directobjectival は、過去には predicative と 1st completive が用いられており、Мельчук 自身
も、タグが何種類必要なのかは明らかにしていません[17] 。
UD の係り受け構造は、Мельчук の依存文法におけるタグを、表 4 の 37 種類に限定する野心的な試み、として捉えることができます。図 5 での subjectival・direct-objectival・
modificative・determinative が、図 6 では nsubj・obj・acl・det になった、と考えることもできます。ただ、UD の前身にあたる Stanford Typed Dependencies[18] が、初期には
Bresnan 語彙機能文法[19] からスタートしており、その後に依存文法へとシフトしたことか
ら、いくつか不思議な概念が紛れ込んでしまっています。その一つが、節 (clause) です。
節という概念を、Мельчук は依存文法から刪除したのですが、これを UD は再導入してしまいました。表 4 の nsubj と csubj は、いずれも主語を表す UD 係り受けタグであり、リンク先が節なら csubj を、さもなくば nsubj を使います。obj と ccomp についても同様、advmod と advcl についても同様、amod と acl についても同様です。case と markについては、リンク元が節なら mark を、さもなくば case を使います[20] 。
英語における節という概念は、一定のコンセンサスが得られていると考えられます。しかし、他の言語において、節という概念は、必ずしも自明ではありません。UD は言語横断的ではあるものの、かなり英語寄りである、という点は意識しておくべきでしょう。

[17]

Alain Polguère, Igor A. Mel’čuk: Dependency in Linguistic Description, Amsterdam: John Benjamins(2009).
[18]
Marie-Catherine de Marneffe and Christopher D. Manning: The Stanford Typed Dependencies Representation, Coling 2008: Proceedings of the Workshop on Cross-Framework and Cross-Domain Parser Evaluation(August 2008), pp.1-8.
[19]
Joan Bresnan: Lexical-Functional Syntax, Malden: Blackwell (2001).
[20]
Marie-Catherine de Marneffe, Timothy Dozat, Natalia Silveira, Katri Haverinen, Filip Ginter, Joakim Nivre,
Christopher D. Manning: Universal Stanford Dependencies: A Cross-Linguistic Typology, Proceedings of the
9th International Conference on Language Resources and Evaluation (May 2014), pp.4585-4592.

– 12 –

# text = Those who labour with their minds rule others
1
Those
that
PRON DT
_
7
2
who
who
PRON WP_
3
3
labour labour VERB VBP
_
1
4
with
with
ADP
IN
_
6
5
their
they
PRON PRP$
_
6
6
minds
mind
NOUN NNS$
_
3
7
rule
rule
VERB VBP_
0
8
others other
NOUN NNS
_
7

nsubj
nsubj
acl
case
det
obl
root
obj

_
_
_
_
_
_
_
_

_
_
_
_
_
_
_
SpaceAfter=No# text = 心を労する者は人を治める1
心心
NOUN 名詞-普通名詞-サ変可能
2
を
を
ADP
助詞-格助詞3
労する 労する VERB 動詞-一般
4
者
者
NOUN 名詞-普通名詞-一般
5
は
は
ADP
助詞-係助詞6
人
人
NOUN 名詞-普通名詞-一般
7
を
を
ADP
助詞-格助詞8
治める 治める VERB 動詞-一般

_
_
_
_
_
_
_
_

3
1
4
8
4
8
6
0

obj
case
acl
nsubj
case
obj
case
root

_
_
_
_
_
_
_
_

SpaceAfter=NoSpaceAfter=NoSpaceAfter=NoSpaceAfter=NoSpaceAfter=NoSpaceAfter=NoSpaceAfter=NoSpaceAfter=No# text = 勞心者治人
1
勞
勞
2
心
心
3
者
者
4
治
治
5
人
人

_
_
_
_
_

3
1
4
0
4

acl
obj
nsubj
root
obj

_
_
_
_
_

SpaceAfter=NoSpaceAfter=NoSpaceAfter=NoSpaceAfter=NoSpaceAfter=No

VERB
NOUN
PART
VERB
NOUN

v,動詞,描写,境遇
n,名詞,不可譲,身体
p,助詞,提示,*v,動詞,行為,動作
n,名詞,人,人

root
nsubj
obl
acl

case
nsubj

det

obj

PRON

PRON

VERB

ADP

PRON

NOUN

VERB

NOUN

DT

WP

VBP

IN

PRP$

NNS

VBP

NNS

Those who labour with their minds rule others
root
nsubj
obj

obj

case

acl

case

case

NOUN

ADP

VERB

NOUN

ADP

NOUN

ADP

VERB

名詞-普通名詞-サ変可能

助詞-格助詞

動詞-一般

名詞-普通名詞-一般

助詞-係助詞

名詞-普通名詞-一般

助詞-格助詞

動詞-一般

心

を

は

人

を

治める

労する 者
acl

root

obj

nsubj

obj

VERB

NOUN

PART

VERB

NOUN

v,動詞,描写,境遇

n,名詞,不可譲,身体

p,助詞,提示,*v,動詞,行為,動作

n,名詞,人,人

勞

心

者

治

人

図 6: UD と CoNLL-U による係り受け構造記述– 13 –

1.3

BERT/RoBERTa/DeBERTa モデルと穴埋めゲーム

Google AI Language が発表した BERT[3] は、大量の文章を機械に丸暗記させる際にどのような手法が有効なのかを、端的に示した事前学習モデルです。単純に文章を丸暗記するのではなく、文章中に現れる文と文の繫がり、あるいは、文中に現れるトークン (単語もしくは単語より短い文字列) とトークンの繫がりを、効果的に学習できるような工夫が詰め込まれています。
トークンとトークンの繫がりを学習するために用いられるのが、穴埋めゲームです。
「This [MASK] a pen.」の [MASK] に対し、
「This is a pen.」という答を得るような穴埋め
ゲーム (図 7) を考えてみましょう。bert-base-cased[21] においては、各トークンの入出力は文字コード (UTF-8) でおこなわれますが、内部的には 768 次元のベクトル (数値の列) で表現されます。入力側においては、各入力トークンに対応するベクトルをそのまま用いており、出力側においては、各出力トークンに近い[22] ベクトルになるように学習をおこないます。「This [MASK] a pen.」の例で言えば、「This」「a」「pen」「.」は入力ベクトル
をほぼ素通ししつつ、「is」に近い出力ベクトルが得られるよう、内部の記憶素子をいじるわけです。このような穴埋めゲームを大量の文に対しておこなうことで、トークンとトークンの繫がりを学習[23] できるというのが、BERT の工夫の一つ[24] です。
This [MASK]
?

?

a

pen

.

?

?

?

bert-base-cased
?

This

?

is

?

a

?

pen

?

.

図 7: bert-base-cased における穴埋めゲーム

Google Colaboratory 上の Transformers[25] を使って、bert-base-cased が英文をどのぐらい学習できているのか、試してみましょう (図 8)。
「This [MASK] a pen.」を穴埋めさせてみると、「was」が 48.2%、「is」が 40.2%となっており、出力されているベクトルが「was」と「is」の中間で、やや「was」に近いことがわかります。
[21]

https://huggingface.co/bert-base-cased
ここでいう「近い」は、コサイン類似度 (2 つのベクトルの内積を、ベクトルのユークリッド・ノルムで割った値) が 1 に近い、という意味です。
[23]
bert-base-cased の内部では、穴埋め用の [MASK] に加えて、文頭を表す [CLS]、文の切れ目を表す [SEP]、
未知語を表す [UNK]、空きトークンを表す [PAD] なども用いられます。
[24]
BERT のもう一つの工夫は、文と文の繫がりを学習する隣接文ゲームですが、本書では扱いません。
[25]
Thomas Wolf, Lysandre Debut, Victor Sanh, Julien Chaumond, Clement Delangue, Anthony Moi, Pierric
Cistac, Tim Rault, Rémi Louf, Morgan Funtowicz, Joe Davison, Sam Shleifer, Patrick von Platen, Clara Ma,
Yacine Jernite, Julien Plu, Canwen Xu, Teven Le Scao, Sylvain Gugger, Mariama Drame, Quentin Lhoest,
Alexander M. Rush: Transformers: State-of-the-Art Natural Language Processing, Proceedings of the 2020
Conference on Empirical Methods in Natural Language Processing (October 2020): System Demonstrations,pp.38-45.
[22]– 14 –

!pip install transformers
from transformers import pipeline
fmp=pipeline("fill-mask","bert-base-cased")
prd=fmp("This [MASK] a pen.")print("\n".join("{:8} {:.3f}".format(t["token_str"],t["score"]) for t in prd))

was
is
from
had
has

0.482
0.402
0.008
0.007
0.007

図 8: 「This [MASK] a pen.」に対する穴埋めゲームプログラムと結果

BERT を多言語拡張する際に問題となるのは、モデルの入出力に文という単位を仮定している点です。言語によっては (たとえば古典中国語においては)、文という単位は必
ずしも明確ではありません。あるいは SNS での「つぶやき」など、文境界がハッキリしない例は多くあります。これに対し RoBERTa[4] や DeBERTa[5] は、文という単位を仮定せず、トークンの並びを用いて、穴埋めゲームのみに特化した学習をおこないます。これにより、文という単位に捉われることなく、大量の文章を丸暗記できるのです。
roberta-classical-chinese-base-char[26] は、古典中国語における漢字をトークンとみなし、漢字単位での穴埋めゲーム (図 9) を学習したモデルです。各漢字 (約 26000 字種) の入出
力は UTF-8 ですが、内部的には 768 次元のベクトルで表現します。Google Colaboratory
上の Transformers で「勞 [MASK] 者治人」を穴埋めするプログラムと、その結果を図 10に示します。「心」が 19.9%となっていて、「人」の 32.7%に負けているのがわかります。
BERT・RoBERTa・DeBERTa などの事前学習モデルは、出力部を付け替えることで、様々な用途に応用可能です。出力ベクトルを品詞情報だとみなせば、品詞付与に使えます。係り受けタグだとみなせば、係り受け解析に使えます。UD においては、系列ラベリ
ングや係り受け解析に、事前学習モデルを応用することができます。
勞[MASK]

者

治

人

?

?

?

?

?

roberta-classical-chinese-base-char
?

勞

?

心

?

者

?

治

?

人

図 9: roberta-classical-chinese-base-char における穴埋めゲーム[26]

https://huggingface.co/KoichiYasuoka/roberta-classical-chinese-base-char– 15 –

!pip install transformers
from transformers import pipeline
fmp=pipeline("fill-mask","KoichiYasuoka/roberta-classical-chinese-base-char")
prd=fmp("勞[MASK]者治人")
print("\n".join("{:8} {:.3f}".format(t["token_str"],t["score"]) for t in prd))

人
心
民
神
神

0.327
0.199
0.129
0.054
0.047
図 10: 「勞 [MASK] 者治人」に対する穴埋めゲームプログラムと結果

1.4

Universal Dependencies における係り受け解析

係り受け解析は、UD による言語処理の「キモ」であり、多くの解析アルゴリズムが乱立しています。これらの係り受け解析アルゴリズムを、状態遷移型アルゴリズムと隣接行列型アルゴリズムに分けて、概説します。
arc-swap[27] に代表される状態遷移型アルゴリズムは、単語列の先頭から末尾に向かって「垣根」(stack-buffer boundary) を移動していく、というイメージで処理をおこないます。「垣根」がおこなう遷移は、以下の 6 種類に定式化されます。

• Shift 「垣根」を右に 1 単語分、移動する。
• Reduce 「垣根」のすぐ左の単語を除去して、解析結果へ移す。
• Left-Arc 「垣根」のすぐ右の単語から、すぐ左の単語へリンクを繫ぐ。
• Right-Arc 「垣根」のすぐ左の単語から、すぐ右の単語へリンクを繫ぐ。
• Unshift 「垣根」を左に 1 単語分、移動する。
• Swap 「垣根」のすぐ右の単語と、すぐ左の単語を入れ替える。
単語が全て Reduce されて、「垣根」がポツンと取り残された時点で、状態遷移型アルゴ
リズムは終了です。解析例を図 11 に示します。解析結果において、入るリンクがない単語に対しては、通常は root を割り当てます。なお、6 種類のうち Unshift・Swap を実装しない場合は、リンクに交差がある UD を扱えません。また、現実の実装においては、
Left-Arc の直後には Reduce を、Right-Arc の直後には Shift と Reduce を、それぞれまとめて遷移させる手法が主流です。
Biaffine[28] に代表される隣接行列型アルゴリズムは、UD 依存構造を有向グラフとみなし、その隣接行列を求めます。たとえば、図 11 右下「Who did you wait for?」の有向グ
ラフであれば[27]

Joakim Nivre: Non-Projective Dependency Parsing in Expected Linear Time, Proceedings of the Joint Conference of the 47th Annual Meeting of the ACL and the 4th International Joint Conference on Natural Language
Processing of the AFNLP (August 2009), pp.351-359.
[28]
Timothy Dozat, Christopher D. Manning: Deep Biaffine Attention for Neural Dependency Parsing, 5th International Conference on Learning Representations (April 2017), C25.

– 16 –

|


Who

did

you

wait

for

?

Who | did

you

wait

for

?

Who

did | you

wait

for

?

Who

did

you | wait

for

?

for

?

Shift
Shift
Shift
Left-Arcnsubj

you | wait

Who

did

Who

did | wait

ReduceLeft-Arc

for

?

for

?

aux

did | wait

Who
ReduceWho | wait

for

?

Who

wait | for?

Whofor | wait

?

Shift
Swap
Unshift

Who | for
Right-Arc

wait

?

wait

?

for | wait

?

case

Who | for
Shift

case

Who
ReduceWho | wait
Left-Arc?

obl

Who | wait?

Reduce
|


wait

?

Shift

wait | ?
Right-Arc

punctwait | ?
Shift

punct

wait

?

|


Reducewait |Reduce
|


root
case
obl
aux
nsubj

Who didpunct

you waitfor?

図 11: 状態遷移型アルゴリズムによる「Who did you wait for?」の係り受け解析– 17 –

⎡

−
⎢ −
⎢
⎢ −
⎢
⎢ obl
⎢
⎣ −
−

⎤
−
−
− case −
−
−
−
−
− ⎥
⎥
−
−
−
−
− ⎥
⎥
aux nsubj root − punct⎥
⎥
−
−
−
−
− ⎦
−
−
−
−
−

という 6×6 の隣接行列を求めます (図 12)。具体的には、隣接行列の各列ごとに要素を1 つ選びつつ、対角成分上の root から 1 つを選ぶ、というのを確率的におこないます。
ただ、ループが発生してしまう場合があるので、適宜 Chu-Liu-Edmonds[29][30] 等を使ってループを解消します。

Who

did

you

wait

for

root

acl

conj

acl

case punct

nsubj

root

obj

ccomp

nsubj csubj

root

acl

case punct

obl

nsubj

root

fixed punct

aux

?

punct

root

punct
root

図 12: 隣接行列型アルゴリズムによる「Who did you wait for?」の係り受け解析
状態遷移型アルゴリズムは、BERT・RoBERTa・DeBERTa などの事前学習モデルを用いる
ことで精度向上が期待できる[31] のですが、これは実装がかなり難しいのです。一方、隣接行列型アルゴリズムは、事前学習モデルとの相性が良く、実装もそこそこ簡単です。Google
Colaboratory 上の Transformers を使って、roberta-base-english-ud-goeswith[32] で「Who did
you wait for?」の隣接行列のロジット[33] を求めるプログラムと、その結果を図 13 に示します。図 13 の例では、各列ごとにロジット最大の要素を選ぶだけで、「Who did you waitfor?」の依存構造グラフを正しく導出できますが、現実の処理では Chu-Liu-Edmonds 等をおこなうことになります。
[29]

Chu Yoeng-jin (朱永津) and Liu Tseng-hong (刘振宏): On the Shortest Arborescence of a Directed Graph,
Scientia Sinica, Vol.XIV, No.10 (October 1965), pp.1396-1400.
[30]
Jack Edmonds: Optimum Branchings, Journal of Research of the National Bureau of Standards—B. Mathematics and Mathematical Physics, Vol.71B, No.4 (October-December 1967), pp.233-240.
[31]
Alireza Mohammadshahi, James Henderson: Graph-to-Graph Transformer for Transition-based Dependency
Parsing, Findings of the Association for Computational Linguistics: EMNLP 2020 (November 2020), pp.32783289.
[32]
https://huggingface.co/KoichiYasuoka/roberta-base-english-ud-goeswithp[33]
ラベルの生起確率を p とおくとき、ロジット (対数オッド) は log 1−pとなります。

– 18 –

!pip install transformers
import torch,numpy
from transformers import AutoTokenizer,AutoModelForTokenClassification
brt="KoichiYasuoka/roberta-base-english-ud-goeswith"
txt="Who did you wait for?"tkz=AutoTokenizer.from_pretrained(brt)
mdl=AutoModelForTokenClassification.from_pretrained(brt)v,l=tkz(txt,return_offsets_mapping=True),mdl.config.id2label
w=[t for t,(s,e) in zip(v["input_ids"],v["offset_mapping"]) if s<e]u=[txt[s:e] for s,e in v["offset_mapping"] if s<e]cls,msk,sep=tkz.cls_token_id,tkz.mask_token_id,tkz.sep_token_id
x=[[cls]+w[:i]+[msk]+w[i+1:]+[sep,j] for i,j in enumerate(w)]with torch.no_grad():m=mdl(input_ids=torch.tensor(x)).logits.numpy()[:,1:-2,:]
r=[1 if i==0 else -1 if l[i].endswith("|root") else 0 for i in range(len(l))]
m+=numpy.where(numpy.add.outer(numpy.identity(m.shape[0]),r)==0,0,numpy.nan)
g=mdl.config.label2id["X|_|goeswith"]
r=numpy.tri(m.shape[0])for i in range(r.shape[0]):for j in range(i+2,r.shape[1]):r[i,j]=r[i,j-1] if numpy.nanargmax(m[i,j-1])==g else 1m[:,:,g]+=numpy.where(r==0,0,numpy.nan)d,p=numpy.nanmax(m,axis=2),numpy.nanargmax(m,axis=2)
print(" ".join(x[:9].rjust(9) for x in u))
for i,j in enumerate(u):print("\n"+" ".join("{:9.3f}".format(x) for x in d[i])," ",j)print(" ".join(l[x].split("|")[-1][:9].rjust(9) for x in p[i]))

Who

did

you

wait

for

?

2.036
root

2.522
punct

3.163
punct

3.705
acl:relcl

12.105
case

8.971
punct

Who

3.170
obj

0.727
root

3.536
punct

2.851
xcomp

8.797
case

7.458
punct

did

3.715
obj

1.873
punct

0.808
root

4.100
parataxis

9.255
case

7.630
punct

you

11.452obl

14.337aux

14.130nsubj

15.159root

8.094
compound:15.684
punct

wait

5.232
obj

1.943
aux

2.694
punct

2.293
parataxis

2.099
root

7.492
punct

for

1.921
appos

1.544
nmod

2.072
punct

1.039
nmod

9.437
case

1.919
root

?

図 13: 「Who did you wait for?」に対する隣接行列ロジットの導出– 19 –

2 古典中国語 (漢文) 編
2.1 古典中国語 UD における品詞付与と文切り
古典中国語 (漢文) は、単語と単語の間に区切りがなく、文と文の間にも区切りがありません。これが、白文と呼ばれる古典中国語の書写形態であり、傍目には、漢字が連続的に並んでいるだけです。
古典中国語 UD における品詞付与は、端的に言えば、白文の各漢字に UPOS を付与する作業です。ただし、古典中国語における単語 (漢語) は 2 文字以上のものもあるので、その場合は、複数の漢字をまとめつつ UPOS を付与します。Transformers の系列ラベリン
グを用いるなら、1 文字の漢語に対しては UPOS をラベルとして付与し、2 文字以上の漢語に対しては、1 文字目に「B-」を付けた UPOS を、2 文字目以降に「I-」を付けた UPOS
を、それぞれ付与するやり方が考えられます。これにより原理的には、複数の漢字を漢語にまとめつつ、UPOS を付与することができます。

!pip install deplacy transformers
class SeqL(object):def __init__(self,bert):
from transformers import pipeline
self.tagger=pipeline(task="ner",model=bert)
def __call__(self,text):
w=[(t["start"],t["end"],t["entity"]) for t in self.tagger(text)]
u="# text = "+text.replace("\n"," ")+"\n"for i,(s,e,p) in enumerate(w,1):
m,q="_" if i<len(w) and e<w[i][0] else "SpaceAfter=No",p.split("|")
f="_" if p.find("=")<0 else "|".join(t for t in q if t.find("=")>0)
u+="\t".join([str(i),text[s:e],"_",q[0],"_",f,"_","_","_",m])+"\n"return u+"\n"nlp=SeqL("KoichiYasuoka/roberta-classical-chinese-base-upos")
doc=nlp("子曰學而時習之不亦説乎有朋自遠方來不亦樂乎人不知而不慍不亦君子乎")import deplacy
deplacy.serve(doc,port=None)

NOUN

VERB

VERB

CCONJ

NOUN

VERB

PRON

ADV

ADV

VERB

PART

子

曰

學

而

時

習

之

不

亦

説

乎

VERB

NOUN

ADP

VERB

NOUN

VERB

ADV

ADV

VERB

PART

NOUN

有

朋

自

遠

方

來

不

亦

樂

乎

人

ADV

VERB

CCONJ

ADV

VERB

ADV

ADV

B-NOUNI-NOUN

PART

不

知

而

不

慍

不

亦

君

子

乎

図 14: roberta-classical-chinese-base-upos による UPOS 付与– 20 –

Google Colaboratory 上の Transformers を用いて、roberta-classical-chinese-base-upos[34]で「子曰學而時習之不亦説乎有朋自遠方來不亦樂乎人不知而不慍不亦君子乎」に UPOSを付与するプログラムと、その結果を図 14 に示します。
「君子」が 2 文字の漢語であり、「君」に B-NOUN が、「子」に I-NOUN が付与されています。「君子」以外は漢字 1 字が漢語 1 語と判定されていて、それぞれに UPOS が付与されています。
Transformers の系列ラベリングは、他の用途にも適用できます。roberta-classical-chinesebase-sentence-segmentation[35] は、古典中国語の文切りに Transformers の系列ラベリングを用いています。具体的には、文頭の漢字に対するラベルを B、文末の漢字に対するラベルを E とし、B・M・E3・E2・E を用いて各文を表します。ただし、1 文字のみで構成される文は、ラベルを S とします。2 文字で構成される文のラベルは、B・E とします。
3 文字で構成される文のラベルは、B・E2・E とします。4 文字で構成される文のラベル
は、B・E3・E2・E とします。

!pip install deplacy transformers
class SeqL(object):def __init__(self,bert):
from transformers import pipeline
self.tagger=pipeline(task="ner",model=bert)
def __call__(self,text):
w=[(t["start"],t["end"],t["entity"]) for t in self.tagger(text)]
u="# text = "+text.replace("\n"," ")+"\n"for i,(s,e,p) in enumerate(w,1):
m,q="_" if i<len(w) and e<w[i][0] else "SpaceAfter=No",p.split("|")
f="_" if p.find("=")<0 else "|".join(t for t in q if t.find("=")>0)
u+="\t".join([str(i),text[s:e],"_",q[0],"_",f,"_","_","_",m])+"\n"return u+"\n"nlp=SeqL("KoichiYasuoka/roberta-classical-chinese-base-sentence-segmentation")
doc=nlp("子曰學而時習之不亦説乎有朋自遠方來不亦樂乎人不知而不慍不亦君子乎")import deplacy
deplacy.serve(doc,port=None)

B

E

B

M

E3

E2

E

B

E3

E2

E

子

曰

學

而

時

習

之

不

亦

説

乎

B

M

M

E3

E2

E

B

E3

E2

E

B

有

朋

自

遠

方

來

不

亦

樂

乎

人

M

M

E3

E2

E

B

M

E3

E2

E

不

知

而

不

慍

不

亦

君

子

乎

図 15: roberta-classical-chinese-base-sentence-segmentation による古典中国語の文切り[34]

https://huggingface.co/KoichiYasuoka/roberta-classical-chinese-base-upos
安岡孝一: Transformers を用いた古典中国語 (漢文) 文切りモデルの製作, 人文科学とコンピュータシン
ポジウム「じんもんこん 2021」論文集 (2021 年 12 月), pp.104-109.
[35]– 21 –

!pip install deplacy transformers
class SeqB(object):def __init__(self,bert,trans=[]):
from transformers import AutoTokenizer,AutoModelForTokenClassification
import numpy
self.tokenizer=AutoTokenizer.from_pretrained(bert)
self.tagger=AutoModelForTokenClassification.from_pretrained(bert)
x=self.tagger.config.label2id
self.transition=numpy.full((len(x),len(x)),0 if trans==[] else numpy.nan)
for f,t in trans:
self.transition[x[f],x[t]]=0
def __call__(self,text):
import torch,numpy
v=self.tokenizer(text,return_offsets_mapping=True)with torch.no_grad():m=self.tagger(torch.tensor([v["input_ids"]])).logits[0].numpy()
for i in range(m.shape[0]-1,0,-1):m[i-1]+=numpy.nanmax(m[i]+self.transition,axis=1)
j,k=v["offset_mapping"],[numpy.nanargmax(m[0])]for i in range(1,m.shape[0]):k.append(numpy.nanargmax(m[i]+self.transition[k[-1]]))w=[(s,e,self.tagger.config.id2label[q]) for (s,e),q in zip(j,k) if s<e]u="# text = "+text.replace("\n"," ")+"\n"for i,(s,e,p) in enumerate(w,1):
m="_" if i<len(w) and e<w[i][0] else "SpaceAfter=No"
u+="\t".join([str(i),text[s:e],"_",p]+["_"]*5+[m])+"\n"return u+"\n"t=[("S","S"),("S","B"),("B","M"),("B","E3"),("B","E2"),("B","E"),("M","M"),("M","E3"),("E3","E2"),("E2","E"),("E","S"),("E","B")]
nlp=SeqB("KoichiYasuoka/roberta-classical-chinese-base-sentence-segmentation",t)doc=nlp("子曰學而時習之不亦説乎有朋自遠方來不亦樂乎人不知而不慍不亦君子乎")import deplacy
deplacy.serve(doc,port=None)

B

E

B

M

E3

E2

E

B

E3

E2

E

子

曰

學

而

時

習

之

不

亦

説

乎

B

M

M

E3

E2

E

B

E3

E2

E

B

有

朋

自

遠

方

來

不

亦

樂

乎

人

M

M

E3

E2

E

B

M

E3

E2

E

不

知

而

不

慍

不

亦

君

子

乎

図 16: 古典中国語の文切りに Bellman-Ford を応用– 22 –

Google Colaboratory 上の Transformers を用いて、roberta-classical-chinese-base-sentencesegmentation で「子曰學而時習之不亦説乎有朋自遠方來不亦樂乎人不知而不慍不亦君子乎」
を文切りするプログラムと、その結果を図 15 に示します。
「子曰」「學而時習之」「不亦説
乎」「有朋自遠方來」「不亦樂乎」「人不知而不慍」「不亦君子乎」の 7 つの文に切られているのがわかります。ただし、系列ラベリングで文切りをおこなう場合は、Bellman-Ford[36]や Conditional Random Fields[37] を応用する方が、より高い精度が得られると考えられます (図 16)。

2.2 古典中国語 UD における係り受け解析
SuPar-Kanbun[38] は、隣接行列型係り受け解析アルゴリズムを、古典中国語向けに実装しています。UPOS 品詞付与と文切りも同時に実装しており、roberta-classical-chinese-basechar[26] を元にした「オールインワン設計」です。Google Colaboratory 上の SuPar-Kanbun
を用いて、「子曰學而時習之不亦説乎有朋自遠方來不亦樂乎人不知而不慍不亦君子乎」を品詞付与・文切り・係り受け解析するプログラムと、その結果を図 17 に示します。各文の解析結果を、順に見ていくことにしましょう。
「子曰」は、動詞「曰」の主語が「子」という文であり、主語を表す nsubj で繫がれています。
「學而時習之」は、並列接続詞「而」によって「學」と「習」が並置されていて、「學」と「習」が conj で、「習」と「而」が cc で繫がれています。「之」は「習」の目的語で、obj で繫がれています。「時」は「習」の斜格補語で、本来 obl で繫ぐところですが、古典中国語 UD では、obl を拡張した obl:tmod (時に関する斜格補語) を導入しています。「不亦説乎」は、「不」と「亦」がいずれも「説」を連用修飾していて、いずれもadvmod で繫がれています。
「乎」は文全体を修飾する句末の終助詞 (sentence particle) ですが、これを表すような UD 係り受けタグが表 4 に無いため、discourse:sp を導入[39] しています。「有朋自遠方來」は、「有朋」と「自遠方來」の 2 句から構成されていて、これらが parataxis で繫がれています。「朋」は「有」の目的語で、obj で繫がれています。
「遠方」は「來」の斜格補語で、本来 obl で繫ぐところですが、古典中国語 UD では、oblを拡張した obl:lmod (場所に関する斜格補語) を導入しています。ただし「遠方」の内部
では、動詞「遠」(古典中国語 UD には形容詞という分類は無く、動詞として扱います[40] )が名詞「方」を連体修飾していて、amod で繫がれています。なお、前置詞「自」も「方」を修飾しているとみなし、格表示を表す case で繫がれています。「不亦樂乎」は「不亦説乎」と同様の依存構造です。「人不知而不慍」は、「而」によって「知」と「慍」が並[36]

Richard Bellman: On a Routing Problem, Quarterly of Applied Mathematics, Vol.16, No.1 (April 1958),
pp.87-90.
[37]
John Lafferty, Andrew McCallum, Fernando Pereira: Conditional Random Fields: Probabilistic Models for
Segmenting and Labeling Sequence Data, Proceedings of the 18th International Conference on Machine Learning(June 2001), pp.282-289.
[38]
安岡孝一, ウィッテルン クリスティアン, 守岡知彦, 池田巧, 山崎直樹, 二階堂善弘, 鈴木慎吾, 師茂樹, 藤田一乘: 古典中国語 (漢文) Universal Dependencies とその応用, 情報処理学会論文誌, Vol.63, No.2 (2022 年 2月), pp.355-363.
[39]
Herman Leung, Rafaël Poiret, Tak-sum Wong, Xinying Chen, Kim Gerdes and John Lee: Developing Universal Dependencies for Mandarin Chinese, 12th Workshop on Asian Language Resources (December 2016),
pp.20-29.
[40]
安岡孝一, ウィッテルン クリスティアン, 守岡知彦, 池田巧, 山崎直樹, 二階堂善弘, 鈴木慎吾, 師茂樹: 古典中国語 (漢文) の形態素解析とその応用, 情報処理学会論文誌, Vol.59, No.2 (2018 年 2 月), pp.323-331.

– 23 –

!pip install suparkanbun
import suparkanbun
nlp=suparkanbun.load(Danku=True)
doc=nlp("子曰學而時習之不亦説乎有朋自遠方來不亦樂乎人不知而不慍不亦君子乎")import deplacy
deplacy.serve(doc,port=None)
ROOT
nsubj
NOUN

VERB

n,名詞,人,人

v,動詞,行為,伝達

子

曰

ROOT
conj
cc
obl:tmod

obj

VERB

CCONJ

NOUN

VERB

PRON

v,動詞,行為,動作

p,助詞,接続,並列

n,名詞,時,*v,動詞,行為,動作n,代名詞,人称,止格

學

而

時

習

之

ROOT
advmodadvmoddiscourse:sp
ADV

ADV

VERB

PART

v,副詞,否定,無界

v,副詞,頻度,重複

v,動詞,行為,態度

p,助詞,句末,*

不

亦

説

乎

ROOT
parataxis
case
obj

amod

obl:lmod

VERB

NOUN

ADP

VERB

NOUN

VERB

v,動詞,存在,存在n,名詞,人,関係

v,前置詞,経由,*v,動詞,描写,量n,名詞,固定物,関係

v,動詞,行為,移動

有

朋

自

遠

方

來

ROOT
advmodadvmoddiscourse:sp
ADV

ADV

VERB

PART

v,副詞,否定,無界

v,副詞,頻度,重複

v,動詞,行為,態度

p,助詞,句末,*

不

亦

樂

乎

ROOT
conj
nsubj
advmodcc
advmod

NOUN

ADV

VERB

CCONJ

ADV

VERB

n,名詞,人,人

v,副詞,否定,無界

v,動詞,行為,動作

p,助詞,接続,並列

v,副詞,否定,無界

v,動詞,行為,態度

人

不

知

而

不

慍

ROOT
advmodadvmoddiscourse:sp
ADV

ADV

NOUN

PART

v,副詞,否定,無界

v,副詞,頻度,重複n,名詞,人,役割

p,助詞,句末,*

不

亦

君子

乎

図 17: SuPar-Kanbun による古典中国語の係り受け解析– 24 –

置されていて、「知」と「慍」が conj で、「慍」と「而」が cc で繫がれています。「人」
は「知」と「慍」の両方の主語だと考えられるのですが、近い方の「知」に nsubj で繫
がれています。また、「知」と「慍」には、それぞれ否定の「不」が連用修飾していて、いずれも advmod で繫がれています。「不亦君子乎」は、「不亦説乎」や「不亦樂乎」と類似した依存構造ですが、「君子」が名詞でありコピュラ文です (ただし主語も繫辞もありません)。
このような形で SuPar-Kanbun は、漢字の列である白文に品詞付与をおこない、さらに漢語の列に係り受け解析をおこなうことで、漢文の依存構造を抽出します。なお、古典中
国語 UD の係り受けタグには、表 4 と図 17 に加え、受動文の主語を表す nsubj:pass、重畳を表す compound:redup、動詞並列を表す flat:vv、古典中国語以外を表す flat:foreignも用いられます[41] 。

2.3 古典中国語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar[42] で、古典中国語ミニ DeBERTa モデルを製作してみましょう。手順を図 18〜22 に示します。
最初に、訓練のための白文を準備しましょう (図 18)。train.txt の白文の材料として、こ!pip install esupar accelerate
import os
url="https://github.com/UniversalDependencies/UD_Classical_Chinese-Kyoto"
d=os.path.basename(url)!test -d {d} || git clone --depth=1 {url}!for F in train dev test ; do cp {d}/*-$$F.conllu $$F.conllu ; done
!sed -n "s/^# text = //p" *.conllu > train.txt

図 18: 古典中国語ミニモデル製作のための準備
from transformers import BertTokenizerFast
from tokenizers.pre_tokenizers import Sequence,Whitespace,Split
from tokenizers import Regex
s=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
with open("train.txt","r",encoding="utf-8") as r:v=set(c for c in r.read() if not c.isspace())
with open("vocab.txt","w",encoding="utf-8") as w:
print("\n".join(s+sorted(v)),file=w)
tkz=BertTokenizerFast(vocab_file="vocab.txt",never_split=s,
do_lower_case=False,strip_accents=False,tokenize_chinese_chars=True)b=tkz.backend_tokenizerb.pre_tokenizer=Sequence([Whitespace(),Split(Regex("."),"isolated")])b.decoder.prefix=b.model.continuing_subword_prefix=""
tkz.save_pretrained("my-dir/tokenizer-lzh")

図 19: 古典中国語向け単文字トークナイザの作成
[41]
[42]

https://universaldependencies.org/lzh/#syntax
https://github.com/KoichiYasuoka/esupar– 25 –

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-lzh",model_max_length=128)
tkz.backend_tokenizer.model.max_input_chars_per_word=tkz.model_max_lengtht=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-lzh")tkz.save_pretrained("my-dir/deberta-lzh")

図 20: 古典中国語ミニ DeBERTa モデルの作成

import torchfrom transformers import AutoTokenizer,AutoModelForMaskedLM
from esupar.tradify import tradify
tkz=AutoTokenizer.from_pretrained("my-dir/deberta-lzh")
mdl=AutoModelForMaskedLM.from_pretrained("my-dir/deberta-lzh")c=[(k,v) for k,v in tradify.items() if tkz.add_tokens([k,v])==1]
e=mdl.resize_token_embeddings(len(tkz))
with torch.no_grad():for k,v in c:
t=sorted(tkz.convert_tokens_to_ids([k,v]))e.weight[t[1],:]=e.weight[t[0],:]mdl.set_input_embeddings(e)mdl.save_pretrained("my-dir/deberta-lzh-ext")
tkz.save_pretrained("my-dir/deberta-lzh-ext")

図 21: 古典中国語ミニ DeBERTa モデルの拡張 (異体字追加)!python -m esupar.train my-dir/deberta-lzh-ext my-dir/deberta-lzh-upos .

図 22: 古典中国語向け品詞付与・係り受け解析ミニモデルの製作– 26 –

こでは UD Classical Chinese-Kyoto[43] を元にしていますが、好みに応じ、他の白文を増量するのもいいでしょう。なお、UD Classical Chinese-Kyoto の各 CoNLL-U ファイルは、
品詞付与・係り受け解析の学習にも用います。
続けて、入力文字列を単文字に分解するためのトークナイザを、my-dir/tokenizer-lzhに作成しましょう。図 19 では、BertTokenizerFast という Transformers のトークナイザを使って、単文字トークナイザを作成しています。
次に train.txt の白文から、DeBERTa モデルを my-dir/deberta-lzh に作成しましょう。図20 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしており、CPU なら 1
時間程度、GPU なら 10 分程度で作成できます。ただし、この DeBERTa モデルは繁體字で作られており、日本の常用漢字や中国の簡化字は含まれていません。そこで、これらの異体字に対しベクトルのコピーをおこない、新たなモデルを my-dir/deberta-lzh-ext に保存しましょう (図 21)。
最後に、my-dir/deberta-lzh-ext と UD Classical Chinese-Kyoto から、品詞付与・係り受
け解析モデル my-dir/deberta-lzh-upos を製作しましょう (図 22)。ただ、隣接行列型アルゴ
リズムの学習は収束が遅く、GPU でも 3 時間程度かかってしまいます。
うまく my-dir/deberta-lzh-upos が製作できたかどうか、esupar でテストしてみましょう(図 23)。繁體字のみならず、日本の常用漢字や中国の簡化字で書かれた漢文も、品詞付
与・係り受け解析できるはずなので、ぜひ試してみて下さい。
ちなみに図 24 は、my-dir/deberta-lzh-ext と UD Classical Chinese-Kyoto から、ミニ文切りモデル my-dir/deberta-lzh-seg を作成 (ファインチューニング) するプログラムです。ただし、ミニモデルでは文切りの精度が上がらないので、もっと大きなモデルを作成した方がいいでしょう。
!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-lzh-upos")
doc=nlp("労心者治人")
import deplacy
deplacy.serve(doc,port=None)
acl

root

obj

nsubj

obj

VERB

NOUN

PART

VERB

NOUN

労

心

者

治

人

図 23: 古典中国語向け品詞付与・係り受け解析ミニモデルのテスト[43]

Koichi Yasuoka: Universal Dependencies Treebank of the Four Books in Classical Chinese, DADH2019:
10th International Conference of Digital Archives and Digital Humanities (December 2019), pp.20-28.

– 27 –

from transformers import (AutoTokenizer,AutoModelForTokenClassification,
AutoConfig,DataCollatorForTokenClassification,TrainingArguments,Trainer)
src,lid="my-dir/deberta-lzh-ext",{"B":0,"E":1,"E2":2,"E3":3,"M":4,"S":5}tkz,cfg=AutoTokenizer.from_pretrained(src),AutoConfig.from_pretrained(src,
num_labels=len(lid),label2id=lid,id2label={i:l for l,i in lid.items()})
wd=cfg.max_position_embeddings-3
dat=[{"input_ids":[tkz.cls_token_id],"labels":[5]}]with open("train.conllu","r",encoding="utf-8") as r:
for t in [s[9:].strip() for s in r if s.startswith("# text = ")]:
i=tkz(t,add_special_tokens=False)["input_ids"]
j=[0 if len(i)>1 else 5]+[min(k,4) for k in range(len(i)-1,0,-1)]
if len(dat[-1]["input_ids"])+len(i)>wd:
dat.append({"input_ids":[tkz.cls_token_id]+i[0:wd],"labels":[5]+j[0:wd]})
elif len(i)>0:
dat[-1]["input_ids"].extend(i)dat[-1]["labels"].extend(j)trn=Trainer(train_dataset=dat,args=TrainingArguments(num_train_epochs=3,
per_device_train_batch_size=64,output_dir="/tmp",overwrite_output_dir=True,
save_total_limit=2),data_collator=DataCollatorForTokenClassification(tkz),
model=AutoModelForTokenClassification.from_pretrained(src,config=cfg))
trn.train()trn.save_model("my-dir/deberta-lzh-seg")tkz.save_pretrained("my-dir/deberta-lzh-seg")

図 24: 古典中国語文切りミニモデルの作成– 28 –

3 日本語編
書写言語としての日本語は、単語と単語の間に区切りがありません。そもそも、単語の長さに決まりがないので、様々な単語長が使われている[44] のです (図 25)。日本語 UDでは、これらの単語長のうち、国語研短単位と国語研長単位がサポートされています。その一方で、日本語の事前学習モデルのトークン長は、国語研短単位 (あるいはその細分化) や文字単位のものが多いのですが、図 25 以外のトークン長を採用しているモデルもあり、かなり混沌としています。
国語研短単位|| 全 || 学年 || に || わたっ|| て || 小 || 学校 || の || 国語 || の ||教科 || 書 || に || 大量 || の || 挿し絵 || が || 用い || られ || て || いる ||国語研長単位|| 全学年 || にわたって || 小学校 || の || 国語 || の ||教科書 || に || 大量 || の || 挿し絵 || が || 用い || られ || ている ||文節|| 全学年にわたって || 小学校の || 国語の ||教科書に || 大量の || 挿し絵が || 用いられている ||図 25: 国語研短単位・国語研長単位・文節

3.1 国語研短単位にもとづく品詞付与と係り受け解析
SuPar-UniDic[45] は、青空文庫 (+Wikipedia) BERT モデル[46] をベースに、隣接行列型係り受け解析アルゴリズムを、国語研短単位向けに実装しています。形態素解析 (単語切り・XPOS 品詞付与) 部には、MeCab[47] と UniDic[48] を流用しています。Google Colaboratory
上の SuPar-UniDic を用いて、「全学年にわたって小学校の国語の教科書に大量の挿し絵が用いられている」を品詞付与・係り受け解析するプログラムと、その結果を図 26 に示します。解析結果を見ていくことにしましょう。
国語研短単位 UD では、「全学年」「小学校」「教科書」が複数の単語に分かれていて、compound で繫がれているのが特徴的です。
「小学校の国語の教科書」は、名詞が名詞を修飾していて nmod で繫がれていると同時に、「の」が case で繫がれています。
「大量の挿し絵」も同様です。
「全学年」は「わたって」のニ格であり、obl で繫がれていると同時に、「に」が case で繫がれています。「挿し絵」は「用いられて」のガ格であり、nsubj
で繫がれていると同時に、「が」が case で繫がれています。
「全学年にわたって」は「挿[44]

Mai Omura, Aya Wakasa, Masayuki Asahara: Word Delimitation Issues in UD Japanese, Proceedings of the
5th Workshop on Universal Dependencies (December 2021), pp.142-150.
[45]
安岡孝一: 世界の Universal Dependencies と係り受け解析ツール群, 第 3 回 Universal Dependencies 公開
研究会 (2021 年 6 月).
[46]
https://github.com/akirakubo/bert-japanese-aozora[47]
Taku Kudo, Kaoru Yamamoto, Yuji Matsumoto: Applying Conditional Random Fields to Japanese Morphological Analysis, Proceedings of the 2004 Conference on Empirical Methods in Natural Language Processing(July 2004), pp.230-237.
[48]
伝康晴, 小木曽智信, 小椋秀樹, 山田篤, 峯松信明, 内元清貴, 小磯花絵: コーパス日本語学のための言語
資源: 形態素解析用電子化辞書の開発とその応用, 日本語科学, 第 22 号 (2007 年 10 月), pp.101-123.

– 29 –

!pip install suparunidic
import suparunidic
nlp=suparunidic.load("gendai")
doc=nlp("全学年にわたって小学校の国語の教科書に大量の挿し絵が用いられている")
import deplacy
deplacy.serve(doc,port=None)obl
compound

case

mark

nmod
case

compound

advcl
nmod
compound

case

NOUN

NOUN

ADP

VERB

SCONJ

NOUN

NOUN

ADP

NOUN

ADP

NOUN

接頭辞

名詞-普通名詞-一般

助詞-格助詞

動詞-非自立可能

助詞-接続助詞

接頭辞

名詞-普通名詞-一般

助詞-格助詞

名詞-普通名詞-一般

助詞-格助詞

名詞-普通名詞-一般

全

学年

に

小

学校

の

国語

の

教科

わたっ て

ROOT
advcl
nmod
compound

obl
nmod
case

case

aux
nsubj
case

mark
aux

NOUN

ADP

NOUN

ADP

NOUN

ADP

VERB

AUX

SCONJ

AUX

接尾辞-名詞的-一般

助詞-格助詞

名詞-普通名詞-形状詞可能

助詞-格助詞

名詞-普通名詞-一般

助詞-格助詞

動詞-一般

助動詞

助詞-接続助詞

動詞-非自立可能

書

に

大量

の

て

いる

挿し絵 が

用い られ

図 26: SuPar-UniDic による日本語係り受け解析 (国語研短単位)
し絵が用いられて」の連用修飾節であり、advcl で繫がれています。「いる」は、UniDic
品詞 (XPOS) が「動詞-非自立可能」なのですが、ここでは非自立だとみなして UPOS を
AUX にすると同時に、aux で繫がれています。
国語研短単位 UD では、XPOS と UPOS が微妙に乖離しています。XPOS は UniDic 品
詞を流用しているのですが、UPOS の品詞付与ルールとはズレているためです。極端な例として「難儀な難儀は難儀する」(図 27) を見てみましょう。「難儀」の UniDic 品詞は「名詞-普通名詞-サ変形状詞可能」ですが、「難儀な」は形状詞 (形容動詞) として扱うべきであり、UPOS は ADJ が妥当です。
「難儀する」はサ変動詞として扱うべきで、UPOS は
VERB が妥当です。ただし「難儀な」も「難儀する」も、国語研短単位では 2 つの単語に分かれてしまうので、「難儀」の UPOS に、それぞれ ADJ と VERB を付与しています。

!pip install suparunidic
import suparunidic
nlp=suparunidic.load("gendai")
doc=nlp("難儀な難儀は難儀する")
import deplacy
deplacy.serve(doc,port=None)
ROOT
acl

nsubj
case

aux

aux

ADJ

AUX

NOUN

ADP

VERB

AUX

名詞-普通名詞-サ変形状詞可能

助動詞

名詞-普通名詞-サ変形状詞可能

助詞-係助詞

名詞-普通名詞-サ変形状詞可能

動詞-非自立可能

難儀

な

難儀

は

難儀 する

図 27: 国語研短単位 UD における XPOS (UniDic 品詞) と UPOS の関係– 30 –

3.2 国語研短単位ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar[42] で、国語研短単位ミニ DeBERTa モデルを製作してみましょう。手順を図 28〜31 に示します。
最初に、訓練のための文章を準備しましょう (図 28)。train.txt の文章の材料として、ここでは UD Japanese-GSD[49] と Wikitext-JA[50] を元にしていますが、好みに応じ、他の日本語文を増量するのもいいでしょう。なお、UD Japanese-GSD の各 CoNLL-U ファイル
は、品詞付与・係り受け解析の学習にも用います。
!pip install esupar fugashi unidic-lite accelerate
import os,urllib.request
url="https://github.com/UniversalDependencies/UD_Japanese-GSD"
d=os.path.basename(url)!test -d {d} || git clone --depth=1 {url}!for F in train dev test ; do cp {d}/*-$$F.conllu $$F.conllu ; done
!sed -n "s/^# text = //p" *.conllu > train.txt
url="http://www.lsta.media.kyoto-u.ac.jp/resource/data/wikitext-ja/"with open("train.txt","a",encoding="utf-8") as w:
for t in ["Featured_Contents.txt","Good_Contents.txt"]:
with urllib.request.urlopen(url+t) as r:
print(r.read().decode("utf-8").replace("。","。\n"),file=w)

図 28: 国語研短単位ミニモデル製作のための準備
続けて、入力文を国語研短単位に分解するためのトークナイザを、my-dir/tokenizer-suwに作成しましょう。図 29 では、fugashi[51] と unidic-lite[52] で train.txt を国語研短単位に区切り、それを BertJapaneseTokenizer という Transformers のトークナイザに組み上げて、国
語研短単位トークナイザを作成しています。語彙数 (vocab_size) を 8000 に、異なり字数(limit_alphabet) を 3000 に絞っていますが、もう少し大きい方がいいかもしれません。

!fugashi -Owakati < train.txt > token.txt
from transformers import BertJapaneseTokenizer
from tokenizers import BertWordPieceTokenizers=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
wpt=BertWordPieceTokenizer(lowercase=False,strip_accents=False,
handle_chinese_chars=False)
wpt.train(files=["token.txt"],vocab_size=8000,limit_alphabet=3000,
special_tokens=s)
wpt.save_model(".")
tkz=BertJapaneseTokenizer(vocab_file="vocab.txt",word_tokenizer_type="mecab",
mecab_kwargs={"mecab_dic":"unidic_lite"},do_lower_case=False,never_split=s)
tkz.save_pretrained("my-dir/tokenizer-suw")

図 29: 国語研短単位トークナイザの作成[49]

松田寛, 若狭絢, 山下華代, 大村舞, 浅原正幸: UD Japanese GSD の再整備と固有表現情報付与, 言語処理学会第 26 回年次大会発表論文集 (2020 年 3 月), pp.133-136.
[50]
http://www.lsta.media.kyoto-u.ac.jp/resource/data/wikitext-ja/[51]
https://github.com/polm/fugashi[52]
https://github.com/polm/unidic-lite– 31 –

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-suw",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-suw")
tkz.save_pretrained("my-dir/deberta-suw")

図 30: 国語研短単位ミニ DeBERTa モデルの作成!python -m esupar.train my-dir/deberta-suw my-dir/deberta-suw-upos .

図 31: 国語研短単位向け品詞付与・係り受け解析ミニモデルの製作
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-suw に作成しましょう。図30 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしていますが、GPUでも 3 時間程度かかってしまいます。
最後に、my-dir/deberta-suw と UD Japanese-GSD から、品詞付与・係り受け解析モデ
ル my-dir/deberta-suw-upos を製作しましょう (図 31)。ただ、隣接行列型アルゴリズムの学習は収束が遅く、GPU でも 2 時間程度かかってしまいます。
うまく my-dir/deberta-suw-upos が製作できたかどうか、esupar でテストしてみましょう。図 32 の例では、「にわたって」「ている」のリンクに fixed が現れていて、図 26 とは異なる結果になっているようです。

– 32 –

!pip install esupar fugashi unidic-lite
import esupar
nlp=esupar.load("my-dir/deberta-suw-upos")
doc=nlp("全学年にわたって小学校の国語の教科書に大量の挿し絵が用いられている")
import deplacy
deplacy.serve(doc,port=None)

fixed
compound

case

fixed

NOUN

NOUN

ADP

全

学年

に

nmod
case

compound

VERB

obl
nmod
compound

case

SCONJ

NOUN

NOUN

ADP

NOUN

ADP

NOUN

わたっ て

小

学校

の

国語

の

教科

root
obl
nmod
compound

obl
nmod
case

case

NOUN

ADP

NOUN

ADP

書

に

大量

の

nsubj
case
NOUN

ADP

挿し絵 が

mark
aux
VERB

fixed
AUX

SCONJ

VERB

て

いる

用い られ

図 32: 国語研短単位向け品詞付与・係り受け解析ミニモデルのテスト

3.3 国語研長単位にもとづく品詞付与と係り受け解析
国語研長単位トークナイザ Japanese-LUW-Tokenizer[53] と、青空文庫 RoBERTa モデル
roberta-base-japanese-luw-upos[54] を元に、国語研長単位にもとづく品詞付与を考えてみましょう。Google Colaboratory 上の Transformers を用いて、「全学年にわたって小学校の国
語の教科書に大量の挿し絵が用いられている」に UPOS を付与するプログラムと、その結果を図 33 に示します。各トークンに系列ラベリングで UPOS を付与しているのですが、Japanese-LUW-Tokenizer が完璧ではなく、やや短めに「全」「学年」「にわたって」
「小学
校」
「の」
「国語」
「の」
「教科書」
「に」
「大量」
「の」
「挿し」
「絵」
「が」
「用い」
「られて」
「いる」とトークナイズしてしまうため、「全」と「挿し」に B-NOUN、「学年」と「絵」に I-NOUN が付与されています。一方、「大量」に ADJ が付与されていますが、これはNOUN の方が適切だと考えられます。
続いて、国語研長単位での係り受け解析[55] も見てみましょう。Google Colaboratory 上の esupar を用いて、「全学年にわたって小学校の国語の教科書に大量の挿し絵が用いられている」を係り受け解析するプログラムと、その結果を図 34 に示します。「小学校の国語の教科書」は、名詞が名詞を修飾していて nmod で繫がれていると同時に、「の」がcase で繫がれています。「大量の挿し絵」も同様のはずですが、「大量」が NOUN では
なく ADJ になってしまっています。
「挿し絵」はガ格であり、nsubj で繫がれていると同時に、「が」が case で繫がれています。「教科書」はニ格であり、obl で繫がれていると同時に、「に」が case で繫がれています。「全学年」もニ格と判断されていて、obl で繫[53]

https://github.com/KoichiYasuoka/Japanese-LUW-Tokenizer
https://huggingface.co/KoichiYasuoka/roberta-base-japanese-luw-upos[55]
安岡孝一: Transformers と国語研長単位による日本語係り受け解析モデルの製作, 情報処理学会研究報
告, Vol.2022-CH-128『人文科学とコンピュータ』, No.7 (2022 年 2 月 19 日), pp.1-8.
[54]– 33 –

!pip install deplacy transformers
class SeqL(object):def __init__(self,bert):
from transformers import pipeline
self.tagger=pipeline(task="ner",model=bert)
def __call__(self,text):
w=[(t["start"],t["end"],t["entity"]) for t in self.tagger(text)]
u="# text = "+text.replace("\n"," ")+"\n"for i,(s,e,p) in enumerate(w,1):
m,q="_" if i<len(w) and e<w[i][0] else "SpaceAfter=No",p.split("|")
f="_" if p.find("=")<0 else "|".join(t for t in q if t.find("=")>0)
u+="\t".join([str(i),text[s:e],"_",q[0],"_",f,"_","_","_",m])+"\n"return u+"\n"nlp=SeqL("KoichiYasuoka/roberta-base-japanese-luw-upos")
doc=nlp("全学年にわたって小学校の国語の教科書に大量の挿し絵が用いられている")
import deplacy
deplacy.serve(doc,port=None)

B-NOUN全

I-NOUN

ADP

NOUN

ADP

NOUN

ADP

学年 にわたって 小学校 の国語のB-NOUNI-NOUN

ADP

VERB

AUX

挿し

絵

が

用い られ ている

NOUN

ADP

教科書 に

ADJ

ADP

大量

の

AUX

図 33: roberta-base-japanese-luw-upos による UPOS 付与!pip install esupar
import esupar
nlp=esupar.load("KoichiYasuoka/roberta-base-japanese-luw-upos")
doc=nlp("全学年にわたって小学校の国語の教科書に大量の挿し絵が用いられている")
import deplacy
deplacy.serve(doc,port=None)

nmod
case

case
NOUN

ADP

NOUN

nmod
case

ADP

NOUN

ADP

全学年 にわたって 小学校 の

国語

の

nmod
case

case
NOUN

ADP

教科書 に

obl
obl
nsubj
case

ADJ

ADP

NOUN

大量

の

挿し絵

root
obl
obl
nsubj
case

aux
aux

ADP

VERB

AUX

AUX

が

用い られ ている

図 34: roberta-base-japanese-luw-upos による日本語係り受け解析 (国語研長単位)– 34 –

がれていると同時に、「にわたって」が case で繫がれています。

3.4 国語研長単位ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar で、国語研長単位ミニ DeBERTa モデルを製作してみましょう。図 35 では、図 28〜30 で作成した my-dir/deberta-suw を、国語研長単位に使い回す形で、品詞付与・係り受け解析モデル my-dir/deberta-luw-upos を製作しています。国
語研短単位の BertJapaneseTokenizer (内部的には fugashi と unidic-lite) を使うことになる
ので、国語研長単位の UD Japanese-GSDLUW[56] に較べてトークンが短くなるのですが、
esupar が UPOS 付与に「B-」「I-」を駆使することで、うまく動作するはずです (図 36)。
!pip install esupar fugashi unidic-lite spacy-alignments accelerate
url="https://github.com/UniversalDependencies/UD_Japanese-GSDLUW"!python -m esupar.train my-dir/deberta-suw my-dir/deberta-luw-upos {url}

図 35: 国語研長単位向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar fugashi unidic-lite
import esupar
nlp=esupar.load("my-dir/deberta-luw-upos")
doc=nlp("全学年にわたって小学校の国語の教科書に大量の挿し絵が用いられている")
import deplacy
deplacy.serve(doc,port=None)

nmod
case

case
NOUN

ADP

NOUN

nmod
case

ADP

NOUN

ADP

全学年 にわたって 小学校 の

国語

の

nmod
case

case
NOUN

obl
obl
nsubj
case

ADP

NOUN

ADP

NOUN

教科書 に

大量

の

挿し絵

root
obl
obl
nsubj
case

aux
aux

ADP

VERB

AUX

AUX

が

用い られ ている
図 36: 国語研長単位向け品詞付与・係り受け解析ミニモデルのテスト[56]

大村舞, 若狭絢, 浅原正幸: 国語研長単位に基づく UD Japanese, 言語処理学会第 28 回年次大会発表論文
集 (2022 年 3 月), pp.1618-1623.

– 35 –

3.5 文節にもとづく係り受け解析
GiNZA[57] は、国語研短単位にもとづく状態遷移型係り受け解析アルゴリズムを実装しており、その上で、文節にもとづく係り受け解析が可能です。ただし、文節にもとづく係り受けは、慣習的に文頭から文末へとリンクする[58] ため、矢印の方向が日本語 UD と逆になってしまいます。
Google Colaboratory 上の GiNZA を用いて、「全学年にわたって小学校の国語の教科書に大量の挿し絵が用いられている」を文節係り受け解析するプログラムと、その結果 (可視化は Graphviz[59] を使用) を図 37 に示します。文節にもとづく係り受け解析は、UD とは全く異なっていることから、ここでは参考に留めておきます。
!pip install ja_ginza ginza deplacy
import ja_ginza,ginza
nlp=ja_ginza.load()
doc=nlp("全学年にわたって小学校の国語の教科書に大量の挿し絵が用いられている")
d=ginza.bunsetu_spans(doc)from deplacy.deprelja import deprelja
g="digraph{"+";".join([’x{}[label="{}"]’.format(b.start,b.text) for b in d]+[’x{}->x{}[label="{}",fontsize=9]’.format(ginza.bunsetu_span(t).start,b.start,deprelja[t.dep_]) for b in d for t in b.lefts])+"}"
import graphviz
graphviz.Source(g)小学校の体言による連体修飾語

国語の

大量の

体言による連体修飾語

全学年にわたって

教科書に
斜格補語

斜格補語

体言による連体修飾語

挿し絵が
主語

用いられている

図 37: 文節にもとづく日本語係り受け解析[57]

松田寛: GiNZA - Universal Dependencies による実用的日本語解析, 自然言語処理, Vol.27, No.3 (2020 年
9 月), pp.695-701.
[58]
吉田将: 二文節間の係り受けを基礎とした日本語文の構文分析, 電子通信学会論文誌, Vol.55-D, No.4
(1972 年 4 月), pp.238-244.
[59]https://graphviz.readthedocs.io– 36 –

4 英語編
4.1 英語 UD における品詞付与と係り受け解析
Trankit[60] は、XLM-RoBERTa[61] をベースに、隣接行列型係り受け解析アルゴリズムを、様々な言語向けに実装しています。各言語向けに品詞付与も実装していて、複数の言語を同時に扱うことも可能です。Google Colaboratory 上の Trankit を用いて、英文「It didn’t
take long to repair my car」を品詞付与・係り受け解析するプログラムと、その結果を図38 に示します。解析結果を見ていくことにしましょう。
!pip install trankit transformers deplacy
import trankit
nlp=trankit.Pipeline("english")
doc=nlp("It didn’t take long to repair my car")import deplacy
deplacy.serve(doc,port=None)
root
expl
advmodcsubj
advmodobj
nmod:poss

mark

PRON

PART

VERB

ADV

PART

VERB

PRON

NOUN

PRP

RB

VB

RB

TO

VB

PRP$

NN

It

didn’t take longtorepair mycar

図 38: Trankit による英語の係り受け解析
動詞「take」の主語は「It」ですが、「It」は形式主語で、実際の主語は「to repair mycar」という節 (clause) です。これを反映して、「It」が expl で、「repair」が csubj で繫がれています。
「didn’t」と「long」は「take」を連用修飾していて、いずれも advmod で繫
がれています。
「to repair my car」においては、「to」が節全体に前置されていて、mark で繫がれています。
「car」は「repair」の目的語で、obj で繫がれています。
「my」は「car」
を修飾しており、本来は det が適切だと考えられるのですが、英語 UD では nmod:poss(所有に関する連体修飾) を導入しています。なお、Trankit は「didn’t」を 1 語だとみなしていますが、英語 UD では「did」「n’t」の 2 語に分けるべきであり、単語切りが不十分です。
UDPipe 2 WebAPI[62] は、UDPipe 2 の係り受け解析モデル[63] を、WebAPI の形で公開しています。内部的には、隣接行列型係り受け解析アルゴリズムを使っています。Google
Colaboratory から UDPipe 2 WebAPI の english-ewt にアクセスするプログラムと、その結[60]

Minh Van Nguyen, Viet Dac Lai, Amir Pouran Ben Veyseh and Thien Huu Nguyen: Trankit: A LightWeight Transformer-based Toolkit for Multilingual Natural Language Processing, EACL 2021: 16th Conferenceof the European Chapter of the Association for Computational Linguistics (April 2021), System Demonstrations,pp.80-90.
[61]
Alexis Conneau, Kartikay Khandelwal, Naman Goyal, Vishrav Chaudhary, Guillaume Wenzek, Francisco
Guzmán, Edouard Grave, Myle Ott, Luke Zettlemoyer, Veselin Stoyanov: Unsupervised Cross-lingual Representation Learning at Scale, Proceedings of the 58th Annual Meeting of the Association for Computational
Linguistics (July 2020), pp.8440-8451.
[62]
https://lindat.mff.cuni.cz/services/udpipe/[63]
Milan Straka: UDPipe 2.0 Prototype at CoNLL 2018 UD Shared Task, Proceedings of the CoNLL 2018
Shared Task (October 2018), pp.197-207.

– 37 –

!pip install deplacy
class UDPipe2WebAPI(object):def __init__(self,lang):
self.url="https://lindat.mff.cuni.cz/services/udpipe/api/process"self.params={"model":lang,"tokenizer":"","tagger":"","parser":""}
def __call__(self,text):
import urllib.parse,urllib.request,json
self.params["data"]=urllib.parse.quote(text)
u=self.url+"?"+"&".join(k+"="+v for k,v in self.params.items())
with urllib.request.urlopen(u) as r:
return json.loads(r.read())["result"]
nlp=UDPipe2WebAPI("english-ewt")
doc=nlp("It didn’t take long to repair my car")import deplacy
deplacy.serve(doc,port=None)
root
expl
aux

csubj
advmodadvmodobj
nmod:poss

mark

PRON

AUX

PART

VERB

ADV

PART

VERB

PRON

NOUN

PRP

VBD

RB

VB

RB

TO

VB

PRP$

NN

It

did

n’t

take longtorepair mycar

図 39: UDPipe 2 WebAPI による英語の係り受け解析
果を図 39 に示します。
「It didn’t take long to repair my car」の解析において、「did」「n’t」
が 2 語に分かれていて、それぞれ aux と advmod で繫がれています。
なお、英語 UD の係り受けタグには、表 4 と nmod:poss に加え、斜格補語による連用修飾を表す obl:npmod、時に関する連体修飾を表す nmod:tmod、時に関する斜格補語を表す
obl:tmod、受動態の主語を表す nsubj:pass、受動態の節主語を表す csubj:pass、関係代名
詞による連体修飾節を表す acl:relcl、限定詞の前に置かれる形容詞を表す det:predet、接続における前置副詞を表す cc:preconj、句動詞を表す compound:prt も用いられます[64] 。

4.2 英語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar[42] で、英語ミニ DeBERTa モデルを製作してみましょう。手順を図 40〜43 に示します。
最初に、訓練のための文章を準備しましょう (図 40)。train.txt の文章の材料として、ここでは UD English-EWT[65] と WikiText-2[66] を元にしていますが、好みに応じ、他の英文を増量するのもいいでしょう。なお、UD English-EWT の各 CoNLL-U ファイルは、品詞付与・係り受け解析の学習にも用います。
続けて、英語向けトークナイザを、my-dir/tokenizer-en に作成しましょう。図 41 では、Transformers の BertTokenizerFast を使って、英語向けトークナイザを作成しています。語
[64]

https://universaldependencies.org/en/#syntax
https://github.com/UniversalDependencies/UD_English-EWT[66]
Stephen Merity, Caiming Xiong, James Bradbury and Richard Socher: Pointer Sentinel Mixture Models,
ICLR 2017: 5th International Conference on Learning Representations, Wednesday Afternoon Poster Session
C27 (April 26, 2017).
[65]– 38 –

!pip install esupar spacy-alignments accelerate datasets
import os,datasets
url="https://github.com/UniversalDependencies/UD_English-EWT"
d=os.path.basename(url)!test -d {d} || git clone --depth=1 {url}!for F in train dev test ; do cp {d}/*-$$F.conllu $$F.conllu ; donewith open("train.txt","w",encoding="utf-8") as w:
for k in datasets.load_dataset("wikitext","wikitext-2-raw-v1")["train"]:print(k["text"],file=w)!sed -n "s/^# text = //p" *.conllu >> train.txt

図 40: 英語ミニモデル製作のための準備

from transformers import BertTokenizerFast
from tokenizers import BertWordPieceTokenizers=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
wpt=BertWordPieceTokenizer()
wpt.train(files=["train.txt"],vocab_size=8000,special_tokens=s)
wpt.save_model(".")
tkz=BertTokenizerFast(vocab_file="vocab.txt",never_split=s)
tkz.save_pretrained("my-dir/tokenizer-en")

図 41: 英語向けトークナイザの作成

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-en",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-en")tkz.save_pretrained("my-dir/deberta-en")

図 42: 英語ミニ DeBERTa モデルの作成– 39 –

彙数 (vocab_size) を 8000 に絞っていますが、もう少し大きくした方がいいかもしれません。
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-en に作成しましょう。図42 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしており、CPU なら
2 時間程度、GPU なら 20 分程度で作成できます。
最後に、my-dir/deberta-en と UD English-EWT から、品詞付与・係り受け解析モデル
my-dir/deberta-en-upos を製作しましょう (図 43)。うまく my-dir/deberta-en-upos が製作できたら、esupar でテストしてみましょう (図 44)。
!python -m esupar.train my-dir/deberta-en my-dir/deberta-en-upos .

図 43: 英語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-en-upos")
doc=nlp("It didn’t take long to repair my car")import deplacy
deplacy.serve(doc,port=None)
root
nsubj
aux

advcl
advmodadvmod

PRON

AUX

PART

VERB

ADV

It

did

n’t

take longobj
nmod:poss

mark
PART

to

VERB

PRON

NOUN

repair mycar

図 44: 英語向け品詞付与・係り受け解析ミニモデルのテスト

4.3 英語 UD による構成素解析
Stanza[67] は、隣接行列型係り受け解析アルゴリズムを実装しており、それに加えて、状態遷移型構成素解析アルゴリズム[68] も実装しています。Google Colaboratory 上の Stanzaを用いて、「It didn’t take long to repair my car」を構成素解析するプログラムと、その結果 (可視化は Graphviz[59] を使用) を図 45 に示します。構成素解析は、UD とは全く異なっていることから、ここでは参考に留めておきます。

[67]

Peng Qi, Yuhao Zhang, Yuhui Zhang, Jason Bolton, Christopher D. Manning: Stanza: A Python Natural
Language Processing Toolkit for Many Human Languages, 58th Annual Meeting of the Association for Computational Linguistics: Proceedings of the System Demonstration (July 2020), pp.101-108.
[68]
Jiangming Liu and Yue Zhang: In-Order Transition-based Constituent Parsing, Transactions of the Association for Computational Linguistics, Vol.5, pp.413-424 (November 2017).

– 40 –

!pip install stanza
import stanza
nlp=stanza.Pipeline("en")doc=nlp("It didn’t take long to repair my car")tree2dot=lambda x,y="x":(’graph{{node[shape="plaintext"];{}}}’ if len(y)<2else y[0:-1]+"--"+y+";{}").format(";\n".join([y+’[label="’+x.label+’"]’]+[tree2dot(c,y+chr(i+97)) for i,c in enumerate(x.children)]))import graphviz
graphviz.Source(tree2dot(doc.sentences[0].constituency))

ROOT

S

NP

VP

NP

VBD

RB

PRP

did

n’t

It

VP

VB

ADVP

S

take

RB

VP

long

TO

VP

to

VB

NP

repair

PRP$

NN

my

car

図 45: Stanza による英語の構成素解析– 41 –

5 フランス語編
5.1 フランス語 UD における品詞付与と係り受け解析
spacy-transformers[69] は、事前学習モデルによる状態遷移型係り受け解析アルゴリズムを実装しており、フランス語向けには、CamemBERT[70] を元にした fr dep news trf を公開[71] しています。Google Colaboratory 上の spacy-transformers を用いて、フランス語の例
文「Il ne peut pas prêter attention aux articles contractés」を品詞付与・係り受け解析するプ
ログラムと、その結果を図 46 に示します。解析結果を見ていくことにしましょう。
!pip install spacy-transformers deplacy!python -m spacy download fr_dep_news_trf
import spacy
nlp=spacy.load("fr_dep_news_trf")
doc=nlp("Il ne peut pas pr^eter attention aux articles contractés")
import deplacy
deplacy.serve(doc,port=None)
ROOT
nsubj
xcomp
advmodadvmodobl:arg
obj

case

acl

PRON

ADV

VERB

ADV

VERB

NOUN

ADP

NOUN

VERB

PRON

ADV

VERB

ADV

VERB

NOUN

ADP

NOUN

VERB

Il

ne

peut pas prêter attention aux articles contractés

図 46: spacy-transformers によるフランス語の係り受け解析「Il」が nsubj
動詞「peut」の主語「Il」は、同時に「prêter」の主語でもあることから、
で、「prêter」が xcomp で繫がれています。
「ne」「pas」は「peut」を否定しているとみなして、いずれも advmod で繫がれています。
「attention」は「prêter」の目的語であり、obj
で繫がれています。斜格補語「articles」については、説明が必要です。フランス語 UD では、obl を obl:agent・obl:arg・obl:mod の 3 つに分離しており、それぞれ動作主 (agent)・
項 (argument)・修飾子 (modificateur) を表しています。「articles」は obl:arg で繫がれていることから、「prêter」の項 (ただし動作主ではない) だとみなされています。
「articles」に対し「aux」は前置詞、「contractés」は連体修飾節だとみなされており、それぞれ case・acl で繫がれています。なお、spacy-transformers は「aux」を 1 語だとみなしていますが、フランス語 UD では「à」「les」の 2 語に分離した上で扱うことになっており、縮合語の解析が不十分です。
Trankit[60] は、XLM-RoBERTa をベースに、隣接行列型係り受け解析アルゴリズムを、様々な言語向けに実装しています。Google Colaboratory 上の Trankit を用いて「Il ne peut
pas prêter attention aux articles contractés」を品詞付与・係り受け解析するプログラムと、その結果を図 47 に示します。
「aux」が内部的には 2 語として扱われており、「à」が「articles」の前置詞、「les」が限定詞 (冠詞) として、それぞれ case・det で繫がれています。
[69]

https://github.com/explosion/spacy-transformers
Louis Martin, Benjamin Muller, Pedro Javier Ortiz Suárez, Yoann Dupont, Laurent Romary, Éric Villemontede la Clergerie, Djamé Seddah, Benoı̂t Sagot: CamemBERT: a Tasty French Language Model, Proceedings of the58th Annual Meeting of the Association for Computational Linguistics (July 2020), pp.7203-7219.
[71]
https://huggingface.co/spacy/fr_dep_news_trf[70]– 42 –

!pip install trankit transformers deplacy
import trankit
nlp=trankit.Pipeline("french")
doc=nlp("Il ne peut pas pr^eter attention aux articles contractés")
import deplacy
deplacy.serve(doc,port=None)
root
nsubj
advmodobl:arg
xcomp
advmod
ADV

case
obj
VERB

det

PRON

ADV

VERB

NOUN

Il

ne

peut pas prêter attention

ADP

DET

aux

acl
NOUN

VERB

articles contractés

図 47: Trankit によるフランス語の係り受け解析
なお、フランス語 UD の係り受けタグには、表 4 と obl:agent・obl:arg・obl:mod に加え、数多くの拡張が用いられている[72] のですが、拡張どうしの間で混乱が起こっており、事態の収拾が望まれます。

5.2 フランス語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar[42] で、フランス語ミニ DeBERTa モデルを製作してみましょう。手順を図 48〜51 に示します。
最初に、訓練のための文章を準備しましょう (図 48)。train.txt の文章の材料として、ここでは UD French-Sequoia[73] と UD French-GSD[74] を元にしていますが、好みに応じ、フランス語の他の文章を増量するのもいいでしょう。なお、各 CoNLL-U ファイルは、品詞付与・係り受け解析の学習にも用います。
続けて、フランス語向けトークナイザを、my-dir/tokenizer-fr に作成しましょう。図 49
では、Transformers の BertTokenizerFast を使って、フランス語向けトークナイザを作成
しています。
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-fr に作成しましょう。図 50では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンションヘッ!pip install esupar spacy-alignments accelerate
import os
url="https://github.com/UniversalDependencies/UD_French-Sequoia"!test -d {os.path.basename(url)} || git clone --depth=1 {url}url="https://github.com/UniversalDependencies/UD_French-GSD"!test -d {os.path.basename(url)} || git clone --depth=1 {url}!for F in train dev test ; do cat UD_French-*/*-$$F.conllu > $$F.conllu ; done
!sed -n "s/^# text = //p" *.conllu > train.txt

図 48: フランス語ミニモデル製作のための準備[72]

https://universaldependencies.org/fr/dep
https://github.com/UniversalDependencies/UD_French-Sequoia[74]
https://github.com/UniversalDependencies/UD_French-GSD[73]– 43 –

from transformers import BertTokenizerFast
from tokenizers import BertWordPieceTokenizers=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
wpt=BertWordPieceTokenizer(strip_accents=False)
wpt.train(files=["train.txt"],vocab_size=30000,special_tokens=s)
wpt.save_model(".")
tkz=BertTokenizerFast(vocab_file="vocab.txt",strip_accents=False,never_split=s)
tkz.save_pretrained("my-dir/tokenizer-fr")

図 49: フランス語向けトークナイザの作成

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-fr",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-fr")
tkz.save_pretrained("my-dir/deberta-fr")

図 50: フランス語ミニ DeBERTa モデルの作成!python -m esupar.train my-dir/deberta-fr my-dir/deberta-fr-upos .

図 51: フランス語向け品詞付与・係り受け解析ミニモデルの製作– 44 –

ド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしており、CPU なら 1 時
間程度、GPU なら 10 分程度で作成できます。
最後に、my-dir/deberta-fr と UD French-Sequoia・UD French-GSD から、品詞付与・係
り受け解析モデル my-dir/deberta-fr-upos を製作しましょう (図 51)。ただ、隣接行列型ア
ルゴリズムの学習は収束が遅く、GPU でも 3 時間程度かかってしまいます。
うまく my-dir/deberta-fr-upos が製作できたら、esupar でテストしてみましょう (図 52)。
esupar は縮合語を UPOS 付与においてサポート (図 53) しており、係り受け解析では「aux」
を 2 語として処理します。
!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-fr-upos")
doc=nlp("Il ne peut pas pr^eter attention aux articles contractés")
import deplacy
deplacy.serve(doc,port=None)
root
nsubj
advmodobl:arg
xcomp
advmod
ADV

case
obj
VERB

det

PRON

ADV

VERB

NOUN

Il

ne

peut pas prêter attention

ADP

DET

aux

amod
NOUN

VERB

articles contractés

図 52: フランス語向け品詞付与・係り受け解析ミニモデルのテスト!pip install deplacy transformers
class SeqL(object):def __init__(self,bert):
from transformers import pipeline
self.tagger=pipeline(task="ner",model=bert)
def __call__(self,text):
w=[(t["start"],t["end"],t["entity"]) for t in self.tagger(text)]
u="# text = "+text.replace("\n"," ")+"\n"for i,(s,e,p) in enumerate(w,1):
m,q="_" if i<len(w) and e<w[i][0] else "SpaceAfter=No",p.split("|")
f="_" if p.find("=")<0 else "|".join(t for t in q if t.find("=")>0)
u+="\t".join([str(i),text[s:e],"_",q[0],"_",f,"_","_","_",m])+"\n"return u+"\n"nlp=SeqL("my-dir/deberta-fr-upos")
doc=nlp("Il ne peut pas pr^eter attention aux articles contractés")
import deplacy
deplacy.serve(doc,port=None)

PRON

ADV

VERB

ADV

VERB

NOUN

ADP+DET

NOUN

B-VERBIl

nepeut pas prêter attention aux articles contract

I-VERBés

図 53: フランス語向け品詞付与・係り受け解析ミニモデルでの UPOS 付与– 45 –

6 ドイツ語編
6.1 ドイツ語 UD における品詞付与と係り受け解析
Trankit[60] は、XLM-RoBERTa をベースに、隣接行列型係り受け解析アルゴリズムを、様々な言語向けに実装しています。Google Colaboratory 上の Trankit を用いて、ドイツ語の例文「Im Krankenzimmer sah er krank aus aber wollte gut aussehen」を品詞付与・係り受
け解析するプログラムと、その結果を図 54 に示します。
!pip install trankit transformers deplacy
import trankit
nlp=trankit.Pipeline("german")doc=nlp("Im Krankenzimmer sah er krank aus aber wollte gut aussehen")import deplacy
deplacy.serve(doc,port=None)
root
conj
compound:prt
xcomp
nsubj

case
det

obl

cc
aux
advmod

ADP

DET

NOUN

VERB

PRON

ADJ

ADP

CCONJ

AUX

ADV

VERB

APPR

ART

NN

VVFIN

PPER

ADJD

PTKVZ

KON

VMFIN

ADJD

VVINF

Im

Krankenzimmer sah

erkrank aus aber wollte gut aussehen

図 54: Trankit によるドイツ語の係り受け解析
ドイツ語 UD は、単語の扱いが非常に独特です。図 54 の「Im Krankenzimmer」では、縮合語「Im」を前置詞「In」と冠詞「dem」の 2 語に分離して扱う一方、複合語である「Krankenzimmer」は 1 語として扱っています。この結果、「Krankenzimmer」から前置詞
へ case が、冠詞へ det が繫がれています。
「aussehen」など分離動詞は、分離していない
場合は 1 語として扱い、分離している場合は 2 語として扱うと同時に compound:prt で繫ぐ、というルールが採用されています。結果として「sah」から「aus」へ compound:prt が繫がれています。また「sah」からは、主語「er」が nsubj で、補語「krank」が xcomp で、斜格補語「Krankenzimmer」が obl で、それぞれ繫がれています。
「sah aus」と「aussehen」は並置されていて、conj で繫がれています。
「aussehen」からは、接続詞「aber」が cc で、助動詞「wollte」が aux で繫がれています。補語「gut」は advmod で繫がれていますが、これは xcomp の方が適切だと考えられます。
なお、ドイツ語 UD の係り受けタグには、表 4 と compound:prt に加え、受動態を表す
nsubj:pass・csubj:pass・aux:pass、斜格補語の動作主を表す obl:agent、項 (動作主以外) の斜格補語を表す obl:arg、所有を表す det:pos・nmod:poss、再帰動詞における再帰代名詞を表す expl:pv も用いられます[75] 。

[75]https://universaldependencies.org/de/#relations-overview– 46 –

6.2 ドイツ語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar[42] で、ドイツ語ミニ DeBERTa モデルを製作してみましょう。手順を図 55〜58 に示します。
最初に、訓練のための文章を準備しましょう (図 55)。train.txt の文章の材料として、ここでは UD German-HDT[76] を元にしていますが、好みに応じ、ドイツ語の他の文章を増量するのもいいでしょう。なお、UD German-HDT の CoNLL-U ファイルは、品詞付与・係り受け解析の学習にも用います。
!pip install esupar spacy-alignments accelerate
import os
url="https://github.com/UniversalDependencies/UD_German-HDT"
d=os.path.basename(url)!test -d {d} || git clone --depth=1 {url}!for F in train dev test ; do cat {d}/*-$$F*.conllu > $$F.conllu ; done
!sed -n "s/^# text = //p" *.conllu > train.txt

図 55: ドイツ語ミニモデル製作のための準備
続けて、ドイツ語向けトークナイザを、my-dir/tokenizer-de に作成しましょう。図 56 では、Transformers の BertTokenizerFast を使って、ドイツ語向けトークナイザを作成しています。
from transformers import BertTokenizerFast
from tokenizers import BertWordPieceTokenizers=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
wpt=BertWordPieceTokenizer(strip_accents=False)
wpt.train(files=["train.txt"],vocab_size=30000,special_tokens=s)
wpt.save_model(".")
tkz=BertTokenizerFast(vocab_file="vocab.txt",strip_accents=False,never_split=s)
tkz.save_pretrained("my-dir/tokenizer-de")

図 56: ドイツ語向けトークナイザの作成
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-de に作成しましょう。図57 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしていますが、GPUでも 1 時間程度かかってしまいます。
最後に、my-dir/deberta-de と UD German-HDT から、品詞付与・係り受け解析モデル
my-dir/deberta-de-upos を製作しましょう (図 58)。うまく my-dir/deberta-de-upos が製作できたら、esupar でテストしてみましょう (図 59)。esupar は縮合語を UPOS 付与においてサポート (図 60) しており、係り受け解析では「Im」を 2 語として処理します。

[76]https://github.com/UniversalDependencies/UD_German-HDT– 47 –

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-de",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-de")tkz.save_pretrained("my-dir/deberta-de")

図 57: ドイツ語ミニ DeBERTa モデルの作成!python -m esupar.train my-dir/deberta-de my-dir/deberta-de-upos .

図 58: ドイツ語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-de-upos")
doc=nlp("Im Krankenzimmer sah er krank aus aber wollte gut aussehen")import deplacy
deplacy.serve(doc,port=None)
root
conj
compound:prt
xcomp
nsubj

case
det
ADP

Im

DET

obl
NOUN

VERB

PRON

Krankenzimmer sah

er

ADJ

cc
aux
advmod
ADP

ADV

AUX

ADJ

VERB

krank aus aber wollte gut aussehen

図 59: ドイツ語向け品詞付与・係り受け解析ミニモデルのテスト– 48 –

!pip install deplacy transformers
class SeqL(object):def __init__(self,bert):
from transformers import pipeline
self.tagger=pipeline(task="ner",model=bert)
def __call__(self,text):
w=[(t["start"],t["end"],t["entity"]) for t in self.tagger(text)]
u="# text = "+text.replace("\n"," ")+"\n"for i,(s,e,p) in enumerate(w,1):
m,q="_" if i<len(w) and e<w[i][0] else "SpaceAfter=No",p.split("|")
f="_" if p.find("=")<0 else "|".join(t for t in q if t.find("=")>0)
u+="\t".join([str(i),text[s:e],"_",q[0],"_",f,"_","_","_",m])+"\n"return u+"\n"nlp=SeqL("my-dir/deberta-de-upos")
doc=nlp("Im Krankenzimmer sah er krank aus aber wollte gut aussehen")import deplacy
deplacy.serve(doc,port=None)

ADP+DET

B-NOUNI-NOUNVERBPRONIm Kranken zimmer sah

er

ADJ

ADP

ADV

AUX

ADJ

VERB

krank aus aber wollte gut aussehen

図 60: ドイツ語向け品詞付与・係り受け解析ミニモデルでの UPOS 付与– 49 –

7 オランダ語編
7.1 オランダ語 UD における品詞付与と係り受け解析
Trankit[60] は、XLM-RoBERTa をベースに、隣接行列型係り受け解析アルゴリズムを、様々な言語向けに実装しています。Google Colaboratory 上の Trankit を用いて、オランダ語の例文「In de ziekenkamer zag hij ziek uit maar wilde goed uitzien」を品詞付与・係り受
け解析するプログラムと、その結果を図 61 に示します。解析結果を見ていくことにしましょう。
!pip install trankit transformers deplacy
import trankit
nlp=trankit.Pipeline("dutch")
doc=nlp("In de ziekenkamer zag hij ziek uit maar wilde goed uitzien")
import deplacy
deplacy.serve(doc,port=None)
root
conj
compound:prt
xcomp
nsubj

case
det

obl

xcomp
advmod

cc

ADP

DET

NOUN

VERB

PRON

ADJ

ADP

CCONJ

VERB

ADJ

VERB

VZ|init

LID|bep|stan|rest

N|soort|ev|basis|zijd|stan

WW|pv|verl|ev

VNW|pers|pron|nomin|vol|3|ev|masc

ADJ|vrij|basis|zonder

VZ|fin

VG|neven

WW|pv|verl|ev

ADJ|vrij|basis|zonder

WW|inf|vrij|zonder

In

de

hij

ziek

ziekenkamer zag

uit maar wilde goed uitzien

図 61: Trankit によるオランダ語の係り受け解析「uitzien」など分離動詞は、分離していない場合は 1 語として扱い、分離している場
合は 2 語として扱うと同時に compound:prt で繫ぐ、というルールが採用されています。
結果として「zag」から「uit」へ compound:prt が繫がれています。また「zag」からは、主語「hij」が nsubj で、補語「ziek」が xcomp で、斜格補語「ziekenkamer」が obl で、それぞれ繫がれています。「ziekenkamer」からは、前置詞「In」が case で、冠詞「de」
が det で繫がれています。
「zag uit」と「wilde uitzien」は並置されていて、conj で繫がれています。
「wilde」には接続詞「maar」が cc で、「uitzien」が xcomp で繫がれています。
「uitzien」と「goed」は advmod で繫がれていますが、これは xcomp の方が適切だと考えられます。
なお、オランダ語 UD の係り受けタグには、表 4 と compound:prt に加え、受動態を表す nsubj:pass と aux:pass、受動態の動作主を表す obl:agent、所有を表す nmod:pos、関係代名詞による連体修飾節を表す acl:relcl、再帰動詞における再帰代名詞を表す expl:pv
も用いられます[77] 。

7.2 オランダ語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar[42] で、オランダ語ミニ DeBERTa モデルを製作してみましょう。手順を図 62〜65 に示します。
[77]

https://universaldependencies.org/nl/#syntax– 50 –

最初に、訓練のための文章を準備しましょう (図 62)。train.txt の文章の材料として、ここでは UD Dutch-Alpino[78] と UD Dutch-LassySmall[79] を元にしていますが、好みに応じ、オランダ語の他の文章を増量するのもいいでしょう。なお、各 CoNLL-U ファイルは、品
詞付与・係り受け解析の学習にも用います。
!pip install esupar accelerate
import os
url="https://github.com/UniversalDependencies/UD_Dutch-Alpino"!test -d {os.path.basename(url)} || git clone --depth=1 {url}url="https://github.com/UniversalDependencies/UD_Dutch-LassySmall"!test -d {os.path.basename(url)} || git clone --depth=1 {url}!for F in train dev test ; do cat UD_Dutch-*/*-$$F.conllu > $$F.conllu ; done
!sed -n "s/^# text = //p" *.conllu > train.txt

図 62: オランダ語ミニモデル製作のための準備
続けて、オランダ語向けトークナイザを、my-dir/tokenizer-nl に作成しましょう。図 63
では、Transformers の BertTokenizerFast を使って、オランダ語向けトークナイザを作成
しています。語彙数 (vocab_size) を 8000 に絞っていますが、もう少し大きくした方がいいかもしれません。
from transformers import BertTokenizerFast
from tokenizers import BertWordPieceTokenizers=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
wpt=BertWordPieceTokenizer(strip_accents=False)
wpt.train(files=["train.txt"],vocab_size=8000,special_tokens=s)
wpt.save_model(".")
tkz=BertTokenizerFast(vocab_file="vocab.txt",strip_accents=False,never_split=s)
tkz.save_pretrained("my-dir/tokenizer-nl")

図 63: オランダ語向けトークナイザの作成
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-nl に作成しましょう。図64 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしており、CPU なら
1 時間程度、GPU なら 10 分程度で作成できます。
最後に、my-dir/deberta-nl と UD Dutch-Alpino・UD Dutch-LassySmall から、品詞付与・係
り受け解析モデル my-dir/deberta-nl-upos を製作しましょう (図 65)。うまく my-dir/debertanl-upos が製作できたら、esupar でテストしてみましょう (図 66)。

[78]
[79]

https://github.com/UniversalDependencies/UD_Dutch-Alpino
https://github.com/UniversalDependencies/UD_Dutch-LassySmall– 51 –

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-nl",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-nl")
tkz.save_pretrained("my-dir/deberta-nl")

図 64: オランダ語ミニ DeBERTa モデルの作成!python -m esupar.train my-dir/deberta-nl my-dir/deberta-nl-upos .

図 65: オランダ語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-nl-upos")
doc=nlp("In de ziekenkamer zag hij ziek uit maar wilde goed uitzien")
import deplacy
deplacy.serve(doc,port=None)
root
conj
compound:prt
advmod
nsubj

case
det
ADP

DET

In

de

obl
NOUN

VERB

PRON

ADJ

ziekenkamer zag

hij

ziek

xcomp
advmod

cc
ADP

CCONJ

VERB

ADJ

uit maar wilde goed uitzien

図 66: オランダ語向け品詞付与・係り受け解析ミニモデルのテスト– 52 –VERB

8 タイ語編
8.1 タイ語 UD における品詞付与
書写言語としてのタイ語は、単語と単語の間に区切りがありません。数字や氏名の前後には、空白を入れる場合があるのですが、単語の区切りというわけではないのです。事
前学習モデルでタイ語を扱う際には、各トークンを単語と合致させるのが理想です。しかし、それは現実には困難なため、各トークンは単語より短めにトークナイズした上で、系列ラベリング (UPOS 付与) によって、単語をまとめ上げる手法が考えられます。すな
わち、トークンが単語と合致した場合には UPOS をラベルとして付与し、そうでない場
合には、最初のトークンに「B-」を付けた UPOS を、それ以降のトークンに「I-」を付けた UPOS を、それぞれ付与するのです。
!pip install deplacy transformers
class SeqL(object):def __init__(self,bert):
from transformers import pipeline
self.tagger=pipeline(task="ner",model=bert)
def __call__(self,text):
w=[(t["start"],t["end"],t["entity"]) for t in self.tagger(text)]
u="# text = "+text.replace("\n"," ")+"\n"for i,(s,e,p) in enumerate(w,1):
m,q="_" if i<len(w) and e<w[i][0] else "SpaceAfter=No",p.split("|")
f="_" if p.find("=")<0 else "|".join(t for t in q if t.find("=")>0)
u+="\t".join([str(i),text[s:e],"_",q[0],"_",f,"_","_","_",m])+"\n"return u+"\n"nlp=SeqL("KoichiYasuoka/deberta-base-thai-upos")
doc=nlp("หลายหัวดีกว่าหัวเดียว ")import deplacy
deplacy.serve(doc,port=None)

DET

NOUN

หลาย หัว

VERB

ADP

NOUN

B-NUM

I-NUM

ดี

กว่า

หัว

เ

ดียว

図 67: deberta-base-thai-upos による UPOS 付与

Google Colaboratory 上の Transformers を用いて、deberta-base-thai-upos[80] でタイ語の例文「หลายหัวดีกว่าหัวเดียว 」に UPOS を付与するプログラムと、その結果を図 67 に示します。「หลาย」「หัว」「ดี」「กว่า」の各単語では、各トークンがそのまま単語と合致し「เดียว」ており、それぞれ UPOS 品詞 DET・NOUN・VERB・ADP が付与されています。
は、2 つのトークンに泣き別れてしまっており、それぞれに B-NUM と I-NUM が付与されています。なお「ดี」は形容詞とみなせますが、タイ語においては形容詞と動詞に文法的な区別がないことから、ADJ ではなく VERB が付与されています。

[80]

https://huggingface.co/KoichiYasuoka/deberta-base-thai-upos– 53 –

8.2 タイ語 UD における係り受け解析
esupar[42] は、隣接行列型係り受け解析アルゴリズムを、事前学習モデルで実装しています。Google Colaboratory 上の esupar を用いて、deberta-base-thai-upos でタイ語の例文「หลายหัวดีกว่าหัวเดียว 」を係り受け解析するプログラムと、その結果を図 68 に示します。
解析結果を見ていくことにしましょう。
!pip install esupar
import esupar
nlp=esupar.load("KoichiYasuoka/deberta-base-thai-upos")
doc=nlp("หลายหัวดีกว่าหัวเดียว ")import deplacy
deplacy.serve(doc,port=None)
root
obl
det
DET

nsubj
NOUN

หลาย หัว

casenummod

VERB

ADP

NOUN

NUM

ดี

กว่า

หัว

เดียว

図 68: deberta-base-thai-upos によるタイ語の係り受け解析
動詞 (形容詞)「ดี」には、名詞「หัว」が 2 つ繫がっており、前者が主語 (nsubj)、後者「เดียว」で修飾されてが斜格補語 (obl) です。2 つの「หัว」は、それぞれ数量詞「หลาย」おり、前者は名詞に前置されていて det で、後者は名詞に後置されていて nummod で繫
がれています。後者の「หัว」には、前置詞「กว่า」が case で繫がれています。

8.3 タイ語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar で、タイ語ミニ DeBERTa モデルを製作してみましょう。手順を図 69〜72 に示します。
最初に、訓練のための文章を準備しましょう (図 69)。train.txt の文章の材料として、ここでは VISTEC-TP-TH-2021[81] と UD Thai-Corpora[82] を元にしていますが、好みに応じ、タイ語の他の文章を増量するのもいいでしょう。train.txt と同時に、各単語を空白で区切った token.txt も準備しており、トークナイザの作成に用います。UD Thai-Corpora の各
CoNLL-U ファイルは、train.upos にまとめ上げて、品詞付与の学習にも用います。また、
これらの CoNLL-U ファイルのうち、依存構造記述が UD のフォーマットを満たしている
ものは、train.conllu・dev.conllu・test.conllu に分け、係り受け解析の学習にも用います。
続けて、token.txt の各単語から、タイ語向けトークナイザを、my-dir/tokenizer-th に作成しましょう。図 70 では、Unigram トークナイザ (SentencePiece[83] の改造版) を token.txt[81]

Peerat Limkonchotiwat, Wannaphong Phatthiyaphaibun, Raheem Sarwar, Ekapol Chuangsuwanich, Sarana
Nutanong: Handling Cross- and Out-of-Domain Samples in Thai Word Segmentaion, Findings of the Association
for Computational Linguistics: ACL-IJCNLP 2021 (August 2021), pp.1003-1016.
[82]
https://github.com/KoichiYasuoka/spaCy-Thai/tree/master/UD_Thai-Corpora[83]
Taku Kudo, John Richardson: SentencePiece: A simple and language independent subword tokenizer anddetokenizer for Neural Text Processing, Proceedings of the 2018 Conference on Empirical Methods in Natural
Language Processing (November 2018): System Demonstrations, pp.66-71.

– 54 –

!pip install esupar spacy-alignments accelerate
import os
url="https://github.com/mrpeerat/OSKut"
v=os.path.join(os.path.basename(url),"VISTEC-TP-TH-2021")!test -d {v} || git clone --depth=1 {url}!sed "s/<[^>]*>//g;s/[|_]/ /g" {v}/*/*processed.txt > token.txt
url="https://github.com/KoichiYasuoka/spaCy-Thai"
d=os.path.join(os.path.basename(url),"UD_Thai-Corpora")!test -d {d} || git clone --depth=1 {url}s=’’’{print>"train.upos";if($0~/^# text = /)print substr($0,10);if(NF==10&&$1~/^[1-9][0-9]*$/)printf($1>1?" %s":"%s",$2)>>"token.txt";
if(NF>0)u=u$0"\\n";else{print>>"token.txt";f=FILENAME;if(u~/\\t0\\troot\\t/)print u>(f~/-dev/?"dev":f~/-test/?"test":"train")".conllu";u=""}}’’’!nawk -F’\t’ ’{s}’ {d}/*-ud-*.conllu | cat {v}/*/*raw.txt - > train.txt

図 69: タイ語ミニモデル製作のための準備に適用し、それを DebertaV2TokenizerFast という Transformers のトークナイザに組み上げて、タイ語向けトークナイザを作成しています。語彙数を 3000 に絞った上で、各トークンの文字数を最大 4 文字 (母音や声調記号を 1 文字に数える) としています。なお、各トークンは、タイ文字クラスター (คลัสเตอร์อักษรไทย)[84][85] を途中で切ってしまわないよ
う調整しています。
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-th に作成しましょう。図71 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしていますが、GPUでも 1 時間程度かかってしまいます。
最後に、my-dir/deberta-th と UD Thai-Corpora から、品詞付与・係り受け解析モデル
my-dir/deberta-th-upos を製作しましょう (図 72)。うまく my-dir/deberta-th-upos ができた
ら、esupar でテストしてみましょう (図 73)。

วิรัช ศรเลิศล้ําวาณิช : การตัดคําไทยในระบบแปลภาษา [Word Segmentation for Thai in Machine Translation
System], การแปลภาษาด้วยคอมพิวเตอร์ [Machine Translation], Bankok: NECTEC (1993), pp.556-561.
[85]
Thanaruk Theeramunkong, Virach Sornlertlamvanich, Thanasan Tanhermhong, Wirat Chinnan: Character
Cluster Based Thai Information Retrieval, IRAL ’00: Proceedings of the Fifth International Workshop on Information Retrieval with Asian Languages (November 2000), pp.75-80[84]– 55 –

from transformers import DebertaV2TokenizerFast
from tokenizers import (Tokenizer,models,pre_tokenizers,normalizers,processors,
decoders,trainers)
import json,unicodedata
s=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
spt=Tokenizer(models.Unigram())
spt.pre_tokenizer=pre_tokenizers.Sequence([pre_tokenizers.Whitespace(),pre_tokenizers.Punctuation()])
spt.normalizer=normalizers.Sequence([normalizers.Nmt(),normalizers.NFKC()])
spt.post_processor=processors.TemplateProcessing(single="[CLS] $A [SEP]",
pair="[CLS] $A [SEP] $B:1 [SEP]:1",special_tokens=[("[CLS]",0),("[SEP]",2)])
spt.decoder=decoders.WordPiece(prefix="",cleanup=True)
spt.train(trainer=trainers.UnigramTrainer(vocab_size=3000,max_piece_length=4,
special_tokens=s,unk_token="[UNK]",n_sub_iterations=2),files=["token.txt"])
d=json.loads(spt.to_str())
d["model"]["vocab"]=[t for t in d["model"]["vocab"] if len(t[0])<2 orunicodedata.category(t[0][0])!="Mn" and int((ord(t[0][-1])-1)/7)!=521]
spt.from_str(json.dumps(d)).save("tokenizer.json")
tkz=DebertaV2TokenizerFast(tokenizer_file="tokenizer.json",split_by_punct=True,
do_lower_case=False,keep_accents=True,vocab_file="/dev/null")
tkz.save_pretrained("my-dir/tokenizer-th")

図 70: タイ語向けトークナイザの作成

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-th",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-th")tkz.save_pretrained("my-dir/deberta-th")

図 71: タイ語ミニ DeBERTa モデルの作成– 56 –

s,d="my-dir/deberta-th","my-dir/deberta-th-upos"!python -m esupar.train {s} {d} 32 /tmp train.upos!python -m esupar.train {d} {d} 32 /// train.conllu dev.conllu test.conllu

図 72: タイ語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-th-upos")
doc=nlp("หลายหัวดีกว่าหัวเดียว ")import deplacy
deplacy.serve(doc,port=None)
root
obl
det
DET

nsubj
NOUN

หลาย หัว

casenummod

VERB

ADP

NOUN

NUM

ดี

กว่า

หัว

เดียว

図 73: タイ語向け品詞付与・係り受け解析ミニモデルのテスト– 57 –

9 ベトナム語編
9.1 ベトナム語 UD における品詞付与
書写言語としてのベトナム語は、単語と単語の間ではなく、音節と音節の間に空白があります。したがって、複数の音節で構成される単語は、語中に空白を含むことになります。事前学習モデルでベトナム語を扱う際には、各トークンを音節と合致させて、系
列ラベリング (UPOS 付与) によって、単語をまとめ上げる手法が考えられます。すなわ
ち、単音節の単語に対しては UPOS をラベルとして付与し、そうでない場合には、最初のトークンに「B-」を付けた UPOS を、それ以降のトークンに「I-」を付けた UPOS を、それぞれ付与するのです。
!pip install deplacy transformers
class SeqL(object):def __init__(self,bert):
from transformers import pipeline
self.tagger=pipeline(task="ner",model=bert)
def __call__(self,text):
w=[(t["start"],t["end"],t["entity"]) for t in self.tagger(text)]
u="# text = "+text.replace("\n"," ")+"\n"for i,(s,e,p) in enumerate(w,1):
m,q="_" if i<len(w) and e<w[i][0] else "SpaceAfter=No",p.split("|")
f="_" if p.find("=")<0 else "|".join(t for t in q if t.find("=")>0)
u+="\t".join([str(i),text[s:e],"_",q[0],"_",f,"_","_","_",m])+"\n"return u+"\n"nlp=SeqL("KoichiYasuoka/roberta-base-vietnamese-upos")
doc=nlp("Nó không xử lý được các từ có nhiều âm tiết ")import deplacy
deplacy.serve(doc,port=None)

PRON

ADV

B-VERBNó không xử

I-VERB

lý

ADV

DET

NOUN

VERB

được các

từ

có

ADJ

B-NOUNI-NOUNnhiều âmtiết

図 74: roberta-base-vietnamese-upos による UPOS 付与

Google Colaboratory 上の Transformers を用いて、roberta-base-vietnamese-upos[86] でベトナム語の例文「Nó không xử lý được các từ có nhiều âm tiết」に UPOS を付与するプログ
ラムと、その結果を図 74 に示します。「Nó」「không」「được」「các」「từ」「có」「nhiều」の各単語では、各トークンがそのまま単語と合致しており、それぞれ UPOS 品詞 PRON・
ADV・ADV・DET・NOUN・VERB・ADJ が付与されています。「xử lý」と「âm tiết」は2 音節の単語であり、「xử lý」には B-VERB と I-VERB が、「âm tiết」には B-NOUN とI-NOUN が、それぞれ付与されています。

[86]https://huggingface.co/KoichiYasuoka/roberta-base-vietnamese-upos– 58 –

9.2 ベトナム語 UD における係り受け解析
esupar[42] は、隣接行列型係り受け解析アルゴリズムを、事前学習モデルで実装しています。Google Colaboratory 上の esupar を用いて、roberta-base-vietnamese-upos でベトナ
ム語の例文「Nó không xử lý được các từ có nhiều âm tiết」を係り受け解析するプログラ
ムと、その結果を図 75 に示します。解析結果を見ていくことにしましょう。
!pip install esupar
import esupar
nlp=esupar.load("KoichiYasuoka/roberta-base-vietnamese-upos")
doc=nlp("Nó không xử lý được các từ có nhiều âm tiết ")import deplacy
deplacy.serve(doc,port=None)
root
nsubj
advmod:neg
PRON

ADV

obj

obj

advmod

VERB

ADV

det

acl:subj

DET

NOUN

VERB

Nó không xử lý được các

từ

có

amod
ADJ

NOUN

nhiều âm tiết図 75: roberta-base-vietnamese-upos によるベトナム語の係り受け解析
動詞「xử lý」の主語「Nó」は nsubj で、目的語「các từ」は obj で繫がれています。ただし「các từ」は 2 語だとみなされており、内部に det が繫がれています。
「không」「được」
は「xử lý」を否定しており、それぞれ advmod:neg と advmod で繫がれています。「cónhiều âm tiết」は「các từ」の連体修飾節だとみなされていて、acl:subj で繫がれています。「có nhiều âm tiết」の内部では、「có」の目的語「âm tiết」が obj で繫がれていて、さらに「nhiều」が amod で繫がれています。
なお、ベトナム語 UD の係り受けタグには、表 4 と advmod:neg・acl:subj に加え、数多くの拡張が用いられている[87] のですが、拡張どうしの間で混乱が起こっており、事態の収拾が望まれます。

9.3 ベトナム語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar で、ベトナム語ミニ DeBERTa モデルを製作してみましょう。手順を図 76〜79 に示します。
最初に、訓練のための文章を準備しましょう (図 76)。train.txt の文章の材料として、ここでは VNESEcorpus[88] と UD Vietnamese-VTB[89] を元にしていますが、好みに応じ、ベトナム語の他の文章を増量するのもいいでしょう。
続けて、ベトナム語向けトークナイザを、my-dir/tokenizer-vi に作成しましょう。図 77
では、Transformers の BertTokenizerFast を使って、ベトナム語向けトークナイザを作成
しています。
[87]

https://universaldependencies.org/treebanks/vi_vtb/#relations-overview
Tuan Anh Luu, Kazuhide Yamamoto: A Pointwise Approach for Vietnamese Diacritics Restoration, Proceedings of the 2012 International Conference on Asian Language Processing (November 2012), pp.189-192.
[89]
https://github.com/UniversalDependencies/UD_Vietnamese-VTB[88]– 59 –

!pip install esupar accelerate
import os
url="https://github.com/UniversalDependencies/UD_Vietnamese-VTB"
d=os.path.basename(url)!test -d {d} || git clone --depth=1 {url}!for F in train dev test ; do cp {d}/*-$$F.conllu $$F.conllu ; done
url="https://filedn.com/lit4DCIlHwxfS1gj9zcYuDJ/SNOW/VNESEcorpus.txt"
f=os.path.basename(url)!test -f {f} || curl -LO {url}!sed -n "s/^# text = *//p" *.conllu | cat {f} - > train.txt

図 76: ベトナム語ミニモデル製作のための準備

from transformers import BertTokenizerFast
from tokenizers import BertWordPieceTokenizers=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
wpt=BertWordPieceTokenizer(strip_accents=False)
wpt.train(files=["train.txt"],vocab_size=8000,special_tokens=s)
wpt.save_model(".")
tkz=BertTokenizerFast(vocab_file="vocab.txt",strip_accents=False,never_split=s)
tkz.save_pretrained("my-dir/tokenizer-vi")

図 77: ベトナム語向けトークナイザの作成

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-vi",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-vi")
tkz.save_pretrained("my-dir/deberta-vi")

図 78: ベトナム語ミニ DeBERTa モデルの作成– 60 –

次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-vi に作成しましょう。図78 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしていますが、GPUでも 1 時間程度かかってしまいます。
最後に、my-dir/deberta-vi と UD Vietnamese-VTB から、品詞付与・係り受け解析モデ
ル my-dir/deberta-vi-upos を製作しましょう (図 79)。うまく my-dir/deberta-vi-upos ができたら、esupar でテストしてみましょう (図 80)。
!python -m esupar.train my-dir/deberta-vi my-dir/deberta-vi-upos .

図 79: ベトナム語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-vi-upos")
doc=nlp("Nó không xử lý được các từ có nhiều âm tiết ")import deplacy
deplacy.serve(doc,port=None)
root
nsubj
advmod:neg
PRON

ADV

obj

obj

advmod

VERB

ADV

det

acl

amod

DET

NOUN

VERB

Nó không xử lý được các

từ

có

ADJ

NOUN

nhiều âm tiết図 80: ベトナム語向け品詞付与・係り受け解析ミニモデルのテスト– 61 –

10

ロシア語編

10.1 ロシア語 UD における品詞付与と係り受け解析
Trankit[60] は、XLM-RoBERTa をベースに、隣接行列型係り受け解析アルゴリズムを、様々な言語向けに実装しています。Google Colaboratory 上の Trankit を用いて、ロシア語の例文「Москва слезам не верила а верила любви」を品詞付与・係り受け解析するプロ
グラムと、その結果を図 81 に示します。解析結果を見ていくことにしましょう。
!pip install trankit transformers deplacy
import trankit
nlp=trankit.Pipeline("russian")
doc=nlp("Москва слезам не верила а верила любви ")import deplacy
deplacy.serve(doc,port=None)
root
nsubj
iobj

conj
advmod

PROPN

NOUN

PART

VERB

Москва слезам не верила

cc
CCONJ

а

iobj
VERB

NOUN

верила любви

図 81: Trankit によるロシア語の係り受け解析

2 つの動詞「верила」が並置されていて、conj で繫がれています。前者には、否定の「не」
が advmod で繫がれています。後者には、接続詞「а」が cc で繫がれています。
「Москва」
は、両方の「верила」の主語ですが、前者に nsubj で繫がれています。前者の目的語は「слезам」、後者の目的語は「любви」で、いずれも obj ではなく iobj で繫がれています。
Trankit は、与格 (датив) の目的語を、間接目的語 (iobj) だとみなしてしまうようです。
なお、ロシア語 UD の係り受けタグには、表 4 に加え、受動態を表す nsubj:pass・
csubj:pass・aux:pass、受動態の動作主を表す obl:agent、関係代名詞による連体修飾
節を表す acl:relcl、数詞と名詞の格変化の関係を示す nummod:gov・nummod:entity、氏名を表す flat:name、ロシア語以外を表す flat:foreign も用いられます[90] 。

10.2 ロシア語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar[42] で、ロシア語ミニ DeBERTa モデルを製作してみましょう。手順を図 82〜85 に示します。
最初に、訓練のための文章を準備しましょう (図 82)。train.txt の文章の材料として、ここでは UD Russian-SynTagRus[91] と UD Russian-Taiga[92] を元にしていますが、好みに応[90]

https://universaldependencies.org/ru/#relations-overview
Kira Droganova, Olga Lyashevskaya, Daniel Zeman: Data Conversion and Consistency of Monolingual
Corpora: Russian UD Treebanks, Proceedings of the 17th International Workshop on Treebanks and Linguistic
Theories (December 2018), pp.52-65.
[92]
T. O. Sharvina, O. Shapovalova: To the Methodology of Corpus Construction for Machine Learning: “Taiga”
Syntax Tree Corpus and Parser, Proceedings of «CORPUS LINGUISTICS–2017» (June 2017), pp.78-84.
[91]– 62 –

!pip install esupar spacy-alignments accelerate
import os
url="https://github.com/UniversalDependencies/UD_Russian-SynTagRus"!test -d {os.path.basename(url)} || git clone --depth=1 {url}url="https://github.com/UniversalDependencies/UD_Russian-Taiga"!test -d {os.path.basename(url)} || git clone --depth=1 {url}!for F in train dev test ; do cat UD_Russian-*/*-$$F*.conllu > $$F.conllu ; done
!sed -n "s/^# text = //p" *.conllu > train.txt

図 82: ロシア語ミニモデル製作のための準備

from transformers import BertTokenizerFast
from tokenizers import BertWordPieceTokenizers=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
wpt=BertWordPieceTokenizer(strip_accents=False)
wpt.train(files=["train.txt"],vocab_size=30000,special_tokens=s)
wpt.save_model(".")
tkz=BertTokenizerFast(vocab_file="vocab.txt",strip_accents=False,never_split=s)
tkz.save_pretrained("my-dir/tokenizer-ru")

図 83: ロシア語向けトークナイザの作成

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-ru",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-ru")tkz.save_pretrained("my-dir/deberta-ru")

図 84: ロシア語ミニ DeBERTa モデルの作成– 63 –

じ、ロシア語の他の文章を増量するのもいいでしょう。なお、各 CoNLL-U ファイルは、
品詞付与・係り受け解析の学習にも用います。
続けて、ロシア語向けトークナイザを、my-dir/tokenizer-ru に作成しましょう。図 83 では、Transformers の BertTokenizerFast を使って、ロシア語向けトークナイザを作成しています。
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-ru に作成しましょう。図84 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしています。
最後に、my-dir/deberta-ru と、UD Russian-SynTagRus・UD Russian-Taiga の CoNLL-U
ファイルから、品詞付与・係り受け解析モデル my-dir/deberta-ru-upos を製作しましょう(図 85)。うまく my-dir/deberta-ru-upos が製作できたら、esupar でテストしてみましょう(図 86)。
!python -m esupar.train my-dir/deberta-ru my-dir/deberta-ru-upos .

図 85: ロシア語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-ru-upos")
doc=nlp("Москва слезам не верила а верила любви ")import deplacy
deplacy.serve(doc,port=None)
root
nsubj
obj

conj
advmod

PROPN

NOUN

PART

VERB

Москва слезам не верила

cc
CCONJ

а

obj
VERB

NOUN

верила любви

図 86: ロシア語向け品詞付与・係り受け解析ミニモデルのテスト– 64 –

11

ウクライナ語編

11.1 ウクライナ語 UD における品詞付与と係り受け解析
Trankit[60] は、XLM-RoBERTa をベースに、隣接行列型係り受け解析アルゴリズムを、様々な言語向けに実装しています。Google Colaboratory 上の Trankit を用いて、ウクライ
ナ語の例文「Не скупись на втіху їй і ласку любий брате」を品詞付与・係り受け解析するプログラムと、その結果を図 87 に示します。解析結果を見ていくことにしましょう。
!pip install trankit transformers deplacy
import trankit
nlp=trankit.Pipeline("ukrainian")
doc=nlp("Не скупись на втіху їй і ласку любий брате ")import deplacy
deplacy.serve(doc,port=None)root
vocativeconj

obl
advmod

case

nmod

cc

amod

PART

VERB

ADP

NOUN

PRON

CCONJ

NOUN

ADJ

NOUN

Q

Vmpm-2s

Spsa

NcfsanPp-3f-sdn

Ccs

NcfsanAfpmsvf

NcmsvyїйіНе скупись на втіху

ласку любий брате

図 87: Trankit によるウクライナ語の係り受け解析
不完了相動詞「скупись」は、否定の「Не」が advmod で繫がれていて、禁止の命令を表しています。名詞 (呼格)「брате」が vocative で繫がれていて、さらに「любий」がamod で繫がれています。「втіху」と「ласку」は、いずれも「скупись」の斜格補語で、たがいに conj で繫がれていると同時に、前者が「скупись」に obl で繫がれています。前
置詞「на」と代名詞 (与格)「їй」は、前者にそれぞれ case と nmod で繫がれており、接続詞「і」は後者に cc で繫がれています。
なお、ウクライナ語 UD の係り受けタグには、表 4 に加え、数多くの拡張が用いられている[93] のですが、拡張どうしの間で混乱が起こっており、事態の収拾が望まれます。

11.2 ウクライナ語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar[42] で、ウクライナ語ミニ DeBERTa モデルを製作してみましょう。手順を図 88〜91 に示します。
最初に、訓練のための文章を準備しましょう (図 88)。train.txt の文章の材料として、ここでは UD Ukrainian-IU[94] と Ukr-Synth[95] を元にしていますが、好みに応じ、ウクライ
ナ語の他の文章を増量するのもいいでしょう。なお、UD Ukrainian-IU・Ukr-Synth の各
CoNLL-U ファイルは、train.upos にまとめ上げて、品詞付与の学習に用います。また、
UD Ukrainian-IU の各 CoNLL-U ファイルは、係り受け解析の学習にも用います。
[93]

https://universaldependencies.org/treebanks/uk_iu/#relations-overview
https://github.com/UniversalDependencies/UD_Ukrainian-IU[95]
https://huggingface.co/datasets/ukr-models/Ukr-Synth[94]– 65 –

!pip install esupar spacy-alignments accelerate
import os
url="https://github.com/UniversalDependencies/UD_Ukrainian-IU"
d=os.path.basename(url)!test -d {d} || git clone --depth=1 {url}!for F in train dev test ; do cp {d}/*-$$F.conllu $$F.conllu ; done
url="https://huggingface.co/datasets/ukr-models/Ukr-Synth"d=os.path.basename(url)!test -d {d} || git-lfs clone --depth=1 {url}!zcat {d}/data/*.conllu.gz | tr -d "\015" | cat - *.conllu > train.upos!sed -n "s/# text = //p" train.upos > train.txt

図 88: ウクライナ語ミニモデル製作のための準備
from transformers import BertTokenizerFast
from tokenizers import BertWordPieceTokenizers=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
wpt=BertWordPieceTokenizer(strip_accents=False)
wpt.train(files=["train.txt"],vocab_size=30000,special_tokens=s)
wpt.save_model(".")
tkz=BertTokenizerFast(vocab_file="vocab.txt",strip_accents=False,never_split=s)
tkz.save_pretrained("my-dir/tokenizer-uk")

図 89: ウクライナ語向けトークナイザの作成
続けて、ウクライナ語向けトークナイザを、my-dir/tokenizer-uk に作成しましょう。図89 では、Transformers の BertTokenizerFast を使って、ウクライナ語向けトークナイザを作成しています。
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-uk に作成しましょう。図90 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしています。
最後に、my-dir/deberta-uk と UD Ukrainian-IU・Ukr-Synth から、品詞付与・係り受け解析モデル my-dir/deberta-uk-upos を製作しましょう (図 91)。うまく my-dir/deberta-uk-uposが製作できたら、esupar でテストしてみましょう (図 92)。

– 66 –

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-uk",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-uk")
tkz.save_pretrained("my-dir/deberta-uk")

図 90: ウクライナ語ミニ DeBERTa モデルの作成

s,d="my-dir/deberta-uk","my-dir/deberta-uk-upos"!python -m esupar.train {s} {d} 32 /tmp train.upos!python -m esupar.train {d} {d} 32 /// train.conllu dev.conllu test.conllu

図 91: ウクライナ語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-uk-upos")
doc=nlp("Не скупись на втіху їй і ласку любий брате ")import deplacy
deplacy.serve(doc,port=None)root
discourse
conj

obl
advmod
PART

VERB

case
ADP

nmod
NOUN

Не скупись на втіху

cc

PRON

CCONJ

їй

і

amod
NOUN

ADJ

NOUN

ласку любий брате

図 92: ウクライナ語向け品詞付与・係り受け解析ミニモデルのテスト– 67 –

12

ベラルーシ語編

12.1 ベラルーシ語 UD における品詞付与と係り受け解析
Camphr-Udify[96] は、bert-base-multilingual-cased[97] をベースに、隣接行列型係り受け解析アルゴリズムを、75 の言語に対して[98] 統合的に実装しています。Google Colaboratory
上の Camphr-Udify を用いて、ベラルーシ語の例文「Насамрэч інтэрнэт стварае міфы тыху чыіх руках інтэрнэт」を品詞付与・係り受け解析するプログラムと、その結果を図 93に示します。解析結果を見ていくことにしましょう。
!pip install deplacy
import sys
v=".".join(sys.version.split(".")[0:2])!apt install python3.8 python3.8-dev python3.8-distutils!update-alternatives --remove-all python3!update-alternatives --install /usr/bin/python3 python3 /usr/bin/python{v} 1!update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 2!apt install python3-pip!python3 -m pip install -U pip
url="https://github.com/PKSHATechnology-Research/camphr_models"
f="en_udify-0.7.tar.gz"!test -f {f} || curl -LO {url+"/releases/download/0.7.0/"+f}d="/usr/local/lib/python3.8/dist-packages/camphr"!test -d {d} || pip install {f} "numpy<1.20.0" deplacy!echo 1 | update-alternatives --config python3
import subprocess
nlp=lambda t:subprocess.run(["python3.8","-c","\n".join(["import spacy,deplacy","n=spacy.load(’en_udify’)","print(deplacy.to_conllu(n(input())),end=’’)"])],
input=t,stdout=subprocess.PIPE,encoding="utf-8").stdout
doc=nlp("Насамрэч інтэрнэт стварае міфы тых у чыіх руках інтэрнэт ")import deplacy
deplacy.serve(doc,port=None)root
advmod
nsubj
ADV

nmod
case
obj

det

det

NOUN

VERB

NOUN

DET

Animacy=Inan|Case=Nom|Gender=Masc|Number=Sing

Aspect=Imp|Mood=Ind|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin|Voice=Act

Animacy=Inan|Case=Acc|Gender=Masc|Number=Plur

Case=Gen|Number=PlurНасамрэч інтэрнэт стварае міфы тых

ADP

у

nsubj

DET

NOUN

NOUN

Case=Loc|Number=Plur

Animacy=Inan|Case=Loc|Gender=Fem|Number=Plur

Animacy=Inan|Case=Nom|Gender=Masc|Number=Singчыіх руках інтэрнэт

図 93: Camphr-Udify によるベラルーシ語の係り受け解析

2 つの「інтэрнэт」は、前者が「стварае」の主語、後者が「у чыіх руках інтэрнэт」というコピュラ節の主語であり、いずれも nsubj で繫がれています。コピュラ節「у чыіхруках інтэрнэт」の内部では、前置詞「у」が case で、関係代名詞「чыіх」が det で繫がれており、コピュラ節全体が「тых」を修飾しています。ベラルーシ語 UD のルール上、
ここは acl:relcl で繫がれるべきなのですが、解析ミスで nmod になってしまっています。
[96]

https://camphr.readthedocs.io/en/stable/notes/udify.html
https://huggingface.co/bert-base-multilingual-cased[98]
Dan Kondratyuk and Milan Straka: 75 Languages, 1 Model: Parsing Universal Dependencies Universally,
Proceedings of the 2019 Conference on Empirical Methods in Natural Language (November 2019), pp.27792795.
[97]– 68 –

「тых」は「міфы」を修飾していて、det で繫がれています。「міфы」は「стварае」の目的語で、obj で繫がれています。「Насамрэч」は advmod で繫がれています。
なお、ベラルーシ語の係り受けタグには、表 4 に加え、受動態を表す nsubj:pass と
aux:pass、受動態の動作主を表す obl:agent、関係代名詞による連体修飾節を表す acl:relcl、
数詞と名詞の格変化の関係を表す nummod:gov と nummod:entity、コピュラ節に対する副詞的修飾語を表す advmod:discourse、氏名を表す flat:name、ベラルーシ語以外を表す flat:foreign も用いられます[99] 。

12.2 ベラルーシ語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar[42] で、ベラルーシ語ミニ DeBERTa モデルを製作してみましょう。手順を図 94〜97 に示します。
最初に、訓練のための文章を準備しましょう (図 94)。train.txt の文章の材料として、ここでは UD Belarusian-HSE[100] を元にしていますが、好みに応じ、ベラルーシ語の他の文章を増量するのもいいでしょう。なお、各 CoNLL-U ファイルは、品詞付与・係り受け解析の学習にも用います。
!pip install esupar accelerate
import os
url="https://github.com/UniversalDependencies/UD_Belarusian-HSE"
d=os.path.basename(url)!test -d {d} || git clone --depth=1 {url}!for F in train dev test ; do cp {d}/*-$$F.conllu $$F.conllu ; done
!sed -n "s/^# text = //p" *.conllu > train.txt

図 94: ベラルーシ語ミニモデル製作のための準備
続けて、ベラルーシ語向けトークナイザを、my-dir/tokenizer-be に作成しましょう。図95 では、Transformers の BertTokenizerFast を使って、ベラルーシ語向けトークナイザを作成しています。語彙数 (vocab_size) を 8000 に絞っていますが、もう少し大きくした方がいいかもしれません。
from transformers import BertTokenizerFast
from tokenizers import BertWordPieceTokenizers=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
wpt=BertWordPieceTokenizer(strip_accents=False)
wpt.train(files=["train.txt"],vocab_size=8000,special_tokens=s)
wpt.save_model(".")
tkz=BertTokenizerFast(vocab_file="vocab.txt",strip_accents=False,never_split=s)
tkz.save_pretrained("my-dir/tokenizer-be")

図 95: ベラルーシ語向けトークナイザの作成

[99]
[100]

https://universaldependencies.org/be/#relation-subtypes
https://github.com/UniversalDependencies/UD_Belarusian-HSE– 69 –

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-be",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-be")tkz.save_pretrained("my-dir/deberta-be")

図 96: ベラルーシ語ミニ DeBERTa モデルの作成
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-be に作成しましょう。図96 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしています。
最後に、my-dir/deberta-be と UD Belarusian-HSE から、品詞付与・係り受け解析モデル
my-dir/deberta-be-upos を製作しましょう (図 97)。うまく my-dir/deberta-be-upos が製作できたら、esupar でテストしてみましょう (図 98)。
!python -m esupar.train my-dir/deberta-be my-dir/deberta-be-upos .

図 97: ベラルーシ語向け品詞付与・係り受け解析ミニモデルの製作– 70 –

!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-be-upos")
doc=nlp("Насамрэч інтэрнэт стварае міфы тых у чыіх руках інтэрнэт ")import deplacy
deplacy.serve(doc,port=None)root
advmod
nsubj
ADV

NOUN

acl
case
obj

VERB

det
NOUN

det
DET

Насамрэч інтэрнэт стварае міфы тых

ADP

у

DET

nsubj
NOUN

NOUN

чыіх руках інтэрнэт

図 98: ベラルーシ語向け品詞付与・係り受け解析ミニモデルのテスト– 71 –

13

セルビア語編13.1 セルビア語 UD における品詞付与と係り受け解析
Camphr-Udify[96] は、bert-base-multilingual-cased をベースに、隣接行列型係り受け解析
アルゴリズムを、75 の言語に対して統合的に実装しています。Google Colaboratory 上のCamphr-Udify を用いて、セルビア語の例文「Моја би мати знала гибати гибаницу да имасира и масла」を品詞付与・係り受け解析するプログラムと、その結果を図 99 に示します。解析結果を見ていくことにしましょう。
!pip install deplacy
import sys
v=".".join(sys.version.split(".")[0:2])!apt install python3.8 python3.8-dev python3.8-distutils!update-alternatives --remove-all python3!update-alternatives --install /usr/bin/python3 python3 /usr/bin/python{v} 1!update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 2!apt install python3-pip!python3 -m pip install -U pip
url="https://github.com/PKSHATechnology-Research/camphr_models"
f="en_udify-0.7.tar.gz"!test -f {f} || curl -LO {url+"/releases/download/0.7.0/"+f}d="/usr/local/lib/python3.8/dist-packages/camphr"!test -d {d} || pip install {f} "numpy<1.20.0" deplacy!echo 1 | update-alternatives --config python3
import subprocess
nlp=lambda t:subprocess.run(["python3.8","-c","\n".join(["from spacy.lang.sr import Serbian","n=Serbian()","import spacy,deplacy","n.pipeline.extend(spacy.load(’en_udify’).pipeline)","print(deplacy.to_conllu(n(input())),end=’’)"])],
input=t,stdout=subprocess.PIPE,encoding="utf-8").stdout
doc=nlp("Моја би мати знала гибати гибаницу да има сира и масла ")import deplacy
deplacy.serve(doc,port=None)
root
aux
det

advcl
nsubj

xcomp

obj

DET

AUX

NOUN

VERB

VERB

NOUN

Case=Nom|Gender=Fem|Number=Sing|Number[psor]=Sing|Person=1|Poss=Yes|PronType=Prs

Aspect=Imp|Mood=Cnd|Number=Sing|Person=3|Tense=Past|VerbForm=FinDefinite=Ind|Gender=Fem|Number=Sing

Aspect=Perf|Definite=Ind|Gender=Fem|Number=Sing|Tense=Past|VerbForm=Part|Voice=Act

Aspect=Imp|Mood=Ind|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin|Voice=Act

Definite=Ind|Gender=Fem|Number=SingМоја би

conj
mark

SCONJ

мати знала гибати гибаницу да

obj

cc

VERB

NOUN

Aspect=Imp|Mood=Ind|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin|Voice=Act

Definite=Ind|Gender=Fem|Number=Singима сира

CCONJ

NOUN
Definite=Ind|Gender=Neut|Number=Plur

и

масла

図 99: Camphr-Udify によるセルビア語 (キリル文字) の係り受け解析
図 99 の例文は、主節「Моја би мати знала гибати гибаницу」と条件節「да има сира имасла」から構成されており、advcl で繫がれています。動詞「знала」の主語「мати」は、同時に「гибати」の主語でもあることから、「мати」が nsubj で、「гибати」が xcomp で繫がれています。助動詞「би」は aux で繫がれています。所有代名詞「Моја」は「мати」
を修飾しており、det のリンクが交差しています。「гибаницу」は「гибати」の目的語であり、obj で繫がれています。条件節では、「да」が mark で繫がれています。「има」の目的語は「сира」と「масла」の 2 つですが、「сира」の方が obj で繫がれていて、その先に conj で「масла」が繫がれており、そのまた先に cc で「и」が繫がれています。

– 72 –

!pip install deplacy
import sys
v=".".join(sys.version.split(".")[0:2])!apt install python3.8 python3.8-dev python3.8-distutils!update-alternatives --remove-all python3!update-alternatives --install /usr/bin/python3 python3 /usr/bin/python{v} 1!update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 2!apt install python3-pip!python3 -m pip install -U pip
url="https://github.com/PKSHATechnology-Research/camphr_models"
f="en_udify-0.7.tar.gz"!test -f {f} || curl -LO {url+"/releases/download/0.7.0/"+f}d="/usr/local/lib/python3.8/dist-packages/camphr"!test -d {d} || pip install {f} "numpy<1.20.0" deplacy!echo 1 | update-alternatives --config python3
import subprocess
nlp=lambda t:subprocess.run(["python3.8","-c","\n".join(["from spacy.lang.sr import Serbian","n=Serbian()","import spacy,deplacy","n.pipeline.extend(spacy.load(’en_udify’).pipeline)","print(deplacy.to_conllu(n(input())),end=’’)"])],
input=t,stdout=subprocess.PIPE,encoding="utf-8").stdout
doc=nlp("Moja bi mati znala gibati gibanicu da ima sira i masla")
import deplacy
deplacy.serve(doc,port=None)
root
aux
det

advcl
nsubj

xcomp

obj

conj
mark

DET

AUX

NOUN

VERB

VERB

NOUN

Case=Nom|Gender=Fem|Number=Sing|Number[psor]=Sing|Person=1|Poss=Yes|PronType=Prs

Mood=Cnd|Number=Sing|Person=3|Tense=Past|VerbForm=Fin

Case=Nom|Gender=Fem|Number=Sing

Gender=Fem|Number=Sing|Tense=Past|VerbForm=Part|Voice=Act

VerbForm=Inf

Case=Acc|Gender=Fem|Number=Sing

Moja

bi

SCONJ

mati znala gibati gibanicu da

obj

cc

VERB

NOUN

Mood=Ind|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin

Animacy=Anim|Case=Acc|Gender=Masc|Number=Sing

ima

sira

CCONJ

NOUN
Case=Gen|Gender=Neut|Number=Sing

i

masla

図 100: Camphr-Udify によるセルビア語 (ラテン文字) の係り受け解析
セルビア語は、公式にはキリル文字で書かれるのですが、ラテン文字による表記も多く用いられており、UD Serbian-SET[101] などのセルビア語コーパスも、多くはラテン文字で書かれています。Camphr-Udify は、ラテン文字で書かれたセルビア語も、キリル文
字と同様に解析可能です。Google Colaboratory 上の Camphr-Udify を用いて、セルビア語の例文「Moja bi mati znala gibati gibanicu da ima sira i masla」を品詞付与・係り受け解析するプログラムと、その結果を図 100 に示します。
なお、セルビア語 UD の係り受けタグには、表 4 に加え、数詞と名詞 (および代名詞)の格変化の関係を表す nummod:gov と det:numgov も用いられます[102] 。

13.2 セルビア語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar[42] で、セルビア語ミニ DeBERTa モデルを製作してみましょう。手順を図 101〜105 に示します。srtools[103] の助けを借りて、キリル文字とラテ[101]

https://github.com/UniversalDependencies/UD_Serbian-SET
https://universaldependencies.org/treebanks/sr_set/#relations-overview[103]
https://gitlab.com/andrejr/srtools[102]– 73 –

!pip install esupar srtools accelerate
import os
url="https://www.clarin.si/repository/xmlui/bitstream/handle/11356/1063"!test -f srWaC1.1.06.xml.gz || curl -LO {url}/srWaC1.1.06.xml.gz
s=’{if($0~/^</){s="";if($1=="
")print""}else{printf("%s%s",s,$1);s=" "}}’
!zcat *.xml.gz | awk ’{s}’ | fgrep -v "&" > train.txt
url="https://github.com/UniversalDependencies/UD_Serbian-SET"
d=os.path.basename(url)!test -d {d} || git clone --depth=1 {url}!for F in train dev test ; do cp {d}/*-$$F.conllu $$F.conllu ; done
!sed -n "s/^# text = //p" *.conllu >> train.txt

図 101: セルビア語ミニモデル製作のための準備
ン文字の両方が使えるモデルを目指します。
最初に、訓練のための文章を準備しましょう (図 101)。train.txt の文章の材料として、
ここでは srWaC[104] の一部と、UD Serbian-SET を元にしていますが、好みに応じ、セルビア語の他の文章を増量するのもいいでしょう。なお、UD Serbian-SET の各 CoNLL-U
ファイルは、品詞付与・係り受け解析の学習にも用います。
続けて、train.txt の各単語をキリル文字に変換しつつ、セルビア語向けトークナイザを、
my-dir/tokenizer-sr に作成しましょう。図 102 では、Transformers の BertTokenizerFast を使って、セルビア語向けトークナイザを作成しています。語彙数 (vocab_size) を 8000に絞っていますが、もう少し大きくした方がいいかもしれません。
次に、train.txt の文章をキリル文字に変換しつつ、DeBERTa モデルを my-dir/deberta-srに作成しましょう。図 103 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンションヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしています。さらに、キリル文字のトークンに対応するラテン文字のトークンを追加し、新たなモデルを my-dir/deberta-sr-ext に保存しましょう (図 104)。
最後に、my-dir/deberta-sr-ext と UD Serbian-SET から、品詞付与・係り受け解析モデル
my-dir/deberta-sr-upos を製作しましょう (図 105)。うまく my-dir/deberta-sr-upos が製作できたら、esupar でテストしてみましょう。キリル文字とラテン文字の両方が使えるはずです。ただ、図 106 の例では「гибати гибаницу」を固有名詞だと解釈してしまっており、
図 99 とは異なる結果になっているようです。

[104]

http://nlp.ffzg.hr/resources/corpora/srWaC– 74 –

from transformers import BertTokenizerFast
from tokenizers import BertWordPieceTokenizer
from srtools import latin_to_cyrillic
s=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
wpt=BertWordPieceTokenizer(strip_accents=False)with open("train.txt","r",encoding="utf-8") as r:t=latin_to_cyrillic(r.read().strip()).split("\n")wpt.train_from_iterator(iterator=t,vocab_size=8000,special_tokens=s)
wpt.save_model(".")
tkz=BertTokenizerFast(vocab_file="vocab.txt",strip_accents=False,never_split=s)
tkz.save_pretrained("my-dir/tokenizer-sr")

図 102: セルビア語向けトークナイザの作成

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-sr",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineCyr(object):def __init__(self,file,tokenizer):from srtools import latin_to_cyrillic
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[latin_to_cyrillic(s.strip()) for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineCyr("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-sr")tkz.save_pretrained("my-dir/deberta-sr")

図 103: セルビア語ミニ DeBERTa モデルの作成– 75 –

import torch,srtools
from transformers import BertTokenizerFast,AutoModelForMaskedLM
tkz=BertTokenizerFast.from_pretrained("my-dir/deberta-sr")
mdl=AutoModelForMaskedLM.from_pretrained("my-dir/deberta-sr")n,s,m=len(tkz),tkz.all_special_tokens,tkz.model_max_lengthc=[t if t in s else srtools.cyrillic_to_latin(t)for t in tkz.convert_ids_to_tokens(range(n))]
t=[False]*n+[True]*tkz.add_tokens(c)e=mdl.resize_token_embeddings(len(tkz))
with torch.no_grad():for i,j in enumerate(tkz.convert_tokens_to_ids(c)):
if t[j]:e.weight[j,:]=e.weight[i,:]t[j]=False
mdl.set_input_embeddings(e)mdl.save_pretrained("my-dir/deberta-sr-ext")
with open("vocab.txt","w",encoding="utf-8") as w:
print("\n".join(tkz.convert_ids_to_tokens(range(len(tkz)))),file=w)
tkz=BertTokenizerFast(vocab_file="vocab.txt",strip_accents=False,never_split=s,model_max_length=m)tkz.save_pretrained("my-dir/deberta-sr-ext")

図 104: セルビア語ミニ DeBERTa モデルの拡張 (ラテン文字追加)!python -m esupar.train my-dir/deberta-sr-ext my-dir/deberta-sr-upos .

図 105: セルビア語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-sr-upos")
doc=nlp("Моја би мати знала гибати гибаницу да има сира и масла ")import deplacy
deplacy.serve(doc,port=None)root
advmod
aux

advcl
nsubj

DET

AUX

Моја би

NOUN

obj
VERB

PROPN

conj

flat
PROPN

mark
SCONJ

мати знала гибати гибаницу да

obj
VERB

cc
NOUN

има сира

CCONJ

NOUN

и

масла

図 106: セルビア語向け品詞付与・係り受け解析ミニモデルのテスト– 76 –

クロアチア語編

1414.1 クロアチア語 UD における品詞付与と係り受け解析
Trankit[60] は、XLM-RoBERTa をベースに、隣接行列型係り受け解析アルゴリズムを、様々な言語向けに実装しています。Google Colaboratory 上の Trankit を用いて、クロアチ
ア語の例文「Moja bi mati znala gibati gibanicu da ima sira i masla」を品詞付与・係り受け解析するプログラムと、その結果を図 107 に示します。解析結果を見ていくことにしましょう。
!pip install trankit transformers deplacy
import trankit
nlp=trankit.Pipeline("croatian")
doc=nlp("Moja bi mati znala gibati gibanicu da ima sira i masla")
import deplacy
deplacy.serve(doc,port=None)
root
aux
det

advcl
nsubj

xcomp

conj

obj

mark

obj

cc

DET

AUX

NOUN

VERB

VERB

NOUN

SCONJ

VERB

NOUN

CCONJ

NOUN

Ps1fsn

Vaa3s

Ncfsn

Vmp-sf

Vmn

Ncfsa

Cs

Vmr3s

Ncmsg

Cc

Ncnsg

Moja

bi

ima

sira

i

masla

mati znala gibati gibanicu da

図 107: Trankit によるクロアチア語の係り受け解析
図 107 の例文は、主節「Moja bi mati znala gibati gibanicu」と条件節「da ima sira i masla」
から構成されており、advcl で繫がれています。動詞「znala」の主語「mati」は、同時に「gibati」の主語でもあることから、「mati」が nsubj で、「gibati」が xcomp で繫がれています。助動詞「bi」は aux で繫がれています。所有代名詞「Moja」は「mati」を修飾しており、det のリンクが交差しています。
「gibanicu」は「gibati」の目的語であり、obj で繫
がれています。条件節では、「da」が mark で繫がれています。「ima」の目的語は「sira」と「masla」の 2 つですが、「sira」の方が obj で繫がれていて、その先に conj で「masla」
が繫がれており、そのまた先に cc で「i」が繫がれています。
なお、クロアチア語 UD の係り受けタグには、表 4 に加え、強調の連用修飾語を表す
advmod:emph、数詞と代名詞の格変化の関係を表す det:numgov、クロアチア語以外を表す flat:foreign も用いられます[105] 。

14.2 クロアチア語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar[42] で、クロアチア語ミニ DeBERTa モデルを製作してみましょう。手順を図 108〜111 に示します。
最初に、訓練のための文章を準備しましょう (図 108)。train.txt の文章の材料として、ここでは UD Croatian-SET[106] と hr500k[107] を元にしていますが、好みに応じ、クロアチア語[105]

https://universaldependencies.org/treebanks/hr_set/#relations-overview
https://github.com/UniversalDependencies/UD_Croatian-SET[107]
https://huggingface.co/datasets/classla/hr500k[106]– 77 –

!pip install esupar accelerate
import os
url="https://github.com/UniversalDependencies/UD_Croatian-SET"
d=os.path.basename(url)!test -d {d} || git clone --depth=1 {url}!for F in train dev test ; do cp {d}/*-$$F.conllu $$F.conllu ; done
url="https://huggingface.co/datasets/classla/hr500k"d=os.path.basename(url)!test -d {d} || ( git clone --depth=1 {url} ; cd {d} ; unzip data_ner.zip )!cat {d}/data_ner/*.conllu *.conllu > train.upos!sed -n "s/^# text = //p" train.upos > train.txt

図 108: クロアチア語ミニモデル製作のための準備
from transformers import BertTokenizerFast
from tokenizers import BertWordPieceTokenizers=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
wpt=BertWordPieceTokenizer(lowercase=False,strip_accents=False)
wpt.train(files=["train.txt"],vocab_size=8000,special_tokens=s)
wpt.save_model(".")
tkz=BertTokenizerFast(vocab_file="vocab.txt",do_lowercase=False,
strip_accents=False,never_split=s)
tkz.save_pretrained("my-dir/tokenizer-hr")

図 109: クロアチア語向けトークナイザの作成の他の文章を増量するのもいいでしょう。なお、UD Croatian-SET・hr500k の各 CoNLL-U
ファイルは、train.upos にまとめ上げて、品詞付与の学習に用います。また、UD CroatianSET の各 CoNLL-U ファイルは、係り受け解析の学習にも用います。
続けて、クロアチア語向けトークナイザを、my-dir/tokenizer-hr に作成しましょう。図109 では、Transformers の BertTokenizerFast を使って、クロアチア語向けトークナイザを作成しています。語彙数 (vocab_size) を 8000 に絞っていますが、もう少し大きくした方がいいかもしれません。
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-hr に作成しましょう。図110 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしています。
最後に、my-dir/deberta-hr と UD Croatian-SET・hr500k から、品詞付与・係り受け解析
モデル my-dir/deberta-hr-upos を製作しましょう (図 111)。うまく my-dir/deberta-hr-upos が製作できたら、esupar でテストしてみましょう。ただ、図 112 の例では「gibati gibanicu」
を固有名詞だと解釈してしまっており、図 107 とは異なる結果になっているようです。

– 78 –

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-hr",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-hr")tkz.save_pretrained("my-dir/deberta-hr")

図 110: クロアチア語ミニ DeBERTa モデルの作成

s,d="my-dir/deberta-hr","my-dir/deberta-hr-upos"!python -m esupar.train {s} {d} 32 /tmp train.upos!python -m esupar.train {d} {d} 32 /// train.conllu dev.conllu test.conllu

図 111: クロアチア語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-hr-upos")
doc=nlp("Moja bi mati znala gibati gibanicu da ima sira i masla")
import deplacy
deplacy.serve(doc,port=None)
root
aux
det

advcl
nsubj

obj
VERB

PROPN

conj

flat
PROPN

mark

obj

cc

DET

AUX

NOUN

SCONJ

VERB

NOUN

CCONJ

NOUN

Moja

bi

mati znala gibati gibanicu da

ima

sira

i

masla

図 112: クロアチア語向け品詞付与・係り受け解析ミニモデルのテスト– 79 –

15

コプト語編

15.1 コプト語 UD における品詞付与
書写言語としてのコプト語は、単語と単語の間に区切りがありません。空白や改行が入っている場合が多いのですが、単語の区切りとは限らないのです。事前学習モデルでコプト語を扱う際には、各トークンを単語と合致させるのが理想です。しかし、それは現実には困難なため、各トークンは単語より短めにトークナイズした上で、系列ラベリ
ング (UPOS 付与) によって、単語をまとめ上げる手法が考えられます。すなわち、トークンが単語と合致した場合には UPOS をラベルとして付与し、そうでない場合には、最初のトークンに「B-」を付けた UPOS を、それ以降のトークンに「I-」を付けた UPOS を、それぞれ付与するのです。
!pip install deplacy transformers
class SeqL(object):def __init__(self,bert):
from transformers import pipeline
self.tagger=pipeline(task="ner",model=bert)
def __call__(self,text):
w=[(t["start"],t["end"],t["entity"]) for t in self.tagger(text)]
u="# text = "+text.replace("\n"," ")+"\n"for i,(s,e,p) in enumerate(w,1):
m,q="_" if i<len(w) and e<w[i][0] else "SpaceAfter=No",p.split("|")
f="_" if p.find("=")<0 else "|".join(t for t in q if t.find("=")>0)
u+="\t".join([str(i),text[s:e],"_",q[0],"_",f,"_","_","_",m])+"\n"return u+"\n"nlp=SeqL("KoichiYasuoka/roberta-base-coptic-upos")
doc=nlp("ⲙⲟⲟϣⲉϩⲱⲥϣⲏⲣⲉⲙⲡⲟⲩⲟⲉⲓⲛ ")import deplacy
deplacy.serve(doc,port=None)

B-VERB

I-VERB

I-VERB

ⲙ

ⲟⲟϣ

ⲉ

SCONJ

NOUN

ϩⲱⲥ ϣⲏⲣⲉ

ADP

DET

NOUN

ⲙ

ⲡ

ⲟⲩⲟⲉⲓⲛ

図 113: roberta-base-coptic-upos による UPOS 付与

Google Colaboratory 上の Transformers を用いて、roberta-base-coptic-upos[108] でコプト語の例文「ⲙⲟⲟϣⲉϩⲱⲥϣⲏⲣⲉⲙⲡⲟⲩⲟⲉⲓⲛ 」に UPOS を付与するプログラムと、その結果を
図 113 に示します。「ϩⲱⲥ」「ϣⲏⲣⲉ」「ⲙ」「ⲡ」「ⲟⲩⲟⲉⲓⲛ」の各単語では、各トークンがそのまま単語と合致しており、それぞれ UPOS 品詞 SCONJ・NOUN・ADP・DET・NOUNが付与されています。
「ⲙⲟⲟϣⲉ」は、3 つのトークンに泣き別れてしまっており、それぞれに B-VERB・I-VERB・I-VERB が付与されています。

[108]https://huggingface.co/KoichiYasuoka/roberta-base-coptic-upos– 80 –

15.2 コプト語 UD における係り受け解析
esupar[42] は、隣接行列型係り受け解析アルゴリズムを、事前学習モデルで実装しています。Google Colaboratory 上の esupar を用いて、roberta-base-coptic-upos でコプト語の例
文「ⲙⲟⲟϣⲉϩⲱⲥϣⲏⲣⲉⲙⲡⲟⲩⲟⲉⲓⲛ 」を係り受け解析するプログラムと、その結果を図 114に示します。解析結果を見ていくことにしましょう。
!pip install esupar
import esupar
nlp=esupar.load("KoichiYasuoka/roberta-base-coptic-upos")
doc=nlp("ⲙⲟⲟϣⲉϩⲱⲥϣⲏⲣⲉⲙⲡⲟⲩⲟⲉⲓⲛ ")import deplacy
deplacy.serve(doc,port=None)
root

nmod
case

advcl
mark
VERB

SCONJ

det
NOUN

ADP

DET

NOUN

ⲙ

ⲡ

ⲟⲩⲟⲉⲓⲛ

ⲙⲟⲟϣⲉ ϩⲱⲥ ϣⲏⲣⲉ

図 114: roberta-base-coptic-upos によるコプト語の係り受け解析
図 114 の例文は、主節「ⲙⲟⲟϣⲉ」と従属節「ϩⲱⲥϣⲏⲣⲉⲙⲡⲟⲩⲟⲉⲓⲛ」から構成されており、advcl で繫がれています。主節は動詞「ⲙⲟⲟϣⲉ」のみです。従属節はコピュラ文 (ただし主語も繫辞もない) で、「ϩⲱⲥ」が mark で繫がれています。
「ⲙⲡⲟⲩⲟⲉⲓⲛ」は「ϣⲏⲣⲉ」を修飾していて、nmod で繫がれています。
「ⲙⲡⲟⲩⲟⲉⲓⲛ」は、前置詞「ⲙ」と冠詞「ⲡ」と名詞「ⲟⲩⲟⲉⲓⲛ」から成っていて、それぞれ case と det で繫がれています。
なお、コプト語 UD の係り受けタグには、表 4 に加え、斜格補語による連用修飾を表す obl:npmod、関係転換詞による連体修飾節を表す acl:relcl も用いられます[109] 。

15.3 コプト語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar で、コプト語ミニ DeBERTa モデルを製作してみましょう。手順を図 115〜118 に示します。
最初に、訓練のための文章を準備しましょう (図 115)。train.txt の文章の材料として、ここでは Coptic Scriptorium Corpora[110] と UD Coptic-Scriptorium[111] を元にしていますが、好みに応じ、コプト語の他の文章を増量するのもいいでしょう。train.txt と同時に、各単語を空白で区切った token.txt も準備しており、トークナイザの作成に用います。Coptic
Scriptorium Corpora の各 CoNLL-U ファイルは、train.upos にまとめ上げて、品詞付与の学習に用います。また、UD Coptic-Scriptorium の各 CoNLL-U ファイルは、係り受け解析の学習に用います。
続けて、token.txt の各単語から、コプト語向けトークナイザを、my-dir/tokenizer-copに作成しましょう。図 116 では、Unigram トークナイザ (SentencePiece[83] の改造版) を[109]

https://universaldependencies.org/cop/dep
http://data.copticscriptorium.org/index/corpus[111]
https://github.com/UniversalDependencies/UD_Coptic-Scriptorium[110]– 81 –

!pip install esupar spacy-alignments accelerate
import os
url="https://github.com/UniversalDependencies/UD_Coptic-Scriptorium"d=os.path.basename(url)!test -d {d} || git clone --depth=1 {url}!for F in train dev test ; do cp {d}/*-$$F.conllu $$F.conllu ; done
url="https://github.com/CopticScriptorium/corpora"d=os.path.basename(url)!test -d {d} || git clone --depth=1 {url}s=’’’{if(NF==10&&$1~/^[1-9][0-9]*$/)printf($1>1?" %s":"%s",$2);if(NF==0){print;
if(u!~/\\n[^#1-9]/)print u>"train.upos";u=""}else u=u$0"\\n"}’’’!nawk -F’\t’ ’{s}’ {d}/*/*/*.conllu | tee token.txt > train.txt!sed -n "s/^# text = //p" train.upos *.conllu >> train.txt

図 115: コプト語ミニモデル製作のための準備
from transformers import DebertaV2TokenizerFast
from tokenizers import (Tokenizer,models,pre_tokenizers,normalizers,processors,
decoders,trainers)
s=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
spt=Tokenizer(models.Unigram())
spt.pre_tokenizer=pre_tokenizers.Sequence([pre_tokenizers.Whitespace(),pre_tokenizers.Punctuation()])
spt.normalizer=normalizers.Sequence([normalizers.Nmt(),normalizers.NFD(),normalizers.StripAccents()])
spt.post_processor=processors.TemplateProcessing(single="[CLS] $A [SEP]",
pair="[CLS] $A [SEP] $B:1 [SEP]:1",special_tokens=[("[CLS]",0),("[SEP]",2)])
spt.decoder=decoders.WordPiece(prefix="",cleanup=True)
spt.train(trainer=trainers.UnigramTrainer(vocab_size=3000,max_piece_length=8,
special_tokens=s,unk_token="[UNK]",n_sub_iterations=2),files=["token.txt"])
spt.save("tokenizer.json")
tkz=DebertaV2TokenizerFast(tokenizer_file="tokenizer.json",split_by_punct=True,
do_lower_case=False,keep_accents=False,vocab_file="/dev/null")
tkz.save_pretrained("my-dir/tokenizer-cop")

図 116: コプト語向けトークナイザの作成

token.txt に適用し、それを DebertaV2TokenizerFast という Transformers のトークナイザに組み上げて、コプト語向けトークナイザを作成しています。語彙数を 3000 に絞った上で、各トークンの文字数を最大 8 文字 (アクセント記号は除去) としています。
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-cop に作成しましょう。図117 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしていますが、GPUでも 15 分程度かかってしまいます。
最後に、my-dir/deberta-cop と各 ConLL-U ファイルから、品詞付与・係り受け解析モデル
my-dir/deberta-cop-upos を製作しましょう (図 118)。うまく my-dir/deberta-cop-upos ができたら、esupar でテストしてみましょう。ただ、図 119 の例では、「ϣⲏⲣⲉ」を「ⲙⲟⲟϣⲉ」の斜格補語 (obl) だと解釈してしまっており、図 114 とは異なる結果になっているようです。

– 82 –

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-cop",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-cop")tkz.save_pretrained("my-dir/deberta-cop")

図 117: コプト語ミニ DeBERTa モデルの作成

s,d="my-dir/deberta-cop","my-dir/deberta-cop-upos"!python -m esupar.train {s} {d} 32 /tmp train.upos!python -m esupar.train {d} {d} 32 /// train.conllu dev.conllu test.conllu

図 118: コプト語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-cop-upos")
doc=nlp("ⲙⲟⲟϣⲉϩⲱⲥϣⲏⲣⲉⲙⲡⲟⲩⲟⲉⲓⲛ ")import deplacy
deplacy.serve(doc,port=None)
root

nmod
case

obl
case
VERB

SCONJ

det
NOUN

ADP

DET

NOUN

ⲙ

ⲡ

ⲟⲩⲟⲉⲓⲛ

ⲙⲟⲟϣⲉ ϩⲱⲥ ϣⲏⲣⲉ

図 119: コプト語向け品詞付与・係り受け解析ミニモデルのテスト– 83 –

16

スペイン語編16.1 スペイン語 UD における品詞付与と係り受け解析
spacy-transformers[69] は、BERT など事前学習モデルによる状態遷移型係り受け解析ア
ルゴリズムを実装しており、スペイン語向けには、bert-base-spanish-wwm-cased[112] を元にした es dep news trf を公開[113] しています。Google Colaboratory 上の spacy-transformers
を用いて、スペイン語の例文「Deberı́as aclararlo al castellano y al catalán」を品詞付与・係り受け解析するプログラムと、その結果を図 120 に示します。解析結果を見ていくことにしましょう。
!pip install spacy-transformers deplacy!python -m spacy download es_dep_news_trf
import spacy
nlp=spacy.load("es_dep_news_trf")
doc=nlp("Deberı́as aclararlo al castellano y al catalán")
import deplacy
deplacy.serve(doc,port=None)
ROOT

conj
obl

aux

cc
case

case

AUX

VERB

ADP

NOUN

CCONJ

ADP

NOUN

AUX

VERB

ADP

NOUN

CCONJ

ADP

NOUN

al

castellanoyalcatalán

Deberías aclararlo

図 120: spacy-transformers によるスペイン語の係り受け解析
動詞「aclarar」は目的語「lo」が付いた形となっており、助動詞「Deberı́as」と aux で繫がれています。斜格補語は「castellano」と「catalán」の 2 つですが、「castellano」の方が obl で繫がれていて、その先に conj で「catalán」が繫がれており、そのまた先に cc で「y」が繫がれていると同時に、「castellano」と「catalán」にそれぞれ「al」が case で繫
がれています。なお、spacy-transformers は「al」を 1 語だとみなしていますが、スペイン語 UD では「a」「el」の 2 語に分離した上で扱うことになっており、縮合語の解析が不十分です。
UDPipe 2 WebAPI は、UDPipe 2 の係り受け解析モデル[63] を、WebAPI の形で公開しています。内部的には、隣接行列型係り受け解析アルゴリズムを使っています。Google
Colaboratory から UDPipe 2 WebAPI の spanish-ancora にアクセスするプログラムと、スペイン語の例文「Deberı́as aclararlo al castellano y al catalán」を品詞付与・係り受け解析した結果を、図 121 に示します。
「al」が内部的には 2 語として扱われており、「a」が前置詞、「el」が限定詞 (冠詞) として、それぞれ case・det で繫がれています。また、「aclararlo」
が 2 語として扱われており、「aclarar」に「lo」が obj で繫がれています。ただし、そうであれば「aclarar」と「castellano」を繫ぐ obj は解析ミスで、ここは obl となるべきです。

[112]

José Cañete, Gabriel Chaperon, Rodrigo Fuentes, Jorge Pérez: Spanish pre-trained BERT model and evaluation data, ICLR 2020 (April 26, 2020).
[113]
https://huggingface.co/spacy/es_dep_news_trf– 84 –

!pip install deplacy
class UDPipe2WebAPI(object):def __init__(self,lang):
self.url="https://lindat.mff.cuni.cz/services/udpipe/api/process"self.params={"model":lang,"tokenizer":"","tagger":"","parser":""}
def __call__(self,text):
import urllib.parse,urllib.request,json
self.params["data"]=urllib.parse.quote(text)
u=self.url+"?"+"&".join(k+"="+v for k,v in self.params.items())
with urllib.request.urlopen(u) as r:
return json.loads(r.read())["result"]
nlp=UDPipe2WebAPI("spanish-ancora")
doc=nlp("Deberı́as aclararlo al castellano y al catalán")
import deplacy
deplacy.serve(doc,port=None)
root

conj
obj

cc
case

aux

obj

AUX

VERB

vmic1p0

vmn0000

case
det

PRON

Deberías aclararlo

ADP

DET

spcms

al

det
NOUN

CCONJ

ADP

ncms000cc

spcms

castellano

y

DET

NOUN
ncms000alcatalán

図 121: UDPipe 2 WebAPI によるスペイン語の係り受け解析
なお、スペイン語 UD の係り受けタグには、表 4 に加え、受動態を表す nsubj:pass・
csubj:pass・expl:pass・aux:pass、関係代名詞による連体修飾節を表す acl:relcl、再帰
動詞における再帰代名詞を表す expl:pv も用いられます[114] 。

16.2 スペイン語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar[42] で、スペイン語ミニ DeBERTa モデルを製作してみましょう。手順を図 122〜125 に示します。
最初に、訓練のための文章を準備しましょう (図 122)。train.txt の文章の材料として、ここでは UD Spanish-Ancora[115] と UD Spanish-GSD[116] を元にしていますが、好みに応じ、スペイン語の他の文章を増量するのもいいでしょう。なお、各 CoNLL-U ファイルは、品
詞付与・係り受け解析の学習にも用います。
続けて、スペイン語向けトークナイザを、my-dir/tokenizer-es に作成しましょう。図 123
では、Transformers の BertTokenizerFast を使って、スペイン語向けトークナイザを作成
しています。
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-es に作成しましょう。図124 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしており、CPU なら
1 時間程度、GPU なら 10 分程度で作成できます。
[114]

https://universaldependencies.org/es/#syntax
https://github.com/UniversalDependencies/UD_Spanish-Ancora[116]
https://github.com/UniversalDependencies/UD_Spanish-GSD[115]– 85 –

!pip install esupar spacy-alignments accelerate
import os
url="https://github.com/UniversalDependencies/UD_Spanish-AnCora"!test -d {os.path.basename(url)} || git clone --depth=1 {url}url="https://github.com/UniversalDependencies/UD_Spanish-GSD"!test -d {os.path.basename(url)} || git clone --depth=1 {url}!for F in train dev test ; do cat UD_Spanish-*/*-$$F.conllu > $$F.conllu ; done
!sed -n "s/^# text = //p" *.conllu > train.txt

図 122: スペイン語ミニモデル製作のための準備

from transformers import BertTokenizerFast
from tokenizers import BertWordPieceTokenizers=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
wpt=BertWordPieceTokenizer(strip_accents=False)
wpt.train(files=["train.txt"],vocab_size=30000,special_tokens=s)
wpt.save_model(".")
tkz=BertTokenizerFast(vocab_file="vocab.txt",strip_accents=False,never_split=s)
tkz.save_pretrained("my-dir/tokenizer-es")

図 123: スペイン語向けトークナイザの作成

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-es",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-es")tkz.save_pretrained("my-dir/deberta-es")

図 124: スペイン語ミニ DeBERTa モデルの作成– 86 –

最後に、my-dir/deberta-es と UD Spanish-Ancora・UD Spanish-GSD から、品詞付与・係り
受け解析モデル my-dir/deberta-es-upos を製作しましょう (図 125)。うまく my-dir/debertaes-upos が製作できたら、esupar でテストしてみましょう。図 126 の例では「aclararlo」が1 語とみなされており、図 121 とは異なる結果になっているようです。
!python -m esupar.train my-dir/deberta-es my-dir/deberta-es-upos .

図 125: スペイン語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-es-upos")
doc=nlp("Deberı́as aclararlo al castellano y al catalán")
import deplacy
deplacy.serve(doc,port=None)
root

conj
obl

cc
case

aux
AUX

case
det

VERB

Deberías aclararlo

ADP

DET

al

det
NOUN

CCONJ

castellano

y

ADP

DET

al

NOUN

catalán

図 126: スペイン語向け品詞付与・係り受け解析ミニモデルのテスト– 87 –

17

カタルーニャ語編

17.1 カタルーニャ語 UD における品詞付与と係り受け解析
Trankit[60] は、XLM-RoBERTa をベースに、隣接行列型係り受け解析アルゴリズムを、様々な言語向けに実装しています。Google Colaboratory 上の Trankit を用いて、カタルー
ニャ語の例文「Ho hauries d’aclarir al català i al castellà」を品詞付与・係り受け解析するプログラムと、その結果を図 127 に示します。解析結果を見ていくことにしましょう。
!pip install trankit transformers deplacy
import trankit
nlp=trankit.Pipeline("catalan")doc=nlp("Ho hauries d’aclarir al català i al castellà")
import deplacy
deplacy.serve(doc,port=None)
root
obj

conj
aux

obl
mark

cc
case

case

PRON

AUX

ADP

VERB

ADP

NOUN

CCONJ

ADP

NOUN

PRON

AUX

ADP

VERB

ADP

NOUN

CCONJ

ADP

NOUN

d’

aclariralcatalà

ialcastellà

Ho hauries

図 127: Trankit によるカタルーニャ語の係り受け解析
動詞「aclarir」には、目的語「Ho」が obj で繫がれており、さらに助動詞「hauries」と「d’」が aux と mark で繫がれています。斜格補語は「català」と「castellà」の 2 つですが、「català」の方が obl で繫がれていて、その先に conj で「castellà」が繫がれており、その「català」と「castellà」にそれぞれ「al」がまた先に cc で「i」が繫がれていると同時に、
case で繫がれています。なお、Trankit は「al」を 1 語だとみなしていますが、カタルー「el」の 2 語に分離した上で扱うことになっており、縮合語の解析がニャ語 UD では「a」
不十分です。
UDPipe 2 WebAPI は、UDPipe 2 の係り受け解析モデル[63] を、WebAPI の形で公開しています。内部的には、隣接行列型係り受け解析アルゴリズムを使っています。Google
Colaboratory から UDPipe 2 WebAPI の catalan-ancora にアクセスするプログラムと、カタ
ルーニャ語の例文「Ho hauries d’aclarir al català i al castellà」を品詞付与・係り受け解析した結果を、図 128 に示します。「al」が内部的には 2 語として扱われており、「a」が前置詞、「el」が限定詞 (冠詞) として、それぞれ case・det で繫がれています。
なお、カタルーニャ語 UD の係り受けタグには、表 4 に加え、受動態を表す nsubj:pass・
csubj:pass・expl:pass・aux:pass、関係代名詞による連体修飾節を表す acl:relcl、再帰
動詞における再帰代名詞を表す expl:pv も用いられます[117] 。

[117]

https://universaldependencies.org/ca/#syntax– 88 –

!pip install deplacy
class UDPipe2WebAPI(object):def __init__(self,lang):
self.url="https://lindat.mff.cuni.cz/services/udpipe/api/process"self.params={"model":lang,"tokenizer":"","tagger":"","parser":""}
def __call__(self,text):
import urllib.parse,urllib.request,json
self.params["data"]=urllib.parse.quote(text)
u=self.url+"?"+"&".join(k+"="+v for k,v in self.params.items())
with urllib.request.urlopen(u) as r:
return json.loads(r.read())["result"]
nlp=UDPipe2WebAPI("catalan-ancora")
doc=nlp("Ho hauries d’aclarir al català i al castellà")
import deplacy
deplacy.serve(doc,port=None)
root

conj

obj

obl
aux

cc
case

mark
PRON

AUX

ADP

VERB

ADP

pp3nn000

vaic3p0

sps00

vmn0000

spcms

d’aclarir

Ho hauries

case
det

DET

al

det
NOUN

CCONJ

ADP

ncms000

cc

spcms

català

i

DET

NOUN
ncms000alcastellà

図 128: UDPipe 2 WebAPI によるカタルーニャ語の係り受け解析

17.2 カタルーニャ語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar[42] で、カタルーニャ語ミニ DeBERTa モデルを製作してみましょう。手順を図 129〜132 に示します。
最初に、訓練のための文章を準備しましょう (図 129)。train.txt の文章の材料として、
ここでは UD Catalan-Ancora[118] と Softcatalà コーパス[119] を元にしていますが、好みに応じ、カタルーニャ語の他の文章を増量するのもいいでしょう。なお、UD Catalan-Ancoraの各 CoNLL-U ファイルは、品詞付与・係り受け解析の学習にも用います。
続けて、カタルーニャ語向けトークナイザを、my-dir/tokenizer-ca に作成しましょう。
図 130 では、Transformers の BertTokenizerFast を使って、カタルーニャ語向けトークナ
イザを作成しています。
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-ca に作成しましょう。図131 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしています。
最後に、my-dir/deberta-ca と UD Catalan-Ancora から、品詞付与・係り受け解析モデル
my-dir/deberta-ca-upos を製作しましょう (図 132)。うまく my-dir/deberta-ca-upos が製作できたら、esupar でテストしてみましょう (図 133)。esupar は縮合語を UPOS 付与においてサポート (図 134) しており、係り受け解析では「al」を 2 語として処理します。

[118]
[119]

https://github.com/UniversalDependencies/UD_Catalan-Ancora
https://github.com/Softcatala/ca-text-corpus– 89 –

!pip install esupar spacy-alignments accelerate
import os
url="https://github.com/UniversalDependencies/UD_Catalan-AnCora"d=os.path.basename(url)!test -d {d} || git clone --depth=1 {url}!for F in train dev test ; do cat {d}/*-$$F.conllu > $$F.conllu ; done
url="https://github.com/Softcatala/ca-text-corpus"
d=os.path.basename(url)!test -d {d} || git clone --depth=1 {url}!sed -n "s/^# text = //p" *.conllu | cat {d}/data/*.txt - > train.txt

図 129: カタルーニャ語ミニモデル製作のための準備

from transformers import BertTokenizerFast
from tokenizers import BertWordPieceTokenizers=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
wpt=BertWordPieceTokenizer(strip_accents=False)
wpt.train(files=["train.txt"],vocab_size=30000,special_tokens=s)
wpt.save_model(".")
tkz=BertTokenizerFast(vocab_file="vocab.txt",strip_accents=False,never_split=s)
tkz.save_pretrained("my-dir/tokenizer-ca")

図 130: カタルーニャ語向けトークナイザの作成

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-ca",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-ca")
tkz.save_pretrained("my-dir/deberta-ca")

図 131: カタルーニャ語ミニ DeBERTa モデルの作成– 90 –

!python -m esupar.train my-dir/deberta-ca my-dir/deberta-ca-upos .

図 132: カタルーニャ語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-ca-upos")
doc=nlp("Ho hauries d’aclarir al català i al castellà")
import deplacy
deplacy.serve(doc,port=None)
root

conj

obj

obl
aux

cc
case

mark
PRON

AUX

Ho hauries

case
det

ADP

VERB

d’

aclarir

ADP

DET

al

det
NOUN

CCONJ

català

i

ADP

DET

al

NOUN

castellà

図 133: カタルーニャ語向け品詞付与・係り受け解析ミニモデルのテスト!pip install deplacy transformers
class SeqL(object):def __init__(self,bert):
from transformers import pipeline
self.tagger=pipeline(task="ner",model=bert)
def __call__(self,text):
w=[(t["start"],t["end"],t["entity"]) for t in self.tagger(text)]
u="# text = "+text.replace("\n"," ")+"\n"for i,(s,e,p) in enumerate(w,1):
m,q="_" if i<len(w) and e<w[i][0] else "SpaceAfter=No",p.split("|")
f="_" if p.find("=")<0 else "|".join(t for t in q if t.find("=")>0)
u+="\t".join([str(i),text[s:e],"_",q[0],"_",f,"_","_","_",m])+"\n"return u+"\n"nlp=SeqL("my-dir/deberta-ca-upos")
doc=nlp("Ho hauries d’aclarir al català i al castellà")
import deplacy
deplacy.serve(doc,port=None)

PRON

B-AUX

I-AUX

B-ADP

I-ADP

VERB

ADP+DET

NOUN

CCONJ

ADP+DETNOUN

Ho hauriesd’aclariralcatalà

ialcastellà

図 134: カタルーニャ語向け品詞付与・係り受け解析ミニモデルでの UPOS 付与– 91 –

18

ガリシア語編18.1 ガリシア語 UD における品詞付与と係り受け解析
UDPipe 2 WebAPI は、UDPipe 2 の係り受け解析モデル[63] を、WebAPI の形で公開しています。内部的には、隣接行列型係り受け解析アルゴリズムを使っています。Google
Colaboratory から UDPipe 2 WebAPI の galician-treegal にアクセスするプログラムと、ガ
リシア語の例文「Deberı́as acláralo no galego」を品詞付与・係り受け解析した結果を、図135 に示します。解析結果を見ていくことにしましょう。
!pip install deplacy
class UDPipe2WebAPI(object):def __init__(self,lang):
self.url="https://lindat.mff.cuni.cz/services/udpipe/api/process"self.params={"model":lang,"tokenizer":"","tagger":"","parser":""}
def __call__(self,text):
import urllib.parse,urllib.request,json
self.params["data"]=urllib.parse.quote(text)
u=self.url+"?"+"&".join(k+"="+v for k,v in self.params.items())
with urllib.request.urlopen(u) as r:
return json.loads(r.read())["result"]
nlp=UDPipe2WebAPI("galician-treegal")
doc=nlp("Deberı́as acláralo no galego")
import deplacy
deplacy.serve(doc,port=None)
root
obl
case
aux

obj

det

AUX

VERB

PRON

ADP

DET

Vci30s

V0f000Raa3msP

Ddms

Deberías

acláralo

no

NOUN
Scms

galego

図 135: UDPipe 2 WebAPI によるガリシア語の係り受け解析「acláralo」は、動詞「aclarar」と目的語「lo」の 2 語として扱われていて、obj で繫がれています。助動詞「Deberı́as」は aux で、斜格補語「galego」は obl で、それぞれ繫がれています。
「no」は、前置詞「em」と限定詞 (冠詞)「o」の 2 語として扱われていて、それぞれ「galego」から case・det で繫がれています。
なお、ガリシア語 UD の係り受けタグには、表 4 に加え、受動態を表す nsubj:pass と
aux:pass、氏名を表す flat:name、ガリシア語以外を表す flat:foreign も用いられます[120] 。

18.2 ガリシア語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar[42] で、ガリシア語ミニ DeBERTa モデルを製作してみましょう。手順を図 136〜139 に示します。
[120]

https://universaldependencies.org/gl/#syntax– 92 –

!pip install esupar spacy-alignments accelerate
import os
url="https://github.com/UniversalDependencies/UD_Galician-TreeGal"!test -d {os.path.basename(url)} || git clone --depth=1 {url}url="https://github.com/UniversalDependencies/UD_Galician-CTG"!test -d {os.path.basename(url)} || git clone --depth=1 {url}!for F in train dev test ; do cat UD_Galician-*/*-$$F.conllu > $$F.conllu ; done
!sed -n "s/^# text = //p" *.conllu > train.txt

図 136: ガリシア語ミニモデル製作のための準備
from transformers import BertTokenizerFast
from tokenizers import BertWordPieceTokenizers=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
wpt=BertWordPieceTokenizer()
wpt.train(files=["train.txt"],vocab_size=3000,special_tokens=s)
wpt.save_model(".")
tkz=BertTokenizerFast(vocab_file="vocab.txt",never_split=s)
tkz.save_pretrained("my-dir/tokenizer-gl")

図 137: ガリシア語向けトークナイザの作成
最初に、訓練のための文章を準備しましょう (図 136)。train.txt の文章の材料として、
ここでは UD Galician-TreeGal[121] と UD Galician-CTG[122] を元にしていますが、好みに応じ、ガリシア語の他の文章を増量するのもいいでしょう。なお、各 CoNLL-U ファイル
は、品詞付与・係り受け解析の学習にも用います。
続けて、ガリシア語向けトークナイザを、my-dir/tokenizer-gl に作成しましょう。図 137
では、Transformers の BertTokenizerFast を使って、ガリシア語向けトークナイザを作成
しています。語彙数 (vocab_size) を 3000 に絞っていますが、もう少し大きくした方がいいかもしれません。
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-gl に作成しましょう。図138 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしています。
最後に、my-dir/deberta-gl と UD Galician-TreeGal・UD Galician-CTG から、品詞付与・係
り受け解析モデル my-dir/deberta-gl-upos を製作しましょう (図 139)。うまく my-dir/debertagl-upos が製作できたら、esupar でテストしてみましょう。図 140 の例では「acláralo」が1 語とみなされており、図 135 とは異なる結果になっているようです。

[121]
[122]

https://github.com/UniversalDependencies/UD_Galician-TreeGal
https://github.com/UniversalDependencies/UD_Galician-CTG– 93 –

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-gl",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-gl")tkz.save_pretrained("my-dir/deberta-gl")

図 138: ガリシア語ミニ DeBERTa モデルの作成!python -m esupar.train my-dir/deberta-gl my-dir/deberta-gl-upos .

図 139: ガリシア語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-gl-upos")
doc=nlp("Deberı́as acláralo no galego")
import deplacy
deplacy.serve(doc,port=None)
root
obl
case
aux
AUX

det
VERB

Deberías acláralo

ADP

DET

no

NOUN

galego

図 140: ガリシア語向け品詞付与・係り受け解析ミニモデルのテスト– 94 –

19

ポルトガル語編

19.1 ポルトガル語 UD における品詞付与と係り受け解析
UDPipe 2 WebAPI は、UDPipe 2 の係り受け解析モデル[63] を、WebAPI の形で公開しています。内部的には、隣接行列型係り受け解析アルゴリズムを使っています。Google
Colaboratory から UDPipe 2 WebAPI の portuguese-bosque にアクセスするプログラムと、
ポルトガル語の例文「Você deve esclarecê-lo no português」を品詞付与・係り受け解析した結果を、図 141 に示します。解析結果を見ていくことにしましょう。
!pip install deplacy
class UDPipe2WebAPI(object):def __init__(self,lang):
self.url="https://lindat.mff.cuni.cz/services/udpipe/api/process"self.params={"model":lang,"tokenizer":"","tagger":"","parser":""}
def __call__(self,text):
import urllib.parse,urllib.request,json
self.params["data"]=urllib.parse.quote(text)
u=self.url+"?"+"&".join(k+"="+v for k,v in self.params.items())
with urllib.request.urlopen(u) as r:
return json.loads(r.read())["result"]
nlp=UDPipe2WebAPI("portuguese-bosque")
doc=nlp("Voc^e deve esclarec^
e-lo no portugu^es")import deplacy
deplacy.serve(doc,port=None)
obl
root
nsubj
PRON

case
xcomp

VERB

VERB

obj

det
PRON

Você deve esclarecê-lo

ADP

DET

no

NOUN

português

図 141: UDPipe 2 WebAPI によるポルトガル語の係り受け解析「esclarecê-lo」は、動詞「esclarecer」と目的語「lo」の 2 語として扱われていて、obj
で繫がれています。動詞「deve」の主語「Você」は、同時に「esclarecer」の主語でもあることから、「Você」が nsubj で、「esclarecer」が xcomp で繫がれています。
「português」
は「esclarecer」の斜格補語であり、obl で繫がれています。
「no」は、前置詞「em」と限
定詞 (冠詞)「o」の 2 語として扱われていて、それぞれ「português」から case・det で繫
がれています。
なお、ポルトガル語 UD の係り受けタグには、表 4 に加え、受動態を表す nsubj:passと csubj:pass、所有に関する連体修飾を表す nmod:poss、限定詞の前に置かれる形容詞を表す det:predet、接続における前置副詞を表す cc:preconj も用いられます[123] 。

[123]https://universaldependencies.org/pt/#syntax– 95 –

19.2 ポルトガル語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar[42] で、ポルトガル語ミニ DeBERTa モデルを製作してみましょう。手順を図 142〜145 に示します。
最初に、訓練のための文章を準備しましょう (図 142)。train.txt の文章の材料として、
ここでは UD Portuguese-Bosque[124] と UD Portuguese-PetroGold[125] を元にしていますが、好みに応じ、ポルトガル語の他の文章を増量するのもいいでしょう。なお、各 CoNLL-U
ファイルは、品詞付与・係り受け解析の学習にも用います。
!pip install esupar spacy-alignments accelerate
import os
url="https://github.com/UniversalDependencies/UD_Portuguese-Bosque"!test -d {os.path.basename(url)} || git clone --depth=1 {url}url="https://github.com/UniversalDependencies/UD_Portuguese-PetroGold"!test -d {os.path.basename(url)} || git clone --depth=1 {url}!for F in train dev test ; do cat UD_Port*/*-$$F.conllu > $$F.conllu ; done
!sed -n "s/^# text = //p" *.conllu > train.txt

図 142: ポルトガル語ミニモデル製作のための準備

from transformers import BertTokenizerFast
from tokenizers import BertWordPieceTokenizers=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
wpt=BertWordPieceTokenizer(strip_accents=False)
wpt.train(files=["train.txt"],vocab_size=30000,special_tokens=s)
wpt.save_model(".")
tkz=BertTokenizerFast(vocab_file="vocab.txt",strip_accents=False,never_split=s)
tkz.save_pretrained("my-dir/tokenizer-pt")

図 143: ポルトガル語向けトークナイザの作成
続けて、ポルトガル語向けトークナイザを、my-dir/tokenizer-pt に作成しましょう。図143 では、Transformers の BertTokenizerFast を使って、ポルトガル語向けトークナイザを作成しています。
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-pt に作成しましょう。図144 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしています。
最後に、my-dir/deberta-pt と UD Portuguese-Bosque・UD Portuguese-PetroGold から、品
詞付与・係り受け解析モデル my-dir/deberta-pt-upos を製作しましょう (図 145)。うまくmy-dir/deberta-pt-upos が製作できたら、esupar でテストしてみましょう。図 146 の例では、ハイフンが 1 語とみなされており、その周辺の係り受けや品詞が、図 141 とは異なる結果になっているようです。

[124]
[125]

https://github.com/UniversalDependencies/UD_Portuguese-Bosque
https://github.com/UniversalDependencies/UD_Portuguese-PetroGold– 96 –

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-pt",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-pt")
tkz.save_pretrained("my-dir/deberta-pt")

図 144: ポルトガル語ミニ DeBERTa モデルの作成!python -m esupar.train my-dir/deberta-pt my-dir/deberta-pt-upos .

図 145: ポルトガル語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-pt-upos")
doc=nlp("Voc^e deve esclarec^
e-lo no portugu^es")import deplacy
deplacy.serve(doc,port=None)
root
obl
nsubj

obj
aux

PRON

AUX

case

punct
VERB

Você deve esclarecê

det

PUNCT

PRON

-

lo

ADP

DET

no

NOUN

português

図 146: ポルトガル語向け品詞付与・係り受け解析ミニモデルのテスト– 97 –

20

イタリア語編20.1 イタリア語 UD における品詞付与と係り受け解析
UDPipe 2 WebAPI は、UDPipe 2 の係り受け解析モデル[63] を、WebAPI の形で公開しています。内部的には、隣接行列型係り受け解析アルゴリズムを使っています。Google
Colaboratory から UDPipe 2 WebAPI の italian-isdt にアクセスするプログラムと、イタリ
ア語の例文「Dovresti chiarirlo nel documento in italiano o latino」を品詞付与・係り受け解析した結果を、図 147 に示します。解析結果を見ていくことにしましょう。
!pip install deplacy
class UDPipe2WebAPI(object):def __init__(self,lang):
self.url="https://lindat.mff.cuni.cz/services/udpipe/api/process"self.params={"model":lang,"tokenizer":"","tagger":"","parser":""}
def __call__(self,text):
import urllib.parse,urllib.request,json
self.params["data"]=urllib.parse.quote(text)
u=self.url+"?"+"&".join(k+"="+v for k,v in self.params.items())
with urllib.request.urlopen(u) as r:
return json.loads(r.read())["result"]
nlp=UDPipe2WebAPI("italian-isdt")
doc=nlp("Dovresti chiarirlo nel documento in italiano o latino")
import deplacy
deplacy.serve(doc,port=None)
root
obl
case
aux

obj

nmod
case

det

conj
cc

AUX

VERB

PRON

ADP

DET

NOUN

ADP

NOUN

CCONJ

NOUN

VM

V

PC

E

RD

S

E

S

CC

S

documentoinitalianoolatinoDovresti chiarirlonel

図 147: UDPipe 2 WebAPI によるイタリア語の係り受け解析「chiarirlo」は、動詞「chiarire」と目的語「lo」の 2 語として扱われていて、obj で繫
がれています。助動詞「Dovresti」は aux で、斜格補語「documento」は obl で、それぞれ繫がれています。「nel」は、前置詞「in」と限定詞 (冠詞)「il」の 2 語として扱われていて、それぞれ「documento」から case・det で繫がれています。「italiano」と「latino」
は、いずれも「documento」を修飾していますが、「italiano」の方が nmod で繫がれていて、その先に「latino」が conj で繫がれており、そのまた先に cc で「o」が繫がれていると同時に、「italiano」には「in」が case で繫がれています。
なお、イタリア語 UD の係り受けタグには、表 4 に加え、受動態を表す nsubj:pass・
csubj:pass・expl:pass・aux:pass、受動態の動作主を表す obl:agent、非人称形式主語を表す expl:impers、所有を表す det:poss、限定詞の前に置かれる形容詞を表す det:predet、
関係代名詞による連体修飾節を表す acl:relcl、氏名を表す flat:name、イタリア語以外を表す flat:foreign など、多数のタグが用いられます[126] 。
[126]

https://universaldependencies.org/it/#syntax– 98 –

20.2 イタリア語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar[42] で、イタリア語ミニ DeBERTa モデルを製作してみましょう。手順を図 148〜151 に示します。
最初に、訓練のための文章を準備しましょう (図 148)。train.txt の文章の材料として、
ここでは UD Italian-ISDT[127] と UD Italian-VIT[128] を元にしていますが、好みに応じ、イタリア語の他の文章を増量するのもいいでしょう。なお、各 CoNLL-U ファイルは、品詞付与・係り受け解析の学習にも用います。
!pip install esupar spacy-alignments accelerate
import os
url="https://github.com/UniversalDependencies/UD_Italian-ISDT"!test -d {os.path.basename(url)} || git clone --depth=1 {url}url="https://github.com/UniversalDependencies/UD_Italian-VIT"!test -d {os.path.basename(url)} || git clone --depth=1 {url}!for F in train dev test ; do cat UD_Italian-*/*-$$F.conllu > $$F.conllu ; done
!sed -n "s/^# text = //p" *.conllu > train.txt

図 148: イタリア語ミニモデル製作のための準備

from transformers import BertTokenizerFast
from tokenizers import BertWordPieceTokenizers=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
wpt=BertWordPieceTokenizer(strip_accents=False)
wpt.train(files=["train.txt"],vocab_size=30000,special_tokens=s)
wpt.save_model(".")
tkz=BertTokenizerFast(vocab_file="vocab.txt",strip_accents=False,never_split=s)
tkz.save_pretrained("my-dir/tokenizer-it")

図 149: イタリア語向けトークナイザの作成
続けて、イタリア語向けトークナイザを、my-dir/tokenizer-it に作成しましょう。図 149
では、Transformers の BertTokenizerFast を使って、イタリア語向けトークナイザを作成
しています。
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-it に作成しましょう。図150 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしています。
最後に、my-dir/deberta-it と UD Italian-ISDT・UD Italian-VIT から、品詞付与・係り受
け解析モデル my-dir/deberta-it-upos を製作しましょう (図 151)。うまく my-dir/deberta-itupos が製作できたら、esupar でテストしてみましょう。図 152 の例では「chiarirlo」が 1
語とみなされており、図 147 とは異なる結果になっているようです。

[127]
[128]

https://github.com/UniversalDependencies/UD_Italian-ISDT
https://github.com/UniversalDependencies/UD_Italian-VIT– 99 –

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-it",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-it")tkz.save_pretrained("my-dir/deberta-it")

図 150: イタリア語ミニ DeBERTa モデルの作成!python -m esupar.train my-dir/deberta-it my-dir/deberta-it-upos .

図 151: イタリア語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-it-upos")
doc=nlp("Dovresti chiarirlo nel documento in italiano o latino")
import deplacy
deplacy.serve(doc,port=None)
root
obl
case
aux
AUX

nmod
case

det
VERB

Dovresti chiarirlo

ADP

DET

nel

conj
cc

NOUN

ADP

NOUN

CCONJ

NOUN

documentoinitalianoolatino図 152: イタリア語向け品詞付与・係り受け解析ミニモデルのテスト– 100 –

21

ラテン語編

21.1 ラテン語 UD における品詞付与と係り受け解析
Trankit[60] は、XLM-RoBERTa をベースに、隣接行列型係り受け解析アルゴリズムを、様々な言語向けに実装しています。Google Colaboratory 上の Trankit を用いて、ラテン語の例文「hoc in documento latino italicove declarare debes」を品詞付与・係り受け解析するプログラムと、その結果を図 153 に示します。解析結果を見ていくことにしましょう。
!pip install trankit deplacy
import trankit
nlp=trankit.Pipeline("latin")
doc=nlp("hoc in documento latino italicove declarare debes")
import deplacy
deplacy.serve(doc,port=None)
obj
obl
amod
case

root

amod

xcomp

PRON

ADP

NOUN

ADJ

ADJ

VERB

VERB

F1|grn1|casD|gen3

S4

B1|grn1|casF|gen3

B1|grn1|casF|gen3

C1|grn1|casF|gen3

J3|modH|tem1

N3|modA|tem1|gen5

hoc

in

documento latino italicove declarare debes

図 153: Trankit によるラテン語の係り受け解析
動詞「debes」の主語 (二人称単数) は、動詞「declarare」の意味上の主語でもあることか
ら、これらは xcomp で繫がれています。目的語「hoc」は obj で、斜格補語「documento」
は obl で、それぞれ「declarare」に繫がれています。「latino」と「italicove」は、いずれ「in」は case で繫がれています。
も「documento」を修飾していて amod で繫がれており、「italicove」を「italico」と「ve」の 2 語とすべきかどうかは、議論の分かれるところで、ここでは 1 語とみなしています。
なお、ラテン語 UD の係り受けタグには、表 4 に加え、数多くの拡張が用いられてい[129]るのですが、拡張どうしの間で混乱が起こっており、事態の収拾が望まれます。

21.2 ラテン語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar[42] で、ラテン語ミニ DeBERTa モデルを製作してみましょう。手順を図 154〜157 に示します。
最初に、訓練のための文章を準備しましょう (図 154)。train.txt の文章の材料として、
ここでは UD Latin-ITTB[130] と UD Latin-LLCT[131] を元にしていますが、好みに応じ、ラテン語の他の文章を増量するのもいいでしょう。なお、各 CoNLL-U ファイルは、品詞付
与・係り受け解析の学習にも用います。

[129]

https://universaldependencies.org/la/#relations-overview
https://github.com/UniversalDependencies/UD_Latin-ITTB[131]
https://github.com/UniversalDependencies/UD_Latin-LLCT[130]– 101 –

!pip install esupar spacy-alignments accelerate
import os
url="https://github.com/UniversalDependencies/UD_Latin-ITTB"!test -d {os.path.basename(url)} || git clone --depth=1 {url}url="https://github.com/UniversalDependencies/UD_Latin-LLCT"!test -d {os.path.basename(url)} || git clone --depth=1 {url}!for F in train dev test ; do cat UD_Latin-*/*-$$F.conllu > $$F.conllu ; done
!sed -n "s/^# text = //p" *.conllu > train.txt

図 154: ラテン語ミニモデル製作のための準備

from transformers import BertTokenizerFast
from tokenizers import BertWordPieceTokenizers=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
wpt=BertWordPieceTokenizer(strip_accents=False)
wpt.train(files=["train.txt"],vocab_size=8000,special_tokens=s)
wpt.save_model(".")
tkz=BertTokenizerFast(vocab_file="vocab.txt",strip_accents=False,never_split=s)
tkz.save_pretrained("my-dir/tokenizer-la")図 155: ラテン語向けトークナイザの作成

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-la",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-la")tkz.save_pretrained("my-dir/deberta-la")図 156: ラテン語ミニ DeBERTa モデルの作成– 102 –

続けて、ラテン語向けトークナイザを、my-dir/tokenizer-la に作成しましょう。図 155
では、Transformers の BertTokenizerFast を使って、ラテン語向けトークナイザを作成しています。語彙数 (vocab_size) を 8000 に絞っていますが、もう少し大きくした方がいいかもしれません。
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-la に作成しましょう。図156 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしています。
最後に、my-dir/deberta-la と UD Latin-ITTB・UD Latin-LLCT から、品詞付与・係り受
け解析モデル my-dir/deberta-la-upos を製作しましょう (図 157)。うまく my-dir/deberta-laupos が製作できたら、esupar でテストしてみましょう (図 158)。
!python -m esupar.train my-dir/deberta-la my-dir/deberta-la-upos .

図 157: ラテン語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-la-upos")
doc=nlp("hoc in documento latino italicove declarare debes")
import deplacy
deplacy.serve(doc,port=None)
obj
obl
amod
case
PRON

ADP

hoc

in

root

amod
NOUN

xcomp
ADJ

ADJ

VERB

VERB

documento latino italicove declarare debes

図 158: ラテン語向け品詞付与・係り受け解析ミニモデルのテスト– 103 –

22

バスク語編

22.1 バスク語 UD における品詞付与と係り受け解析
バスク語は、絶対格 (absolutibo) と能格 (ergatibo) と与格 (datibo) で動詞の項を示す能格言語です。動詞の項が 1 つの場合は絶対格を、2 つの場合は絶対格と能格を、3 つの場合は絶対格と能格と与格を使います。ただし、バスク語 UD においては、動詞の項が 1 つの場合は絶対格を主語とみなし、動詞の項が 2 つ以上の場合は絶対格を目的語とみなす (能格を主語とみなし、与格を間接目的語とみなす)[132][133] 点で、むしろラテン語 UD やスペ
イン語 UD との連絡性を重視しています。
Trankit[60] は、XLM-RoBERTa をベースに、隣接行列型係り受け解析アルゴリズムを、様々な言語向けに実装しています。Google Colaboratory 上の Trankit を用いて、バスク語の例文「Gaur ama hil zen gaur goizean ama hil nuen」を品詞付与・係り受け解析するプロ
グラムと、その結果を図 159 に示します。解析結果を見ていくことにしましょう。
!pip install trankit transformers deplacy
import trankit
nlp=trankit.Pipeline("basque")
doc=nlp("Gaur ama hil zen gaur goizean ama hil nuen")
import deplacy
deplacy.serve(doc,port=None)
root
conj
advmodadvmod
nsubj
ADV

obl
aux

obj
ADV

NOUN

aux

NOUN

VERB

AUX

NOUN

VERB

AUX

Gaur amahil

zen gaur goizean ama

hil

nuen

図 159: Trankit によるバスク語の係り受け解析

2 つの動詞「hil」は conj で繫がれており、それぞれに絶対格の名詞「ama」が繫がっています。前者は「zen」(izan の 3 人称単数・直接法過去) が aux で繫がれていることから、絶対格「ama」は主語 (nsubj) とみなされます。後者は「nuen」(izan の絶対格 3 人称
単数・能格 1 人称単数・直接法過去) が aux で繫がれていることから、能格 (1 人称単数)は「nuen」に内包されているとみなされ、絶対格「ama」は目的語 (obj) とみなされます。
名詞「goizean」(goiz の内格 (inesibo) 単数) は、斜格補語 (obl) です。副詞「gaur」は、それぞれ advmod で繫がれています。

[132]

Izaskun Aldezabal, Maria Jesus Aranzabe, Jose Mari Arriola, and Arantza Diaz de Ilarraza: Syntactic annotation in the Reference Corpus for the Processing of Basque (EPEC): Theoretical and practical issues, Corpus
Linguistics and Linguistic Theory, Vol.5, No.2 (October 2009), pp.241-269.
[133]
Maria Jesus Aranzabe, Aitziber Atutxa, Kepa Bengoetxea, Arantza Diaz de Ilarraza, Iakes Goenaga, Koldo
Gojenola, Larraitz Uria: Dependentzia Unibertsalen eredura egokitutako euskarazko zuhaitz-bankua, Ekaia, zk:35(2019), pp.291-307.

– 104 –

22.2 バスク語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar[42] で、バスク語ミニ DeBERTa モデルを製作してみましょう。手順を図 160〜163 に示します。
最初に、訓練のための文章を準備しましょう (図 160)。train.txt の文章の材料として、ここでは UD Basque-BDT[134] と BasqueParl コーパス[135] を元にしていますが、好みに応じ、バスク語の他の文章を増量するのもいいでしょう。なお、UD Basque-BDT の各 CoNLL-U
ファイルは、品詞付与・係り受け解析の学習にも用います。
!pip install esupar accelerate datasets
import os,datasets
url="https://github.com/UniversalDependencies/UD_Basque-BDT"
d=os.path.basename(url)!test -d {d} || git clone --depth=1 {url}!for F in train dev test ; do cat {d}/*-$$F.conllu > $$F.conllu ; done
c=[k["text"] for k in datasets.load_dataset("HiTZ/basqueparl")["train"]]with open("train.txt","w",encoding="utf-8") as w:
print("\n".join(c),file=w)!sed -n "s/^# text = //p" *.conllu >> train.txt

図 160: バスク語ミニモデル製作のための準備

from transformers import BertTokenizerFast
from tokenizers import BertWordPieceTokenizers=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
wpt=BertWordPieceTokenizer(strip_accents=False)
wpt.train(files=["train.txt"],vocab_size=30000,special_tokens=s)
wpt.save_model(".")
tkz=BertTokenizerFast(vocab_file="vocab.txt",strip_accents=False,never_split=s)
tkz.save_pretrained("my-dir/tokenizer-eu")

図 161: バスク語向けトークナイザの作成
続けて、バスク語向けトークナイザを、my-dir/tokenizer-eu に作成しましょう。図 161
では、Transformers の BertTokenizerFast を使って、バスク語向けトークナイザを作成しています。
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-eu に作成しましょう。図162 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしています。
最後に、my-dir/deberta-eu と UD Basque-BDT から、品詞付与・係り受け解析モデル
my-dir/deberta-eu-upos を製作しましょう (図 163)。うまく my-dir/deberta-eu-upos が製作できたら、esupar でテストしてみましょう (図 164)。
[134]

https://github.com/UniversalDependencies/UD_Basque-BDT
Nayla Escribano, Jon Ander González, Julen Orbegozo-Terradillos, Ainara Larrondo-Ureta, Simón PeñaFernández, Olatz Perez-de-Viñaspre and Rodrigo Agerri: BasqueParl: A Bilingual Corpus of Basque Parliamentary Transcriptions, LREC 2022: Thirteenth Conference on Language Resources and Evaluation (June 2022),
pp.3382-3390.
[135]– 105 –

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-eu",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-eu")tkz.save_pretrained("my-dir/deberta-eu")

図 162: バスク語ミニ DeBERTa モデルの作成!python -m esupar.train my-dir/deberta-eu my-dir/deberta-eu-upos .

図 163: バスク語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-eu-upos")
doc=nlp("Gaur ama hil zen gaur goizean ama hil nuen")
import deplacy
deplacy.serve(doc,port=None)
root
conj
advmodadvmod
nsubj
ADV

obl
aux

obj
ADV

NOUN

aux

NOUN

VERB

AUX

NOUN

VERB

AUX

Gaur amahil

zen gaur goizean ama

hil

nuen

図 164: バスク語向け品詞付与・係り受け解析ミニモデルのテスト– 106 –

23

韓国語編

23.1 韓国語 UD における品詞付与と係り受け解析
書写言語としての韓国語は、ハングルが語節 (어절) ごとに分かち書きされています。
これにしたがって韓国語 UD では、語節ごとに品詞付与をおこない、語節と語節の係り受けを定義しています。
esupar[42] は、隣接行列型係り受け解析アルゴリズムを、事前学習モデルで実装しています。Google Colaboratory 上の esupar を用いて、roberta-base-korean-upos で韓国語の例
文「한국어는 한자를 사용하지 않고 한글만으로 쓴다」を係り受け解析するプログラムと、
その結果を図 165 に示します。解析結果を見ていくことにしましょう。
!pip install esupar
import esupar
nlp=esupar.load("KoichiYasuoka/roberta-base-korean-upos")
doc=nlp("한국어는 한자를 사용하지 않고 한글만으로 쓴다")import deplacy
deplacy.serve(doc,port=None)
root
nsubj

conj
obj

NOUN

NOUN

aux
VERB

obl
AUX

ADV

VERB

한국어는 한자를 사용하지 않고 한글만으로 쓴다
図 165: roberta-base-korean-upos による韓国語の係り受け解析
この例文は、「사용하지」と「쓴다」を中心とする 2 つの節から成っており、conj で繫
がれています。述語「사용하지」からは、主語「한국어는」が nsubj で、目的語「한자를」が obj で、否定語「않고」が aux で、それぞれ繫がれています。述語「쓴다」からは、斜!pip install esupar
import esupar
nlp=esupar.load("KoichiYasuoka/roberta-base-korean-upos")
doc=nlp("한국어는 한자(漢字)를 사용하지 않고 한글만으로 쓴다")import deplacy
deplacy.serve(doc,port=None)
root
nsubj
obj
case
appos
punct
NOUN

NOUN

한국어는 한자

conj
punct

aux

PUNCT

SYM

PUNCT

ADP

(

漢字

)

를

VERB

obl
AUX

ADV

사용하지 않고 한글만으로 쓴다

図 166: カッコ書きの漢字を含む韓国語の係り受け解析– 107 –

VERB

格補語「한글만으로」が obl で繫がれていますが、UPOS 品詞が ADV になってしまっています。
韓国語の文には、しばしばカッコ書きの漢字が挿入されます。たとえば「한자를」という語節に「한자(漢字)를」という形で、漢字が挿入されます。この場合、韓国語 UD ではカッコ書きの部分を独立して扱う[136] ため、結果的に「한자」と「를」は分断されて、形態素としての係り受け解析がおこなわれます (図 166)。つまり、このような文においては、語節と形態素が入り混じった形で係り受け解析をおこなう必要があり、どうしても解析精度が下がってしまうのです。

23.2 韓国語の形態素にもとづく品詞付与と係り受け解析
一方で、語節ではなく形態素のみを用いて、韓国語の係り受け解析をおこなうアプロー
チ[137] も可能です。Google Colaboratory 上の esupar を用いて、roberta-base-korean-morphupos で韓国語の例文「한국어는 한자(漢字)를 사용하지 않고 한글만으로 쓴다」を係り受け解析するプログラムと、その結果を図 167 に示します。
!pip install esupar
import esupar
nlp=esupar.load("KoichiYasuoka/roberta-base-korean-morph-upos")
doc=nlp("한국어는 한자(漢字)를 사용하지 않고 한글만으로 쓴다")import deplacy
deplacy.serve(doc,port=None)
root
nsubj
obj

conj

case
appos
punct

case
NOUN

flat
mark
punct

aux

mark

ADP

NOUN

PUNCT

SYM

PUNCT

ADP

NOUN

PART

CCONJ

VERB

한국어 는

한자

(

漢字

)

를

사용

하

지

않

conj
obl
case
mark

case

mark

CCONJ

NOUN

ADP

ADP

고

한글

만

으로

VERB

CCONJ

쓴다

図 167: roberta-base-korean-morph-upos による韓国語の係り受け解析
述語を形態素に分解すると、品詞付与が複雑になります。述語「사용하지」の「사용」は名詞なので NOUN とすべきですが、その場合に「하」と「지」の UPOS 品詞が PART[136]

Jayeol Chun, Na-Rae Han, Jena D. Hwang, Jinho D. Choi: Building Universal Dependency Treebanks in
Korean, LREC 2018: Eleventh International Conference on Language Resources and Evaluation (May 2018),
pp.2194-2202.
[137]
Yige Chen, Eunkyul Leah Jo, Yundong Yao, KyungTae Lim, Miikka Silfverberg, Francis M. Tyers, Jungyeul
Park: Yet Another Format of Universal Dependencies for Korean, Proceedings of the 29th International Conference on Computational Linguistics (October 2022), pp.5432-5437.

– 108 –

と CCONJ でいいのか、議論の余地があります。あるいは述語「쓴다」を形態素に分解すると「쓰」「ㄴ다」なので、ハングルの途中に形態素の境界が来てしまいます。韓国語の形態素にもとづく品詞付与と係り受け解析は、理論的には可能なものの、述語の処理単位としては複雑すぎて、あまり実用的ではないようです。

23.3 韓国語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar で、韓国語ミニ DeBERTa モデルを製作してみましょう。手順を図 168〜171 に示します。
最初に、訓練のための文章を準備しましょう (図 168)。train.txt の文章の材料として、
ここでは UD Korean-Kaist[138] と UD Korean-GSD[139] を元にしていますが、好みに応じ、韓国語の他の文章を増量するのもいいでしょう。なお、各 CoNLL-U ファイルは、品詞付
与・係り受け解析の学習にも用います。
!pip install esupar spacy-alignments accelerate
import os
url="https://github.com/UniversalDependencies/UD_Korean-Kaist"!test -d {os.path.basename(url)} || git clone --depth=1 {url}url="https://github.com/UniversalDependencies/UD_Korean-GSD"!test -d {os.path.basename(url)} || git clone --depth=1 {url}!for F in train dev test ; do cat UD_Korean-*/*-$$F.conllu > $$F.conllu ; done
!sed -n "s/^# text = //p" *.conllu > train.txt

図 168: 韓国語ミニモデル製作のための準備

from transformers import BertTokenizerFast
from tokenizers import pre_tokenizers,normalizers
from esupar.hangul import hanguls,t=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"],{}
for k,v in hangul.items():
for c in "".join(v).replace("(","").replace(")",""):
t[c]=kwith open("train.txt","r",encoding="utf-8") as r:v=set(t[c] if c in t else c for c in r.read() if not c.isspace())
with open("vocab.txt","w",encoding="utf-8") as w:
print("\n".join(s+sorted(v))+"\n##".join([""]+sorted(v)),file=w)
tkz=BertTokenizerFast(vocab_file="vocab.txt",never_split=s,
do_lower_case=False,strip_accents=False,tokenize_chinese_chars=False)
tkz.backend_tokenizer.pre_tokenizer=pre_tokenizers.Whitespace()tkz.backend_tokenizer.normalizer=normalizers.Sequence([normalizers.Nmt()]+[normalizers.Replace(k,v) for k,v in t.items()]+[normalizers.NFKC()])
tkz.save_pretrained("my-dir/tokenizer-ko")

図 169: 韓国語向け単文字トークナイザの作成
[138]
[139]

https://github.com/UniversalDependencies/UD_Korean-Kaist
https://github.com/UniversalDependencies/UD_Korean-GSD– 109 –

続けて、韓国語向け単文字トークナイザを、my-dir/tokenizer-ko に作成しましょう。図169 では、Transformers の BertTokenizerFast を使って、韓国語向け単文字トークナイザを作成しています。なお、漢字はハングルに変換しています。
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-ko に作成しましょう。図170 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしています。
最後に、my-dir/deberta-ko と UD Korean-Kaist・UD Korean-GSD から、品詞付与・係り
受け解析モデル my-dir/deberta-ko-upos を製作しましょう (図 171)。うまく my-dir/debertako-upos が製作できたら、esupar でテストしてみましょう (図 172)。

– 110 –

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-ko",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-ko")tkz.save_pretrained("my-dir/deberta-ko")

図 170: 韓国語ミニ DeBERTa モデルの作成!python -m esupar.train my-dir/deberta-ko my-dir/deberta-ko-upos .

図 171: 韓国語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-ko-upos")
doc=nlp("한국어는 한자(漢字)를 사용하지 않고 한글만으로 쓴다")import deplacy
deplacy.serve(doc,port=None)
root
nsubj
obj
case
appos
punct
NOUN

NOUN

한국어는 한자

conj
punct

aux

PUNCT

NOUN

PUNCT

ADP

(

漢字

)

를

VERB

obl
AUX

NOUN

사용하지 않고 한글만으로 쓴다

図 172: 韓国語向け品詞付与・係り受け解析ミニモデルのテスト– 111 –

VERB

24

アイヌ語編

24.1 アイヌ語 UD における品詞付与と係り受け解析
esupar[42] は、隣接行列型係り受け解析アルゴリズムを、事前学習モデルで実装しています。Google Colaboratory 上の esupar を用いて、deberta-base-ainu-upos でアイヌ語の例
文「アイヌイタㇰ アニ エネ アカㇻ ヒ エチヌカレ」を係り受け解析するプログラムと、
その結果を図 173 に示します。解析結果を見ていくことにしましょう。
!pip install esupar
import esupar
nlp=esupar.load("KoichiYasuoka/deberta-base-ainu-upos","ainu")
doc=nlp("アイヌイタㇰ アニ エネ アカㇻ ヒ エチヌカレ")
import deplacy
deplacy.serve(doc,port=None)
obl
nmod

root
advmod
nsubj

case

obj
acl

nsubj

NOUN

NOUN

SCONJ

ADV

PART

VERB

NOUN

PART

VERB

名詞

名詞

後置副詞

副詞

人称接辞

他動詞

形式名詞

人称接辞

他動詞

ア

カㇻ

ヒ

アイヌ イタㇰ アニ エネ

エチ ヌカレ

図 173: deberta-base-ainu-upos によるアイヌ語 (カタカナ) の係り受け解析
複他動詞「ヌカレ」は、本来は 3 つの項 (主語・目的語・間接目的語) を取るのですが、ここでは「エチ」が主語 (1 人称複数) と間接目的語 (2 人称複数) を兼ねています。したがって「エチ」は nsubj と iobj の両方で繫ぐべきなのですが、UD では各単語に入るリ
ンクは 1 つだけなので nsubj を優先しています。目的語「ヒ」は obj で繫がれています。
「アカㇻ」は「ヒ」を体言修飾していて、「カㇻ」と「ヒ」が acl で繫がれており、「ア」はnsubj で繫がれています。「エネ」は advmod で、複合名詞の「アイヌイタㇰ」は obl で繫がれています。
「アイヌ」と「イタㇰ」は nmod で繫がれた上に、「アニ」が case で繫
がれています。

!pip install esupar
import esupar
nlp=esupar.load("KoichiYasuoka/deberta-base-ainu-upos","ainu")
doc=nlp("aynu itak ani ene a=kar hi eci=nukare")import deplacy
deplacy.serve(doc,port=None)
obl
nmod

root
advmod
nsubj

case

obj
acl

nsubj

NOUN

NOUN

SCONJ

ADV

PART

VERB

NOUN

PART

VERB

名詞

名詞

後置副詞

副詞

人称接辞

他動詞

形式名詞

人称接辞

他動詞

ani

ene

a=

kar

hi

aynu itak

eci= nukare

図 174: deberta-base-ainu-upos によるアイヌ語 (ラテン文字) の係り受け解析– 112 –

!pip install esupar
import esupar
nlp=esupar.load("KoichiYasuoka/deberta-base-ainu-upos","ainu")
doc=nlp("айну итак ани энэ акар хи эчинукарэ ")import deplacy
deplacy.serve(doc,port=None)
obl
nmod

root
advmod
nsubj

case

obj
acl

nsubj

NOUN

NOUN

SCONJ

ADV

PART

VERB

NOUN

PART

VERB

名詞

名詞

後置副詞

副詞

人称接辞

他動詞

形式名詞

人称接辞

他動詞

энэ

а

кар

хи

айну итак аниэчи нукарэ

図 175: deberta-base-ainu-upos によるアイヌ語 (キリル文字) の係り受け解析

deberta-base-ainu-upos は、カタカナで書かれたアイヌ語のみならず、ラテン文字やキ
リル文字で書かれたアイヌ語も解析可能[140] です。Google Colaboratory 上の esupar を用いて、deberta-base-ainu-upos でアイヌ語の例文「aynu itak ani ene a=kar hi eci=nukare」を係り受け解析するプログラムと、その結果を図 174 に示します。同様に「айну итак ани энэакар хи эчинукарэ」を係り受け解析するプログラムと、その結果を図 175 に示します。

24.2 アイヌ語ミニ DeBERTa モデルの製作
Google Colaboratory 上の esupar で、アイヌ語ミニ DeBERTa モデルを製作してみましょう。手順を図 176〜180 に示します。
最初に、訓練のための文章を準備しましょう (図 176)。train.txt の文章の材料として、ここでは国立国語研究所アイヌ語口承文芸コーパス[141] と UD-Ainu[142] を元にしていますが、!pip install esupar pdfminer accelerate
import os
url="https://ainu.ninjal.ac.jp/static/pdf/text_jp/all.text.jp.pdf"
f=os.path.basename(url)!test -f {f} || curl -LO {url}s="y/\\t/ /;s/^[0-9/]*//;/^ *$/d;/^[!-?A-Za-z ]*$/p;d"!pdf2txt.py {f} | LANG=C sed "{s}" > train.txt
url="https://github.com/KoichiYasuoka/UD-Ainu"
d=os.path.basename(url)!test -d {d} || git clone --depth=1 {url}t=’’’BEGIN{FS=OFS="\\t"};{if(NF==10){u=u$0"\\n";if($1!~/-/){printf("%s ",$3);$2=$3;t=t$0"\\n"}}else if($0==""){print;print u"\\n"t>"train.upos";if(u~/\\t0\\troot\\t/)print u>(NR%10?"train":"test")".conllu";u=t=""}}’’’!nawk ’{t}’ {d}/ain_*.conllu | LANG=C sed "{s}" >> train.txt

図 176: アイヌ語ミニモデル製作のための準備[140]

安岡孝一: ローマ字・カタカナ・キリル文字併用アイヌ語 RoBERTa・DeBERTa モデルの開発, 情報処
理学会研究報告, Vol.2023-CH-131『人文科学とコンピュータ』, No.7 (2023 年 2 月 18 日), pp.1-7.
[141]https://ainu.ninjal.ac.jp/folklore[142]
https://github.com/KoichiYasuoka/UD-Ainu– 113 –

好みに応じ、アイヌ語の他の文章を増量するのもいいでしょう。UD-Ainu の各 CoNLL-U
ファイルは、train.upos にまとめ上げて、品詞付与の学習にも用います。また、これらの
CoNLL-U ファイルのうち、依存構造記述が UD のフォーマットを満たしているものは、train.conllu と test.conllu に分け、係り受け解析の学習にも用います。
続けて、train.txt の各単語から、アイヌ語向けトークナイザを、my-dir/tokenizer-ain に作成しましょう。図 177 では、Unigram トークナイザ (SentencePiece[83] の改造版) を train.txtに適用しつつ、アイヌ語のカタカナ・キリル文字をラテン文字に変換する仕掛けを組み込み、それらを DebertaV2TokenizerFast という Transformers のトークナイザに組み上げて、アイヌ語向けトークナイザを作成しています。
次に train.txt の文章から、DeBERTa モデルを my-dir/deberta-ain に作成しましょう。図178 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしています。ただし、
この DeBERTa モデルはカタカナの処理が不十分なので、単語ベクトルのコピーをおこな
い、新たなモデルを my-dir/deberta-ain-ext に保存しましょう (図 179)。
最後に、my-dir/deberta-ain-ext と UD-Ainu から、品詞付与・係り受け解析モデル mydir/deberta-ain-upos を製作しましょう (図 180)。うまく my-dir/deberta-ain-upos ができた
ら、esupar でテストしてみましょう (図 181)。

– 114 –

from esupar.ainu import katakana,cyrillicfrom transformers import DebertaV2TokenizerFast
from tokenizers import (Tokenizer,models,pre_tokenizers,normalizers,processors,
decoders,trainers)
s=["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"]
spt=Tokenizer(models.Unigram())
spt.pre_tokenizer=pre_tokenizers.Sequence([pre_tokenizers.Whitespace(),pre_tokenizers.Punctuation()])
spt.normalizer=normalizers.Sequence([normalizers.Nmt()]+[normalizers.Replace(k,v) for k,v in {**katakana,**cyrillic}.items()]+[normalizers.NFKD(),normalizers.Lowercase(),normalizers.StripAccents()]+[normalizers.Replace(i,j) for i,j in zip("bdfgjlqvwxyz","pthkcrcwuhis")])spt.post_processor=processors.TemplateProcessing(single="[CLS] $A [SEP]",
pair="[CLS] $A [SEP] $B:1 [SEP]:1",special_tokens=[("[CLS]",0),("[SEP]",2)])
spt.decoder=decoders.WordPiece(prefix="",cleanup=True)
spt.train(trainer=trainers.UnigramTrainer(vocab_size=64000,max_piece_length=8,
special_tokens=s,unk_token="[UNK]",n_sub_iterations=2),files=["train.txt"])
spt.save("tokenizer.json")
tkz=DebertaV2TokenizerFast(tokenizer_file="tokenizer.json",split_by_punct=True,
do_lower_case=True,keep_accents=False,vocab_file="/dev/null")
tkz.save_pretrained("my-dir/tokenizer-ain")

図 177: アイヌ語向けトークナイザの作成

from transformers import (AutoTokenizer,DebertaV2Config,DebertaV2ForMaskedLM,
DataCollatorForLanguageModeling,TrainingArguments,Trainer)
tkz=AutoTokenizer.from_pretrained("my-dir/tokenizer-ain",model_max_length=128)
t=tkz.convert_tokens_to_ids(["[CLS]","[PAD]","[SEP]","[UNK]","[MASK]"])
cfg=DebertaV2Config(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,relative_attention=True,position_biased_input=False,
pos_att_type=["p2c","c2p"],max_position_embeddings=tkz.model_max_length,
vocab_size=len(tkz),tokenizer_class=type(tkz).__name__,bos_token_id=t[0],pad_token_id=t[1],eos_token_id=t[2])arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)class ReadLineDS(object):def __init__(self,file,tokenizer):
self.tokenizer=tokenizer
with open(file,"r",encoding="utf-8") as r:self.lines=[s.strip() for s in r if s.strip()!=""]__len__=lambda self:len(self.lines)__getitem__=lambda self,i:self.tokenizer(self.lines[i],truncation=True,
add_special_tokens=True,max_length=self.tokenizer.model_max_length-2)
trn=Trainer(args=arg,data_collator=DataCollatorForLanguageModeling(tkz),
model=DebertaV2ForMaskedLM(cfg),train_dataset=ReadLineDS("train.txt",tkz))
trn.train()trn.save_model("my-dir/deberta-ain")tkz.save_pretrained("my-dir/deberta-ain")

図 178: アイヌ語ミニ DeBERTa モデルの作成– 115 –

import torch,jsonfrom transformers import AutoModelForMaskedLM,AutoTokenizer
mdl=AutoModelForMaskedLM.from_pretrained("my-dir/deberta-ain")with open("my-dir/deberta-ain/tokenizer.json","r",encoding="utf-8") as r:
spt=json.load(r)d,c={t[0]:i for i,t in enumerate(spt["model"]["vocab"])},[]
for k,v in list(d.items()):
s=k.replace("tu","tou").replace("ca","cia").replace("ce","cie").replace("cu","ciu").replace("co","cio").replace("kk","tk").replace("pp","tp")if s not in d:c.append((k,s))d[s]=len(d)e=mdl.resize_token_embeddings(len(d))
with torch.no_grad():for k,v in c:e.weight[d[v],:]=e.weight[d[k],:]spt["model"]["vocab"].append([v,spt["model"]["vocab"][d[k]][1]])with open("tokenizer.json","w",encoding="utf-8") as w:
json.dump(spt,w,ensure_ascii=False,indent=2)
tkz=AutoTokenizer.from_pretrained("my-dir/deberta-ain",use_fast=True,
tokenizer_file="tokenizer.json")
mdl.save_pretrained("my-dir/deberta-ain-ext")
tkz.save_pretrained("my-dir/deberta-ain-ext")

図 179: アイヌ語向けミニ DeBERTa モデルの拡張

s,d="my-dir/deberta-ain-ext","my-dir/deberta-ain-upos"!python -m esupar.train {s} {d} 32 /tmp train.upos!python -m esupar.train {d} {d} 32 /// train.conllu test.conllu test.conllu

図 180: アイヌ語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/deberta-ain-upos","ainu")
doc=nlp("アイヌイタㇰ アニ エネ アカㇻ ヒ エチヌカレ")
import deplacy
deplacy.serve(doc,port=None)
obl
nmod
NOUN

case
NOUN

SCONJ

root
advmodnsubj

ADV

アイヌ イタㇰ アニ エネ

obj
acl

nsubj

PART

VERB

NOUN

PART

VERB

ア

カㇻ

ヒ

エチ ヌカレ

図 181: アイヌ語向け品詞付与・係り受け解析ミニモデルのテスト– 116 –

Universal Dependencies と BERT/RoBERTa/DeBERTa モデルによる多言語情報処理
安岡孝一
発行日

2022 年 2 月 28 日 (初版)・2024 年 8 月 30 日 (改訂版)発行所

京都大学人文科学研究所・未踏科学研究ユニット・
データサイエンスで切り拓く総合地域研究ユニット