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

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

RB

VV

NN

,

RB

MD

VV

PFA

NN

.

，

怎么

能

抓到

小

老虎

。

不

进入 虎穴

PUNCT

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

NOUN

NEG

VACT

NCMN

NCMN

XVBM

NEG

VSTA

NCMN

NCMN

ไม่

เข้า

ถ้า

เสือ

ย่อม

ไม่

2022 年 4 月版

ได้

ลูก

เสือ

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

1

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

4
4
8
13
15

2

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

18
18
20
22

3

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

26
26
28
30
32
32

4

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

34
34
35

5

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

38
38
39

6

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

42
42
43

7

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

46
46
46

8

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

49
49
50
50

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

53
53
53

10 ウクライナ語編
10.1 ウクライナ語 UD における品詞付与と係り受け解析 . . . . . . . . . . . .
10.2 ウクライナ語ミニ RoBERTa モデルの製作 . . . . . . . . . . . . . . . . .

56
56
56

11 ベラルーシ語編
11.1 ベラルーシ語 UD における品詞付与と係り受け解析 . . . . . . . . . . . .
11.2 ベラルーシ語ミニ RoBERTa モデルの製作 . . . . . . . . . . . . . . . . .

59
59
60

12 セルビア語編
12.1 セルビア語 UD における品詞付与と係り受け解析 . . . . . . . . . . . . .
12.2 セルビア語ミニ RoBERTa モデルの製作 . . . . . . . . . . . . . . . . . . .

62
62
63

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

67
67
67

9

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

1.1

Universal Dependencies と CoNLL-U

UD は、書写言語における品詞・形態素属性・依存構造 (係り受け関係) を、言語に関わらず記述する手法です。句構造を考慮せずに係り受け関係を記述することで、言語横断性を高めていて、全ての文法構造を単語間のリンクで記述するのが特徴です。
依存構造解析それ自体は、Tesnière の構造的統語論[8] に源を発し、Мельчук の有向グラ
フ記述[9] によって、一応の完成を見た手法です。その最大の特長は、いわゆる動詞中心主義によって言語横断的な記述が可能だという点にあり、Мельчук 依存文法をコンピュー
タ向けに洗練した 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]
https://colab.research.google.com[6]
安岡孝一: Universal Dependencies にもとづく多言語係り受け可視化ツール deplacy, 人文科学とコン
ピュータシンポジウム「じんもんこん 2020」論文集 (2020 年 12 月), pp.95-100.
[7]https://koichiyasuoka.github.io/deplacy/#templates-for-google-colaboratory[8]
Lucien Tesnière: Éléments de Syntaxe Structurale, Paris: C. Klincksieck (1959).
[9]
Igor A. Mel’čuk: Dependency Syntax: Theory and Practice, New York: State University of New York Press(1988).

–4–

表 1: deplacy に接続可能な各言語の係り受け解析ツール (2022 年 4 月 28 日現在)
アフリカーンス語
アラビア語
ベラルーシ語
ブルガリア語
カタルーニャ語
コプト語
チェコ語
ウェールズ語
デンマーク語
ドイツ語
ギリシア語
英語
スペイン語
エストニア語
バスク語
ペルシア語
スオミ語
フェロー語
フランス語
ゲール語 (アイルランド)
ゲール語 (スコットランド)
ガリシア語
古典ギリシア語
ヘブライ語
ヒンディー語
クロアチア語
ハンガリー語
アルメニア語
インドネシア語
アイスランド語
イタリア語
日本語
カザフ語
韓国語
ラテン語
リトアニア語
ラトビア語
古典中国語
マケドニア語
マルタ語
ノルウェー語 (ブークモール)
ノルウェー語 (ニーノルスク)
オランダ語
ポーランド語
ポルトガル語
ルーマニア語
ロシア語
スロバキア語
スロベニア語
セルビア語 (キリル)セルビア語 (ラテン)スウェーデン語
タミル語
タイ語
タガログ語
トルコ語
ウクライナ語
ベトナム語
ウォロフ語
中国語 (簡化字)
中国語 (繁體字)Camphr-Udify, spaCy-COMBO, UDPipe 2, Trankit, spaCy-jPTDP, Stanza, COMBO-pytorch など
Trankit, UDPipe 2, spacy-udpipe, spaCy-COMBO, Stanza, spaCy-jPTDP
Camphr-Udify, Stanza, Trankit, UDPipe 2, spacy-udpipe
Trankit, Camphr-Udify, UDPipe 2, CLASSLA, Stanza, spaCy-COMBO, spaCy-jPTDP, spacy-udpipe
Camphr-Udify, Stanza, spacy-udpipe, COMBO-pytorch, Trankit, UDPipe 2, spaCy, spaCy-COMBO など
Stanza, spaCy-Coptic, spacy-udpipe, UDPipe 2
Camphr-Udify, spaCy-jPTDP, Trankit, UDPipe 2, spacy-udpipe, Stanza, COMBO-pytorch など
UDPipe 2, luigi/custom models, Stanza, Camphr-Udify
Camphr-Udify, UDPipe 2, Stanza, Trankit, spaCy, COMBO-pytorch, spacy-udpipe, spaCy-jPTDP など
Camphr-Udify, Stanza, COMBO-pytorch, UDPipe 2, spaCy-jPTDP, NLP-Cube, spacy-udpipe など
Stanza, UDPipe 2, Trankit, spacy-udpipe, NLP-Cube, spaCy-jPTDP, Camphr-Udify など
Camphr-Udify, Stanza, COMBO-pytorch, UDPipe 2, NLP-Cube, spaCy-COMBO, Trankit など
Stanza, NLP-Cube, spaCy, UDPipe 2, spacy-udpipe, Trankit, Camphr-Udify など
Stanza, spacy-udpipe, EstMalt, COMBO-pytorch, spaCy-COMBO, spaCy-jPTDP, UDPipe 2 など
spaCy-ixaKat, COMBO-pytorch, Trankit, Stanza, spacy-udpipe, Camphr-Udify, spaCy-COMBO など
Stanza, spaCy-COMBO, spaCy-jPTDP, spacy-udpipe, Trankit, Camphr-Udify, UDPipe 2 など
Stanza, UDPipe 2, spacy-udpipe, spacy-fi, Turku-neural-parser-pipeline, COMBO-pytorch など
StanzaspaCy, Stanza, UDPipe 2, Trankit, spacy-udpipe, Camphr-Udify, NLP-Cube, spaCy-COMBO など
Stanza, UDPipe 2, COMBO-pytorch, Trankit, spacy-udpipe, spaCy-COMBO, spaCy-jPTDP など
GLA, Stanza, UDPipe 2, spacy-udpipe, Trankit
Camphr-Udify, Stanza, spaCy-jPTDP, spacy-udpipe, COMBO-pytorch, spaCy-COMBO, Trankit など
Camphr-Udify, UDPipe 2, spaCy-COMBO, spaCy-jPTDP, Stanza, Trankit, spacy-udpipe
Trankit, HebPipe, Stanza, spaCy-COMBO, spaCy-jPTDP, UDPipe 2, COMBO-pytorch など
spaCy-COMBO, UDPipe 2, Trankit, Stanza, spaCy-jPTDP, spacy-udpipe, Camphr-Udify
UDPipe 2, COMBO-pytorch, Trankit, Camphr-Udify, Stanza, CLASSLA, spaCy-COMBO など
Trankit, UDPipe 2, COMBO-pytorch, Camphr-Udify, HuSpacy, hu core ud lg, spaCy-COMBO など
Stanza, Camphr-Udify, Trankit, UDPipe 2, spacy-udpipe, spaCy-COMBO
Stanza, Trankit, spacy-udpipe, Camphr-Udify, UDPipe 2, COMBO-pytorch, spaCy-jPTDP など
COMBO-pytorch, Stanza, is ud is pud
NLP-Cube, COMBO-pytorch, spaCy-COMBO, Trankit, Camphr-Udify, Stanza, spaCy など
spaCy-SynCha, spaCy-ChaPAS, UniDic-COMBO, spaCy, GiNZA, UDPipe 2, Stanza, UniDic2UD など
Camphr-Udify, spaCy-COMBO, Trankit, NLP-Cube, kazdet
Camphr-Udify, Stanza, UDPipe 2, Trankit, spaCy-jPTDP, spacy-udpipe, spaCy-COMBO, Stanza
spaCy-COMBO, 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-COMBO, spacy-udpipe, spaCy-jPTDP
SuPar-Kanbun, UD-Kanbun, GuwenCOMBO, UD-Chinese, Trankit, esupar, spacy-udpipe, Stanza など
Camphr-Udify, spaCy
Stanza, UDPipe 2, spacy-udpipe, COMBO-pytorch, Camphr-Udify
Stanza, COMBO-pytorch, spaCy-COMBO, Camphr-Udify, UDPipe 2, Trankit, spaCy-jPTDP, spaCy
Stanza, spacy-udpipe, spaCy-COMBO, spaCy-jPTDP, UDPipe 2, Trankit
spaCy-Alpino, Camphr-Udify, Stanza, UDPipe 2, Trankit, spacy-udpipe, spaCy, spaCy-COMBO など
spaCy, spaCyPL, Camphr-Udify, Stanza, UDPipe 2, spacy-udpipe, Trankit, COMBO-pytorch など
spaCy, Camphr-Udify, Stanza, COMBO-pytorch, spaCy-COMBO, spaCy-jPTDP, UDPipe 2 など
UDPipe 2, COMBO-pytorch, Trankit, NLP-Cube, Camphr-Udify, spaCy, Stanza, spaCy-COMBO など
Stanza, Trankit, Camphr-Udify, UDPipe 2, NLP-Cube, spaCy, COMBO-pytorch, spacy-udpipe など
Camphr-Udify, UDPipe 2, Trankit, spacy-udpipe, NLP-Cube, spaCy-COMBO, Stanza など
CLASSLA, UDPipe 2, COMBO-pytorch, spacy-udpipe, Camphr-Udify, Trankit, spaCy-COMBO など
esupar, Camphr-Udify
CLASSLA, UDPipe 2, Trankit, Camphr-Udify, esupar, Stanza, spacy-udpipe, spaCy-COMBO など
Camphr-Udify, COMBO-pytorch, Trankit, Stanza, spaCy-COMBO, UDPipe 2, spacy-udpipe など
Camphr-Udify, Trankit, UDPipe 2, spacy-udpipe, Stanza
esupar, spaCy-Thai
Camphr-Udify
Stanza, spaCy-COMBO, spaCy-jPTDP, Camphr-Udify, UDPipe 2, spacy-udpipe, COMBO-pytorch など
Stanza, NLP-Cube, Camphr-Udify, spaCy-COMBO, UDPipe 2, Trankit, spacy-udpipe など
Trankit, Stanza, spaCy-jPTDP, spaCy-COMBO, COMBO-pytorch, 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 など–5–表 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 未定義–6–

# 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 による可視化–7–

UD 係り受けコーパスの交換用フォーマットとして、CoNLL-U と呼ばれるタブ区切りテ
キスト (文字コードは UTF-8[10] ) が規定されています。CoNLL-U の各行は各単語に対応していて、表 2 に示す 10 個のタブ区切りフィールドで構成されます。ID・FORM・LEMMA
は、単語そのものに関するフィールドです。UPOS・XPOS・FEATS は、単語の品詞と形態素属性に関するフィールドです。HEAD・DEPREL・DEPS は、単語の係り受けに関す
るフィールドです。
UD における係り受け関係は、単語間の有向グラフを HEAD と DEPREL で記述します。
HEAD は、その単語に入る有向枝のリンク元 ID を示していて、DEPREL は、その有向枝における係り受けタグです。ただし、HEAD が 0 の場合、その枝に入るリンク元は存在しません。リンクの本数は単語の個数に等しく、各リンクのリンク先は、全て互いに異なっています。すなわち、各単語から出るリンクは複数の可能性がありますが、各単語に入るリンクは 1 つだけなのです。なお、リンクはループしません。
UD の係り受けリンクは、Мельчук 依存文法の後裔にあたり、いわゆる動詞中心主義です。動詞をリンク元として、主語や目的語へとリンクします。修飾関係においては、被修飾語から修飾語へとリンクします。ただし、側置詞 (前置詞や後置詞) を体言の修飾語だとみなす点[11] が、Мельчук とは異なっています。また、コピュラ文においては動詞中心主義を採らず、補語をリンク元として、主語や繫辞へとリンクします。
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 の文法構造[12] を取り入れています。このあたりについて、簡単に紹介
しておきましょう。
述語
目的語 という構造を基本に、英文を視
Reed-Kellogg 文法構造図は、 主語
覚化します。主文 (main sentence) を太線で、それ以外の節 (clause) を細線で視覚化した
上に、修飾語を斜線に載せて示します。たとえば英文「Those who labour with their minds[10]

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).
[11]
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.
[12]
Alonzo Reed and Brainerd Kellogg: Higher Lessons in English: A Work on English Grammar and Composition, New York: Clark & Maynard (1877).

–8–

# 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 文法構造図–9–

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

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

– 10 –

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 が用いられており、Мельчук 自身
も、タグが何種類必要なのかは明らかにしていません[16] 。
UD の係り受け構造は、Мельчук の依存文法におけるタグを、表 4 の 37 種類に限定する野心的な試み、として捉えることができます。図 5 での subjectival・direct-objectival・
modificative・determinative が、図 6 では nsubj・obj・acl・det になった、と考えることもできます。ただ、UD の前身にあたる Stanford Typed Dependencies[17] が、初期には
Bresnan 語彙機能文法[18] からスタートしており、その後に依存文法へとシフトしたことか
ら、いくつか不思議な概念が紛れ込んでしまっています。その一つが、節 (clause) です。
節という概念を、Мельчук は依存文法から刪除したのですが、これを UD は再導入してしまいました。表 4 の nsubj と csubj は、いずれも主語を表す UD 係り受けタグであり、リンク先が節なら csubj を、さもなくば nsubj を使います。obj と ccomp についても同様、advmod と advcl についても同様、amod と acl についても同様です。case と markについては、リンク元が節なら mark を、さもなくば case を使います[19] 。
英語における節という概念は、一定のコンセンサスが得られていると考えられます。しかし、他の言語において、節という概念は、必ずしも自明ではありません。UD は言語横断的ではあるものの、かなり英語寄りである、という点は意識しておくべきでしょう。

[16]

Alain Polguère, Igor A. Mel’čuk: Dependency in Linguistic Description, Amsterdam: John Benjamins(2009).
[17]
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.
[18]
Joan Bresnan: Lexical-Functional Syntax, Malden: Blackwell (2001).
[19]
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.

– 11 –

# 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 による係り受け構造記述– 12 –

1.3

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

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

?

a

pen

.

?

?

?

bert-base-cased
?

This

?

is

?

a

?

pen

?

.

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

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

https://huggingface.co/bert-base-cased
ここでいう「近い」は、コサイン類似度 (2 つのベクトルの内積を、ベクトルのユークリッド・ノルムで割った値) が 1 に近い、という意味です。
[22]
bert-base-cased の内部では、穴埋め用の [MASK] に加えて、文頭を表す [CLS]、文の切れ目を表す [SEP]、
未知語を表す [UNK]、空きトークンを表す [PAD] なども用いられます。
[23]
BERT のもう一つの工夫は、文と文の繫がりを学習する隣接文ゲームですが、本書では扱いません。
[24]
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.
[21]– 13 –

!pip install transformers
from transformers import AutoTokenizer,AutoModelForMaskedLM,FillMaskPipeline
brt="bert-base-cased"
tkz=AutoTokenizer.from_pretrained(brt)
mdl=AutoModelForMaskedLM.from_pretrained(brt)
fmp=FillMaskPipeline(tokenizer=tkz,model=mdl)
prd=fmp("This [MASK] a pen.")print("\n".join("{:8} {:.03f}".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 は、文という単位を仮定せず、トークンの並びを用いて、穴埋めゲームのみに特化した学習をおこないます。これにより、文という単位に捉われることなく、大量の文章を丸暗記できるのです。
roberta-classical-chinese-base-char[25] は、古典中国語における漢字をトークンとみなし、漢字単位での穴埋めゲーム (図 9) を学習したモデルです。各漢字 (約 26000 字種) の入出
力は UTF-8 ですが、内部的には 768 次元のベクトルで表現します。Google Colaboratory
上の Transformers で「勞 [MASK] 者治人」を穴埋めするプログラムと、その結果を図 10に示します。「心」が 19.9%となっていて、「人」の 32.7%に負けているのがわかります。
BERT/RoBERTa モデルは、出力部を付け替えることで、様々な用途に応用可能です。
出力ベクトルを品詞情報だとみなせば、品詞付与に使えます。係り受けタグだとみな勞[MASK]

者

治

人

?

?

?

?

?

roberta-classical-chinese-base-char
?

勞

?

心

?

者

?

治

?

人

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

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

!pip install transformers
from transformers import AutoTokenizer,AutoModelForMaskedLM,FillMaskPipeline
brt="KoichiYasuoka/roberta-classical-chinese-base-char"
tkz=AutoTokenizer.from_pretrained(brt)
mdl=AutoModelForMaskedLM.from_pretrained(brt)
fmp=FillMaskPipeline(tokenizer=tkz,model=mdl)
prd=fmp("勞[MASK]者治人")
print("\n".join("{:8} {:.03f}".format(t["token_str"],t["score"]) for t in prd))

人
心
民
神
神

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

せば、係り受け解析に使えます。UD においては、系列ラベリングや係り受け解析に、
BERT/RoBERTa モデルを応用することができます。

1.4

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

係り受け解析は、UD による言語処理の「キモ」であり、多くの解析アルゴリズムが乱立しています。これらの係り受け解析アルゴリズムを、状態遷移型アルゴリズムと隣接行列型アルゴリズムに分けて、概説します。
arc-swap[26] に代表される状態遷移型アルゴリズムは、単語列の先頭から末尾に向かって「垣根」(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 を、それぞれまとめて遷移させる手法が主流です。
[26]

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.

– 15 –

|


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?」の係り受け解析– 16 –

Biaffine[27] に代表される隣接行列型アルゴリズムは、UD 依存構造を有向グラフとみなし、その隣接行列を求めます。たとえば、図⎡⎤11 右下「Who did you wait for?」の有向グ
−
⎢ −
⎢
⎢ −
ラフであれば ⎢
⎢ obl
⎢
⎣ −
−

−
−
− case −
−
−
−
−
− ⎥
⎥
−
−
−
−
− ⎥
⎥ という 6×6 の隣接行列を求めます (図 12)。
aux nsubj root − punct⎥
⎥
−
−
−
−
− ⎦
−
−
−
−
−

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

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 モデルを用いることで精度向上が期待できる[29] のですが、これは実装がかなり難しいのです。一方、隣接行列型アルゴリズムは、
BERT/RoBERTa モデルとの相性が良いと考えられます。ただし、隣接行列型アルゴリズ
ムに BERT/RoBERTa モデルを用いると、計算機資源 (メモリや GPU) を大量に必要とすることから、BERT/RoBERTa モデルを使用しない実装もありえます。

[27]

Timothy Dozat, Christopher D. Manning: Deep Biaffine Attention for Neural Dependency Parsing, 5th International Conference on Learning Representations (April 2017), C25.
[28]
H. N. Gabow, Z. Galil, T. Spencer and R. E. Tarjan: Efficient Algorithms for Finding Minimum Spanning
Trees in Undirected and Directed Graphs, Combinatorica, Vol.6, No.2 (June 1986), pp.109-122.
[29]
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.

– 17 –

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,aggr="none"):from transformers import pipeline
self.pipeline=pipeline(task="ner",model=bert,aggregation_strategy=aggr)
self.entity="entity" if aggr=="none" else "entity_group"
def __call__(self,text):
w=[(t["start"],t["end"],t[self.entity]) for t in self.pipeline(text)]
u="# text = "+text.replace("\n"," ")+"\n"for i,(s,e,p) in enumerate(w,1):
m="_" if i<len(w) and w[i][0]<e else "SpaceAfter=No"
u+="\t".join([str(i),text[s:e],"_",p]+["_"]*5+[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

不

知

而

不

慍

不

亦

君

子

乎

図 13: roberta-classical-chinese-base-upos による UPOS 付与– 18 –

Google Colaboratory 上の Transformers を用いて、roberta-classical-chinese-base-upos[30]で「子曰學而時習之不亦説乎有朋自遠方來不亦樂乎人不知而不慍不亦君子乎」に UPOSを付与するプログラムと、その結果を図 13 に示します。
「君子」が 2 文字の漢語であり、「君」に B-NOUN が、「子」に I-NOUN が付与されています。「君子」以外は漢字 1 字が漢語 1 語と判定されていて、それぞれに UPOS が付与されています。
Transformers の系列ラベリングは、他の用途にも適用できます。roberta-classical-chinesebase-sentence-segmentation[31] は、古典中国語の文切りに 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,aggr="none"):from transformers import pipeline
self.pipeline=pipeline(task="ner",model=bert,aggregation_strategy=aggr)
self.entity="entity" if aggr=="none" else "entity_group"
def __call__(self,text):
w=[(t["start"],t["end"],t[self.entity]) for t in self.pipeline(text)]
u="# text = "+text.replace("\n"," ")+"\n"for i,(s,e,p) in enumerate(w,1):
m="_" if i<len(w) and w[i][0]<e else "SpaceAfter=No"
u+="\t".join([str(i),text[s:e],"_",p]+["_"]*5+[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

不

知

而

不

慍

不

亦

君

子

乎

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

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

Google Colaboratory 上の Transformers を用いて、roberta-classical-chinese-base-sentencesegmentation で「子曰學而時習之不亦説乎有朋自遠方來不亦樂乎人不知而不慍不亦君子
乎」を文切りするプログラムと、その結果を図 14 に示します。
「子曰」「學而時習之」「不亦説乎」「有朋自遠方來」「不亦樂乎」「人不知而不慍」「不亦君子乎」の 7 つの文に切られているのがわかります。

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

安岡孝一, ウィッテルン クリスティアン, 守岡知彦, 池田巧, 山崎直樹, 二階堂善弘, 鈴木慎吾, 師茂樹, 藤田一乘: 古典中国語 (漢文) Universal Dependencies とその応用, 情報処理学会論文誌, Vol.63, No.2 (2022 年 2月), pp.355-363.
[33]
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.
[34]
安岡孝一, ウィッテルン クリスティアン, 守岡知彦, 池田巧, 山崎直樹, 二階堂善弘, 鈴木慎吾, 師茂樹: 古典中国語 (漢文) の形態素解析とその応用, 情報処理学会論文誌, Vol.59, No.2 (2018 年 2 月), pp.323-331.

– 20 –

!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,助詞,句末,*

不

亦

君子

乎

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

このような形で SuPar-Kanbun は、漢字の列である白文に品詞付与をおこない、さらに漢語の列に係り受け解析をおこなうことで、漢文の依存構造を抽出します。なお、古典中
国語 UD の係り受けタグには、表 4 と図 15 に加え、受動文の主語を表す nsubj:pass、重畳を表す compound:redup、動詞並列を表す flat:vv、古典中国語以外を表す flat:foreignも用いられます[35] 。

2.3 古典中国語ミニ RoBERTa モデルの製作
Google Colaboratory 上の esupar[36] で、古典中国語ミニ RoBERTa モデルを製作してみましょう。手順を図 16〜20 に示します。
最初に、訓練のための白文を準備しましょう (図 16)。train.txt の白文の材料として、ここでは UD Classical Chinese-Kyoto[37] を元にしていますが、好みに応じ、他の白文を増量するのもいいでしょう。なお、UD Classical Chinese-Kyoto の各 CoNLL-U ファイルは、
品詞付与・係り受け解析の学習にも用います。
続けて、入力文字列を単文字に分解するためのトークナイザを、my-dir/tokenizer-lzhに作成しましょう。図 17 では、BertTokenizerFast という Transformers のトークナイザを!pip install esupar
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

図 16: 古典中国語ミニモデル製作のための準備
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")

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

https://universaldependencies.org/lzh/#syntax
https://github.com/KoichiYasuoka/esupar[37]
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.
[36]– 22 –

from transformers import (AutoTokenizer,RobertaConfig,RobertaForMaskedLM,
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=RobertaConfig(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,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 ReadLineDataset(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=RobertaForMaskedLM(cfg),train_dataset=ReadLineDataset("train.txt",tkz))
trn.train()trn.save_model("my-dir/roberta-lzh")tkz.save_pretrained("my-dir/roberta-lzh")

図 18: 古典中国語ミニ RoBERTa モデルの作成

import torchfrom transformers import AutoTokenizer,AutoModelForMaskedLM
from esupar.tradify import tradify
tkz=AutoTokenizer.from_pretrained("my-dir/roberta-lzh")
mdl=AutoModelForMaskedLM.from_pretrained("my-dir/roberta-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/roberta-lzh-ext")
tkz.save_pretrained("my-dir/roberta-lzh-ext")

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

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

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

root

obj

nsubj

obj

VERB

NOUN

PART

VERB

NOUN

労

心

者

治

人

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

from transformers import (AutoTokenizer,AutoModelForTokenClassification,
AutoConfig,DataCollatorForTokenClassification,TrainingArguments,Trainer)
brt="my-dir/roberta-lzh-ext"
tkz=AutoTokenizer.from_pretrained(brt)lid={"B":0,"E":1,"E2":2,"E3":3,"M":4,"S":5}
cfg=AutoConfig.from_pretrained(brt,num_labels=len(lid),label2id=lid,
id2label={i:l for l,i in lid.items()})
arg=TrainingArguments(num_train_epochs=3,per_device_train_batch_size=64,
output_dir="/tmp",overwrite_output_dir=True,save_total_limit=2)
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(args=arg,data_collator=DataCollatorForTokenClassification(tkz),
model=AutoModelForTokenClassification.from_pretrained(brt,config=cfg),
train_dataset=dat)
trn.train()trn.save_model("my-dir/roberta-lzh-seg")tkz.save_pretrained("my-dir/roberta-lzh-seg")

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

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

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

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.
[39]
安岡孝一: 世界の Universal Dependencies と係り受け解析ツール群, 第 3 回 Universal Dependencies 公開
研究会 (2021 年 6 月).
[40]
https://github.com/akirakubo/bert-japanese-aozora[41]
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.
[42]
伝康晴, 小木曽智信, 小椋秀樹, 山田篤, 峯松信明, 内元清貴, 小磯花絵: コーパス日本語学のための言語
資源: 形態素解析用電子化辞書の開発とその応用, 日本語科学, 第 22 号 (2007 年 10 月), pp.101-123.

– 26 –

!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

接尾辞-名詞的-一般

助詞-格助詞

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

助詞-格助詞

名詞-普通名詞-一般

助詞-格助詞

動詞-一般

助動詞

助詞-接続助詞

動詞-非自立可能

書

に

大量

の

て

いる

挿し絵 が

用い られ

図 24: SuPar-UniDic による日本語係り受け解析 (国語研短単位)
し絵が用いられて」の連用修飾節であり、advcl で繫がれています。「いる」は、UniDic
品詞 (XPOS) が「動詞-非自立可能」なのですが、ここでは非自立だとみなして UPOS を
AUX にすると同時に、aux で繫がれています。
国語研短単位 UD では、XPOS と UPOS が微妙に乖離しています。XPOS は UniDic 品
詞を流用しているのですが、UPOS の品詞付与ルールとはズレているためです。極端な例として「難儀な難儀は難儀する」(図 25) を見てみましょう。「難儀」の 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

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

助動詞

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

助詞-係助詞

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

動詞-非自立可能

難儀

な

難儀

は

難儀 する

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

3.2 国語研短単位ミニ RoBERTa モデルの製作
Google Colaboratory 上の esupar[36] で、国語研短単位ミニ RoBERTa モデルを製作してみましょう。手順を図 26〜29 に示します。
最初に、訓練のための文章を準備しましょう (図 26)。train.txt の文章の材料として、ここでは UD Japanese-GSD[43] と Wikitext-JA[44] を元にしていますが、好みに応じ、他の日本語文を増量するのもいいでしょう。なお、UD Japanese-GSD の各 CoNLL-U ファイル
は、品詞付与・係り受け解析の学習にも用います。
!pip install esupar fugashi unidic-lite
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)

図 26: 国語研短単位ミニモデル製作のための準備
続けて、入力文を国語研短単位に分解するためのトークナイザを、my-dir/tokenizer-suwに作成しましょう。図 27 では、fugashi[45] と unidic-lite[46] で train.txt を国語研短単位に区切り、それを BertJapaneseTokenizer という Transformers のトークナイザに組み上げて、国
語研短単位トークナイザを作成しています。語彙数 (vocab_size) を 8000 に絞っていま
すが、もう少し大きくした方がいいかもしれません。
!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,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")

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

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

from transformers import (AutoTokenizer,RobertaConfig,RobertaForMaskedLM,
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=RobertaConfig(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,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 ReadLineDataset(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=RobertaForMaskedLM(cfg),train_dataset=ReadLineDataset("train.txt",tkz))
trn.train()trn.save_model("my-dir/roberta-suw")
tkz.save_pretrained("my-dir/roberta-suw")

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

図 29: 国語研短単位向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar fugashi unidic-lite pytokenizations
import esupar
nlp=esupar.load("my-dir/roberta-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

て

いる

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

次に train.txt の文章から、RoBERTa モデルを my-dir/roberta-suw に作成しましょう。図28 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしていますが、GPUでも 3 時間程度かかってしまいます。
最後に、my-dir/roberta-suw と UD Japanese-GSD から、品詞付与・係り受け解析モデル
my-dir/roberta-suw-upos を製作しましょう (図 29)。ただ、隣接行列型アルゴリズムの学
習は収束が遅く、GPU でも 2 時間程度かかってしまいます。
うまく my-dir/roberta-suw-upos が製作できたかどうか、esupar でテストしてみましょう。なお、esupar で BertJapaneseTokenizer を用いる場合、fugashi と unidic-lite に加えて、
pytokenizations[47] も必要です。図 30 の例では、「にわたって」「ている」のリンクに fixedが現れていて、図 24 とは異なる結果になっているようです。

3.3 国語研長単位にもとづく品詞付与と係り受け解析
国語研長単位トークナイザ Japanese-LUW-Tokenizer[48] と、青空文庫 RoBERTa モデル
roberta-base-japanese-luw-upos[49] を元に、国語研長単位にもとづく品詞付与を考えてみま!pip install deplacy transformers
class SeqL(object):def __init__(self,bert,aggr="none"):from transformers import pipeline
self.pipeline=pipeline(task="ner",model=bert,aggregation_strategy=aggr)
self.entity="entity" if aggr=="none" else "entity_group"
def __call__(self,text):
w=[(t["start"],t["end"],t[self.entity]) for t in self.pipeline(text)]
u="# text = "+text.replace("\n"," ")+"\n"for i,(s,e,p) in enumerate(w,1):
m="_" if i<len(w) and w[i][0]<e else "SpaceAfter=No"
u+="\t".join([str(i),text[s:e],"_",p]+["_"]*5+[m])+"\n"return u+"\n"nlp=SeqL("KoichiYasuoka/roberta-base-japanese-luw-upos")
doc=nlp("全学年にわたって小学校の国語の教科書に大量の挿し絵が用いられている")
import deplacy
deplacy.serve(doc,port=None)

B-NOUN

ADP

NOUN

ADP

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

ADP

VERB

SCONJ

挿し

絵

が

用い られ ている

全

I-NOUN

ADP

NOUN

AUX

NOUN

ADP

教科書 に

図 31: roberta-base-japanese-luw-upos による UPOS 付与[47]

https://github.com/explosion/tokenizations
https://github.com/KoichiYasuoka/Japanese-LUW-Tokenizer[49]
https://huggingface.co/KoichiYasuoka/roberta-base-japanese-luw-upos[48]– 30 –

ADJ

ADP

大量

の

!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

mark
aux

ADP

VERB

AUX

SCONJ

が

用い られ ている

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

[50]

安岡孝一: Transformers と国語研長単位による日本語係り受け解析モデルの製作, 情報処理学会研究報
告, Vol.2022-CH-128『人文科学とコンピュータ』, No.7 (2022 年 2 月 19 日), pp.1-8.

– 31 –

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

図 33: 国語研長単位向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar fugashi unidic-lite pytokenizations
import esupar
nlp=esupar.load("my-dir/roberta-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

mark
aux

ADP

VERB

AUX

SCONJ

が

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

3.5 文節にもとづく係り受け解析
GiNZA[52] は、国語研短単位にもとづく状態遷移型係り受け解析アルゴリズムを実装しており、その上で、文節にもとづく係り受け解析が可能です。ただし、文節にもとづく[51]

大村舞, 若狭絢, 浅原正幸: 国語研長単位に基づく UD Japanese, 言語処理学会第 28 回年次大会発表論文
集 (2022 年 3 月), pp.1618-1623.
[52]
松田寛: GiNZA - Universal Dependencies による実用的日本語解析, 自然言語処理, Vol.27, No.3 (2020 年
9 月), pp.695-701.

– 32 –

係り受けは、慣習的に文頭から文末へとリンクする[53] ため、矢印の方向が日本語 UD と逆になってしまいます。
Google Colaboratory 上の GiNZA を用いて、「全学年にわたって小学校の国語の教科書に大量の挿し絵が用いられている」を文節係り受け解析するプログラムと、その結果 (可視化は Graphviz[54] を使用) を図 35 に示します。文節にもとづく係り受け解析は、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)小学校の体言による連体修飾語

国語の

大量の

体言による連体修飾語

全学年にわたって

教科書に
斜格補語

斜格補語

体言による連体修飾語

挿し絵が
主語

用いられている

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

吉田将: 二文節間の係り受けを基礎とした日本語文の構文分析, 電子通信学会論文誌, Vol.55-D, No.4
(1972 年 4 月), pp.238-244.
[54]https://graphviz.readthedocs.io– 33 –

4 英語編
4.1 英語 UD における品詞付与と係り受け解析
Trankit[55] は、XLM-RoBERTa[56] をベースに、隣接行列型係り受け解析アルゴリズムを、様々な言語向けに実装しています。各言語向けに品詞付与も実装していて、複数の言語を同時に扱うことも可能です。Google Colaboratory 上の Trankit を用いて、英文「It didn’t
take long to repair my car」を品詞付与・係り受け解析するプログラムと、その結果を図36 に示します。解析結果を見ていくことにしましょう。
!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

図 36: 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[57] は、UDPipe 2 の係り受け解析モデル[58] を、WebAPI の形で公開しています。内部的には、隣接行列型係り受け解析アルゴリズムを使っているようです。
Google Colaboratory から UDPipe 2 WebAPI の英語モデルにアクセスするプログラムと、[55]

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.
[56]
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.
[57]
https://lindat.mff.cuni.cz/services/udpipe/[58]
Milan Straka: UDPipe 2.0 Prototype at CoNLL 2018 UD Shared Task, Proceedings of the CoNLL 2018
Shared Task (October 2018), pp.197-207.

– 34 –

!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("en")doc=nlp("It didn’t take long to repair my car")import deplacy
deplacy.serve(doc,port=None)
root
nsubj
aux

advcl
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

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

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

https://universaldependencies.org/en/#syntax
https://github.com/UniversalDependencies/UD_English-EWT[61]
https://arxiv.org/abs/1609.07843[60]– 35 –

!pip install esupar pytokenizations
import os
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 ; done
!sed -n "s/^# text = //p" *.conllu > train.txt
url="https://s3.amazonaws.com/research.metamind.io/wikitext/wikitext-2-v1.zip"!test -d wikitext-2 || ( curl -LO {url} ; unzip {os.path.basename(url)} )!sed "s/<unk>/[UNK]/g" wikitext-2/*.tokens >> train.txt

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

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")

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

from transformers import (AutoTokenizer,RobertaConfig,RobertaForMaskedLM,
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=RobertaConfig(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,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 ReadLineDataset(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=RobertaForMaskedLM(cfg),train_dataset=ReadLineDataset("train.txt",tkz))
trn.train()trn.save_model("my-dir/roberta-en")tkz.save_pretrained("my-dir/roberta-en")

図 40: 英語ミニ RoBERTa モデルの作成– 36 –

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

図 41: 英語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/roberta-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

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

5 フランス語編
5.1 フランス語 UD における品詞付与と係り受け解析
spacy-transformers[62] は、BERT/RoBERTa モデルによる状態遷移型係り受け解析アルゴ
リズムを実装しており、フランス語向けには、CamemBERT[63] を元にした fr dep news trfを公開[64] しています。Google Colaboratory 上の spacy-transformers を用いて、フランス語の例文「Il ne peut pas prêter attention aux articles contractés」を品詞付与・係り受け解析するプログラムと、その結果を図 43 に示します。解析結果を見ていくことにしましょう。
!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

図 43: 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[55] は、XLM-RoBERTa をベースに、隣接行列型係り受け解析アルゴリズムを、様々な言語向けに実装しています。Google Colaboratory 上の Trankit を用いて「Il ne peut
pas prêter attention aux articles contractés」を品詞付与・係り受け解析するプログラムと、その結果を図 44 に示します。
「aux」が内部的には 2 語として扱われており、「à」が「articles」の前置詞、「les」が限定詞 (冠詞) として、それぞれ case・det で繫がれています。
[62]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.
[64]
https://huggingface.co/spacy/fr_dep_news_trf[63]– 38 –

!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

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

5.2 フランス語ミニ RoBERTa モデルの製作
Google Colaboratory 上の esupar[36] で、フランス語ミニ RoBERTa モデルを製作してみましょう。手順を図 45〜48 に示します。
最初に、訓練のための文章を準備しましょう (図 45)。train.txt の文章の材料として、ここでは UD French-Sequoia[66] と UD French-GSD[67] を元にしていますが、好みに応じ、フランス語の他の文章を増量するのもいいでしょう。なお、各 CoNLL-U ファイルは、品詞付与・係り受け解析の学習にも用います。
続けて、フランス語向けトークナイザを、my-dir/tokenizer-fr に作成しましょう。図 46
では、Transformers の BertTokenizerFast を使って、フランス語向けトークナイザを作成
しています。
次に train.txt の文章から、RoBERTa モデルを my-dir/roberta-fr に作成しましょう。図 47では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンションヘッ!pip install esupar pytokenizations
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

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

https://universaldependencies.org/fr/dep
https://github.com/UniversalDependencies/UD_French-Sequoia[67]
https://github.com/UniversalDependencies/UD_French-GSD[66]– 39 –

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")

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

from transformers import (AutoTokenizer,RobertaConfig,RobertaForMaskedLM,
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=RobertaConfig(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,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 ReadLineDataset(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=RobertaForMaskedLM(cfg),train_dataset=ReadLineDataset("train.txt",tkz))
trn.train()trn.save_model("my-dir/roberta-fr")
tkz.save_pretrained("my-dir/roberta-fr")

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

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

ド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしており、CPU なら 1 時
間程度、GPU なら 10 分程度で作成できます。
最後に、my-dir/roberta-fr と UD French-Sequoia・UD French-GSD から、品詞付与・係
り受け解析モデル my-dir/roberta-fr-upos を製作しましょう (図 48)。ただ、隣接行列型ア
ルゴリズムの学習は収束が遅く、GPU でも 3 時間程度かかってしまいます。
うまく my-dir/roberta-fr-upos が製作できたら、esupar でテストしてみましょう (図 49)。
esupar は縮合語を UPOS 付与においてサポート (図 50) しており、係り受け解析では「aux」
を 2 語として処理します。
!pip install esupar
import esupar
nlp=esupar.load("my-dir/roberta-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

図 49: フランス語向け品詞付与・係り受け解析ミニモデルのテスト!pip install deplacy transformers
class SeqL(object):def __init__(self,bert,aggr="none"):from transformers import pipeline
self.pipeline=pipeline(task="ner",model=bert,aggregation_strategy=aggr)
self.entity="entity" if aggr=="none" else "entity_group"
def __call__(self,text):
w=[(t["start"],t["end"],t[self.entity]) for t in self.pipeline(text)]
u="# text = "+text.replace("\n"," ")+"\n"for i,(s,e,p) in enumerate(w,1):
m="_" if i<len(w) and w[i][0]<e else "SpaceAfter=No"
u+="\t".join([str(i),text[s:e],"_",p]+["_"]*5+[m])+"\n"return u+"\n"nlp=SeqL("my-dir/roberta-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

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

6 ドイツ語編
6.1 ドイツ語 UD における品詞付与と係り受け解析
Trankit[55] は、XLM-RoBERTa をベースに、隣接行列型係り受け解析アルゴリズムを、様々な言語向けに実装しています。Google Colaboratory 上の Trankit を用いて、ドイツ語の例文「Im Krankenzimmer sah er krank aus aber wollte gut aussehen」を品詞付与・係り受
け解析するプログラムと、その結果を図 51 に示します。
!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

図 51: Trankit によるドイツ語の係り受け解析
ドイツ語 UD は、単語の扱いが非常に独特です。図 51 の「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 も用いられます[68] 。

[68]https://universaldependencies.org/de/#relations-overview– 42 –

6.2 ドイツ語ミニ RoBERTa モデルの製作
Google Colaboratory 上の esupar[36] で、ドイツ語ミニ RoBERTa モデルを製作してみましょう。手順を図 52〜55 に示します。
最初に、訓練のための文章を準備しましょう (図 52)。train.txt の文章の材料として、ここでは UD German-HDT[69] を元にしていますが、好みに応じ、ドイツ語の他の文章を増量するのもいいでしょう。なお、UD German-HDT の CoNLL-U ファイルは、品詞付与・係り受け解析の学習にも用います。
!pip install esupar pytokenizations
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

図 52: ドイツ語ミニモデル製作のための準備
続けて、ドイツ語向けトークナイザを、my-dir/tokenizer-de に作成しましょう。図 53 では、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")

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

[69]

https://github.com/UniversalDependencies/UD_German-HDT– 43 –

from transformers import (AutoTokenizer,RobertaConfig,RobertaForMaskedLM,
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=RobertaConfig(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,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 ReadLineDataset(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=RobertaForMaskedLM(cfg),train_dataset=ReadLineDataset("train.txt",tkz))
trn.train()trn.save_model("my-dir/roberta-de")tkz.save_pretrained("my-dir/roberta-de")

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

図 55: ドイツ語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/roberta-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

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

!pip install deplacy transformers
class SeqL(object):def __init__(self,bert,aggr="none"):from transformers import pipeline
self.pipeline=pipeline(task="ner",model=bert,aggregation_strategy=aggr)
self.entity="entity" if aggr=="none" else "entity_group"
def __call__(self,text):
w=[(t["start"],t["end"],t[self.entity]) for t in self.pipeline(text)]
u="# text = "+text.replace("\n"," ")+"\n"for i,(s,e,p) in enumerate(w,1):
m="_" if i<len(w) and w[i][0]<e else "SpaceAfter=No"
u+="\t".join([str(i),text[s:e],"_",p]+["_"]*5+[m])+"\n"return u+"\n"nlp=SeqL("my-dir/roberta-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

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

7 オランダ語編
7.1 オランダ語 UD における品詞付与と係り受け解析
Trankit[55] は、XLM-RoBERTa をベースに、隣接行列型係り受け解析アルゴリズムを、様々な言語向けに実装しています。Google Colaboratory 上の Trankit を用いて、オランダ語の例文「In de ziekenkamer zag hij ziek uit maar wilde goed uitzien」を品詞付与・係り受
け解析するプログラムと、その結果を図 58 に示します。解析結果を見ていくことにしましょう。
!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

図 58: 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
も用いられます[70] 。

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

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

最初に、訓練のための文章を準備しましょう (図 59)。train.txt の文章の材料として、ここでは UD Dutch-Alpino[71] と UD Dutch-LassySmall[72] を元にしていますが、好みに応じ、オランダ語の他の文章を増量するのもいいでしょう。なお、各 CoNLL-U ファイルは、品
詞付与・係り受け解析の学習にも用います。
!pip install esupar
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

図 59: オランダ語ミニモデル製作のための準備
続けて、オランダ語向けトークナイザを、my-dir/tokenizer-nl に作成しましょう。図 60
では、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")

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

[71]
[72]

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

from transformers import (AutoTokenizer,RobertaConfig,RobertaForMaskedLM,
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=RobertaConfig(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,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 ReadLineDataset(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=RobertaForMaskedLM(cfg),train_dataset=ReadLineDataset("train.txt",tkz))
trn.train()trn.save_model("my-dir/roberta-nl")
tkz.save_pretrained("my-dir/roberta-nl")

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

図 62: オランダ語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/roberta-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

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

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

DET

NOUN

หลาย หัว

VERB

ADP

NOUN

B-NUM

I-NUM

ดี

กว่า

หัว

เ

ดียว

図 64: roberta-base-thai-spm-upos による UPOS 付与

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

[73]

https://huggingface.co/KoichiYasuoka/roberta-base-thai-spm-upos– 49 –

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

nsubj
NOUN

หลาย หัว

casenummod

VERB

ADP

NOUN

NUM

ดี

กว่า

หัว

เดียว

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

8.3 タイ語ミニ RoBERTa モデルの製作
Google Colaboratory 上の esupar で、タイ語ミニ RoBERTa モデルを製作してみましょう。手順を図 66〜69 に示します。
最初に、訓練のための文章を準備しましょう (図 66)。train.txt の文章の材料として、ここでは VISTEC-TP-TH-2021[74] と UD Thai-Corpora[75] を元にしていますが、好みに応じ、タイ語の他の文章を増量するのもいいでしょう。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 に作成しましょう。図 67 では、Unigram トークナイザ (SentencePiece[76] の改造版) を token.txt[74]

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.
[75]
https://github.com/KoichiYasuoka/spaCy-Thai/tree/master/UD_Thai-Corpora[76]
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.

– 50 –

!pip install esupar pytokenizations
import os
url="https://github.com/mrpeerat/OSKut"d=os.path.join(os.path.basename(url),"VISTEC-TP-TH-2021")!test -d {d} || git clone --depth=1 {url}!cat {d}/*/*raw.txt > train.txt!sed "s/<[^>]*>//g;s/[|_]/ /g" {d}/*/*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)>>"train.txt";
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

図 66: タイ語ミニモデル製作のための準備
from transformers import RemBertTokenizerFast
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.Whitespace()
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"])
spt.save("spt.json")
vcb=sorted(spt.get_vocab().items(),key=lambda x:x[1])with open("vocab.txt","w",encoding="utf-8") as w:
print("\n".join(k for k,v in vcb),file=w)
tkz=RemBertTokenizerFast(tokenizer_file="spt.json",vocab_file="vocab.txt",
do_lower_case=False,keep_accents=True,bos_token="[CLS]",cls_token="[CLS]",
pad_token="[PAD]",sep_token="[SEP]",unk_token="[UNK]",mask_token="[MASK]")tkz.save_pretrained("my-dir/tokenizer-th")

図 67: タイ語向けトークナイザの作成に適用し、それを RemBertTokenizerFast という Transformers のトークナイザに組み上げて、タイ語向けトークナイザを作成しています。語彙数を 3000 に絞った上で、各トークンの文字数を最大 4 文字 (母音や声調記号を 1 文字に数える) としています。
次に train.txt の文章から、RoBERTa モデルを my-dir/roberta-th に作成しましょう。図68 では、入出力幅 128 トークン・入出力ベクトル 256 次元・深さ 12 層・アテンション
ヘッド 4 個・中間ベクトル 768 次元という、やや小さめのモデルにしていますが、GPUでも 1 時間程度かかってしまいます。
最後に、my-dir/roberta-th と UD Thai-Corpora から、品詞付与・係り受け解析モデル
my-dir/roberta-th-upos を製作しましょう (図 69)。うまく my-dir/roberta-th-upos ができた
ら、esupar でテストしてみましょう (図 70)。

– 51 –

from transformers import (AutoTokenizer,RobertaConfig,RobertaForMaskedLM,
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=RobertaConfig(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,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 ReadLineDataset(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=RobertaForMaskedLM(cfg),train_dataset=ReadLineDataset("train.txt",tkz))
trn.train()trn.save_model("my-dir/roberta-th")tkz.save_pretrained("my-dir/roberta-th")

図 68: タイ語ミニ RoBERTa モデルの作成

s,d="my-dir/roberta-th","my-dir/roberta-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

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

nsubj
NOUN

หลาย หัว

casenummod

VERB

ADP

NOUN

NUM

ดี

กว่า

หัว

เดียว

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

9 ロシア語編
9.1 ロシア語 UD における品詞付与と係り受け解析
Trankit[55] は、XLM-RoBERTa をベースに、隣接行列型係り受け解析アルゴリズムを、様々な言語向けに実装しています。Google Colaboratory 上の Trankit を用いて、ロシア語の例文「Москва слезам не верила а верила любви」を品詞付与・係り受け解析するプロ
グラムと、その結果を図 71 に示します。解析結果を見ていくことにしましょう。
!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

верила любви

図 71: 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 も用いられます[77] 。

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

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.
[79]
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.
[78]– 53 –

!pip install esupar pytokenizations
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

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

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")

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

from transformers import (AutoTokenizer,RobertaConfig,RobertaForMaskedLM,
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=RobertaConfig(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,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 ReadLineDataset(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=RobertaForMaskedLM(cfg),train_dataset=ReadLineDataset("train.txt",tkz))
trn.train()trn.save_model("my-dir/roberta-ru")tkz.save_pretrained("my-dir/roberta-ru")

図 74: ロシア語ミニ RoBERTa モデルの作成– 54 –

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

図 75: ロシア語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/roberta-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

верила любви

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

10

ウクライナ語編

10.1 ウクライナ語 UD における品詞付与と係り受け解析
Trankit[55] は、XLM-RoBERTa をベースに、隣接行列型係り受け解析アルゴリズムを、様々な言語向けに実装しています。Google Colaboratory 上の Trankit を用いて、ウクライ
ナ語の例文「Не скупись на втіху їй і ласку любий брате」を品詞付与・係り受け解析するプログラムと、その結果を図 77 に示します。解析結果を見ていくことにしましょう。
!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їйіНе скупись на втіху

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

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

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

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

!pip install esupar pytokenizations
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

図 78: ウクライナ語ミニモデル製作のための準備
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")

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

– 57 –

from transformers import (AutoTokenizer,RobertaConfig,RobertaForMaskedLM,
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=RobertaConfig(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,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 ReadLineDataset(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=RobertaForMaskedLM(cfg),train_dataset=ReadLineDataset("train.txt",tkz))
trn.train()trn.save_model("my-dir/roberta-uk")
tkz.save_pretrained("my-dir/roberta-uk")

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

s,d="my-dir/roberta-uk","my-dir/roberta-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

図 81: ウクライナ語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/roberta-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

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

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

11

ベラルーシ語編

11.1 ベラルーシ語 UD における品詞付与と係り受け解析
Camphr-Udify[83] は、bert-base-multilingual-cased[84] をベースに、隣接行列型係り受け解析アルゴリズムを、75 の言語に対して[85] 統合的に実装しています。Google Colaboratory
上の Camphr-Udify を用いて、ベラルーシ語の例文「Насамрэч інтэрнэт стварае міфы тыху чыіх руках інтэрнэт」を品詞付与・係り受け解析するプログラムと、その結果を図 83に示します。解析結果を見ていくことにしましょう。
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}!pip install camphr {f} deplacy
import pkg_resources,imp
imp.reload(pkg_resources)
import spacy
nlp=spacy.load("en_udify")
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чыіх руках інтэрнэт

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

2 つの「інтэрнэт」は、前者が「стварае」の主語、後者が「у чыіх руках інтэрнэт」というコピュラ節の主語であり、いずれも nsubj で繫がれています。コピュラ節「у чыіхруках інтэрнэт」の内部では、前置詞「у」が case で、関係代名詞「чыіх」が det で繫がれており、コピュラ節全体が「тых」を修飾しています。ベラルーシ語 UD のルール上、
ここは acl:relcl で繫がれるべきなのですが、解析ミスで nmod になってしまっています。
「тых」は「міфы」を修飾していて、det で繫がれています。「міфы」は「стварае」の目的語で、obj で繫がれています。「Насамрэч」は advmod で繫がれています。
なお、ベラルーシ語の係り受けタグには、表 4 に加え、受動態を表す nsubj:pass と
aux:pass、受動態の動作主を表す obl:agent、関係代名詞による連体修飾節を表す acl:relcl、
数詞と名詞の格変化の関係を表す nummod:gov と nummod:entity、コピュラ節に対する副詞的修飾語を表す advmod:discourse、氏名を表す flat:name、ベラルーシ語以外を表す flat:foreign も用いられます[86] 。
[83]https://camphr.readthedocs.io/en/stable/notes/udify.html
https://huggingface.co/bert-base-multilingual-cased[85]
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.
[86]
https://universaldependencies.org/be/#relation-subtypes[84]– 59 –

11.2 ベラルーシ語ミニ RoBERTa モデルの製作
Google Colaboratory 上の esupar[36] で、ベラルーシ語ミニ RoBERTa モデルを製作してみましょう。手順を図 84〜87 に示します。
最初に、訓練のための文章を準備しましょう (図 84)。train.txt の文章の材料として、ここでは UD Belarusian-HSE[87] を元にしていますが、好みに応じ、ベラルーシ語の他の文章を増量するのもいいでしょう。なお、各 CoNLL-U ファイルは、品詞付与・係り受け解析の学習にも用います。
!pip install esupar
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

図 84: ベラルーシ語ミニモデル製作のための準備
続けて、ベラルーシ語向けトークナイザを、my-dir/tokenizer-be に作成しましょう。図85 では、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")

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

[87]

https://github.com/UniversalDependencies/UD_Belarusian-HSE– 60 –

from transformers import (AutoTokenizer,RobertaConfig,RobertaForMaskedLM,
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=RobertaConfig(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,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 ReadLineDataset(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=RobertaForMaskedLM(cfg),train_dataset=ReadLineDataset("train.txt",tkz))
trn.train()trn.save_model("my-dir/roberta-be")tkz.save_pretrained("my-dir/roberta-be")

図 86: ベラルーシ語ミニ RoBERTa モデルの作成!python -m esupar.train my-dir/roberta-be my-dir/roberta-be-upos .

図 87: ベラルーシ語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/roberta-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

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

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

セルビア語編

1212.1 セルビア語 UD における品詞付与と係り受け解析
Camphr-Udify[83] は、bert-base-multilingual-cased をベースに、隣接行列型係り受け解析
アルゴリズムを、75 の言語に対して統合的に実装しています。Google Colaboratory 上のCamphr-Udify を用いて、セルビア語の例文「Моја би мати знала гибати гибаницу да имасира и масла」を品詞付与・係り受け解析するプログラムと、その結果を図 89 に示します。解析結果を見ていくことにしましょう。
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}!pip install camphr {f} deplacy
import pkg_resources,imp
imp.reload(pkg_resources)from spacy.lang.sr import Serbian
nlp=Serbian()
import spacy
nlp.pipeline.extend(spacy.load("en_udify").pipeline)
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

и

масла

図 89: Camphr-Udify によるセルビア語 (キリル文字) の係り受け解析
図 89 の例文は、主節「Моја би мати знала гибати гибаницу」と条件節「да има сира имасла」から構成されており、advcl で繫がれています。動詞「знала」の主語「мати」は、同時に「гибати」の主語でもあることから、「мати」が nsubj で、「гибати」が xcomp で繫がれています。助動詞「би」は aux で繫がれています。所有代名詞「Моја」は「мати」
を修飾しており、det のリンクが交差しています。「гибаницу」は「гибати」の目的語であり、obj で繫がれています。条件節では、「да」が mark で繫がれています。「има」の目的語は「сира」と「масла」の 2 つですが、「сира」の方が obj で繫がれていて、その先に conj で「масла」が繫がれており、そのまた先に cc で「и」が繫がれています。
セルビア語は、公式にはキリル文字で書かれるのですが、ラテン文字による表記も多く用いられており、UD Serbian-SET[88] などのセルビア語コーパスも、多くはラテン文字で書かれています。Camphr-Udify は、ラテン文字で書かれたセルビア語も、キリル文字と同様に解析可能です。Google Colaboratory 上の Camphr-Udify を用いて、セルビア語の例文「Moja bi mati znala gibati gibanicu da ima sira i masla」を品詞付与・係り受け解析するプログラムと、その結果を図 90 に示します。
[88]

https://github.com/UniversalDependencies/UD_Serbian-SET– 62 –

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}!pip install camphr {f} deplacy
import pkg_resources,imp
imp.reload(pkg_resources)from spacy.lang.sr import Serbian
nlp=Serbian()
import spacy
nlp.pipeline.extend(spacy.load("en_udify").pipeline)
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

図 90: Camphr-Udify によるセルビア語 (ラテン文字) の係り受け解析
なお、セルビア語 UD の係り受けタグには、表 4 に加え、数詞と名詞 (および代名詞)の格変化の関係を表す nummod:gov と det:numgov も用いられます[89] 。

12.2 セルビア語ミニ RoBERTa モデルの製作
Google Colaboratory 上の esupar[36] で、セルビア語ミニ RoBERTa モデルを製作してみましょう。手順を図 91〜95 に示します。srtools[90] の助けを借りて、キリル文字とラテン文字の両方が使えるモデルを目指します。
最初に、訓練のための文章を準備しましょう (図 91)。train.txt の文章の材料として、こ!pip install esupar srtools
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

図 91: セルビア語ミニモデル製作のための準備

[89]
[90]

https://universaldependencies.org/treebanks/sr_set/#relations-overview
https://gitlab.com/andrejr/srtools– 63 –

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")

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

[91]

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

from transformers import (AutoTokenizer,RobertaConfig,RobertaForMaskedLM,
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=RobertaConfig(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,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 ReadLineCyrillic(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=RobertaForMaskedLM(cfg),train_dataset=ReadLineCyrillic("train.txt",tkz))
trn.train()trn.save_model("my-dir/roberta-sr")tkz.save_pretrained("my-dir/roberta-sr")

図 93: セルビア語ミニ RoBERTa モデルの作成

import torch,srtools
from transformers import BertTokenizerFast,AutoModelForMaskedLM
tkz=BertTokenizerFast.from_pretrained("my-dir/roberta-sr")
mdl=AutoModelForMaskedLM.from_pretrained("my-dir/roberta-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/roberta-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/roberta-sr-ext")

図 94: セルビア語ミニ RoBERTa モデルの拡張 (ラテン文字追加)– 65 –

!python -m esupar.train my-dir/roberta-sr-ext my-dir/roberta-sr-upos .

図 95: セルビア語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/roberta-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

и

масла

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

クロアチア語編

1313.1 クロアチア語 UD における品詞付与と係り受け解析
Trankit[55] は、XLM-RoBERTa をベースに、隣接行列型係り受け解析アルゴリズムを、様々な言語向けに実装しています。Google Colaboratory 上の Trankit を用いて、クロアチ
ア語の例文「Moja bi mati znala gibati gibanicu da ima sira i masla」を品詞付与・係り受
け解析するプログラムと、その結果を図 97 に示します。解析結果を見ていくことにしましょう。
!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

図 97: Trankit によるクロアチア語の係り受け解析
図 97 の例文は、主節「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 も用いられます[92] 。

13.2 クロアチア語ミニ RoBERTa モデルの製作
Google Colaboratory 上の esupar[36] で、クロアチア語ミニ RoBERTa モデルを製作してみましょう。手順を図 98〜101 に示します。
最初に、訓練のための文章を準備しましょう (図 98)。train.txt の文章の材料として、ここでは UD Croatian-SET[93] と hr500k[94] を元にしていますが、好みに応じ、クロアチア語の他[92]

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

!pip install esupar
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

図 98: クロアチア語ミニモデル製作のための準備
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")

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

– 68 –

from transformers import (AutoTokenizer,RobertaConfig,RobertaForMaskedLM,
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=RobertaConfig(hidden_size=256,num_hidden_layers=12,num_attention_heads=4,
intermediate_size=768,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 ReadLineDataset(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=RobertaForMaskedLM(cfg),train_dataset=ReadLineDataset("train.txt",tkz))
trn.train()trn.save_model("my-dir/roberta-hr")tkz.save_pretrained("my-dir/roberta-hr")

図 100: クロアチア語ミニ RoBERTa モデルの作成

s,d="my-dir/roberta-hr","my-dir/roberta-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

図 101: クロアチア語向け品詞付与・係り受け解析ミニモデルの製作!pip install esupar
import esupar
nlp=esupar.load("my-dir/roberta-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

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

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

2022 年 2 月 28 日 (初版)・2022 年 4 月 29 日 (改訂版)発行所

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