リケラボ論文検索は、全国の大学リポジトリにある学位論文・教授論文を一括検索できる論文検索サービスです。

リケラボ 全国の大学リポジトリにある学位論文・教授論文を一括検索するならリケラボ論文検索大学・研究所にある論文を検索できる

リケラボ 全国の大学リポジトリにある学位論文・教授論文を一括検索するならリケラボ論文検索大学・研究所にある論文を検索できる

大学・研究所にある論文を検索できる 「マルチモーダル情報の対応関係を捉えたモダリティ変換」の論文概要。リケラボ論文検索は、全国の大学リポジトリにある学位論文・教授論文を一括検索できる論文検索サービスです。

コピーが完了しました

URLをコピーしました

論文の公開元へ論文の公開元へ
書き出し

マルチモーダル情報の対応関係を捉えたモダリティ変換

濵園, 侑美 お茶の水女子大学

2023.03.23

概要

2022 年度博士学位論文

マルチモーダル情報の対応関係を捉えた
モダリティ変換

お茶の水女子大学大学院
人間文化創成科学研究科
理学専攻
濵園侑美

2023 年  3 月

要旨

人は自然言語を介して物事をより深く理解する.近年,計算機の発達により,言葉や画
像,数値情報などを扱う手法が発達し,その能力が向上している.さまざまな物事を計算
機上で扱えるようになった一方,それぞれの物事はモダリティ毎に独立して扱われていた
ため,モダリティ間の関係性を捉えるに至っていない.そこで,本論文は言葉を中核に据
えて,異なるモダリティの対応関係を捉え,生成する課題に取り組む.
一つ目は言語から非言語系列を生成する課題として,自然言語からロボット動作を生成
する課題に取り組む.言語を計算機上で扱う手法として,意味の捉え方に文章中の単語の
頻度情報や周辺単語による単語の類似度により自動的に意味を付与する分散意味表現を用
いる.非言語系列として,本課題ではロボット動作を扱う.まず,人間の関節の動きとは
異なるロボットに動作を生成させるためにロボットが行える基本動作を組み合わせること
により,人の動きを真似て行える枠組みを提案する.また,それらの基本動作を組み合わ
せることにより,複雑な動作を表現,生成することを可能とする.これらを達成したのち,
言葉と動作の対応関係を学習する課題に取り組む.2 つの対応関係を捉える方法として,本
課題ではニューラルネットワークを用いる.特に,多様なロボット動作と曖昧な表現との
対応関係を学習できるようなニューラルネットワークの構造を提案し,検証する.
二つ目は非言語から言語を生成する課題として,一般ドメインの動画の実況生成課題に
取り組む.本課題に則したデータセットは存在しないため,既存のビデオコーパスを用い
て実況の収集を行い,データセットの構築を行う.その後,課題をタイミング推定と発話
生成の 2 つのサブタスクに分割して,動画のみから実況を生成する課題の解決に取り組む.
これは,実況は映像に合わせて出力されるテキストのため,実況を開始するタイミングや,
実況テキストの長さを制御する必要があるためである.タイミング推定には,人の行動を
推定できる枠組みを用いる.発話生成には,言語生成に適したニューラルネットワークモ
デル,特に Transformer を用いる.
最後に,非言語から言語を生成する課題のうち,実世界で得られたデータとテキストを
用いる場合に発生する問題について取り上げ,問題の原因を分析し,解決策を提案する.特
に,時系列数値データの概況テキスト生成における問題点を取り上げる.既存の時系列数
値データの概況テキスト生成に用いるデータセットには,時系列データの data-to-text に
特有の参照時刻の不整合問題と,実世界のデータとテキストを用いた場合に起こりうる,入
力データから予測できない属性を含む出力を求められる問題が含まれている.データセッ

i
トの作成手順や入出力データの特性を理解することで,既存の枠組みを大きく変えること
なく,これらの問題を解決する方法を提案する.
以上三つの取り組みにより,言葉を中心としてモダリティーの方向性を変更する手法の
提案と,方向性を示す.
キーワード:自然言語処理,機械学習,ヒューマノイドロボット,ニューラルネットワー
ク,言語生成,data-to-text,vision-to-text

Abstract

People understand things more deeply through natural language. In recent years, the
development of computers has led to the development of methods for handling natural language, images and numerical information, and their capabilities have improved.
While various things can now be handled on computers, each thing has been handled
independently for each modality, and the relationship between modalities has not yet
been captured. Therefore, this paper addresses the issue of capturing and generating
correspondence between different modalities, with centered on language.
The first task is generating non-verbal sequences from language, the task of generating
robot behaviours from natural language. As a method for handling language on a computer, the meaning of sentences are captured by using the frequency information of words
in the sentence and the similarity of words in the surrounding words to create a distributed
semantic representation that automatically assigns a meaning. Distributed representation
is used to automatically assign meanings based on the frequency information of words in
a sentence and the similarity of words by surrounding words. As a non-verbal series, this
task deals with robot movements. First, in order to generate movements for the robot
that are different from the movements of human joints ,we propose a framework that
can imitate human movements by combining basic movements that can be performed
by a robot. By combining these basic movements, it is possible to express and generate
complex movements. After achieving these goals, the task of learning the correspondence
between words and actions is tackled. As a method for capturing the correspondence
between the two, we use neural networks in this task. In particular, we propose and
validate a neural network structure that can learn the correspondence between various
robot actions and ambiguous expressions.
Secondly, as a task to generate language from non-verbal language, we tackle the task of
generating live video in the general domain. As there is no dataset available for this task,
the dataset is constructed by collecting the actual situation using an existing video corpus.
The task is then divided into two subtasks, timing estimation and speech generation, to
solve the task of generating the actual situation from the video alone. This is because the
actual situation is text that is output along with the video, so it is necessary to control the
timing of the start of the actual situation and the length of the actual situation text. For

i
timing estimation, a framework that can estimate human behaviour is used. For speech
generation, we use neural network models suitable for language generation, in particular
Transformer.
Finally, we address the problem of generating language from non-verbal data, which
arises when using real-world data and text, analyse the causes of the problem and propose
a solution. In particular, we address the problem of generating summary text from timeseries numerical data. Existing datasets for generating summary text for time-series
numerical data include The problem of inconsistent reference times inherent to data-totext for time-series data, and The problem of being asked to produce output containing
attributes that cannot be predicted from the input data, which can occur when using
real-world data and text. By understanding the procedures for creating datasets and
the characteristics of input and output data, we propose a way to solve these problems
without significantly changing the existing framework.
Through these three efforts, we propose a method for changing the direction of modality
with a focus on natural language, and discuss the future direction of the method.
Keywords: natural language, machine learning, humanoid robot, neural
network, natural language generation, data-to-text, vision-to-text

ii

目次

第 1 章 序論

1

1.1

背景 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1

1.2

本研究の目的 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3

1.3

課題設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4

1.4

本論文の構成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5

第 2 章 ニューラルネットワーク

2.1

2.2

2.3

2.4

6

順伝播型ネットワーク . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6

2.1.1

活性化関数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7

2.1.2

出力層の設計 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8

2.1.3

誤差逆伝播法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9

2.1.4

最適化手法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10

再帰型ニューラルネットワーク . . . . . . . . . . . . . . . . . . . . . . . .

11

2.2.1

LSTM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13

2.2.2

GRU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14

Sequence-to-Sequence モデル . . . . . . . . . . . . . . . . . . . . . . . . .

15

2.3.1

Attention 機構 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15

2.3.2

Copy 機構 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16

Transformer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17

2.4.1

Transformer の基礎構造 . . . . . . . . . . . . . . . . . . . . . . . .

17

2.4.2

Transformer の要素 . . . . . . . . . . . . . . . . . . . . . . . . . . .

17

iii
第 3 章 言葉の意味表現

20

3.1

分散意味表現 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

20

3.2

ニューラルネットワーク言語モデル . . . . . . . . . . . . . . . . . . . . . .

21

3.3

Word2vec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

22

3.3.1

CBOW . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

22

3.3.2

Skip-gram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

23

3.4

事前学習済みモデル

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

24

3.4.1

BERT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

25

3.4.2

BART . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

27

第 4 章 自然言語理解によるロボットの動作生成

29

4.1

研究背景と目的 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

29

4.2

関連研究 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

30

4.3

ロボット動作 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

30

4.3.1

ヒューマノイドロボット HIRONXC

. . . . . . . . . . . . . . . . .

30

4.3.2

動作構成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

33

4.3.3

動作生成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

34

4.4

言語表現からの動作生成 . . . . . . . . . . . . . . . . . . . . . . . . . . . .

37

4.5

ロボット動作制御モデルの構築 . . . . . . . . . . . . . . . . . . . . . . . .

38

4.5.1

実験仕様 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

38

4.5.2

評価指標 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

42

4.5.3

実験結果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

43

4.6

まとめと今後の課題

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

第 5 章 一般ドメイン実況生成

51
52

5.1

概要 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

52

5.2

関連研究 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

54

5.3

データセット . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

55

iv

5.4

5.5

5.6

5.7

5.3.1

実況音声収集 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

55

5.3.2

自動文字起こしと実況テキスト修正 . . . . . . . . . . . . . . . . . .

56

5.3.3

データセット統計および既存データとの比較 . . . . . . . . . . . . .

57

問題設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

59

5.4.1

タイミング推定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

61

5.4.2

発話生成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

63

一般動画実況生成におけるタイミング推定実験 . . . . . . . . . . . . . . . .

63

5.5.1

評価指標 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

64

5.5.2

実験設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

64

5.5.3

ベースライン . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

64

5.5.4

結果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

65

一般ドメイン実況生成における発話生成実験 . . . . . . . . . . . . . . . . .

65

5.6.1

実験設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

65

5.6.2

結果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

66

まとめと今後の課題

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

第 6 章 実データを用いた data-to-text

68
70

6.1

概要 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

70

6.2

関連研究 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

71

6.3

日経平均株価の概況テキスト生成 . . . . . . . . . . . . . . . . . . . . . . .

72

6.3.1

時系列株価データから市況コメントを自動生成するモデル . . . . .

72

6.3.2

数値の汎化演算タグ . . . . . . . . . . . . . . . . . . . . . . . . . .

73

参照時間の不整合 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

74

6.4.1

Multi-timestep 構造と Copy 機構を用いたテキスト生成 . . . . . . .

75

6.4.2

実験設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

79

6.4.3

評価方法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

80

6.4.4

実験結果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

81

6.4

v
6.5

6.6

予測不可能な属性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

85

6.5.1

データセット分析 . . . . . . . . . . . . . . . . . . . . . . . . . . . .

86

6.5.2

ラベルを用いた概況テキスト生成 . . . . . . . . . . . . . . . . . . .

89

6.5.3

実験設定 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

91

6.5.4

実験結果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

92

まとめと今後の課題

第 7 章 結論

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

95
96

参考文献

100

付 録 A 発表業績

112

A.1 学会誌 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
A.2 査読付き国際会議 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
A.3 国内学会 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
付 録 B 使用したプログラム

114

B.1 自然言語からのロボット動作生成 . . . . . . . . . . . . . . . . . . . . . . . 114
B.1.1 動作作成プログラム . . . . . . . . . . . . . . . . . . . . . . . . . . 114
B.1.2 ロボット動作プログラム . . . . . . . . . . . . . . . . . . . . . . . . 116
B.1.3 ロボット動作プログラム . . . . . . . . . . . . . . . . . . . . . . . . 119
B.1.4 cookpad コーパス MySQL から word2vec が使える形への変換 . . . 121
B.1.5 ネットワークの設計プログラム . . . . . . . . . . . . . . . . . . . . 123
B.1.6 訓練プログラム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
B.1.7 3D 描写プログラム . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
B.1.8 評価プログラム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
B.2 一般ドメイン実況生成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
B.2.1 実況コメント録音 UI . . . . . . . . . . . . . . . . . . . . . . . . . . 131
B.2.2 コメント修正 UI . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

vi
B.3 概況テキスト生成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
B.3.1 訓練プログラム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
B.3.2 ネットワーク構成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161

vii

図目次

2.1

各ノードの入出力 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6

2.2

3 層の順伝播型ネットワーク . . . . . . . . . . . . . . . . . . . . . . . . . .

7

2.3

ニューラルネットワークで用いられる代表的な活性化関数

. . . . . . . . .

8

2.4

RNN の構造と処理の流れ . . . . . . . . . . . . . . . . . . . . . . . . . . .

12

2.5

LSTM の構造と処理の流れ . . . . . . . . . . . . . . . . . . . . . . . . . . .

13

2.6

GRU の構造と処理の流れ . . . . . . . . . . . . . . . . . . . . . . . . . . .

14

3.1

ニューラル言語モデル . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

21

3.2

CBOW

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

23

3.3

Skip-gram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

23

3.4

BERT の構造および入力形式 . . . . . . . . . . . . . . . . . . . . . . . . .

25

3.5

BART と BERT および GPT の比較 . . . . . . . . . . . . . . . . . . . . . .

28

4.1

シミュレータ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

31

4.2

ロボットの関節 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

32

4.3

HIRONXC を用いた AAM 作成 . . . . . . . . . . . . . . . . . . . . . . . .

33

4.4

「速く切る」の動作例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

37

4.5

提案手法の概要 (「小さく 混ぜる」の動作推定例) . . . . . . . . . . . . . .

37

4.6

Network の概要 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

39

4.7

word2vec による曖昧表現の分散表現 . . . . . . . . . . . . . . . . . . . . .

40

4.8

ロボット動作(左:切る,右:混ぜる) . . . . . . . . . . . . . . . . . . .

41

4.9

曖昧表現の動作の程度変化 . . . . . . . . . . . . . . . . . . . . . . . . . . .

42

図目次

viii

4.10 正解動作表現 o の可視化 . . . . . . . . . . . . . . . . . . . . . . . . . . . .

45

4.11 Net2 の中間層と出力動作表現の可視化 . . . . . . . . . . . . . . . . . . . .

47

4.12 Net4 の中間層と動作表現の可視化 . . . . . . . . . . . . . . . . . . . . . . .

48

4.13 「ザクザク」「混ぜる」のロボット動作 . . . . . . . . . . . . . . . . . . . .

49

4.14 未知語入力時の「切る」ロボット動作 . . . . . . . . . . . . . . . . . . . . .

50

5.1

既存の動画キャプションデータセットと提案の実況との比較. . . . . . . .

53

5.2

MTurk で用いた実況録音用 HIT の例 . . . . . . . . . . . . . . . . . . . . .

56

5.3

MTurk で用いた文字起こしテキスト修正 HIT の例

. . . . . . . . . . . . .

58

5.4

ActivityNet Captions(左) と本データセット (右) の BLEU-4 による内容一
致評価可視化. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

59

ActivityNet Captions(左) と本データセット (右) の SPICE による内容一致
評価可視化. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60

一般ドメイン設定(上)と Ishigaki et al. (2021) によるクローズドメイン設
定(下)のモデルに与える動画・テキスト量を制御した実験結果 . . . . . .

67

6.1

日経平均株価の値動きと,1 月 29 日 9 時を参照時刻とする概況テキスト. .

75

6.2

提案モデルの全体概要図. . . . . . . . . . . . . . . . . . . . . . . . . . . .

76

6.3

コメント配信時刻とイベント発生時刻の時間差に関するデータ分布. . . .

82

6.4

属性ラベルを用いた概況テキスト生成モデルの概要 . . . . . . . . . . . . .

90

5.5

5.6

ix

表目次

4.1

関節の動作可能範囲

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

32

4.2

時系列対応 AAM の概要 . . . . . . . . . . . . . . . . . . . . . . . . . . . .

35

4.3

動作の時系列対応 AAM . . . . . . . . . . . . . . . . . . . . . . . . . . . .

41

4.4

ネットワーク比較 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

43

4.5

Net2 評価結果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

44

4.6

Net4 評価結果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

45

5.1

実況テキスト例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

57

5.2

本データセットと (Krishna et al., 2017), (Ishigaki et al., 2021) の統計値
比較. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

61

5.3

タイミング識別モデルの結果. . . . . . . . . . . . . . . . . . . . . . . . .

64

5.4

モデル初期化の影響. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

66

5.5

ドメインの性質による精度比較.S,T,V はそれぞれ構造化データ,テキスト,
動画コンテキストを表す . . . . . . . . . . . . . . . . . . . . . . . . . . . .

68

6.1

演算タグと対応する算術演算. . . . . . . . . . . . . . . . . . . . . . . . .

74

6.2

使用したデータの統計値 . . . . . . . . . . . . . . . . . . . . . . . . . . . .

79

6.3

BLEU (%) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

81

6.4

開発データでの動向一致・不一致評価 (%, P=precision, R=recall) . . . . .

83

6.5

直近の5分足と前日の終値との差が-48.91 円の生成テキスト例. . . . . . .

84

6.6

同じ入力データで異なる概況テキストの例. . . . . . . . . . . . . . . . . . .

87

6.7

属性予測(%).ベースラインは各属性の多数派がデータセットで占める割合 88

表目次

x

6.8

分類ラベルとその分類値 . . . . . . . . . . . . . . . . . . . . . . . . . . . .

90

6.9

BLEU (%) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

92

6.10 開発データセットによる動作表現による評価 (%) . . . . . . . . . . . . . .

93

6.11 同一入力データでのラベル追加なし・ありの生成テキスト例 . . . . . . . .

94

1

第 1 章 序論

1.1

背景

人工知能の研究とは,これまで人間にしかできなかった知的行為を機械的に実行するに
はどうしたら良いか,人間のような知を構成するにはどうすれば良いかを探究する学問で
ある1 .つまり究極的には,人工知能の研究は人間の外界認識方法や外界との関係性の持ち
方を機械で実行できるようにすることである.人間は物を見たり,匂いを嗅いだり,音を
聞いたりと,外界を複数種類の信号で捉えている.機械が人間を取り巻く外界を捉えるた
めには,このような信号をまとめて解釈できるようにする必要がある.
様々な数値,画像,音声,言語などのデータ種別のことをモダリティ(Modality )と呼び,
異なるモダリティとの関係性を捉えたり,複数のモダリティを組み合わせて用いる課題を
マルチモーダル(Multimodal )情報を用いた課題と呼ぶ.近年,計算機の発達,特に GPU
の登場により,ニューラルネットワークを用いた各モダリティでの課題解決手法の発展が
目覚ましい.例えば,2010 年から始まった大規模画像認識のコンペティション ImageNet
Large Scale Visual Recognition Challenge(ILSVRC)において,Krizhevsky et al. (2012)
は,深層学習を用いた AlexNet により従来の学習方法による画像認識精度を上回り,さら
に二位を大きく引き離して圧勝した.また Mnih et al. (2013) は,強化学習の行動価値関数
Q の学習に深層学習を用いた Deep Q-Network を提案し,Arcade Learning Environment
(ALE) の 7 つの Atari 2600 games のうち,6 つのゲームで従来の学習手法のスコアを上回
り,さらに3つのゲームで人間を上回った.計算機上で言語を扱う方法もニューラルネッ
トワークを用いた手法が登場し,特に word2vec (Mikolov et al., 2013a) が発表されて以来,
その技術は急激に発展している.
各モダリティで独立して発展したニューラルネットワークによる課題解決手法を,複数
のモダリティを処理して関連付けるマルチモーダルの課題に適用しようと,現在さまざまな
マルチモーダル課題の精度を競う大会の開催やデータセットの公開が行われている.例え
ば,2016 年より開催されている International Challenge on Activity Recognition2 は映像
と人の動作の関係性を問うマルチモーダルな課題を設定しており,人間の動作を集めた動画
コーパス ActivityNet の動画から動作認識を行う.この動作認識精度を競う大会のベースラ
1
近年では人間を超える精度を持つ人工知能も出現しており,必ずしも「人間の」知を構造すること目的で
はない場合もある (松原, 2020)
2
http://activity-net.org/challenges/2016/index.html

1.1. 背景

2

インモデルでは,映像の特徴量抽出にニューラルネットワークの C3D (Tran et al., 2015)
を用いている.
マルチモーダル情報を用いた課題には,次の5つの技術的課題 (Baltruˇsaitis et al., 2019)
が存在し,マルチモーダル課題には,これらの技術的課題が組み合わさっている.

1. 表現(Representation)
マルチモーダルデータの表現方法や要約方法についての課題.異なるモダリティの
データを同一空間で扱えるか,なども課題の一つ.
2. 変換(Translation)
あるモダリティから別のモダリティにデータを変換(マッピング)する課題.画像説
明文生成など正解が一つに絞られない場合も存在する.
3. 直接的な関係性獲得 (Alignment)
複数のモダリティ間の直接的な関係性を明らかにする課題.例えば,レシピ手順と調
理動作の一致を獲得する課題などが含まれる.
4. 融合(Fusion)
ある予測行うために複数のモダリティのデータを用いる課題.例えば,唇の動きを含
む動画とその音声を用いた音声認識課題などが含まれる.
5. 共学習(Co-learning)
あるモダリティ内で作成された予測モデルや表現方法を別のモダリティに転移する課
題.共学習,概念的接地,Zero-shot learning などの手法を用いた課題.
マルチモーダル情報を用いた課題において,特に 2. 変換は音声合成 (Hunt and Black, 1996)
や動画説明文生成 (Kojima et al., 2002) などが長年行われている.近年は,各モダリティ
でのニューラルネットワークによる課題解決手法の発展と,画像やテキストを組み合わせ
たデータセットである COCO dataset (Chen et al., 2015) に代表されるマルチモーダルな
大規模データセットの登場により,益々発展している.マルチモーダルな課題における変
換課題には,以下の 2 つのアプローチ方法がある.

• Example-based approaches
あらかじめ用意した辞書を元に,近いサンプルを検索する手法
• Generative approaches
入力データを元に別モダリティのデータを生成する手法
Generative approaches には,入出力データの両方のモダリティの性質を理解したうえで,
出力データを生成する必要があり,構造がより複雑になることから,初期のマルチモーダル
情報のモダリティ変換課題では,Example-based approaches が採用されていた.しかし,

1.2. 本研究の目的

3

Example-based approaches は辞書全体がモデルであるため,モデルが大きくなるほど推論
が遅くなり,また課題が単純であるか辞書が非常に大きくない限り,入力データに対応する
正確なサンプルが辞書に常に存在するとは限らないという問題がある.最近では精密な画
像の生成が可能なモデル (Goodfellow et al., 2014) や,より流暢な文章の生成が可能なモデ
ル (Bahdanau et al., 2015) の登場など,ニューラルネットワークによる各モダリティでの
生成手法の発展により,Example-based approaches における問題を解決できる Generative
approaches が採用されつつある.
Generative approaches によるマルチモーダル情報の変換手法は,まず入出力データをそ
れぞれのモダリティの性質を反映した表現方法を用いて表現した上で,入出力の関係性を捉
えたモデルと出力データに適した出力手法によって生成を行うため,限られたモダリティ
間の変換に特化した手法となっている.そのため,既存のモダリティ変換手法を異なるモダ
リティにはそのまま適用できない.さらに,Generative approaches で特にニューラルネッ
トワークを用いる場合には,大規模なデータセットが必要となる.大規模データセットは
画像とその説明文データセット (Young et al., 2014; Chen et al., 2015) や動画と人の動作
ラベルのデータセット (Fabian Caba Heilbron and Niebles, 2015),テキストと読み上げ音
声のデータセット (Panayotov et al., 2015; K¨
ohn et al., 2016; Ardila et al., 2020) が知ら
れており,それぞれ画像説明文生成課題や動作認識課題,音声認識課題に用いることがで
きる.これら大規模データセットが公開されているマルチモーダル課題ではモダリティ変
換手法の研究が進められている一方,それ以外のモダリティでは変換手法が十分に明らか
になっていない.また,データセットが固有のドメインに特化している場合には,モダリ
ティ変換は限られたドメインに特化した手法となる場合もある (Tanaka-Ishii et al., 1998;
Ishigaki et al., 2021).異なるドメインや新たなモダリティ間の変換に適切なモデルを得る
には,新たにデータセットを作成した上で,入出力データの適切な表現方法を適用し,モデ
ルを構築する必要がある.
また,Generative approaches によるマルチモーダル情報の変換には,音声認識のように
入力に対応する正解が 1 つに限られる課題がある一方,音声合成や画像説明文生成など,複
数の正解が存在しうる課題もある.このような正解が一つに決まらない課題には,人手評
価を行う (van den Oord et al., 2016; Kulkarni et al., 2013; Venugopalan et al., 2015b) な
どの評価方法の工夫や,モダリティ変換の方向性を設定するなどの課題の再設定を行う必
要がある.

1.2

本研究の目的

本研究ではマルチモーダル情報を用いた課題のうち,ニューラルネットワークを用いた
Generative approaches による変換課題に取り組む.特にモダリティ変換を実用に向けて行
う.現在,計算機が発達したことで,大量の情報が得られるようになった一方,人手不足
により得られた情報を適切に処理する人員が足りず,的確に利用できていない.そのため,

1.3. 課題設定

4

分析を人手を借りず,機械的に行う必要性が増している.モダリティ変換を実用に向けて
行うことは,このような人手不足の問題への解決の手掛かりとなりうる.
また人間は言語によって,物事をより深く理解する傾向にあるため,知識の共有や保存
を自然言語を通じて行うことは非常に重要である.言語・非言語間のモダリティ変換が十
分に達成されれば,今まで個人が個々に持つ知識や勘などの優れたナレッジを自然言語で
共有して活用できるようになり,さらなる技術の向上や,業務効率化,生産性の向上が可能
となる.そのため,本研究ではマルチモーダルのモダリティ変換のうち,言語を中心に据
えた変換課題に取り組み,言語と非言語のモダリティ変換の適用手法を明らかにする.
さらに,言語から非言語,非言語から言語へのモダリティ変換をそれぞれ扱い,また非
言語データを複数扱うことで,言語と特定のモダリティ間における言葉の曖昧さや言葉の
広がりを許容するモダリティ変換モデルの獲得を目指す.

1.3

課題設定

はじめに,言語から非言語を生成する課題として,自然言語からロボット動作を生成す
る課題に取り組む.これは,1つの言葉に対して動作が複数あっても許容する,言葉の曖
昧さをモダリティ変換によって扱う課題である.自然言語からロボット動作を生成する課
題は 3 つのサブタスクに分けられる.一つ目は,言葉の意味を捉えるというサブタスクで
ある.言葉の意味を計算機上で扱うため,自然言語処理の技術を用いる.文章の意味を捉
える方法は構文解析等の技術が知られている.一方,言葉の意味を捉える方法は,単語が
元々持っている意味や意味的関係から意味ネットワークを生成する等の方法がある.しか
し,それらは全て人手で作成した辞書がなくてはならない.そこで本課題では,意味の捉え
方に文章中の単語の頻度情報や周辺単語による単語の類似度を用い,自動的に意味を付与
する分散意味表現を用いる.それにより,曖昧な言語表現であっても分散意味表現上では
一意に定まり,扱いが容易になる.二つ目に,ロボットに動作を生成させるというサブタ
スクである.ロボットを用いる際に留意しなければならないこととして,ロボットの関節
の動きと人間の関節の動きは異なるということである.そこでロボットが行える基本動作
を組み合わせることにより,人の動きを真似て行える枠組みを提案する.また,それらの
基本動作を組み合わせることにより,複雑な動作を表現,生成することを可能とする.最
後に,言葉と動作の対応関係を学習するサブタスクである.2 つの対応関係を捉える方法は
様々あるが,本課題ではニューラルネットワークの技術を用いる.また,多様なロボット
動作と曖昧な表現との対応関係を学習する枠組みを提案し検証する.以上の 3 つのサブタ
スクを達成することで,人の言葉による指示からロボットが動作を生成し動作することが
可能となる.また,初めて行う動作であっても言葉の意味から推測し,ロボットが動作生
成することが可能となる.
次に非言語から言語を生成する課題として,動画像データから自然言語文を生成する課

1.4. 本論文の構成

5

題,特に一般ドメインの動画に対する実況生成課題に取り組む.ドメインを限らないオー
プンドメインの課題とすることで,ある事象に対して言葉の広がりを許容する課題となる.
動画や画像に対して自然言語でその内容を記述する研究は現在広く行われており,本課題
で取り組む動画の実況生成もその一つである.主な動画からの自然言語生成の課題は,動
画内のイベントを抽出し,そのイベントに対して説明文(キャプション)を付与する課題が
挙げられる.一方,本課題の対象である実況は,視聴者に映像の内容をわかりやすく伝え
るために,映像と共に音声として出力できたり,映像に被せてテキストが提示されたりす
るテキストである.そのため実況生成では,実況を開始するタイミングや,実況の長さを
制御する必要がある.このような観点から,実況生成を扱った研究では,タイミング推定
と発話生成の2つのサブタスクに分けて課題解決している.実況生成に関する既存研究は,
実況の特性上,例えばスポーツの試合の実況など,特定の分野を対象とするものに限られ
ていた.このような特定の分野を対象として実況生成を行う課題の場合,分野特有の情報
を用いて実況生成を行う場合がほとんどである.しかし,本課題では分野特有の情報を用
いることができず,映像とテキストのみを用いるため,より難しい課題設定と言える.
最後に,非言語から言語を生成する課題のうち,実世界で得られたデータとテキストを
用いる場合に発生する問題について取り上げ,問題の原因を分析し,解決策を探る.限ら
れたデータから適切に目的のテキストを生成する手法の獲得であり,複数の解釈が可能な
データから,言葉によって解釈の方向性を決定する課題とも言える.時系列数値データを
用いてテキスト生成を行う課題では,アライメントが不十分な場合,データとテキストに不
整合が生じ,それにより生成文で誤りが発生することがあるとされている.また,実世界
で得られたデータとテキストを使ってデータセットを作成する場合,入出力をコントロー
ルできないため,入力データから出力テキストを1つに推定できない問題も存在する.実
世界で得られた時系列数値データと,そのデータに関して実際に逐次配信されたテキスト
を用いて構築された既存のデータセットにおける上記の問題について,分析,解決策を探
り,目的のテキストを生成できるようにする.

1.4

本論文の構成

以下に本論文の構成を述べる.第 2 章では,本論文で用いるニューラルネットワークの
基礎技術について,第 3 章では,言葉の意味を捉える技術について説明する.第 4 章から
第6章では,言語と非言語の対応関係獲得課題について取り上げる.第 4 章では,言語か
ら非言語の生成課題として,自然言語理解におけるロボットの動作生成について,第5章で
は,非言語から言語の生成課題として,一般ドメインの実況生成課題を取り上げる.第6
章では,非言語から言語の生成課題で発生する問題のうち,実データを用いた data-to-text
における問題点を上げ,それの解決策について述べる.最後に,第7章で,言語と非言語の
対応関係獲得課題の結論を述べる.

6

第 2 章 ニューラルネットワーク

2.1

順伝播型ネットワーク

ニューラルネットワークは人間等の脳神経系を模倣したモデルである.ネットワークを
構成する各ノードは図 2.1 のように複数の入力を受け取り,1 つの出力を計算する.

図 2.1: 各ノードの入出力
ここで,wi は i 番目の入力 xi に対する結合の重み,θ はしきい値であり,出力 y は
( 4
)

y=f
(2.1)
w i xi − θ
i=1

と表される.ここで常に 1 の値を取る x0 を導入し,x = (x0 , · · · , x4 ),w = (w0 , · · · , w4 )
とすると,
( 4
)

y=f
(2.2)
wi xi = f (wT x)
i=0

となる.ここで,w0 = −θ であり,関数 f は活性化関数である.
順伝播型ネットワークとは一般に,入力層,複数の隠れ層(中間層),出力層からなる,
入力層から出力層への単一方向へ信号が伝搬されながら,式 2.2 に従って変換されるネット
ワークである.ノードは隣り合う層間でのみ結合し,それぞれの結合には結合の重みが割
り当てられている.具体例を図 2.2 に示す.各層での出力を式で表すと,

2.1. 順伝播型ネットワーク

7

図 2.2: 3 層の順伝播型ネットワーク

(
(2)
yj

(3)
yk

= f (1)

= f

(3)

4


i=0
( 3


)
(1)
wij yi

= f (2) (wjT y (1) )

(2.3)

= f (3) (wkT y (2) )

(2.4)

)
(2)
wjk yj

j=0

となる.第 u − 1 層のノード数を i = 1, · · · , I ,第 u 層を j = 1, · · · , J としたとき,第 u 層
での出力 y は次のように一般化される.
( I
)

(u)
(u−1)
(u)
yj
= f
wij yi
= f (u) (wjT y (u−1) )
(2.5)
i=0

ネットワークの結合の重みをまとめて W とすると,順伝播型ネットワークの出力は,y =
f (x, W ) のように入力ベクトルと結合の重みによって決定される.

2.1.1

活性化関数

活性化関数 f には一般に単調増加する非線形関数が用いられる.

f (x) = (1 + exp(−x))−1

(2.6)

f (x) = tanh(x)

(2.7)

2.1. 順伝播型ネットワーク

8

のようなロジスティック関数や双曲線正接関数といったシグモイド関数が主に使われるが,
計算コストが大きく,また深いニューラルネットの学習では誤差消失がおこるため,近年
では ReLU (Nair and Hinton, 2010)

f (x) = max(x, 0)

(2.8)

f (x) = log(1 + ex )

(2.9)

や Softplus 関数

が用いられることがある.

図 2.3: ニューラルネットワークで用いられる代表的な活性化関数

2.1.2

出力層の設計

出力層での活性化関数は問題の種類により適切なものを使用する.回帰問題では目的関
数が任意の実数の場合は恒等写像を,値域が [−1 : 1] の場合は双曲線正接関数を用いる.二
値分類にはロジスティック関数を,多クラス分類には出力の合計が 1 となるソフトマック
ス関数を用いることが多い.

2.1. 順伝播型ネットワーク

2.1.3

9

誤差逆伝播法

順伝播型ネットワークの学習は与えられた訓練データと出力された結果との誤差を最小
(m)
(m)
化することである.つまり,誤差関数 (損失関数)E = E(O0 , · · · , OK ) の勾配を計算し,
重み w について最小化することで目的関数を導出する.m 層のネットワークを考える.k
(k)
(u)
層の第 i ノードへの入力の総和を Ij ,出力を Oj ,k − 1 層の第 i ノードから k 層の第 j
(k)

ノードへの結合の重みを wij ,活性化関数を f (k) (·) とすると,これらの関係は以下となる.

(k)

Ij

I


=

(k)

(k−1)

wij Oi

(2.10)

(k)

(2.11)

i=0
(k)
Oj

= f (k) (Ij )

(k)

誤差関数 E を wij について微分すると,

∂E
(k)

(k)

∂Ij

(k)

∂wij

∂E ∂Oj

=

(k)

∂wij

∂Oj

(k)
(k)

∂Ij



(k)

(k)
∂E ∂f (Ij ) ∂(

=

(k)

(k) (k−1)
)
i=0 wij Oi
(k)
∂wij

(k)

∂Oj

∂E {

=

∑I

(k)
∂Oj

∂Ij

(k)

f (k) (Ij )

}′

(k−1)

(2.12)

Oi

ここで
(k)

dj

∂E {

=

(k)

∂Oj

(k)

f (k) (Ij )

}′

(2.13)

とする.k = m 層以外の場合,さらに,

∂E
(k)
∂wij

=

=

∂E {
(k)
∂Oj



∂E

l

(k+1)
∂Ol

(
=

(
=

(k)

f (k) (Ij )

(k+1)

(k+1)
∂Il

∂E

l

(k+1)
∂Ol

l

(k−1)

Oi

∂Ol




}′

{

(k+1)

∂Il

(k)
∂Oj
(k+1)

f (k+1) (Il

(k+1) (k+1)
dl
wjl

)

{

{

)

(k)

f (k) (Ij )

}′

(k)

f (k) (Ij )

}′

)
(k+1)

wjl

}′

(k−1)

Oi

(k−1)

Oi

{



(k)

f (k) (Ij )

}′

(k−1)

Oi



(2.14)

2.1. 順伝播型ネットワーク

10

と変形出来る.以上より,
(m)

dj

(k)
dj

=

=

∂E {
(m)

∂Oj
(


(m)

f (m) (Ij

)

}′

)
(k+1) (k+1)
dl
wjl

{

(2.15)
(k)

f (k) (Ij )

}′



(2.16)

l

∂E
(k)
∂wij

(k)

(k−1)

= dj O i

(2.17)

によって誤差が出力層から入力層に向かって伝播する.

2.1.4

最適化手法

伝播した誤差は勾配降下法

w(t+1) = w(t) − ε∇E

(2.18)

を用いて更新する.ここで ε は学習率と呼ばれ,現在の重み w(t) を負の勾配方向 −ε∇E へ
動かすことで重みを更新してより小さな E を求める.ε が小さすぎると反復回数が増え学
習にかかる時間が増大する.一方,ε が大きすぎると E が増大する可能性がある.適切な
学習率を選ぶことがニューラルネットワークの学習では重要である.

確率的勾配降下法
確率的勾配降下法とは,データの一部を使って重み更新を行う勾配降下法である.すべ

ての訓練データに対する誤差関数 E(w) = N
n=1 En (w) を最小化するバッチ学習にくらべ,
確率的勾配降下法は訓練データに冗長性がある場合などでより速く処理出来る.また,バッ
チ学習の場合は誤差関数 E(w) は常に同じである一方,確率的勾配降下法を用いると更新
毎に異なる En (w) のため,望まない局所最適解に収束することも少なく,より適切に学習
が進む.

Adam
Adam (Kingma and Ba, 2015) は学習率を更新する手法の1つであり,勾配の平均と分
散をオンライン推定した情報を利用する.以下にアルゴリズムを示す.

2.2. 再帰型ニューラルネットワーク

11

Algorithm 1 Adam による学習率最適化
Require: α: stepsize
Require: β1 ,β2 ∈ [0,1): Exponential decay rates for the moment estimates
Require: f (θ): Stochastic objective function with parameters θ
Require: θ0 : Initial parameter vector
m0 ← 0 (Initialize 1st moment vector)
v0 ← 0 (Initialize 2nd moment vector)
t ← 0 (Initialize timestep)
while θt not converged do
t ← t + 1 (Initialize timestep)
gt ← ∇θ ft (θt−1 ) (Get gradients w.r.t. stochastic objective at timestep t)
mt ← β1 · mt−1 + (1 − β1 ) · gt (Update biased first moment estimate)
vt ← β2 · vt−1 + (1 − β2 ) · gt2 (Update biased second raw moment estimate)
m
ˆt ← mt /(1 − β1t ) (Compute bias-corrected first moment estimate)
vˆt ← vt /(1 − β2t ) (Compute bias-corrected second raw moment estimate)

θt ← θt−1 − α · m
ˆt /( vˆt + ϵ) (Update parameters)
end while
return θt (Resulting parameters)

2.2

再帰型ニューラルネットワーク

Recurrent Neural Network(再帰型ニューラルネットワーク,RNN)は過去の情報を一
時的に記憶できるようなループ構造を持ち,時系列情報および可変長の入出力に対応でき
る特殊なニューラルネットワークであり,系列データを扱う自然言語処理や音声認識の分
野で広く用いられる.RNN が持つ基本的な構造は入力層,中間層,出力層の 3 層からなる
順伝搬型 NN と同様のものであるが,中間層に有向閉路,すなわちループ構造を持ち,そ
の結合についての重みパラメータを持つ点が大きな違いである.
RNN は入力系列データ x = x1 , x2 , ..., xT について,各時刻 t につきひとつの入力 xt を
受け取り,同時に系列出力 yt を逐次算出する.そのとき,中間層は入力層からの出力に加
え,ループ構造によって一つ前の時刻 t − 1 における中間層の出力を受け取り,計算を行う.
同様に,時刻 t − 1 の計算には時刻 t − 2 の情報が再帰的に考慮されているため,理論上は
それまでに受け取った全ての時刻における入力 xt = x1 , x2 , ..., xt−1 を反映して yt が計算さ
れることになる.中間層における処理は,W hx を各時刻における入力 xt(t = 1, ..., T )に
対する結合の重み,W hh を各時刻において一時刻前の中間層の出力 ht−1(t = 1, ..., T )に
対する結合の重み,中間層の活性化関数を f (·) とすると,
ht = f (Wh ht−1 + Wx xt )         (t = 1, ..., T )

(2.19)

h0 = 0 or initialized randomly

(2.20)

2.2. 再帰型ニューラルネットワーク

12

のように表せる.h0 は 0,あるいは乱数で初期化されることが多いが,タスクに応じて特
定の数値をおくこともある.図 2.4 に処理の流れを示す.

図 2.4: RNN の構造と処理の流れ
自然言語文生成に RNN を用いるときは,文を単語の系列データ(あるいは文字の系列
データ)として表し,過去の文脈から t 番目の単語を予測する.直前時刻の隠れ状態(時刻
1 から t − 1 の単語情報),直前時刻の予測結果(時刻 t − 1 の単語)を入力とし,逐次的に
次の単語の予測を繰り返して文章を生成する.文生成を行う RNN は RNN 言語モデルと呼
ばれ,キャプション付けや機械翻訳のタスクで用いられている.
このように順伝搬型ネットワークとは異なる特性と構造を持つ RNN であるが,学習その
ものは順伝搬型ネットワークとほとんど同様のアルゴリズムで行うことができる.中間層
の出力は時刻毎に変動し次時刻に影響を与えるものの,重みを用いる乗算総和処理につい
ては入力系列データそれぞれの要素 xt について同一の重みパラメータを用いるため,入出
力長は可変長でありながら学習すべきパラメータは固定長となっている.また,ループ構
造を系列の時刻方向に展開すると,通常の順伝搬型ネットワークの計算として一般化する
ことができ,誤差逆伝搬法を含む学習アルゴリズムの適用が可能となる.このように RNN
を学習する手法は Backpropagation Through Time(BPTT)法と呼ばれる.
しかし,標準的な RNN では,短期的な時系列情報は扱うことができても,長い時系列情
報をうまく扱えないという問題が指摘されている (Bengio et al., 1994).RNN の伝搬計算
は時間方向に展開されるため,長すぎる系列情報を扱う RNN は深すぎるニューラルネット
と同様に勾配消失問題などの技術的問題が発生してしまうことが大きな要因のひとつとさ
れる.
そこで,Long Short-Term Memory(LSTM) や GRU に代表される,より長い系列の

2.2. 再帰型ニューラルネットワーク

13

予測や学習を行えるような複雑な構造を持つ RNN が考案され,広く使用されている.

2.2.1

LSTM

図 2.5: LSTM の構造と処理の流れ

LSTM の概要図を図 2.5 に示す.LSTM (Hochreiter and Schmidhuber, 1997) は RNN
の中間層 1 層に相当する構造である.単純な RNN の中間層と異なり,LSTM は中間層内に
過去の計算情報を隠れ状態として保持するメモリセル,および入出力の情報量やメモリセ
ルの更新量を時刻毎に制御するゲートを持つ.直前時刻の計算結果として得られる ht−1 だ
けでなく,それまでの計算情報をゲートによって重み付けして選択的に更新されるメモリ
セルの状態 ct−1 を用いることで,初期の時刻の情報を長期間保てる機能を実現し,長期依
存の学習を可能にしている.最初期の LSTM (Hochreiter and Schmidhuber, 1997) には忘
却ゲートはなく,ゲートは入出力の 2 つしかなかったが,一般に忘却ゲートの導入によって
性能向上が見込めるとされ,現在では入力ゲート,忘却ゲート,出力ゲートの 3 種類のゲー
トを用いることが多い (Gers et al., 1999).以降,Gers et al. (1999) のモデルを説明する.
入力 xt および前時刻の出力 ht−1 をゲートにそれぞれ受け取って,[0, 1] の範囲の値をと
り,そのゲートを通過する情報を反映させる量の割合を制御する.メモリセルの値および
出力 ht は入力 xt と前時刻の出力 ht−1 に加えて前時刻のメモリセルの値 ct−1 から計算され
るが,ゲートによってそれらの情報量が制限されるようになっている.入力をメモリセル
および各ゲートに変換する重みパラメータを W cx , W ix , W ox , W f x ,直前の隠れ状態をメモ
リセルおよび各ゲートに変換する重みパラメータを W ch , W ih , W oh , W f h とし,時刻 t にお
ける入力ゲート it ,忘却ゲート ft ,出力ゲート ot ,メモリセル ct ,出力 ht は,以下のよう

2.2. 再帰型ニューラルネットワーク

14

に算出される.

it = σ(W ih ht−1 + W ix xt )          (t = 1, ..., T )
fh

fx

(2.21)

ft = σ(W ht−1 ) + W xt ))          (t = 1, ..., T )

(2.22)

ot = σ(W oh ht−1 + W ox xt )          (t = 1, ..., T )

(2.23)

ct = ft ⊙ ct−1 + it ⊙ f (W ht−1 + W xt )    (t = 1, ..., T )

(2.24)

ht = ot ⊙ ct                (t = 1, ..., T )

(2.25)

h0 = 0 or initialized randomly

(2.26)

ch

cx

なお,忘却ゲートの値 ft と活性化関数 f (·) は便宜同じ文字で表記したが,両者は無関係で
ある.

2.2.2

GRU

GRU の概要図を図 2.6 に示す.LSTM と比較すると,メモリセルが存在せず,構造がシ

図 2.6: GRU の構造と処理の流れ
ンプルである.LSTM より少ないリセットゲートと更新ゲートの 2 つのゲートだけを使っ
て,忘却と状態の更新を操作し,長期の情報は隠れ状態ベクトルに集約する.入力 x を r, z, h
に変更する重みパラメータを W rx , W zx ,W hx 直前の隠れ状態ベクトル h を r, z, h に変更
する重みパラメータを W rh , W zh , W hh とすると,時刻 t におけるリセットゲート rt ,更新

2.3. SEQUENCE-TO-SEQUENCE モデル

15

ゲート zt ,現時刻の隠れ状態であり,GRU の返り値 ht は,以下のように算出される.

ht = zt ⊙ ht−1 + (1 − zt ) ⊙ f (W hh (rt ⊙ ht−1 + W hx xt )  
rh

rx

(2.27)

ht−1 + W xt )          (t = 1, ..., T )

(2.28)

zt = σ(W zh ht−1 + W zx xt )          (t = 1, ..., T )

(2.29)

rt = σ(W

LSTM と GRU には大きな精度の差はないが,GRU は LSTM よりもゲートが少なく,セ
ルも不要のため,状態変数の数が同じであれば,GRU の方が LSTM より少ない計算量で
済む.

2.3

Sequence-to-Sequence モデル

Sequence-to-Sequence モデル(系列変換モデル,seq2seq)は,系列(Sequence)を入力
とし,別の系列(Sequence)を出力するモデルで,Sutskever et al. (2014) によって提案さ
れた.LSTM をはじめとした RNN では,エンコードした固定長のベクトルを出力するこ
としかできず,長さがわからない入力を処理したり出力を生成することが難しい.そのた
め,例えば音声認識や翻訳に RNN をそのまま用いることは難しかった.Sutskever et al.
(2014) の Sequence-to-Sequencen モデルでは,入力系列を LSTM でエンコードして固定長
のベクトルに変形した後,そのベクトルを LSTM でデコードして出力系列を生成するため,
RNN を系列変換にそのまま用いる場合の問題を解決できる.Sequence-to-Sequence モデル
の発表と同時期に Cho et al. (2014) は同様のモデルを提案し,Encoder-Decoder モデルと
呼んだ.近年では,入出力を系列に限らず,エンコーダー,デコーダーもそれぞれの入出
力に合わせたネットワークを用いたモデルを,広く Encoder-Decoder モデルと呼ぶことが
多い.また,Sequence-to-Sequence モデルのように,1 つのモデルでは表現しきれない処理
をニューラルネットを用いてモデル化し,入出力情報だけを使って一気に学習する方法を,
end-to-end モデルや end-to-end 学習と呼ぶこともある.本論文では,系列情報を扱うモデ
ルでは Sequence-to-Sequence モデル,それ以外では Encoder-Decoder モデルと呼ぶことと
する.

2.3.1

Attention 機構

Sequence-to-Sequence モデルでは,系列情報を固定帳のベクトルに変換するが,長い系列
であるほど最初に入力された情報がデコーダーまで伝搬しにくい.そこで,注意機構 (Luong
et al., 2015) を用いることで,より直接的に入力情報を出力に利用する.
長さ I の入力系列 X = {x1 , . . . , xI } に対して,エンコードされたベクトルを H (e) =
(e)
(e)
(e)
{h1 , . . . , hI } とする.通常の Sequence-to-Sequence モデルでは,hI をデコーダーの初

2.3. SEQUENCE-TO-SEQUENCE モデル

16

期隠れ状態 h0 として利用する.時刻 t のデコーダーの隠れ状態 ht を求める時,通常の
Sequence-to-Sequence モデルの場合は,前時刻のデコーダーの隠れ状態 ht−1 と出力 ot−1
を用いて

ht = f (Wt [ot−1 ; ht−1 ])

(2.30)

となる.この時,f は活性化関数である.
(e)

(e)

注意機構を用いる場合はさらに,ht とエンコーダーの隠れ状態 H (e) = {h1 , . . . , hI }
の関連度 αt = {αt,1 , . . . , αt,I } によって得られた,エンコーダーの隠れ状態の重みつき和で
ある文脈ベクトル ct を用いて,

˜ t = f (Wc [ct ; ht ])
h

(2.31)

をデコーダの時刻 t における最終的な隠れ状態とする.時刻 t における,エンコーダーの隠
れ状態 hi の関連度を示すスカラー値の重み αt,i と文脈ベクトル ct は,次の式によって求め
られる:
(e)

αt,i = align(ht , hi )
(e)

=

exp(score(ht , hi ))

∑I

i′ =1

ct =

I


(e)

(2.32)

exp(score(ht , hi′ )
(e)

(2.33)

αt,i hi .

i=1

ここで,score(·) は以下の 3 種類のいずれかが用いられるが,その効果は大きくは変わら
ない:

⊤ (e)

dot
 ht hi

(e)

score(ht , hi ) =

2.3.2





h⊤
t Wa h i

general

(e)
Wa [ht ; hi ]

concat

(e)

(2.34)

Copy 機構

Copy 機構は Gu et al. (2016) によって提案され,例えば文章要約タスクにおいて,辞書
に含まれていない,入力文に出現した単語を要約文で生成したい場合など,入力側に含ま
れる要素をそのまま出力として利用したい場合に用いられる.具体的には,Attention 機構
で計算される確率や,各入力要素がコピーされる確率を計算し,その確率に従って,入力要
素をそのまま出力するかを決定する方法である.

2.4. TRANSFORMER

2.4

17

Transformer

Transformer は Encoder-Decoder モデルをベースとするモデルであり,当初ニューラル
機械翻訳のモデルとして提案された.Transformer が提案される以前は,機械翻訳などの課
題には,LSTM や GRU に代表される RNN が多く使われていた.しかし,RNN は入力さ
れる系列を処理し,その処理した結果を用いて次の処理を行う,逐次的な処理を行ってい
るため,並列化は不可能である.また,入出力系列の長さに関係なく,入力と出力の間の依
存関係を得ることができる Attention 機構があるが,Attention 機構は RNN と組み合わせ
て使用されていることがほとんどであった.そこで,Vaswani et al. (2017) は,再帰性を除
き,代わりに入力と出力の間のグローバルな依存関係を得るために,Attention 機構のみを
使った Transformer を提案した.

2.4.1

Transformer の基礎構造

Transformer は Encoder と Decoder の両方に self-attention と Position-wise Feed-Forward
Network が使われたモデルである.エンコーダ,デコーダとも入力系列を埋め込みベクト
ルに変換し,それに位置埋め込みベクトルを加えたものを入力とする.
Encoder: N = 6 の独立した層を持っており,各層には multi-head self-attention 構造と
Position-wise Feed-Forward Network の 2 つの副層を持つ.2 つの副層それぞれを適用後に
は,残差結合と層正規化を行う.
Decoder: エンコーダと同じく,N = 6 の独立した層を持っており,エンコーダーの 2 つ
の副層に加えて,multi-head self-attention 構造の副層を1層追加した.各副層それぞれを
適用後には,残差結合と層正規化を行う.

2.4.2

Transformer の要素

本項では,Transformer を構成する次の要素について説明する:1. Positional Encoding,
2. Multi-head self-attention, 3. Position-wise Feed Forward Network,

1. Positional Encoding
入力の埋め込みベクトル(系列の要素数 × dmodel )に位置情報(Positional Embedding)
を付与する.要素の位置および入力の埋め込みベクトルの次元が一意に決まる位置情

2.4. TRANSFORMER

18

報を入力の埋め込みベクトルに加算する.位置情報は下記の式で計算する.  
   P E(pos, 2i) = sin(pos/100002i/dmodel )
   P E(pos, 2i + 1) = cos(pos/10000

2i/dmodel

(2.35)

) 

(2.36)

  pos は要素が系列の何番目か,2i は入力の埋め込みのベクトルの何次元目かを表す.
例えば,300 次元の埋め込みにおいて,3 番目の要素の 13 次元目の位置情報は次のよ
うになる:  
   P E(3, 13) = cos(3/1000012/300 ).  

(2.37)

2. Multi-head self-attention
Transformer で使われている Attention 機構は Query-Key-Value 型の Attention 機構
である.Query と Key で Attention スコアを計算し,その Attention スコアを使っ
て Value を加重和することで Attention を適用した要素の潜在表現を獲得する.Q と
K は次元 dK を持ち,V は次元 dV を持つ.Transformer では縮小付きの Attention
を採用しており,Attention の計算はクエリと全キーの内積によりその関連度を計算
し,√ dK 割った後ソフトマックス関数を適用させる.Attention を使った層出力の
計算は,以下の式で表される.
QK T
Attention(Q, K, V ) = sof tmax( √ )V
dk

(2.38)

(a) self-attention  
Self-Attention とは,ある 1 文内の単語だけを使って計算された,単語間の関連
度スコアのようなものである.このスコアを使って文のベクトル表現を獲得す
る.つまり,入力 (query) とメモリ (key, value) が同じものである.ある文に
出現する単語間の関連度 (スコア,Attention) を計算するのにその文に出現する
単語のみを使うことから,Self-Attention と言われている.
(b) Multi-head attention  
Attention 機構を複数用いるため,次の式で表される Multi-head attention を用
いる:
M ultiHead(Q, K, V ) =
headi =

Concat(head1 , ..., headh )W O
Attention(QWiQ , KWiK , V

WiV ).

(2.39)
(2.40)

MultiHead の引数である Q, K, V は系列の埋め込みベクトルを意味し,重みを掛
ける前のものである.マルチヘッド注意機構では,自己注意機構における Q, K, V
をそれぞれ h 個に分割して(系列の要素数 × dmodel /h),それぞれ Scaled-Dot
Product Attention を適用する.系列の埋め込みベクトルに WiQ , WiK , WiV (i =
1, . . . h) を掛けることで h 個に分割された行列を作成する.ここで,WiQ ∈ Rdmodel ×dk , WiK ∈

2.4. TRANSFORMER

19

Rdmodel ×dk , WiV ∈ Rdmodel ×dk ,W O ∈ Rdmodel ×dmodel は重み行列である.また,
dk = dmodel /h である.Scaled-Dot Product Attention を計算してできた headi
を h 個分結合(concat)することで,self-attention 機構と同様の行列の形状(系
列の要素数 × dmodel )になる.
(c) Masked Attention
Decoder では Encoder での Self-Attention と異なり,ある時刻の入力から次の時
刻の状態を予測し,さらにその予測を次の入力に回してその先を予測する.一
方,学習のときにはすべての時刻で同時に次の時刻の要素を予測する学習を行
うが,この時に Self-Attention で予測対象である未来の情報が得られると,先の
答えが見えてしまうことになっている.そこで,Decoder では Self-Attention に
おいて Mask を行い,今までに得た情報のみで推論するように,先の attention
weight を全て 0 にする. 
3. Position-wise Feed Forward Network
2 層のネットワークからなっており,活性化関数は ReLU を使用する.全結合層に入
力する行列を x とし,W1 ,b1 ,W2 ,b2 は学習パラメータである.
F F N (x) = max(0, xW1 + b1 )W2 + b2

(2.41)

20

第 3 章 言葉の意味表現

現在,コンピュータで人の言葉を理解させる取り組みは様々行われており,身近な例で
はかな漢字変換や検索などがあげられる.文章の意味理解には,一般的に構造的意味と語
彙的意味を組み合わせて用いる.構造的意味とは文章の中で単語が組み合わされ表現され
る意味であり,構文解析を用いる.一方,語彙的意味とは単語が持っている元々の意味であ
り,WordNet などのシソーラス・オントロジーを用いる.しかし,大量の文章を処理する
際にそれらを用いるのは計算コストが高いと考えられるため,また,Bag-of-Words 表現を
用いて文章を理解する取り組みがあり,特に,単語をベクトルとして表すため BoW 表現を
更に発展させ,単語の意味を分散表現で表した Word2vec が提案されたことで,コンピュー
タで自然言語を利用する手法が大きく発展した.近年は,文脈を考慮した単語の埋め込み表
現も提案され,このような埋め込み表現を大規模なコーパスで学習した事前学習済みモデ
ルや,事前学習済みモデルを使って,目的のタスクで高い性能を引き出すアプローチ(ファ
インチューニング)が提案されている.

3.1

分散意味表現

分散表現とは,Hinton (1984) によって提案された単語を固定長の高次元の実数ベクトル
で表現し,類似の意味を持つ単語を近いベクトルに対応させる技術である.各概念に一つの
計算要素を割り当てる局所表現 (one-hot representation) に比べ,より単語同士の関係とベ
クトル同士の関係が対応づけられる.ベクトル構成方法は大きく 2 つのアプローチがある.

1 つは BoW の考えを用い,単語の意味はその単語が出現する文脈によって決まるとい
う分布仮説 (distributional representation) (Harris, 1954; Firth, 1957) を元にコーパス内
の単語の出現頻度,単語周辺の文脈や共起などの統合情報をまとめた行列を作成,次元削
減しベクトルを求める手法で,分布意味表現 (Distributional Semantic Representations)
と呼ばれる.共起頻度の重み付けに相互情報量を用いた PPMI(Positive Pointwise Mutual
Information) に基づく単語文脈行列 (Bullinaria and Levy, 2007) や,次元削減に特異値分
解を用いた LSI(Latent Semantic Indexing)(Deerwester et al., 1990) が知られている.
一方,分布仮説を用いるが各単語の意味表現が m 次元で表されると仮定しベクトルの
要素をコーパスから学習する手法があり, Word embedding や分散意味表現 (Distributed
Semantic Representations) と呼ばれる.分布意味表現に比べ,より低次元で密に表すこと

3.2. ニューラルネットワーク言語モデル

21

ができ,更にベクトルは有数の次元である.次節より分散意味表現を求める手法について
説明する.

3.2

ニューラルネットワーク言語モデル

Bengio et al. (2003) が提案したニューラルネットワーク言語モデル (NNLM) は,Shannon
(1948) によって提案された N-gram 言語モデルをニューラルネット化したモデルであり,語
彙数を V とする連続する単語列 w1 , . . . , wT が存在し,単語列 wt−1 , . . . , wt−n+1 が与えられ
たとき,次の単語 wt の出現する条件付き確率を出力するニューラルネットワークである.
単純な BoW 表現は語順を考慮しないが,NNLM は N-gram を用いるため語順情報を得る
ことができる.図 3.1 に概要を示す.

図 3.1: ニューラル言語モデル
各単語は 1-of-N coding により表現されており,look-up テーブル C 上の C(i) にそれぞ
れ m 次元のベクトルを持つ.n − 1 個の単語 wt−1 , . . . , wt−n+1 それぞれに対するベクトル
C(wt−1 ), . . . , C(wt−n+1 ) を連結し,(n − 1)m 次元のベクトル x が入力となる.このとき,
中間層に対する重み行列を H,中間層でのバイアスを d,中間層での活性化関数を tanh 関
数,中間層から出力層に対する重み行列を U,入力層から出力層に対する重み行列を W,出

3.3. WORD2VEC

22

力層でのバイアスを b とすると正規化前の出力 y は

y = b + W x + U tanh(d + Hx)

(3.1)

と表される.よって,単語 wt の出現する条件付き確率は softmax 関数を用いて,

exp(yt )
P (wt |wt−1 , . . . , wt−n+1 ) = ∑V
i=1 exp(yi )

(3.2)

となる.

3.3

Word2vec

Mikolov et al. (2013a) によって公開された Word2vec1 は,同じ文脈の中にある単語はお
互いに近い意味を持つようにニューラルネットワークを用いて単語の分散意味表現を得る
ツールであり,その学習方法として CBOW と Skip-gram の 2 つの手法を提案している.こ
れにより,単語の意味はベクル計算によって表現可能となり,例えば ‘king’-‘man’+‘woman’

「王様から男を引いて女を足したもの」
)を求める計算をすると,単語 ‘queen(「女王」)’ の
ベクトルに近い値が得られる,といった単語の演算が可能になる.

3.3.1

CBOW

Continuous Bag-of-Words model(CBOW) とは,ある単語 wt が現れている文脈で周辺
単語を使って wt を予測するモデルである.前の文脈から単語を予測する NNLM と違い,
CBOW は後ろの単語列を用いることができる.つまり wt を予測する場合,直前の n 個の単
語 wt−n , . . . , wt−1 と直後の n 個の単語 wt+1 , . . . , wt+n を特徴量として用いることができる.
CBOW は単語 wt が t 番目に出現する確率 p(wt |wt−n , . . . , wt−1 , wt+1 , . . . , wt+n ) を学習
ˆt を文脈中の単語ベクトル平
するので文脈は 2n 個の単語からなり,例えば wt の文脈表現 w
均とすると,
ˆt =
w

1
(wt−n + · · · + wt−1 + wt+1 + · · · + wt+n )
2n

(3.3)

と表すことができ,図 3.2 で示される CBOW は,

ˆ t T wt )
exp(w
p(wt |wt−n , . . . , wt−1 , wt+1 , . . . , wt+n ) = ∑V
ˆ i T wi )
i=1 exp(w
1

https://code.google.com/p/word2vec/

(3.4)

3.3. WORD2VEC

23

図 3.2: CBOW
のように表される.ここで V は語彙数である.この場合,NNLM の中間層での活性化関
数を + 演算子として置き換えたものと考えることができる.

ˆt を式 3.3 とすると単語の語順を考慮することができないので,出
なお,wt の文脈表現 w
現位置に考慮した重み付けや r 次元の文脈ベクトルを 2n 個を連結し 2nr 次元のベクトルと
表現することも可能であるが,パラメータの調節が増える.

3.3.2

Skip-gram

周辺単語から単語を予測する CBOW と違い,Continuous Skip-gram Model(Skip-gram)
はある単語 wt から周辺単語を予測するモデルであり,図 3.3 のように示される.

図 3.3: Skip-gram

3.4. 事前学習済みモデル

24

ある単語 wt の文脈中に出現する別の単語 wj の出現確率 p(wj |wt ) は log-bilinear model
を用い,

exp(wT wj )
p(wj |wt ) = ∑V (w ) t
t
T
i=1 exp(wt wi )

(3.5)

と定義される.ここで V (wt ) は単語 wt が含まれる文脈中に出現する語彙の集合である.
単語 wt から周辺単語列 Cwt = wt−n , . . . , wt−1 , wt+1 , . . . , wt+n を予測するモデルは,

p(Cwt |wt ) =
p(wt+i |wt )
(3.6)
−n≤i≤n,i̸=0



log p(Cwt |wt ) =

log p(wt+i |wt )

(3.7)

−n
となり,目的関数

J

=

T
1∑
T



log p(wt+i |wt )

(3.8)

t=1 −n
p(wt+i |wt ) =

T w )
exp(wt+i
t

∑V (wt )
j=1

exp(wjT wt )

(3.9)

を最大化するように学習をする.なお式 3.9 は p(wt+i |wt ) について式 3.5 のベクトルの内積
を交換法則を用いて変形したものである.式 3.9 の分母はコーパスに含まれる全ての単語に
関する内積を求めるため計算コストが高い.そこで Mikolov et al. (2013b) はロジスティッ
ク回帰を用いて近似し,更に負例 S(wt+j ) はランダムに選択する Negative Sampling を提
案した.Negative Sampling により,式 3.9 は


exp(wT wt )
p(wt+i |wt ) = ∑V (w ) t+i
≈ σ(wjT wt )
σ(−wjT wi )
t
T
j=1 exp(wj wt )
wi ∈S(wt+j )

(3.10)

のようになる.

3.4

事前学習済みモデル

単語埋め込みは,単語に関する一般的な知識を表現できると期待され,さまざまな言語処
理タスクで利用された.しかし,word2vec などの単語埋め込みは文脈から切り離されてお
り,文脈を考慮すべき課題では,RNN などでネットワークを構築し,教師あり学習を行うこ
とで,課題に応じた訓練を行う必要があった.そこで,文脈における単語の意味を表現でき
る単語埋め込みを汎用的に学習する手段として,双方向 LSTM を用いて言語モデルを学習
することで,文全体を考慮した単語の意味表現ベクトルを獲得できる ELMo (Peters et al.,

3.4. 事前学習済みモデル

25

2018) などが提案された.ELMo などによって得られた単語ベクトルは,contextualized word
embedding(文脈化単語埋め込み)と呼ばれる.単語埋め込み表現を学習するモデルと,そ
れを利用する課題のモデルは当初,個別に構築されていた.このため,課題に利用される
埋め込み表現は,事前学習された埋め込み表現のみで,その学習モデルの内部状態を利用
することはなかった.これに対し,埋め込み表現を学習するモデルと,それを利用する課
題を同一の構成とし,事前学習された埋め込み表現だけでなく,事前学習に用いたモデル
のパラメータを課題にそのまま利用し,そのパラメータを課題の訓練データで微調節する
ファインチューニングを行う手法が提案され,その有用性が示されている.

3.4.1

BERT

ELMo では3層の LSTM が用いられているが,その後 12 層の Transformer のデコーダー
部分を採用し,大規模なコーパスを用いて事前学習した GPT (Radford et al., 2018) が提案さ
れた.GPT では Transformer のデコーダー部分を利用したため,事前学習では前の文脈を参
照し,次の単語を予測するタスクにしか取り組んでいない.そこで,Transformer のエンコー
ダー部分を用いて,双方向から文を参照する事前学習タスクを提案したのが BERT (Devlin
et al., 2019) である.BERT は任意の位置の単語をマスクし,そのマスクされた単語を予測
するタスクを事前学習に用いることで,文全体を参照する言語モデルを学習する.さらに,
BERT は入力文がコーパス中における隣接文どうしかを識別するタスクを事前学習に用い
たことで,文の埋め込み表現を獲得することを目指した.図 3.4 に BERT のモデル構造を
示す.

図 3.4: BERT の構造および入力形式

3.4. 事前学習済みモデル

26

BERT の構造
BERT は Transformer のエンコーダ部分を基とする構造を使用している.BERT には
BERTbase と BERTlarge が存在する.L は Transformer のエンコーダ層の層数,H は隠れ
層における次元(単語埋め込みの次元)
,A は Multi-head self-attention 機構におけるヘッ
ド(2.4 節の Multi-head self-attention 機構における h に相当)の数とすると,BERTbase は
L=12,H=768,A=12,パラメータ総数=110M,BERTlarge は L=24,H=1024,A=16,パ
ラメータ総数=340M である.FFN 層における重みは W1 ∈ RH×4H ,W2 ∈ R4H×H である.

入出力の形式

BERT ではファインチューニングの際に様々な下流タスクに対応できるよう,トークン
が連続している単文または文ペアを入力することができる.また,入力は文ではなく任意の
長さのテキストでも入力が可能である.入力形式は,文の初めは必ず special classification
token([CLS])である.また,文末には special token([SEP])を入力し,文ペアを入力する
時も,この [SEP] で区切って入力する.これらの BERT への入力トークン列をシーケンス
と呼ぶ.BERT に入力されたシーケンスは図 3.4 のように,Token Embeddings,Segment
Embeddings,Position Embeddings の和をとることで,埋め込み表現に変換される.

事前学習タスク

BERT はマスクしたトークンを予測する Masked Language Mode と,文章の連続性を判
定する Next Sentence Prediction の 2 つのタスクを使って,事前学習する.
Masked Language Mode MLM は入力トークンの約 15%のトークンをマスクし(入力
トークンを [MASK] トークンに置き換えて隠す)
,マスクしたトークンを予測するタスクで
ある.マスクされているトークンは,直前の単語からのみではなく,文脈を考慮して文全
体の入力から予測される.また 15%のトークン全てを [MASK] トークンに置き換えずに,
15%選んだトークンのうち,80%のトークンを [MASK] トークンに置き換え,10%の単語
はランダムなトークンに置き換え,残りの 10%のトークンは置き換えない,という手法を
とる.選ばれた 15%のトークンは,最終層から出力された特徴量を用いてクロスエントロ
ピーを誤差として学習する.
Next Sentence Prediction (NSP) NSP は文のペアを入力し,その文ペアが連続して
いる文であるかを予測する 2 値分類タスクである.質問応答タスク(QA)や自然言語推論
タスク(NLI)では文ペアの関係性が重要であるため,NSP タスクを事前学習タスクとし

3.4. 事前学習済みモデル

27

て利用する.ここでは入力として,“関係がなく文脈の繋がりがない文ペア” と “連続的に
存在していて意味に繋がりがある文ペア” の 2 パターンを用意する.このタスクでは,文頭
に入力した [CLS] に対する最終層の出力を用いて,2 値分類タスクを解く.

3.4.2

BART

BART (Lewis et al., 2020) は,Transformer のエンコーダ・デコーダの両方を備えた事前
学習済みモデルである.Transfomer のデコーダのみで構成された GPT と比較すると,入
力文に強く条件づけられた言語生成タスクと相性が良いとされている.

BART の構造
BERT,GPT および BART の比較のための概要を図 3.5 に示す.BERT では,トークン
の一部を [MASK] に置き換え,文をエンコードする.Mask されたトークンは独立して予測
されるため,BERT を生成に使うのは難しい.GPT では,トークンを自動的に再起的に予
測するため,生成に使うことができる.しかし,ある時刻から次の時刻の状態を予測するデ
コーダのため,双方向の文脈を学習できていない.そこで,2 つの機能を併せ持つ,BART
が提案された.図 3.5 の BART では,トークンの一部を [Mask] で置き換えられた文は,双
方向の文脈を参照できる Transformer のエンコーダでエンコードされ,自己回帰のデコー
ダーにより,元の文章を生成している.このように BERT とは異なり,文章を生成するこ
とができるため,入力と出力の長さを変えることができ,さらに事前学習の方法に自由度
がある.

BART の事前学習
BART では,さまざまな文章にノイズを付加し,再構成損失(デコーダの出力と元の文
書との間のクロスエントロピー)を最適化する学習方法で事前学習を行う.ノイズ付加の
方法は BERT と同様の手法も含まれるが,新たな付加手法も提案している.

Token Masking

BERT と同様にランダムに単語を [MASK] で置き換える.

Token Deletion ランダムに単語を削除し,その単語を埋めた文章を生成することを学
習する.[MASK] で置き換える場合と異なり,どの単語が抜けているかわからないので,場
所も含めて予測する必要があり,Token Masking と比べて難易度が上がる.

3.4. 事前学習済みモデル

28

  BERT

  GPT

  BART
図 3.5: BART と BERT および GPT の比較

Text Infilling 複数の単語の並びを一つの [MASK] で置き換える.置き換える単語数は、
λ = 3 のポアソン分布に従う乱数を発生させて決定するため,平均 3 個 (分散も 3) の連続し
た単語が [MASK] に置き換わる.

Sentence Permutation

複数の文章からなる文書の,文章の順番を入れ替える.

Document Rotation 文章から単語を一つ選び,その単語が一番初めになるように文章
を回転させる.例えば,元の文章が「私 は 犬 を 飼って いる」であれば,
「犬 を
 飼って いる 私 は」のように回転させ,どの単語が初めの単語であるかを学習する.

29

第 4 章 自然言語理解によるロボットの動作
生成

本章では,言語から非言語の生成課題の 1 つとして,自然言語理解によるロボット動作
の生成課題を扱う.

4.1

研究背景と目的

現在,日本は超高齢化社会に突入している.少子高齢化社会の到来による人手不足を,ロ
ボットを利用することで問題解決をはかろうとする場面が増えると考えられる.近年では,
ロボットを安価に入手出来るようになっており,またロボットに触れる機会も増えたこと
により,人間とロボットとのコミュニケーションが大きく発展する可能性がある.家庭内
でロボットを用いる場合,ロボットが居住者と協調して暮らすことができる条件として,言
葉や身振りを用いいることで居住者の経験をロボットに伝え,ロボットはそれを真似し,学
習することが必要になると考える.このことを踏まえ,人の言葉による指示からロボット
が動作を生成し動作することを目標にする.
まず,ロボットが人の動作を真似て行うことができるように,自らが行える基本動作を
組み合わせてひとつの行為を生成する枠組みを構築し,複数の基本動作から複雑な行為を
表現する対応関係を明確にする.
また,言葉と動作の対応関係を学習することによって,初めて行う動作であっても言葉
の意味から推測し,動作を行なえるようにし,多様なロボット動作と多様な人の言葉の対
応関係を学習する枠組みを提案し検証する.なお,本章ではロボットの動作として調理に
関する動作を対象とし,家庭内でロボットへの指示に慣れていないユーザーが使用するこ
を想定する.そのため与える言葉の指示は,明確な指示,例えば「10cm 右手を動かす」や
「秒速 1m で動く」などの言葉ではなく,
「大きく」など,その対象や状況によって量や数が
変化する,曖昧な言葉の表現に注目する.このような言葉の曖昧さを許容し,ロボット動
作と言葉の対応関係を得る枠組みを提案する.

4.2. 関連研究

4.2

30

関連研究

ニューラルネットワークやリカレントニューラルネットワーク (RNN) を用い,ロボット
に動作を生成させる研究は広く行われている.
神経力学モデル MTRNN(Multiple Timescale Recurrent Neural Network)(Yamashita
and Tani, 2008) は RNN を拡張したモデルで,再起結合を持つことで力学モデルとしての
性質を持つ.現在の状態を入力とし,次時刻の動作を出力とするものであり,動作を学習,
認知,生成することができる.
これを用い,Sugita and Tani (2005) 及び Ogata et al. (2007) はパラメータを共有する
MTRNN と RNN を用い,ロボット動作と単語列をそれぞれ学習することで,相互想起を
実現するモデルを提案した.また,Stramandinoli et al. (2012) は既に獲得している低次元
における動作と言葉の対応関係に基づいて,RNN を用いることでより高次元の動作と言語
表現の統合を目指した.
しかし,いずれの場合も動作パターンと固定の単語を組み合わせた表現のパターンとの
対応関係学習である.本章では,より人間の言葉に対応するために,パターン学習ではな
く,言葉の曖昧さを許容した,曖昧な言葉の意味理解に基づくロボットの動作生成を行う.

4.3

ロボット動作

本研究は家庭内でのロボット利用を目指しているため,複雑な動作が可能で,人に似せ
て作られているヒューマノイドロボットを用いる.次節より,本研究で用いるヒューマノ
イドロボット HIRONXC についての基礎知識と,動作構成,動作生成について説明する.

4.3.1

ヒューマノイドロボット HIRONXC

HIRONXC は(株)川田工業社製ヒューマノイドロボットである.HIRONXC はオープ
ンなソフトウェア OpenHRP3 を持つプラットフォームで,双碗,双眼を持ち,左右手元に
カメラがついている.Jython で動作する.

シミュレータ
(株)川田工業より提供されているシミュレータを図 4.1 に示す.Ubuntu12.04 で動作
し,物体の設置,物体の認識,ロボットの動作が実機と同等に行うことができる.これを用
い,動作を生成し安全を確認した後,実機で動作を確認する.

4.3. ロボット動作

31

図 4.1: シミュレータ

HIRONXC の動き
図 4.21 に HIRONXC の概観を示す.

HIRONXC は全部で 23 つの関節を持っており,体全体を動かす 1 つ(腰ヨー軸:CY),首
の左右上下運動に 2 つ(首ヨー軸:NY,首ピッチ軸:NP)
,両腕に各 6 つ(右肩ヨー軸:RSY,
右肩ピッチ軸:RSP.右肘ピッチ軸:REP,右手首ヨー軸:RWY,右手首ピッチ軸:RWP,右手
首ロール軸:RWR,左肩ヨー軸:LSY,左肩ピッチ軸:LSP,左肘ピッチ軸:LEP,左手首ヨー
軸:LWY,左手首ピッチ軸:LWP,左手首ロール軸 :LWR)
,両手に各 4 つ(右手関節:RH1,
RH2, RH3,RH4,左手関節:LH1, LH2,LH3,LH4)の関節を持つ.それぞれの関節角と時間
T を指定することで,T 秒かけて指定された角度へと関節を動かすことが可能である.表
4.1 にそれぞれの関節が動く範囲を示す.ほぼ全ての関節で,1秒で任意の角度に移動可能
なことがわかる.
Jython を使い,HIRONXC を連続で動作させる場合,1 動作につき以下のフォーマット
での入力が必須であり,全ての関節角情報を HIRONXC に対して与えなければならない.
[[CY, NY, NP],[LSY, LSP, LEP, LWY, LWP, LWR],
[RSY, RSP, REP, RWY, RWP, RWR],
[RH1, RH2, RH3,RH4], [LH1, LH2,LH3,LH4],T]
1

http://robot-support.kawada.jp/support/hiro/ より引用

4.3. ロボット動作

32

図 4.2: ロボットの関節
表 4.1: 関節の動作可能範囲
関節軸名称

記号

可動範囲 (deg)

最大速度 (deg/s)

腰ヨー軸
首ヨー軸
首ピッチ軸
右肩ヨー軸
右肩ピッチ軸
右肘ピッチ軸
右手首ヨー軸
右手首ピッチ軸
右手首ロール軸
左肩ヨー軸
左肩ピッチ軸
左肘ピッチ軸
左手首ヨー軸
左手首ピッチ軸
左手首ロール軸

CY
NY
NP
RSY
RSP
REP
RWY
RWP
RWR
LSY
LSP
LEP
LWY
LWP
LWR

-163 to +163
-70 to +70
-20 to +70
-88 to +88
-140 to +60
-158 to +0
-165 to +105
-100 to +100
-163 to +163
-88 to +88
-140 to +60
-158 to +0
-105 to +165
-100 to +100
-163 to +163

130
150
300
172
133
229
300
223
300
172
133
229
300
223
300

4.3. ロボット動作

4.3.2

33

動作構成

関節情報は可読性が低く,また人手でロボット動作を作成する際にも不便である.イン
バースキネマティクス(逆運動学)を利用することで,全ての関節情報を指示することな
く,ロボットの特定の部位(例えば右手の先など)を目的位置に動作させることも可能であ
るが,本研究では複雑な動作への拡張を考え,ロボットを基本動作からより複雑な動作を
構成するために,Cheng et al. (2013) による Activity-Attribute Matrix を参考にする.

Activity - Attribute Matrix

Activity

Activity-Attribute Matrix(以下 AAM) は動作と動作に関連している意味属性を符号化し
たものである.具体例を図 4.3 で示す.

ふる
ふるう
炒める
切る
混ぜる

0 0 1
0 1 0
1 1 1
0 1 1
1 1 0
x y z
Attribute

図 4.3: HIRONXC を用いた AAM 作成

M を Activity(活動),N を Attribute(属性)とし,各要素 aij (i ∈ M, j ∈ N ) において
Attribute の Activity への含有関係について Activity i を構成するのに Attribute j が用い
られている場合は 1,用いられていない場合 Attribute j は 0 とする,M × N 行列により動
作を表現する.図 4.3 では,Activity として調理動作を例に捉え,それに伴い Attribute と
して図 4.3 の右図ように右手の指先を前後に動かす (x),左右に動かす (y),上下に動かす
(z) を基本ベクトルを設定した.例えば,ふる動作について,x = 0, y = 0, z = 1 となって
いるので,上下に動かす動きであることが分かり,また,切る動きは x = 0, y = 1, z = 1
より,左右と上下の動きが含まれていることが分かる.

4.3. ロボット動作

34

時系列対応 AAM
ロボットを実際に動かすにはそれぞれの関節角を指定する必要がある.そこで,Attribute
の x,y ,z それぞれに対して,係数となるベクトルとの内積をとることにより,ロボットの動作
生成を可能にする.さらに Activity を生成する過程において,それぞれの Attribute の度合い,
時系列性,速度等が重要となるため,x,y ,z の変動割合にその動作を行うスピード ps = [0, 10]
を組み合わせた [px , py , pz , ps ] を時系列に n 個並べた [[px1 , py1 , pz1 , ps1 ], [px2 , py2 , pz2 , ps2 ], …
, [pxn , pyn , pzn , psn ]] を与えることにより動作の生成を可能にする.表 4.2 に本研究で提案す
る時系列対応 AAM を示す.次章にて表 4.2 がどのように使用されるかについて具体例と共
に示す.

4.3.3

動作生成


ロボットの動作生成の手順を以下に示す.

1. 基本ベクトルの準備
要素動作となる x, y, z 方向の基本ベクトルを準備する
2. 係数ベクトルの準備
1. で準備したベクトル方向にどの程度移動させるかを示すベクトル(係数ベクトル)
を生成する
3. 基本ベクトルと係数ベクトルの内積
1. の基本ベクトルと 2. で生成された係数ベクトルの内積を計算し,関節角座標(以
下,
「座標」と呼ぶ)を求める
4. 移動先座標の取得
3. で計算された座標に現在の座標を加えて,移動先の座標を取得する.動作時間 T を
指定し,ロボットに与える座標のフォーマットは以下の様になる.
[[CY, NY, NP],[LSY, LSP, LEP, LWY, LWP, LWR],
[RSY, RSP, REP, RWY, RWP, RWR],
[RH1, RH2, RH3,RH4], [LH1, LH2,LH3,LH4], T]
なお時間 T は,表関節の動作最大速度より,多くの関節でどの角度にも 1 秒以内で動作可
能なため,Tn = 10 − psn とする.具体例を上記の順に従って以下に示す.

1. 基本ベクトルの準備
準備される基本ベクトルは,表 4.2 の x, y, z に示される値となる.

4.3. ロボット動作

35

表 4.2: 時系列対応 AAM の概要

速く切る
速く混ぜる
ゆっくり切る
細かく切る
ザクザク混ぜる

CY
NY
NP
RSY
RSP
REP
RWY
RWP
RWR
LSY
LSP
LEP
LWY
LWP
LWR
RH1
RH2
RH3
RH4
LH1
LH2
LH3
LH4

0
0
0
0
0
px1

x
0.0
0.0
0.0
0.1
-2.3
2.1
0.0
0.2
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0

p1
0
3.5
0
0
6
p y1

y
0.0
0.0
0.0
1.8
0.7
-0.5
0.0
0.2
-1.8
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0

-5
0
-5
-5
0
pz 1

z
0.0
0.0
0.0
0.7
0.1
-2.7
0.1
2.7
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0

8
8
3
5
8
ps 1

0
3.5
0
0
6
p x2

x
0.0
0.0
0.0
0.1
-2.3
2.1
0.0
0.2
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0

p2
3.5
-3.5
3.5
1
-6
py2

y
0.0
0.0
0.0
1.8
0.7
-0.5
0.0
0.2
-1.8
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0

5
0
5
5
0
pz2

z
0.0
0.0
0.0
0.7
0.1
-2.7
0.1
2.7
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0

8
8
3
5
8
ps 2







0
-3.5
0
0
-6
p xn

x
0.0
0.0
0.0
0.1
-2.3
2.1
0.0
0.2
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0

pn
3.5
5
0
0
3.5
5
1
5
0
0
p yn p z n


y
z
0.0 0.0
0.0 0.0
0.0 0.0
1.8 0.7
0.7 0.1
-0.5 -2.7
0.0 0.1
0.2 2.7
-1.8 0.0
0.0 0.0
0.0 0.0
0.0 0.0
0.0 0.0
0.0 0.0
0.0 0.0
0.0 0.0
0.0 0.0
0.0 0.0
0.0 0.0
0.0 0.0
0.0 0.0
0.0 0.0
0.0 0.0

8
8
3
5
8
ps n

4.3. ロボット動作

36

2. 係数ベクトルの生成
係数行列の生成を調理動作「切る」を例に説明する.
切る動作は常に x が 0 で(前後の動きはなく),まず z が負(下へ)の動きをし,次
に z が正(上へ)の動きをしながら y が正(左へ)動く,という特徴から生成され
る.このとき,動作の違いは特に y(左右の動き)と時間 t によって種類を生成でき
る.表 4.2 を見ると,複数の種類の「切る」という動作が,y と t の値によって差別
化されていることがわかる.
次に,「速く切る」という動作を見てみると,[[px1 , py1 , pz1 , ps1 ], [px2 , py2 , pz2 , ps2 ], …
, [pxn , pyn , pzn , psn ]] の値は [[0,0,-5,8],[0,3.5,5,8],…,[0,3.5,5,8]] となっており,時間の経
過と共にその動作を示す係数ベクトルが表示されていることがわかる.

3. 基本ベクトルと係数ベクトルの内積,移動先座標の取得および速度の追加
表 4.2 中,
「速く切る」における最初の係数ベクトルは,[px1 , py1 , pz1 , ps1 ] = [0, 0, −5, 8]
であり,系数ベクトル [px1 , py1 , pz1 ] と基本ベクトルの内積結果は
[[0.0, 0.0, 0.0],
[-3.5, -0.5, 13.5, -0.5, -13.5, 0.0],
[ 0.6, 0, -100, -15.2, 9.4, -3.2],
[0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
となる.現在の座標,つまり初期状態の座標

Initialpose = [[0.0, 0.0, 0.0],
[-0.6, 0, -100, 15.2, 9.4, 3.2],
[ 0.6, 0, -100, -15.2, 9.4, -3.2],
[0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
を内積結果に加え,さらに動作のスピード ps1 から計算した動作時間 T1 = 10 − ps1 を
組み合わせ,以下のようになる.

[[[0.0, 0.0, 0.0],
[-4.1, -0.5, -86.5, 14.7, -4.1, 3.2],
[0.6, 0.1, -100, -15.2, 9.4, -3.2],
[0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]], 2]
この動作生成を引き続き [px2 , py2 , pz2 , ps2 ] = [0, 3.5, 5, 8] にも適用した結果のロボッ
トの動作を図 4.4 に示す.
初期状態と p1 終了時を比べると,ロボットの右手が下に降りており,p1 終了時と次の時
刻の動作 p2 終了時を比べると,ロボットの右手が左斜め上にあがっており,想定した切る
の動作がロボットで生成できていることが確認出来る.

4.4. 言語表現からの動作生成

初期状態

37

p1 終了時

p2 終了時

図 4.4: 「速く切る」の動作例

4.4

言語表現からの動作生成

図 4.5: 提案手法の概要 (「小さく 混ぜる」の動作推定例)
動作を変化させる曖昧表現と動作を意味する動作表現とを組み合わせた言葉と,その言
葉が意味する動作の対応関係が既知であるとする.動作との対応関係が分からない未知の
言葉が与えられた時に,既知の言葉との意味関係から対応する動作を生成する手法を提案
する.図 4.5 に提案手法の概要を例と共に示す.言葉は言葉の意味空間に,動作は動作表現
空間にそれぞれ配置され,言葉と動作の関係により 2 つの空間の関係性を学習することで,
言葉から動作を推定し,動作が生成できるようになる.例えば,
「大きく 混ぜる」

「大きく
切る」

「小さく 切る」の 3 つの言葉とそれぞれの動作が既知であるとする.この時,未知
の「小さく 混ぜる」動作を生成しようとする場合,既知の「大きく 切る」

「小さく 切る」
の関係から「大きい」と「小さい」の関係性を推定でき,
「大きく 混ぜる」動作と「大きい」
と「小さい」の関係性を用いて「小さく 混ぜる」動作を推定し,動作を生成する.

4.5. ロボット動作制御モデルの構築

4.5

38

ロボット動作制御モデルの構築

本節では,曖昧表現と動作表現の組み合わせによって,生成される動作が変化するモデルを
4 種類構築し,そのモデルの比較を行う.モデルの構造は重要である.Gaier and Ha (2019)
は,ニューラルネットの重みを固定したまま,ニューラルネットの構造を変更することで,複
数のタスクである程度の精度を得た.自然言語処理分野では,Collobert and Weston (2008)
が様々な問題に適用可能な共通の言語モデルの構築を深層学習を用いた Multitask Learning
によって目指した.また, Kingma et al. (2014) は一部ラベル付けされた MNIST や SVHN
のデータを用い,Variational AutoEncoder (VAE) (Kingma and Welling, 2013) によって
自動に入力の特徴を捉え,文字を特徴に合わせて出力するモデルを構築した.本研究では
これら先行研究を参考にモデルを構築する.また,入力をラベルとする場合と word2vec に
よる分散表現とする場合についての比較を行い,分散表現の有用性についての検証も行う.
なお,本研究では入力の検証とモデルの検証であるため,出力である動作は単純な動作と
した.

4.5.1

実験仕様

言葉と動作の関係を学習するために,ニューラルネットワーク (NN) を用いる.図 4.6 に
ネットワークの概要を示す.ネットワークの構造は以下の 4 種類を比較する.

Net1: 曖昧表現 wa と動作表現 wv を結合して一つのベクトルとして入力し,ロボッ
ト動作表現 o を出す 3 層のニューラルネットワーク.中間層での活性化関数は
シグモイド関数を用いる.
Net2: 曖昧表現 wa と動作表現 wv からそれぞれ二つの中間層 ha1 ,ha2 および hv1 ,hv2
を経た後結合し,ロボット動作表現 o を出すネットワーク.
Net3: 曖昧表現 wa と動作表現 wv のそれぞれの中間層 ha および hv を結合し,中
間層 h を経た後ロボット動作表現 o を出すネットワーク.
Net4: 動作表現によって曖昧表現が変化すると仮定する.まず,曖昧表現 wa と動
作表現 wv のそれぞれの中間層 ha および hv を足し合わせ,動作表現により変
化した曖昧表現の中間層 h1 と,動作表現の中間層 hv を足し合わせ,中間層 h2
を経た後ロボット動作表現 o を出すネットワーク.
実際にロボットに動作をさせる場合には,動作表現 o を 4.3.3 項の手順により変換し,指示
を行う.入力の曖昧表現 wa および動作表現 wv は,ラベル,つまり One-hot のベクトルと
する場合と word2vec で作った分散意味表現とする場合で比較する.なお,Net1 の中間層
での活性関数はシグモイド関数,Net2,Net3,Net4 の中間層での活性化関数はソフトプラ

4.5. ロボット動作制御モデルの構築

39

Net1

Net2

Net3

Net4
図 4.6: Network の概要

4.5. ロボット動作制御モデルの構築

40

ス関数とする.ネットワークの学習方法は誤差逆伝播法を用い,またロボット動作の出力
では活性化関数にシグモイド関数を用いた.言葉は,クックパッドのレシピに出現する調
理動作表現で最も多い「切る」と2番目に多い「混ぜる」に係り受けしている曖昧表現のう
ち,動作の大きさや速さを表す曖昧表現 12 個 (「さっと」
「ざっと」
「ザクザク」
「たっぷり」
「手早い」
「一気に」
「少し」
「細かい」
「ちょっと」
「しっかり」
「きちんと」
「じっくり」) と,
その曖昧表現と組み合わせて使える調理に関する動作表現 6 個(
「ふる」
「ふるう」
「炒める」
「切る」
「混ぜる」
「つぶす」
)を対象とする.入力の曖昧表現 wa および動作表現 wv をラベ
ルとする場合は,曖昧表現 wa は 12 次元,動作表現 wv は6次元で表す.分散表現の場合
は,クックパッドのレシピをクックパッドデータの材料コーパスを辞書として MeCab で分
かち書きしたのち,word2vec の skip-gram を用いてベクトル化し,1 単語を 100 次元の分
散表現で表す.曖昧表現 12 個 (「さっと」
「ざっと」
「ザクザク」
「たっぷり」
「手早い」
「一
気に」
「少し」
「細かい」
「ちょっと」
「しっかり」
「きちんと」
「じっくり」) の word2vec ベ
クトルの主成分分析結果の可視化を図 4.7 に示す.図 4.7 より,速度が速いことを表す「手

図 4.7: word2vec による曖昧表現の分散表現
早い」と「一気に」
,少量であることを表す「少し」と「ちょっと」がそれぞれ近いことが
わかる.一方で,逆の意味である「細かい」と「ザクザク」が近い.これは,word2vec に
よる分散表現の作成前提である,分布仮説の「同じ文脈に現れる単語は似た意味を持つ傾
向にある」により,対義語同士もまた同じ文脈に出やすいため,類義語と対義語は区別する
ことができないことが原因である.類義語と対義語が近くなる問題を解消するために,潜
在的意味解析をベースとした辞書知識を利用する手法や,意味的に関連している単語群は
似たベクトルになるようにファインチューニングする手法があるが,本研究は分散表現の
精度をあげることが目的ではないため,使用しない.
動作は,4.3.2 節に示した時系列対応 AAM を用いて人手で作成し,動作表現 6 個につい
て表 4.3 に示すような pn = [pxn , pyn , pzn , psn ] の4次元からなる動作を用い,p1 から p6 の

4.5. ロボット動作制御モデルの構築

41

表 4.3: 動作の時系列対応 AAM

p1
動作
ふる
ふるう
炒める
切る
混ぜる
つぶす

p x1
0
0
3.5
0
0
0

py1
0
3.5
0
0
3.5
0

pz1
3.5
0
0
-5
0
-3.5

ps 1
5
5
5
5
5
5

p x2
0
0
-3.5
0
3.5
0

p2
p y2
0
-3.5
0
3.5
-3.5
0

p3
pz2
-3.5
0
3
5
0
3.5

ps 2
5
5
5
5
5
5

px3
0
0
0
0
-3.5
0

py 3
0
3.5
0
0
0
0

p4
pz3
3.5
0
-3
-5
0
-3.5

ps 3
5
5
5
5
5
5

px4
0
0
3.5
0
0
0

py4
0
-3.5
0
3.5
3.5
0

pz4
-3.5
0
0
5
0
3.5

ps 4
5
5
5
5
5
5

p x5
0
0
-3.5
0
3.5
0

p5
p y5
0
3.5
0
0
-3.5
0

pz 5
3.5
0
3
-5
0
-3.5

ps 5
5
5
5
5
5
5

px6
0
0
0
0
-3.5
0

p6
py 6
0
-3.5
0
3.5
0
0

pz 6
-3.5
0
-3
5
0
3.5

連続する 6 つの動作により,24 次元のベクトルで表した.表 4.3 で示した動作のうち「切
る」と「混ぜる」は図 4.8 のように表現出来る.

図 4.8: ロボット動作(左:切る,右:混ぜる)
「切る」の動きを例にとると,p1 の動きは,p1 =[px1 , py1 , pz1 , ps1 ] = [0, 0, −5, 5] 次の p2
の動きは,p2 =[px2 , py2 , pz2 , ps2 ] = [0, 3.5, 5, 5] で表されており,確かに図 4.8 左でも p1 で
z へ,p2 で y と z への動きを同時に行っている.曖昧表現による動作の程度変化は,例え
ば「さっと」という動きは「速」くて「大きい」動作の程度であると仮定し,表 4.3 の着色
部や速さを表す ps を大きくすることで表現する.他の曖昧表現も図 4.9 のように程度変化
を仮定し,それぞれ表 4.3 の着色部や ps を変更することで動作を変化させる.なお,動作
によって変化する px , py , pz は異なる.また,px , py , pz の大きさは [-10, 10] の範囲に限定し
作成する.
以上を用いて,ネットワークを構築する.曖昧表現の次元数はラベルの場合は 12, word2vec
の場合は 100, 動作表現の次元数はラベルの場合は 6, word2vec の場合は 100 とし,入力と
する.出力層のノード数を p1 = [px1 , py1 , pz1 , ps1 ] から p6 = [px6 , py6 , pz6 , ps6 ] の 24 とした.
中間層のノード数は 2 から 30 を試行し,入力を word2vec にした場合に最も平均二乗誤差

ps 6
5
5
5
5
5
5

4.5. ロボット動作制御モデルの構築

42

図 4.9: 曖昧表現の動作の程度変化
が小さくなった 20 とする2 .訓練データとして,6 個の動作表現と,12 個の曖昧表現のう
ちいずれか 7 個をそれぞれ組み合わせた全 42 種の言葉に対し,各 100 個の動作を仮定した
動作程度変化になるように切断正規分布により生成し,全 4200 個の動作を作成した.学習
をした後,訓練データとして与えた曖昧表現と動作表現の組み合わせの 42 種,訓練データ
にない動作表現と曖昧表現の組み合わせの 30 種の動作を評価した.

4.5.2

評価指標

正解動作表現とネットワークにより出力された動作表現の生成結果の距離の差および時
間の差を用いた誤差率によって,生成結果を評価する.実際にロボットで動作を行うには,
生成結果を 4.3.3 項の手順により変換し,指示を行う必要があるが,物理的に動かすと誤差
が生じるため,評価には生成結果を直接用いる.p1 から p6 の各時間終了時の正解動作と生
成結果の距離の差 (単位:cm) を正解動作の移動距離で割った割合と,その動作にかかる時
間の正解動作と生成結果の誤差 (単位:秒) を正解動作の時間で割った割合を足し合わせて
その平均を取る.

√
6
1 ∑
(Xi − xi )2 + (Yi − yi )2 + (Zi − zi )2 |Ti − ti |



誤差率 =
(4.1)
+
12
T
2
2
2
i
Xi + Yi + Z i
i=1
2

入力をラベルとした場合,中間層のノード数が 9 で最も平均二乗誤差が小さくなったが,ノード数 20 と
の差は僅かであったため,ノード数 20 を用いる

4.5. ロボット動作制御モデルの構築

43

ここで Xi ,Yi ,Zi ,Ti は時刻 pi の正解動作,xi ,yi ,zi ,ti は生成結果である.この誤差
率が 0 に近いほど正解動作と似た動きになっており,より正しく生成できていることを表
している.

4.5.3

実験結果

表 4.4 から表 4.6 は式 (4.1 の誤差率を算出し,パーセントで換算した評価結果である.
表 4.4 は入力の言葉をラベル,つまり One-hot にした場合と word2vec による分散表現に
した場合のネットワーク毎の生成動作誤差率の平均を表している.ここで,
「学習済み表現」
とは入力の曖昧表現と動作表現の組み合わせに対応する動作が学習データに含まれている
場合の生成動作の誤差率平均,
「未学習表現」とは,入力の曖昧表現と動作表現を組み合わ
せた動作が学習データに含まれていない場合の生成動作の誤差率平均である.
表 4.4: ネットワーク比較
誤差率平均
学習済み表現 未学習表現

構造

入力処理

Net1

ラベル
word2vec

42.05
40.74

47.49
47.70

Net2

ラベル
word2vec

32.13
32.08

47.78
46.91

Net3

ラベル
word2vec

8.79
8.44

14.00
12.71

Net4

ラベル
word2vec

8.93
8.48

12.54
12.10

表 4.4 より,学習済み表現を入力とする場合でも未学習表現を入力とする場合でも,Net1
の未学習表現の入力を除いて word2vec を用いた場合の方がラベルを用いた場合よりも誤差
率が若干小さくなった.しかしその差は大きくなく,入力処理よりも,ネットワーク構造
が重要であることを示していると言える.
ネットワーク構成について,Net1 と比較し,Net2,Net3,Net4 では誤差率が小さくなっ
た.よって,入力の方法として曖昧表現と動作表現を連結した場合より,分けて入力とし
た場合が有用である.また Net3,Net4 が Net2 よりも誤差率の平均は小さくなっており,
動作表現と曖昧表現の言葉を足し合わせた後,ロボット動作を出力する前に一度中間層を
経たネットワーク構成の学習が有用であると言える.また Net4 はの未学習表現の入力に対

4.5. ロボット動作制御モデルの構築

44

する誤差率の平均が最小であり,未学習表現の入力に対しては,動作表現によって曖昧表
現が変化するという仮定を用いると有効であると言える.
表 4.5,表 4.6 は入力を word2vec のベクトルとした場合の Net2 と Net4 の生成動作の誤
差率を表している.この時,着色部は曖昧表現と動作表現の組み合わせによる動作が学習
データに含まれない,未学習表現の入力を与えた場合であり,それ以外(白色部)は学習
データに含まれている曖昧表現と動作表現の組み合わせを入力とする場合の誤差となって
いる.表 4.5 と表 4.6 を比較すると,Net2 の表 4.5 は,動作表現毎の誤差率の平均が 14.5%
から 50.6%となっており,ばらつきがある一方,Net4 の表 4.6 では動作表現毎の誤差率の
平均が 5.0%から 12.9%と大きくは変わらないことから,Net4 では各動作の特徴を捉える
ことができていると言える.また,1つの曖昧表現における動作表現毎の誤差率について,
Net2 の表 4.5 は,白色部と着色部にばらつきがある一方,Net4 の表 4.6 は白色部と着色部
に大きな差が見られないことより,曖昧表現が動作毎に変化する学習できていると言える.

表 4.5: Net2 評価結果
動作表現
炒める 切る

曖昧表現

ふる

ふるう

さっと
ざっと
ザクザク
たっぷり
手早い
一気に
少し
細かい
ちょっと
しっかり
きちんと
じっくり

30.1
31.8
28.2
21.7
9.7
8.6
99.3
79.1
39.0
158.0
54.4
46.9

30.6
31.3
36.7
23.1
12.7
10.7
140.2
52.8
31.6
130.3
61.4
29.3

26.9
28.0
26.4
18.4
12.4
13.2
65.6
25.3
14.9
50.6
38.8
15.8

平均

50.6

49.2

28.0

混ぜる

つぶす

18.4
19.7
20.3
10.2
9.1
8.7
16.1
13.7
9.1
17.7
18.3
13.0

29.4
30.7
36.6
24.9
13.8
12.3
83.6
48.3
27.2
92.4
58.8
31.4

31.4
34.9
41.5
25.8
15.9
11.4
145.7
43.1
26.2
84.2
73.5
23.8

14.5

40.8

46.5

4.5. ロボット動作制御モデルの構築

45

表 4.6: Net4 評価結果
動作表現
炒める 切る

曖昧表現

ふる

ふるう

さっと
ざっと
ザクザク
たっぷり
手早い
一気に
少し
細かい
ちょっと
しっかり
きちんと
じっくり

9.0
11.3
6.1
0.9
8.4
6.8
18.8
15.1
6.7
25.9
14.6
7.1

9.0
7.9
7.5
1.2
10.0
8.5
37.0
14.7
7.9
23.1
17.2
10.2

9.4
10.6
8.9
1.7
9.0
7.4
9.3
6.1
4.6
12.3
14.8
8.2

平均

10.9

12.9

8.5

混ぜる

つぶす

8.8
7.5
6.5
0.8
9.8
7.5
1.7
1.2
1.7
4.8
6.5
2.9

10.1
9.0
10.4
1.6
10.0
9.7
13.7
12.0
2.9
19.9
22.4
11.9

10.1
12.7
11.2
2.5
10.6
7.5
28.8
7.1
4.4
18.2
15.8
9.7

5.0

11.1

11.6

図 4.10: 正解動作表現 o の可視化
高次元での距離分布が次元削減してもできるだけ合致するように変換が行える t-SNE を
用いて,正解動作表現を次元削減し,可視化した結果を図 4.10 に,Net2 と Net4 の中間層

4.5. ロボット動作制御モデルの構築

46

と出力層を次元削減し可視化した結果をそれぞれ図 4.11 および図 4.12 に示す.それぞれ,
色によって入力の曖昧表現を区別し,マークの形によって入力の動作表現を区別している.
図 4.10 の正解動作表現と Net2 および Net2 と Net4 を比べると,正解動作表現では,同
一のマークは比較的近くに分布しており,また同一の色同士も近い傾向にある.同一の動
作表現による動作表現同士は近く,また同一の動作表現による関係性には劣るが,同一の
曖昧表現による動作表現同士も近い傾向にあると言える.Net4 の出力層も同様の傾向にあ
ることがわかる.一方,Net2 の出力層は,同一のマークで固まっており,同一の色同士の
関係性はみられない.このことから,曖昧表現を捉えられていないことが分かる.
中間層を比較すると,Net2,Net4 それぞれの最初の中間層 ha1 ,hv1 および ha ,hv では,
同一のマーク同士,もしくは同一の色同士でまとまっている.入力に近い中間層であるた
め,より入力の曖昧表現や動作表現を反映した分布になっていると考えられる.次の層で
は,Net2 において ha2 および hv2 は,最初の層と比べて,より同一のマーク同士,もしく
は同一の色同士が近くなっている.つまり,同一の曖昧表現や動作表現による中間層のベ
クトル同士がより近い分布となっている.正解動作は曖昧表現による動作表現の関係性よ
り,動作表現による動作表現の関係性の方が強いため,より hv2 を反映した出力 o となっ
たと考えられる.
一方 Net4 では h1 ,h2 とも同一のマークおよび同一の色の両方が近い傾向にある.つま
り,曖昧表現および動作表現の両方の傾向を持つ中間層のベクトルとなっている.その結
果,出力 o も曖昧表現および動作表現を反映できたと考えられる.
生成した動作表現をロボットに指示した場合に想定される動きの例を示す.「ザクザク」
「混ぜる」の p1 から p3 までの動作は図 4.13 のようになる.Net1 に比べ Net2,Net3,Net4
の 3 つの手法は,より「混ぜる」動きができており,特に Net3,Net4 は予想データとより
似た動きになることが確認出来る.

word2vec を入力として学習したネットワークは,学習データに存在しない表現(ここで
は未知語と呼ぶこととする)を入力として与えることが可能である.例えば,動作表現の
「切る」と共に,未知語の「ちゃんと」の word2vec のベクトルを入力に与えた場合と,学
習データに存在する既知語の曖昧表現の「きちんと」を入力に与えた場合,および,未知語
の「キャベツ」の word2vec のベクトルを入力に与えた場合と,既知語の曖昧表現の「ザク
ザク」を入力に与えた場合のそれぞれの出力動作を図 4.14 に示す.「ちゃんと」
「切る」と
「きちんと」「切る」,
「キャベツ」「切る」と「ザクザク」「切る」はそれぞれ近い動きであ
るが,わずかに差異を持つ動作が生成できた.「ちゃんと」と「きちんと」

「キャベツ」と
「ザクザク」は word2vec のベクトルがそれぞれ近い.言葉での関係性から動作の変化を推
測し,動作生成できていると言える.

4.5. ロボット動作制御モデルの構築

47

中間層

出力層 o
図 4.11: Net2 の中間層と出力動作表現の可視化

4.5. ロボット動作制御モデルの構築

48

中間層

出力層 o
図 4.12: Net4 の中間層と動作表現の可視化

4.5. ロボット動作制御モデルの構築

49

正解動作

Net1

Net2

Net3

Net4
図 4.13: 「ザクザク」「混ぜる」のロボット動作

4.5. ロボット動作制御モデルの構築

既知語:「きちんと」

既知語:「ザクザク」

50

未知語:「ちゃんと」

未知語:「キャベツ」

図 4.14: 未知語入力時の「切る」ロボット動作

4.6. まとめと今後の課題

4.6

51

まとめと今後の課題

本章では言葉と動作の対応関係学習によるロボット動作生成手法の提案,特に複数の動作
生成に適したネットワークについて検証した.一部の言葉と動作の関係が既知の場合,ラベ
ルを入力にした場合も  word2vec を入力とした場合も,曖昧表現と動作表現の組み合わせ
による言葉と動作の関係性を学習していない場合にも動作推定可能であり,特に word2vec
を用いた場合は言葉をラベルとして与えた場合に比べ誤差が小さくなった.一方,word2vec
を用いたことによる精度向上よりも,言葉と動作の関係性獲得に用いたネットワークの構
成による精度の差が大きくなった.入力層について,曖昧表現と動作表現を連結した場合
に比べそれぞれ入力を行った方が良い結果となった.また,適切な中間層の形を得,さら
に動作表現により曖昧表現が変化するという仮説が示された.なお入力に word2vec を用
いたネットワークについて,全く行ったことのない言語表現の動作を生成することができ,
既知の表現からの推測ができていると考えられる.以上により,調理で使われがちな曖昧
な表現と動作表現を組み合わせた言葉による指示で,ロボットを動かすことができ,家庭
内でロボットへの指示に慣れていないユーザーの使用に適したロボット動作手法を獲得し
た.本枠組みにより,言葉の曖昧さを動作というモダリティに限定して対応関係を獲得す
ることで,モダリティ変換することができた.
今後の課題として,肘を上げたまま動かす,動きを連続させるなどのより複雑なロボッ
ト動作への適用,
「にんじんを小さく切る」

「ごぼうを小さく切る」で大きさが変わるよう
に,動作対象に対して動作が変わると考えられるため 3 語以上の入力への対応や,
「きれい
に」や「ちゃんと」のような,より曖昧な言葉の入力に対しての動作生成が挙げられる.ま
た,家庭内で使う場合には口頭での指示が考えられ,非文法文や音声認識誤りが想定され
るが,その対応として,過去の動作からの推定や,周りの状況を判断できるような仕組みの
導入が必要と考えられる.なお本課題では word2vec を用いているため,レシピコーパス
に出現していない単語に対して,ゼロ頻度問題が起こりうるが,例えば subword の組み合
わせによって,対応できると考えられる.

52

第 5 章 一般ドメイン実況生成

本章では,非言語から言語を生成する課題として,一般ドメイン実況生成課題を取り上
げる.一般ドメイン実況生成の概要を述べた後,関連研究を説明する.データセットの作
成手順の説明,データセットの分析を述べ,課題設定について説明する.各課題に対して
実験を行い,評価する.

5.1

概要

動画や画像に対して自然言語でその内容を記述する研究は広く行われている (Vinyals
et al., 2015b; Xu et al., 2015; Venugopalan et al., 2015a; Gao et al., 2017; Pei et al., 2019;
Wang et al., 2018).動画に対する言語生成課題として代表的な課題として,動画キャプショ
ン生成 (Krishna et al., 2017; Zhou et al., 2018a) が挙げられる.これは,動画内の重要な
イベントを複数検出し,それぞれに対して説明テキストを生成する課題である.一方,動画
内で起きているイベントの客観的な説明や主観的な感想を,視聴者が動画の再生と共に音
声として聴く,あるいは字幕テキストとして読むことができる実況は,視聴者が動画の状
況をより深く理解でき,また動画視聴をより楽しむことができる.すなわち,実況を付与
することにより動画の価値向上が期待できる (Schaffrath, 2003).実況は,視聴者に映像の
内容をわかりやすく伝えるために,映像とともに音声として出力されたり,映像にテキス
トを被せ提示されたりする.そのため,実況発話を開始するタイミングや発話の長さを適
切に制御することが求められる.実況生成は既存研究である動画キャプション生成と類似
するが,1) タイムスタンプの重なり,2) タイムスタンプの時間幅の観点から,動画キャプ
ション生成とは異なる設定である.図 5.1 に,既存の動画キャプションデータセットである
ActivityNet Captions (Krishna et al., 2017) のキャプション,および本研究で生成を目指
す実況の例を示す.動画キャプション生成ではイベント検出をまず行い,それぞれに対し
キャプションを生成するため,イベントの発生する時間幅が重なる場合がある.一方,実
況では前の発話が終わってから次の発話を始める必要がある.さらに,動画キャプション
ではリアルタイムに発話することが想定されていないため,図 5.1 の 1 つ目のキャプション
に示すように,短い時間幅に対し長いテキストが対応づくことがある.一方,実況では時
間幅と発話の長さが関係する特徴がある.

図 5.1: 既存の動画キャプションデータセットと提案の実況との比較.

5.1. 概要
53

5.2. 関連研究

54

このように実況は,時間的位置,内容,ビデオ内のオブジェクトの相関が,ビデオ内の
イベントと部分的にしか整合しておらず,これまでの既存の画像キャプション生成課題と
は明確に異なるものである.
一般的に実況は,スポーツ中継やゲームにおいて,観客を興奮させ,没入させる重要な役
割を持っている (Schaffrath, 2003).このような背景から,これまでにも解説を自動生成す
るアプローチが提案されているが,分野固有の情報を活用することが可能な特定分野を対象
としたものが一般的であった.例えば,RoboCup サッカーシミュレーションと連動した実
況生成 Mike (Tanaka-Ishii et al., 1998) では,試合の時々刻々の選手の位置やボール位置
によって実況生成が行われ,レーシングゲーム実況生成 (Ishigaki et al., 2021) では,レー
シングカーの速度やレースの進捗度といったレーシングゲーム特有の情報を用いて生成を
行っている.このように従来の実況生成の研究では,分野固有の情報を活用することが可
能な特定分野,つまりクローズドメインを対象としたものに限られていた.そこで本章で
は,より汎用性の高い技術を目指すため,特定ドメインでなく一般ドメインの動画を対象
とする動画の実況生成タスクを提案する.具体的には,ダーツやサッカーなどのさまざま
なスポーツ,縫い物や編み物の様子,手を洗うなど,人の動作の動画を集めた ActivityNet
コーパスに含まれる動画に対して実況を生成するタスクとする.分野固有の情報を使用す
ることなく,実況を生成する手法の獲得を目指し,これが達成されることで,例えばテレビ
番組の字幕放送や投稿動画の実況付加,CM 作成など,ドメインが限定されない動画に対し
て説明文などを付与したい場合に実用できる技術となりうる.
まず,様々なドメインの人間の動作を含むビデオに対して実況を収録し,新しい大規模
データセットの構築を行なった.また,実況生成課題に取り組むために,一般的なニュー
ラルネットワークに基づく手法を提案する.提案する手法の長所と限界を理解するために,
我々のデータに基づく詳細な実証研究も提示する.

5.2

関連研究

言葉を用いて動画内の状況を説明する機械学習手法の開発は,computer vision   (CV)
の分野と自然言語処理の分野の両方にまたがる挑戦である.オープンドメインの動画に対
して,説明を付与する課題に取り組んだ最初の研究は Venugopalan et al. (2015b) である.
この動画キャプション課題は,30 秒未満の短い動画に対して,主となる内容を自然言語で
記述する課題であった.この課題は後に, Krishna et al. (2017) によって,ビデオで発生
する複数のイベントを検出し,自然言語によってそれぞれのイベントを説明する課題に拡
張された.このように,ビデオで発生する複数のイベントを検出し,説明文を生成する課題
を Dense Video Captioning (DVC) と呼ぶ.DVC は一般的に,1. まず入力動画中のイベン
トが起きている箇所 proposal を特定し,2. その後,特定した proposal 区間に対して、キャ
プション生成モデルが説明テキストを生成する,のように,2 つのサブタスクに分けて課題
解決を目指している.なお,最近では Transformer を用いた end-to-end アプローチも提案

5.3. データセット

55

されている (Zhou et al., 2018b; Wang et al., 2021).

Taniguchi et al. (2019) は,データからテキストに変換して生成する手法として,試合の
イベントデータ(関与した選手,ピッチ内の位置,プレイの種類など構造化されたデータ)
を用いて,ウェブページに表示するサッカーの試合の解説文を生成する手法を提案した.ま
た最近では, Kim and Choi (2020) が野球の試合映像から,試合の合間に表示する解説を
自動生成する手法を提案した.しかしこれらの手法は,動画と一緒に表示されることを想
定していない解説を生成することを目的としているため,本論文で提案する課題とは異な
る.またこれらの手法は,それぞれの課題を解決するためにドメイン固有のデータに依存
している点も本課題とは大きく異なる点である.
Taniguchi et al. (2019) ではもちろんのこと,Kim and Choi (2020) では,解説文の生成
はドメインオントロジーに依存するだけでなく,入力動画からゲームの詳細をモデル化す
ることを目的とした,いくつかのサブコンポーネント(選手検出器や投球結果認識器など)
に基づいている.さらに最近, Ishigaki et al. (2021) はレーシングカーゲームの解説を自
動生成するタスクを提案し,ゲームプレイ動画と音声解説のアノテーションデータセット
を初めて公開した. Ishigaki et al. (2021) は構造化されたデータ,具体的にはテレビゲー
ムエンジンから直接抽出された車の位置と速度,ハンドルの角度を含むテレメトリデータ
を用い,実況文解説を生成するモデルに適用した.これらの特徴を利用することで,動画
情報とテキストのみを入力とするモデルよりも大幅な性能向上を実現し,動画内容を説明
する課題におけるドメイン内情報の重要性を改めて示した.
本章で行うタスクは,リアルタイムに入出力を行う点において,同時通訳 cho (2016) と
も似ている(詳しくは,5.4 節を参照). このような課題の場合,文を生成するために多く
の情報を待つことと,より早く文章を生成することのトレードオフを考慮したモデルを提
案する必要がある.

5.3

データセット

一般ドメインの動画実況データセット作成手順およびデータ分析について述べる.デー
タ作成は実況音声の収集と文字起こしの 2 段階の手順で行った.

5.3.1

実況音声収集

クラウドソーシングサービスの Amazon Mechanical Turk (MTurk) を用い,人の動作の
動画を集めた ActivityNet コーパス (Fabian Caba Heilbron and Niebles, 2015) に含まれ
る YouTube 動画のうち,2021 年 2 月の時点で YouTube 上に存在する動画を実況付与対象
とした.また,動画は 30 秒以上 4 分以下のものに絞った.作業者には,図 5.2 に示す画面

5.3. データセット

56

(HIT)を表示し,動画を視聴しながら動画内で起こっていることを主観的な感想なども含
め実況するよう指示した.作業者が録音を停止しない場合,動画終了後 1 分後に強制的に
録音が停止されるよう設計した.作業者は 2 つの動画に対して二回録音を行い,1動画に
つき 2 人以上の作業者が実況を録音した.1 回目の録音では動画をはじめて視聴する場合の
実況,2 回目の実況では動画の内容をすでに把握している状況での実況を収集することを
目指している.データセットに含める録音の品質を向上させるため,Pydub1 を用いて音量
調節および雑音削除した.また,音声録音時間が動画時間の 90%以上 200%以下のものに絞
り,動画の長さと録音時間が極端に乖離する事例をフィルタリングした.さらに,沈黙時
間が極端に長い低品質な録音を除外するために,発話している時間が動画の長さの 30%以
上 110%未満であるものに限定した.

図 5.2: MTurk で用いた実況録音用 HIT の例

5.3.2

自動文字起こしと実況テキスト修正

次に収集した実況音声を AWS の音声のテキスト変換機能 Amazon Transcribe2 を用い
て自動文字起こした.自動文字起こしにより,発話中の各単語にタイムスタンプが付与され
1
2

https://github.com/jiaaro/pydub
https://aws.amazon.com/jp/transcribe/

5.3. データセット

57

表 5.1: 実況テキスト例
種類

Amazon Transcribe

文字起こし修正

フィラー等削除

テキスト

“uh Let’s see uh there’s a man, there’s a man throwing darts
and I think oh it seems one of them,he threw three darts,
and I think 11 of them hit the center, didn’t it?.”
“uh Let’s see uh there’s a man, there’s a man throwing darts
and I think oh it seems one of them, he threw three darts,
and I think one one of them hit the center, didn’t it?.”
“There is a man throwing darts. He threw three darts.
I think one of them hit the center.”

る.自動文字起こしの結果には誤りが含まれる場合があり,また発話中にはフィラーや言い
淀みが含まれるため,Mturk にて作業者に文字起こし修正と,フィラーや言い淀み,言い直
しの削除や修正作業を依頼した.テキスト修正用の HIT の例を図 5.3 に示す.作業者には
自動文字起こしされたテキストを発話単位に分割して表示し,
,各発話に対して自動文字起
こしの修正と,フィラー等の削除を指示した.さらに,実況音声と共に実況録音時に使用し
た動画を再生する UI を用いて,実況内容と動画との乖離がないかを合わせて確認できるよ
う設計した.表 5.1 に Amazon Transcribe を用いて音声をテキスト変換した結果,MTurk
で文字起こしを修正した結果,フィラーなどを削除した結果の例を示す.作業者が提出し
た修正テキストのうち,数字をスペルアウトできているか,フィラーを削除できているか
を基準として,最終的な文字起こし修正テキストおよびフィラー等削除済実況テキストを
収集した.

5.3.3

データセット統計および既存データとの比較

作業者が意味のある実況を提出したことを確認するために,Krishna et al. (2017) で作
業者が意味のあるイベントをアノテーションしているか確認した手法 (Baldassano et al.,
2017) に従い,ある作業者の各発言タイムスタンプと他の作業者の発言タイムスタンプの
重なりを調査した.その結果,temporal Intersection over Union (tIoU) が 45.5%となっ
た.これは,Dense video captioning のデータセットである ActivityNet Captions (Krishna
et al., 2017) の 59.5%の tIoU より若干低い3 が,本課題であつかう実況における,人によっ
て実況を行う時間帯が若干異なるという性質上,許容範囲と考えられる.また,ActivityNet
Captions と本実況データの平均 tIoU は 18.7%となり,実況者がイベントをより明確にする
ために発言を遅らせたり,逆に急がせたりするために,同時刻の動画中のイベントと発言
との間に強い整合性がないことを再度示唆していると考えられる.
3

Krishna et al. (2017) の論文値では 70.2%だったが,再現できなかった

5.3. データセット

58

図 5.3: MTurk で用いた文字起こしテキスト修正 HIT の例
さらに,実況内容の一致を実況者間で調査するため,DVC のようなタスクを評価する時に
よく使われる,BLEU-4 とシーングラフの一致度合いを F 値で評価する SPICE (Anderson
et al., 2016) の2種類を用いる.本データセットと ActivityNet Captions の 2 つのデータ
セットをそれぞれ用い,同一動画における異なる作業者のテキストを時間順に並べて比較
する.ActivityNet Captions では、BLEU-4 と SPICE の平均値がそれぞれ 4.86 と 0.12 で
あったのに対し,本データセットではそれぞれ 2.59 と 0.034 であった.この結果は,実況は
人によって内容が変わりうるという,本課題の性質を反映していると考えられる.図 5.4 と
図 5.5 は,ランダムに選択した 2 つの動画(動画 ID が “c1RR1cmS9LU”,“KU8VVtam3ig”
の動画)に対する本データセットと ActivityNet Captions の BLEU-4 と SPICE の内容一
致評価結果をそれぞれ可視化したものである.ActivityNet Captions と比べて,本データ
セットでも異なるアノテーションに対して同程度の内容の一致を示していることが観察で
き,この結果は本データセットの実況の品質をある程度担保していると考えられる.
作成したデータセットの統計を表 5.2 に示す.合計 715 人の作業者によって 6,771 本の
動画に対して,合計 25,000 件以上の実況テキストを集めた.図 5.1 は実際に収取したデー
タで,2 人の実況者が動画に対して付与した発話の例を示しており, Krishna et al. (2017)

5.4. 問題設定

59

図 5.4: ActivityNet Captions(左) と本データセット (右) の BLEU-4 による内容一致評価可
視化.
による同一動画の DVC と比較している.この例から分かるように,本データは動画上に密
に分布しており,平均して動画時間の 78 ± 21%を占めている.本課題と最も近い Ishigaki
et al. (2021) によるクローズドメインのデータセットでは 55 ± 17%であり,それと比べて
もより密に分布している.また、1 動画あたりの平均発言数は 17.64 となり, Ishigaki et al.
(2021) の 52.25 に比べ非常に少ない.本データセットでは発言間の無音時間も短いことか
ら,発言数の少なさは本データセットで用いてた動画が短いためと推察される.

5.4

問題設定

本節では,一般ドメイン実況生成課題に向けたモデルの提案を行う.以降,与えられた
動画 V ∈ V が V = {vf }F
f =1 のようなフレームのシーケンスとして特徴付けられると仮定
する.また各動画には,開始と終了のタイムスタンプ ts と te で定義される非重複区間にお
いて,ある期間に何が起こっているかを実況解説した自然言語発話シーケンス U = {ut }Tt=1
がアノテーションされている.
実況生成課題として,以下の 2 種類の設定が考えられる.

5.4. 問題設定

60

図 5.5: ActivityNet Captions(左) と本データセット (右) の SPICE による内容一致評価可
視化.

• Off-line Live Commentary Generation: 録画された動画に対する解説の自動生成.学
習時と推論時に動画全体にアクセスできる.
• Real-time Live Commentary Generation: ライブ映像に対する解説の自動生成,追
加のデータを待つことと、長い遅延なしに発話を生成することのトレードオフのバラ
ンスをとる必要がある.同時通訳に類似したマルチモーダルな設定とみなすことがで
き,より挑戦的な設定である.
本論文では Off-line 設定に焦点を当てるが,本実証研究は 5.2 節で示すように,今後行うで
あろう Real-time 設定の課題に関係している.
関連する先行研究 (Taniguchi et al., 2019; Kim and Choi, 2020) やクローズドメインの
実況生成 (Ishigaki et al., 2021) では大きなタスクをそのまま処理することなく,パイプラ
インアプローチで組み合わせることができる,より単純なサブタスクに分割する慣習があ
る.本研究でもそれを踏襲し,2 つのサブタスクに分割する.

• タイミング推定: 各発言のビデオ内の適切な開始と終了のタイムスタンプを識別する
サブタスク.本研究で対象とするデータの一般ドメイン性を考慮すると,このタスク

5.4. 問題設定

61

表 5.2: 本データセットと (Krishna et al., 2017), (Ishigaki et al., 2021) の統計値比較.
データセット
課題
ドメイン

Krishna et al.

本データセット

DVC
一般ドメイン

Ishigaki et al.

実況生成
クローズドメイン

動画数
- 動画時間合計
- 最大動画時間
- 最小動画時間

14,926
487:35:43
755 s
1s

6,771
239:58:03
238 s
30 s

2,473
226:37:53
452 s
246 s

アノテーション数
- 作業者数
- アノテーション時間の合計
- 合計文章数
- 1 動画あたりの平均文章数
- アノテーション重複率
- 平均沈黙時間

19,811
742:23:29
71,957
3.63
10%
-

25,817
715
904:01:24
455,485
17.64
0%
0.84 s

2,473
5
226:37:53
129,226
52.25
0%
3.46 s

を適切に解決するには,モデルは与えられた粒度の各タイムポイントにおいて,ビデ
オ内の関連するイベントを認識できる必要がある.

• 発話生成: 入力された映像のセグメントに対して、適切な発話を生成するタスク.
以降,簡単のため,与えられた入力例 V に焦点を当てる.すべての場合において,F 個の
入力動画フレームを動画特徴量のシーケンス G = {gn ∈ Rdv } (n = 1, . . . , N ) にマップす
る動画エンコーダ4 と,タイムスタンプ t を特徴量インデックス τ ∈ {1, . . . , N } に変換でき
るマッピング関数が存在すると仮定する.

5.4.1

タイミング推定

これまでの実況生成におけるタイミング推定には,領域内の情報を広範囲に使用してき
た.本タスクは一般ドメインであるため,正規化された知識ベース,もしくはタスクに有用
な情報をすでに獲得している事前学習済みのモデルを利用して,外部の知識にアクセスす
ることが重要であると考えた.そこで,Temporal Action Localization (TAL) を提案する.
TAL は CV の基本タスクで,トリミングされていない動画シーケンス中の人間の活動を時
間的に位置づけることを目的とする.このタスクは従来から Dense Video Caption(DVC)
4

このマッピングは τ = (t · n · fps)/N によって,フレーム/特徴量インデックスを時刻に変換する.

5.4. 問題設定

62

に不可欠な要素であり,モデルは ActivityNet (Fabian Caba Heilbron and Niebles, 2015)
を利用して学習することが多い.一般に,モデルは “proposal”,すなわち,目的の動作が配
置されうる時間の範囲を生成する.ここで,proposa は予測される開始時間と終了時間 tsm ,
tem の pm = (tsm , tem , cm ) からなる P = {pm }M
m=1 と表し,cm はモデルの確からしさである.
s と τe に 1 ≤ τs < τe ≤ N
proposal pm に対して,タイムスタンプを特徴インデックス τm
m
m
m
e − τ s + 1 個の特徴量 g s , . . . , g e と表す.まず,
で対応付けし,pm を G を用いて K = τm
τ
τ
m
m
m
各 roposal に対する固定長表現 pm を以下の式で求める:
s +k−1 , xk−1 )
xk = GRUE (gτm

k = 1, . . . , K,

(5.1)

この時,xk は x0 = 0 を初期状態とする GRUE の k 番目の隠れ状態で,pm = [x1 ; xK ] は
セグメント表現である.各 proposal の開始時刻に従ってセグメント表現を並べて,次に示
すようにポインタネットの初期コンテキスト表現を生成する役割を持つ別の GRU に入力
する:

hm = GRUC (pm , hm−1 )

m = 1, . . . , M.

(5.2)

GRUC の初期隠れ状態を 0 (h0 = 0) とし,その最後の隠れ状態を用いて,s0 = hM とし
て Pointer Net を初期化する.次時刻以降の proposal の集合を 1 つずつ繰り返し,以下の
操作を実行する:
score(si , xm ) = v T tanh([si ; xm ])
exp(score(si , xm ))
∑M
m=1 exp(score(si , xm ))
= GRUP ([xm⋆ ; pos(m⋆ )], si−1 )

ai,m =
si

(5.3)
(5.4)
(5.5)

ここで,v は学習可能なパラメータのベクトル,ai は大きさ M のベクトル,pos(m) は proposal
  pm を大きさ dp のバイナリーベクトルで正規化する関数であり,m⋆ = arg maxm (ai,m )
(m⋆ ∈ {1, . . . , M })である.式 (5.5) に示す通り,各ステップにおいて proposal 集合に対
する確率分布を計算し,最も可能性の高い proposal を選択する.次のステップの Pointer
Net の隠れ状態を計算するため,選択された proposal 表現 xm⋆ をそれの位置表現と連結し
て GRUP に入力する.入力には特別な EOS という proposal を p0 として組み込み,モデ
ルは全ての proposal が選択されるまで,あるいは Pointer Net が p0 を選択するまで反復を
繰り返す.モデルは,以下に定義する損失を最小化し,正解と高い重複を持つ proposal を
選択するように学習される:

L=−

R ∑
M


tIoU(sr , pm ) log ar,m + (1 − tIoU(sr , pm )) log(1 − ar,m ),

(5.6)

r=1 m=1

ここで, {sr }R
r=1 は正解 proposal の系列,ar,m は r 番目の proposal が m 回目の反復で選
ばれる尤度,tIoU(·, ·) は temporal Intersection over Union である.

5.5. 一般動画実況生成におけるタイミング推定実験

5.4.2

63

発話生成

発話生成モデルには,いくつかのマルチモーダルなタスク (Chen et al., 2020; Hong et al.,
2021) で有効性が示されている,Transformer モデル (Vaswani et al., 2017) を用いる.先行
研究に従い,動画およびテキストのコンテキスト両方をモデルに入力する.具体的には,前の
発話に由来するトークン列 sj と、各正解アノテーションの 3 秒前から終了までの (ts − 3, te )
の動画セグメント vt を入力する.これは,本データにおける発話間の平均時間差が約 1 秒
であり,Ishigaki et al. (2021) と比較しても妥当な範囲である.モデルは以降に示す構成要
素を主に持ち,生成されたトークン列と正解のトークン列の間のクロスエントロピーを最
小化するように学習される.

Video Encoder タイミング推定と同様に,タイムスタンプ (ts , te ) を持つビデオセグメ
e に対応付けし,G を用いて K = τ e − τ s + 1 個の特徴量のシーケンス
ントを tausm , τm
m
m
vg1 , . . . , gK として表現する.
Text Encoder 入力テキストを一連のベクトルに対応付けする.文は BERT ベースの単
語分割で分割され,特殊なトークンである CLS が前置され,最後に SEP が追加される.各
トークンは学習された位置エンコーディングが組み込まれた dm 次元の学習された埋め込み
にマップされる.トークン化された入力の長さを L とすると,L+1 個のベクトル vx0 , . . . , xL
の系列ができる.
Multi-modal Encoder エンコーダーによって得られたテキストとビデオの両方の特徴
を受け取る Transformer.テキストは埋め込まれたテキストトークン列を直接入力し,動画
はまず学習可能な線形層を用いて g1 , . . . , gK を隠れ次元に射影し,さらにこれに学習済み
の位置エンコーディング一式を組み合わせて g˜1 , . . . , g˜K とする.この 2 つのエンコードさ
れたベクトル列を長さ方向に連結し,12 個の attention ヘッドを持つ 12 個のエンコーダブ
ロックに通し,h0 , . . . , hK+L とする.
Decoder cross attention を持つ 6 層 8 ヘッドの Transformer のデコーダー.マルチモー
ダル文脈に基づく特徴量 vh0 , . . . , hK+L を受け取り,自己回帰的にキャプションが生成さ
れる.

5.5

一般動画実況生成におけるタイミング推定実験

5.4 節で設定したサブタスクのうち,タイミング推定の実験について述べる.

5.5. 一般動画実況生成におけるタイミング推定実験

5.5.1

64

評価指標

予測された時間間隔が正しいかどうかを判断するために,先行研究の Krishna et al. (2017)
に従って,各正解セグメントとの tIoU を用い,tIoU の値が所定の閾値 (0.3, 0.5, 0.7, およ
び 0.9) 以上であるかかを確認する.すべての閾値の精度と再現率を測定し,それらの値に
基づいて計算した F1 スコアの平均を評価指標とする.また,前述の proposal の重複問題
における本モデルの影響を調べるために,proposal のセットから可能なすべてのペアを比
較し,それらの重複を秒単位で測定し,得られた平均値を評価値とする.

5.5.2

実験設定

off-line の動画を C3D (Tran et al., 2015) の特徴量に変換し,dv = 500 で 8 フレームご
とに取り出す.動作認識には DBG (Lin et al., 2020) の ActivityNet による事前学習済みモ
デルを使用し,soft-NMS アルゴリズムによって選択された上位 100 個の proposal を入力と
して使用した.GRU と LSTM の隠れ状態のサイズは 512 で,dp = 100 とした.モデルは
最大 25 エポックで学習され,最適化手法には Adam を使用し,学習率は 4 × 10−4 とした.

5.5.3

ベースライン

I3D (Carreira and Zisserman, 2017) による特徴と比較する.また,ActivityNet Captions
(ANet Cap) の DVC タスクの proposal 抽出に 5.4.1 項で提案した手法を試行し, Mun et al.
(2019) の性能と比較する.

表 5.3: タイミング識別モデルの結果.
データセット

モデル

動画特徴量 Backend Props.

ANet Cap.
ANet Cap.

Original
提案手法

C3D
C3D

SST
DBG

提案データセット 提案手法
提案データセット 提案手法

I3D
C3D

DBG
DBG

F1

Overlap (s)

2.85
2.73

56.66
55.62

10.5

12.57
12.67

28.03
28.91

4.5
5.6

5.6. 一般ドメイン実況生成における発話生成実験

5.5.4

65

結果

表 5.3 に,Activity Net Captions dataset と本データセットのタイミング識別モデルの
結果を示す.ビデオごとの proposal の平均数(Props.)と,識別の F1 スコア(tIoU の閾
値 0.3、0.5、0.7、0.9 の平均 F1 スコア)
,proposal の平均的な重複 (Overlap) を示す.本
モデルの平均 F1 スコアは 28.91 であり,C3D の代わりに I3D を用いた場合,若干低下する
ことが分かる.F1 スコアは C3D が I3D を上回るが,proposal の重なりは C3D が上回り,
両者の間にトレードオフがあることが分かる.これは,特徴量のサンプリングレートの違
いにより,I3D を用いたモデルの方がより細かい時間粒度が得られるためと考えられる.
また、本タスクにおけるモデルの性能は,ANet Cap の平均 F1 スコアは 55.62 と比較し
て大幅に低い.この性能低下は本タスクが,モデルがより大きなセグメントのセットを選
択する必要があるため ANet Cap と比較して難易度が高いためと推測される.一方提案手
法は,比較的低いオーバーラップで一連の提案を出力できる.これは,ANet Cap の場合
よりも大幅に低いだけでなく,バックエンドモデル (DGB) の平均的な提案のオーバーラッ
プである 7.34 秒よりも低くなる.
このことは,提案したタイミング推定モデルは,TAL を本タスクに適用させる有効な手
法であることを示唆している.ただし,この手法は TAL モデルの学習に使用するアノテー
ションの性質によって精度が左右されうる.

5.6

一般ドメイン実況生成における発話生成実験

5.4 節で設定したサブタスクのうち,発話生成実験について述べる.

5.6.1

実験設定

I3D による特徴量は,前節の実験で C3D 特徴量よりも良い結果を得たため,本節でも I3D
を用いる.動画特徴量は, Rodriguez-Opazo et al. (2021) によって提供されている,25fps,
256 × 256 フレームを入力として,平均プーリングの I3D によって dv = 1024 サイズに圧
縮した, off-line 動画特徴量を用いる.Transformer ベースのモデルは dm = 512 を使用し,
バッチサイズ 8,最適化手法には最大学習率 10−4 ,エポックの 5%の線形アニーリングの
Adam を用いて学習する.これらの学習には,NVIDIA V100 GPU を4つ使用した.推論
時には,ビームサイズ 5 でビームサーチを行う.評価には BLEU-4 (Papineni et al., 2002)
を用い,異なるアノテーターのセグメントに対して個別に評価した.

5.6. 一般ドメイン実況生成における発話生成実験

66

表 5.4: モデル初期化の影響.

5.6.2

Encoder

Decoder

Random
Random
BERT-base
BERT-base

Random
BART-base Dec.
Random
BART-base Dec.

BLEU-4
2.11
1.66
2.07
2.26

結果

まず,エンコーダやデコーダを既存の学習済みモデルで初期化する影響を調べる.エン
コーダには BERT (Devlin et al., 2019) を,デコーダには BART decoder (Lewis et al.,
2020) で初期化する.表 5.4 に示すように,モデルコンポーネントの初期化に事前学習済み
のエンコーダーとデコーダーを同時に利用することで,大幅な性能向上が見込める.これ
らの結果を踏まえ,以降では,すべてのモデルコンポーネントを学習済みモデルで初期化
して使用した.
実況が動画のイベントと部分的にしか一致していないというタスクの性質を考慮し,モ
デルが正しい発話を生成するために,動画およびテキストの前後の状況(コンテキスト)が
どのくらい必要かを検討する.両方のモダリティにおいてモデルに与えるコンテキストの
量を制御する実験を行った.また,本発話生成モデルがクローズドメイン環境でどのように
機能するかを調べるために,Ishigaki et al. (2021) のデータで実験を行った.Ishigaki et al.
(2021) の raw 映像を 256 × 256 次元にリサイズし,Carreira and Zisserman (2017) が公開
している Kinetics データセットで事前に学習されたモデルによって,I3D 特徴を抽出した.
エンコーダの初期化には、日本語 BERT (Suzuki and Takahashi, 2021) 対応のトークナイ
ザーを用いた.また,このデータに対しても,動画・テキストのコンテキストの役割につい
て分析した.
図 5.6 はモデルに与える動画・テキストのコンテキストの量を制御する実験結果をまと
めたものである.図中、Y 軸は入力テキスト量,X 軸は入力動画像の時間間隔を表している
(順序は厳密ではないが,入力全体の長さと正の相関がある).例えば、(ts , te ) は,正解の
アノテーションセグメントから抽出した動画特徴を用いることを意味する.両データセッ
トにおいて,より多くのコンテキストがより良いパフォーマンスをもたらすという状態を
明確に観察することができる.また,片方のモダリティでより多くのコンテキストを使う
ことで,他方のモダリティの使用をある程度補うこともできている.また,発話の開始タ
イムスタンプより前の特徴のみを受け取る場合,モデルは一般的にあまり良い性能となら
なかった.これは、リアルタイム実況生成設定における待機/生成のトレードオフの重要性
を示唆している.

5.6. 一般ドメイン実況生成における発話生成実験

67

図 5.6: 一般ドメイン設定(上)と Ishigaki et al. (2021) によるクローズドメイン設定(下)
のモデルに与える動画・テキスト量を制御した実験結果
最後に,提案する発話生成モデルの性能を,Ishigaki et al. (2021) の性能と比較する.
Ishigaki et al. (2021) のアプローチもマルチモーダルモデルであり,入力は 1 秒ごとにキャ
プチャされた前 10 フレームの動画シーケンス,ゲームプレイから抽出された 10 セットの
構造化データ,および前時刻の正解発話とする.入力画像は ViT で符号化し,入出力テキ
ストは文字単位でトークン化し,全体モデルは LSTM を用いた seq2seq で構成されている.
表 5.5 から分かるように,本モデルは同程度の動画コンテキストのみを用いた場合(ts の 9
秒前と 10 秒前では,BLEU-4 で 10.35 と 7.46)
,大幅に優れた性能を達成できた.これは本
提案モデルと動画特徴量抽出手法が妥当であることを示していると考えられる.また,正
解の標準区間 (ts , te ) の動画特徴を入力した場合,性能は BLEU-4 で 13.96 まで向上するが,
ts 以前の映像を追加してもそれ以上向上しないことも確認した.モデルが追加の動画コン
テキストを活用できるのは,テキストコンテキストにもアクセスできる場合のみであり,最

5.7. まとめと今後の課題

68

表 5.5: ドメインの性質による精度比較.S,T,V はそれぞれ構造化データ,テキスト,動画
コンテキストを表す
ドメイン

モデル

一般ドメイン

提案モデル
提案モデル

V
V+T

1.24
2.38

提案モデル
提案モデル

V
V+T

13.96
18.42

V
S
S+T
S+T+V

7.46
23.39
23.86
24.01

クローズドメイン

Ishigaki et al. (2021)

利用データ

BLEU-4

終的に BLEU-4 スコアは最大の 18.42 となった.これは,入力動画セグメントのコンテン
ツと一致しないものを生成する必要があるときに,テキストコンテキストがモデルの決定
を助け,また以前に何がすでに言われたかを追跡するためであると考えられる.本モデル
と, Ishigaki et al. (2021) で最も良い結果である 24.01 のスコアを得たモデルを比較する
と,ドメイン内情報の使用が最も性能向上に寄与しており,実況生成においてドメイン内
情報の使用は重要であると言える.

5.7

まとめと今後の課題

本章では,一般ドメインの動画に対して実況を生成するタスクを提案した.これは,特
定の情報を利用することが可能なクローズドメインにのみ焦点を当ててきたこれまでの研
究を大幅に拡張するものである.さらに,ドメインを限らないオープンドメインの課題とす
ることで,ある事象に対して言葉の広がりを許容する課題となった.本課題は,新たに導入
したタスクのため,様々なドメインにおける人間の様々な行動を含む 6K 以上の動画と実況
テキストのデータセットを作成した.本章で提案した現在の手法の長所と限界を示す研究
とともに,本課題へのモデルを提案した.この結果を踏まえ,今後は Ishigaki et al. (2021)
による構造化データのようなドメイン固有の情報も取り込むことができるクローズドメイ
ン・マルチモーダル Transformer モデルを開発できると考えている.また,一般ドメイン
の実況生成には,最近 DVC に対して提案された end-to-end モデル (Wang et al., 2021) の
適用や,on-line 設定による課題解決に取り組むべきと考えている.
本章の実況は,動画の内容を正しく途切れることなく説明しているかを重視して収集し
ている.将来的には,人を惹きつけるような娯楽に寄った実況や,逆に動画内容の専門性

5.7. まとめと今後の課題
をより反映した実況なども考えられる.

69

70

第 6 章 実データを用いた data-to-text

本章では,非言語から言語を生成する課題として,実データを用いた data-to-text を扱
う.特に,日経平均株価データの概況テキスト生成に着目し,実データを用いた非言語か
ら言語を生成する課題において発生する問題について2つ取り上げる.それらの問題を解
決する手法について提案・実験し,評価する.

6.1

概要

金融や医療,情報通信などの多くの分野において,様々な形式の非言語データを取り扱
う機会が増えてきている.大規模で複雑なデータを専門知識のない人が解釈できるように,
データを説明するテキストを自動的に生成する技術の必要性が高まっており,近年は様々な
データを題材に,Encoder-Decoder モデルを用いて end-to-end の学習を行うことで,高い
生成性能を発揮している (Puzikov and Gurevych, 2018; Liu et al., 2018a; Iso et al., 2019).

data-to-text のデータセットは,実世界で獲得されたデータを用いたデータセットと,入
出力をコントロールして人手で作成されたデータセットが存在する.人手で作成されたデー
タセットの場合,データとテキストが過不足なく組み合わさっている. 一方、実世界で得ら
れたデータとテキストを使ってデータセットを作成する場合,データとテキストのアライ
メントは,人手によるアノテーションや,データとテキストに付随する他のデータによっ
て取得される.アライメントが不十分な場合,データとテキストの参照箇所に不整合が生
じ,それにより誤りが発生することがある (Taniguchi et al., 2019).また,人手で作成さ
れたデータセットの場合には入力データから出力テキストを推定可能であるように調節し
てデータセットを作ることができるが,実世界で得られたデータとテキストを使ってデー
タセットを作成する場合,入出力をコントロールできないため、入力データから出力テキ
ストを推定できない場合がある.その場合,入力から出力を推定できるように、例えばラ
ベルなどを用いて追加でデータを入力する必要がある.人手で作成されたデータセットと
実データを用いたデータセットはその課題の難易度も異なる.例えば,人手で作成された
データセットを用いた E2E NLG Challenge において,2023 年現在最も高い BLEU スコア
は Kale and Rastogi (2020) による 68.60 だが,実データを用いて作成された WikiBio の生
成課題では,同様の課題でありながら,最も高い BLEU スコアは Liu et al. (2018b) による
44.89 である.このことからも,難易度の差は明確であろう.本章では日経平均株価データ

6.2. 関連研究

71

からの概況テキスト生成を対象に,実データを利用する際に生じる問題について分析し,解
決策を探る.

6.2

関連研究

入力データを説明するテキストを生成するタスクは data-to-text と呼ばれ,さまざまの
領域で研究されている.例えば,時系列の気象情報から天気予報テキストを自動生成する研
究 (Belz, 2007; Angeli et al., 2010) や,臨床データから概況テキストを生成する研究 (Belz,
2007; Angeli et al., 2010),スポーツの試合データやスコア情報から試合内容をテキスト
生成する研究 (Liang et al., 2009) などが挙げられる.伝統的に,data-to-text は “what to
say(何を言うか)” の content selection と,“how to say(どのように言うか)” の surface
realization の 2 つのサブタスクに分けられる (Kukich, 1983; Goldberg et al., 1994).さら
に,Reiter and Dale (1997) は, micro planning をこの2つのサブタスクに加えて,3 つの
サブタスクとした.Data-to-text の初期段階では,主に surface realization のタスクに取り
組み,テンプレートを用いる手法 (van Deemter et al., 2005) や,人手で作成された特徴量
によって統計的に学習されたモデルを用いる手法 (Belz, 2008; Konstas and Lapata, 2012)
が提案された.
一方,近年では金融,製薬,通信など様々な業界で,様々な種類の大規模データを扱う機
会が増えており,データとテキストの大規模なペアデータを基に対応関係を自動的に学習
し,データの内容をテキストで生成する手法への関心が高まっている.特に,上記のサブタ
スクを一度に解決できるニューラルネットワークを用いた手法に注目が集まっており,その
中でも Encoder-Decoder モデルの利用が有用であるとされている (Mei et al., 2016; Lebret
et al., 2016).

Murakami et al. (2017) は Data-to-text の一タスクとして,日経平均株価の市況コメン
トを生成するタスクを取り上げ,時系列数値データから多様な特徴を抽出し,データの概
要をテキスト化する手法を提案した.市況コメントなどの時系列数値データの概況テキス
トでは,
「上がる」

「下がる」といった単純な特徴だけが表出されるわけではない.過去の
データの履歴や,テキストが書かれる時間帯によって言及すべき内容は様々である.また,
数値の時系列データの場合,時系列中の数値や,過去との差分を計算した値が言及されるこ
とが多い.株価の市況コメントにおけるこれらの特性を踏まえ,データから多様な特徴を
自動抽出し,テキスト化するためのエンコード/デコード手法を提案した.まず,
「続落」

「上げに転じる」といった時系列株価データの過去の履歴や変化を捉えるために,株価の短
期的および長期的な時系列データを使用した.次に,
「前引け」

「大引け」といった市況コ
メントが記述される時間帯に依存する表現を生成するために,デコード時に時刻情報を導
入した.
ニューラルネットワークによるテキスト生成は,流暢にテキストを記述できる反面,正確

6.3. 日経平均株価の概況テキスト生成

72

なエンティティーや数値を記述することはできない.そこで,入力から直接単語をコピーで
きるコピー機構 (Vinyals et al., 2015a; Gu et al., 2016) の利用により,表を基にした条件付
き言語生成 (Yang et al., 2017) や Wikipedia のインフォボックスからのバイオグラフィー生
成 (Lebret et al., 2016; Chisholm et al., 2017; Sha et al., 2018; Liu et al., 2018a),スポー
ツのスコアボードからの試合サマリーの生成 (Wiseman et al., 2017; Li and Wan, 2018;
Puduppully et al., 2019) などでは成果を上げている.しかし,コピー機構では入力に現れ
る表層的な内容しか生成できず,算術演算を必要とするコンテンツは生成できない.一方,
Joulin and Mikolov (2015) や Neelakantan et al. (2016) は,現在のニューラルモデルでは,
加算や比較などの算術演算をニューラルネットワークを用いた手法で学習することが困難
であると示している.市況コメントなどの数値の時系列データの内容を言及する場合,時
系列中の数値や,過去との差分を計算した値が言及されることが多い.そこで, Murakami
et al. (2017) は「19,386 円」,「100 円」といった株価の終値や前日からの変動幅などの数
値を市況コメントで言及するために,価格を算術演算に置き換えることで,時系列中の数
値や,過去との差分を計算した値の生成を行えるようにした.数値の出力は推定した演算
操作と入力の時系列株価データを用いて計算することで行う.次節では,Murakami et al.
(2017) について,詳しく説明する.

6.3

日経平均株価の概況テキスト生成

Murakami et al. (2017) は,Encoder-Decoder モデル (Sutskever et al., 2014) に基づい
て,日経平均株価データとその動きに言及しているニュースヘッドラインを例に,時系列
数値データから概況テキストを生成するモデルを開発した.

6.3.1

時系列株価データから市況コメントを自動生成するモデル

Murakami et al. (2017) は,概況テキストが発表された時刻を基準に,長期的な変動
を捉えるための直近 M 取引日分の終値データ xlong = (xlong,1 , xlong,2 , . . . , xlong,M ) と,
短期的な変動を捉えるために 5 分足で収集した株価データの直近の N 個の市況データを
xshort = (xshort,1 , xshort,2 , . . . , xshort,N ) を取得し,入力として用いる.2 種類のデータに対
して,それぞれ以下の前処理を適用する:
xstdi
xmovei
xnormi

xi − µ
,
σ
= x i − ri ,
2 × xmovei − (¯
xmax + x
¯min )
=
.
x
¯max − x
¯min
=

(6.1)
(6.2)
(6.3)

1 つ目は式 (6.1) で表される平均値と標準偏差を用いて標準化する手法であり,2 つ目は,前
日の終値からの価格の変動を捉えるために,式 (6.2) によってそれぞれの入力データに対し

6.3. 日経平均株価の概況テキスト生成

73

て前取引日の終値 ri からの差分を計算し,差分の最大値 x
¯max ,最小値 x
¯min を用いて,式
(6.3) によって [−1, 1] へ正規化を行う手法である.これらの前処理を,xlong および xshort
move
std
move
に適用し,得られたベクトルをそれぞれ xstd
long ,xlong ,xshort および xshort とする.
エンコーダーでは,multi-layer perceptrons (MLP)1 を用いて,それぞれ以下を得る:

[
]
move
hlong = MLP(xstd
long ); MLP(xlong ) ,
[
]
move
hshort = MLP(xstd
short ); MLP(xshort ) .

(6.4)
(6.5)

これらを結合し,市況データをエンコードした隠れ状態 m を得る:

[
]
m = Wm hlong ; hshort + bm .

(6.6)

デコーダは LSTM を用い,デコーダの初期値 s0 として,前述した隠れ状態 m を用いる.
時刻 t におけるデコーダの隠れ層の状態 st は,ニュースヘッドラインの配信時刻 (9 時や 13
時などの 1 時間刻みの数値) を埋め込んだ時間帯情報埋め込みベクトル t と,直前の単語埋
め込み wt−1 ,直前の隠れ層の状態 st−1 を用いて次のように計算される:

si = LSTM([t; wi−1 ], si−1 ).

6.3.2

(6.7)

数値の汎化演算タグ

概況テキストでは,市場価格そのものや、差分や丸めなどの算術演算を行った数値が記
述されることが多い.このような演算を伴う数値をデコード時に生成できるようにするた
めに, Murakami et al. (2017) では演算タグ (表 6.1) を導入し,値を得るためにどの演算
を行うべきかを指定している.デコーダが汎化タグを生成すると、モデルはそのタグを対
応する算術演算によって得られた値に置き換え,最終的に数値を含むテキストを生成する.
Murakami et al. (2017) では,最後のタイムステップの価格 xshort,1 を z ,前日の終値 xlong,1
と z の差を ∆ とする.以下の文章を例に,学習データのテキスト演算タグを用いたの前処
理方法を説明する.

(a) 日経平均、続伸で始まる。9 円高の 17024 円
前処理では,まず表 6.1 中の全ての算術演算を行い,各演算タグに対応する数値を計算す
る.例えば,テキスト (a) が配信された時刻を基準として,前日の終値 xlong,1 が 17,015,最
新の価格 xshort,1 が 17,024 の場合,演算タグに対応する数値は「9」となる.
次に,各演算タグに対応する数値とテキスト (a) 中の数値「9」,「17,015」を比較し,テキ
1
Murakami et al. (2017) では,MLP,RNN,convolutional neural networks (CNN) および long short-term
memory networks (LSTM) を比較実験した.MLP を用いた場合に最も精度が良かったため,本論文では MLP
を用いる.

6.4. 参照時間の不整合

74

表 6.1: 演算タグと対応する算術演算.
演算タグ














算術演算

∆ を返す
∆ を 10 の位で切り下げ
∆ を 100 の位で切り下げ
∆ を 10 の位で切り上げ
∆ を 100 の位で切り上げ
z を返す
z を 100 の位で切り下げ
z を 1,000 の位で切り下げ
z を 10,000 の位で切り下げ
z を 100 の位で切り上げ
z を 1,000 の位で切り上げ
z を 10,000 の位で切り上げ

スト (a) の数値それぞれに最も近い数値を計算した演算タグを求める.最後に導出した演
算タグで正解の数値を置換して,以下の前処理済みテキスト (b) を獲得する.
(b)日経平均、続伸で始まる。円高の
数値を含むテキストを生成する場合,まずデコーダーによってテキスト (c) のような演算
タグを含むテキストが生成される.

(c) 日経平均、反落で始まる。下げ幅円超、円台
この時前日の終値 xlong,1 が 14,612,最新の価格 xshort,1 が 14,508 の場合,
演算により「100」, は「14,500」と計算される.これらの数値でテキスト
(c) の演算タグを置換して,最終的な数値を含むテキスト (d) が出力される.

(d) 日経平均、反落で始まる。下げ幅 100 円超、14, 500 円台 

6.4

参照時間の不整合

Murakami et al. (2017) は,概況テキストが発表された時刻を基準に,長期的な変動を捉える
ための直近 M 取引日分の終値データ xlong = (xlong, 1 , xlong, 2 , . . . , xlong, M ) と,短期的な変動
を捉えるために 5 分足で収集した直近の N 個の市況データ xshort = (xshort, 1 , xshort, 2 , . . . , xshort, N )
を取得し,入力とした.そのため,記事が発表された時刻(以降,配信時刻)と記事を作成

6.4. 参照時間の不整合

75

した時刻(以降,参照時刻)の不整合は無視されてきた.例えば,図 6.1 に示した(I)か
ら(III)の文章は,全て 1 月 29 日 9 時を参照時刻とする概況テキストであり,概況テキス
トでの動向内容と参照時刻での値動きは一致している.(I)は,配信時刻と参照時刻が同じ
ため,概況テキストの動向内容と記事の配信時刻を基準とした値動きは一致している.一
方,(II)および(III)では,配信時刻と参照時刻が異なるため,概況テキストの動向内容
と配信時刻での値動きは異なっている.
そこで,テキストが発表された時刻の直近のデータだけでなく,それ以前の時間帯で取
得できるデータを用いて,参照時刻の不整合解消を目指す.また,データの傾向と時間帯
の情報から,参照時刻を取得する機構を組み込むことで,精度向上に取り組む.

配信時刻
(I) 09:00
(II) 09:05
(III) 09:19

配信時刻の値動き

概況テキスト(動向内容)

反発,86 円高
反発,22 円高
続落,2 円安

日経平均、反発で始まる 86 円高
日経平均、反発で始まる 86 円高、原油高を好感 トヨタ高い
東証寄り付き、反発 原油高を好感、ファナックは大幅安

図 6.1: 日経平均株価の値動きと,1 月 29 日 9 時を参照時刻とする概況テキスト.

6.4.1

Multi-timestep 構造と Copy 機構を用いたテキスト生成

Murakami et al. (2017) は,タスクを単純化するため参照時刻と配信時間が同一であると
いう仮定を置き,基本的なエンコーダ・デコーダの構造を持つモデルを提案している.し
かし、実際の参照時刻と配信時刻の間には時間差があるため、この仮定は現実的ではない.
そこで、このようなアライメントによる問題を解決するために,Multi-timestep 構造を導
入し,モデルを拡張する.図 6.2 にその概要を示す.先行研究の時間差による情報不足を補
うために,概況テキストが発表された時刻から取得できる直近のデータだけでなく,それ

6.4. 参照時間の不整合

76

図 6.2: 提案モデルの全体概要図.
以前の時刻で取得できるデータを入力に追加する.各追加ベクトルは、配信時刻の代わり
に k 前のタイムステップから始まる xshort に相当する.これにより、実際のイベント時刻
を潜在変数として扱うことができる.その上で、データの傾向と時間帯の情報から,参照
時刻を取得するできるように,デコーダにアテンション付き Copy 機構を導入し,ノイズの
ある学習データからデータとテキストの対応関係を容易に学習できるようにする.

Multi-timestep Encoder
入力を長期的な変動を捉えるための直近 M 取引日分の終値データ xlong と,短期的な
変動を捉えるための 5 分足で収集した市況データの直近 N 個の数値 x0 に加え,1 ステッ
プ前から n ステップ前に取得できる各 N 個の数値 x1 ,. . . , xn とする.Murakami et al.
move
std
std
std
(2017) と同様に,各入力に前処理をおこない,xstd
long ,xlong ,x0 ,x1 ,. . . ,xn および
xmove
,xmove
,. . . ,xmove
を得る.これらのベクトルにそれぞれ MLP を用いて,hlong と,
n
0
1
h0 , h1 ,. . . , hn を得る.

xk の重要度を得るために,新たな埋め込みベクトル a,fk と,時間帯情報埋め込みベク

6.4. 参照時間の不整合

77

トル t を導入する.a は概況テキストの種類に関するタグ2 ,fk は xk の最新値が取得され
た5分間隔の時刻を表す.重要な xk˜ は,市況データの価格変動(hk˜ )もしくは,配信時間
(fk˜ )のどちらかで主に決定されるが,概況テキストの種類 a と時間帯 t によって,そのど
ちらを用いるかは異なる.例えば,配信時刻が市場の開始時刻と同じ 9 時で,決まった時刻
に配信されるコメントの場合,コメントは「日経平均、15,430 円で始まる。
」のように,通
常 9 時の価格に言及する.この場合,重要な xk˜ は主に fk˜ でエンコードされた時間によっ
て決定される.つまり,決まった時刻に配信されるコメントの場合,配信時間の変動に関わ
らず,参照時刻はむしろ固定されている.一方,配信時刻が市場の開始時刻と同じであっ
ても,決まった時刻に配信されるコメントではない場合,単なる 9 時時点の価格ではなく,
例えば「前日の終値より 100 円以上高くなった。
」のように,何か特徴的な値動きについて
言及する.この場合,重要な xk˜ は価格変動(hk˜ )によって決定される. 
まず,hk (k = 0, 1, . . . , n) をそれぞれの xk の最新値が取得された時刻 fk と結合し,さらに,
時間帯情報埋め込みベクトル t と,概況テキストの種類に関するタグ a を結合して MLP を
行う.その結果で softmax することで xk の重要度を表す αk を得る.

e = MLP ([t; a; f0 ; h0 ; . . . ; fn ; hn ]) .

αk = exp(ek )/

n


exp(ej ).

(6.8)

(6.9)

j=0

得られた αk と用いて,hshort は

hshort =

n


αk hk .

(6.10)

k=0

のように,hk (k = 0, 1, . . . , n) の加重和とし,式 6.6 と同様に,エンコードした隠れ状態 m
を hlong と hshort から得る.

[
]
m = Wm hlong ; hshort + bm .

(6.11)

これをデコーダの初期値 s0 として用いる.

Copy 機構を用いた Decoder
Murakami et al. (2017) は,演算タグに最後のタイムステップの価格 xshort,1 と前日の終
値 xlong,1 のみを単純に用いた.この単純化では、配信時刻とイベント時刻の不一致の可能性
が無視され,その結果,参照時刻での数値とは異なる数値が生成される.そこで、参照時刻
を予測して表 6.1 の操作でデコード時に各数値を適切に生成できるように,Copy 機構 (Gu
2

決まった時刻に配信されるコメントと,それ以外の2種類

6.4. 参照時間の不整合

78

et al., 2016) を導入し,モデルを拡張する.具体的には,各 xk の最初の値(最新の価格)
であるデータ点 xk,1
˜ を用いて計算され,数値演算は各 (o, k) に対して o ∈ {op1 , · · · , op12 }
で表す.数値の生成は,(o, k) の選択と演算の実行にとどめる.
˜ によって決まる,数値の確率分布を求める.このとき、(o, k) の組が複数存在し,同
(o, k)
じ値になる可能性がある.例えば,ある入力 xk,1
˜ = z = 3200 の場合,op6 と op7 ,op10 は
全て同じ値(3200)となる.
実際には,生成する数値 wi は Attention 機構によって得られたエンコーダの重み αk に
従って (o, k) のスコアの重み付き和 o(xk,1
˜ ) = wi である.
一般的な Copy 機構とは異なり,デコーダー全体で固定の Attention 重み αk を用いる.
これは,生成目的のヘッドラインテキストは言及する事柄が1つのテキストを通して変化し
ないためである.つまり,重要な xk は1つの概況テキスト中で変化することはない.我々
のモデルは、この Copy 機構によって、テキスト中のすべての数値を生成する。そのため
に、モデルのボキャブラリーから数値を除外する。コピーモードと非コピーモードを切り
替えるために、学習データのすべての数値の前に挿入され、次のトークンが価格値である
ことを示す特別なトークン “” を追加する.これにより,“” の次の
単語が数値であることを示す.“” を利用して,時刻 i に対象単語 wi が生成さ
れる各条件付き確率を次のように定義する:
{
pcopy (wi |w”)
(6.12)
p(wi |w pgen (wi |w この時,pgen (wi |·) は generation mode から,pcopy (wi |·) は copy mode からそれぞれ得ら
れる.この手法は, See et al. (2017) によって提案された Pointer-generator network を参
考にした.pgen (wi |·) と pcopy (wi |·) は次のように定義する:

pgen (wi |·) = [softmax(Wv vi + bv )]wi

˜ o)
pcopy (wi |·) =
q(k,

(6.13)
(6.14)

˜
k,o:o(x
˜ )=wi
k,1

˜ o) = αk · [softmax(Wc ci + bc )]o .
q(k,

(6.15)

vi と ci はどちらも LSTM の i 目の出力 si で次のように定義される:
si = LSTM([t; wi−1 ; qi−1 ], si−1 )

(6.16)

v i = Wh s i + b h

(6.17)

ci = MLP(si ).

(6.18)

t は 6.3.1 節で定義した通り,時間帯情報埋め込みベクトルである.式 (6.7) の LSTM に qi
˜ o) である.このベクトルを追加することで,算術演算結果を
を追加しており,各 qi は q(k,
si に直接保持させずに適切に伝播させることができる.

6.4. 参照時間の不整合

6.4.2

79

実験設定

データセット
実験には,時系列データとして,Thomson Reuters DataScope Select3 から,2010 年 12
月から 2016 年 9 月までの期間の日経平均株価指数の時系列データを収集し,実験に使用し
た.概況テキストとして,日経 QUICK ニュース社が提供している日経平均株価に言及して
いるニュース記事のヘッドラインを使用した.2010 年 12 月から 2015 年 9 月の期間のデー
タを学習データ(15,035 件),2015 年 10 月から 2016 年 3 月の期間のデータを開発データ
(1,759 件),2016 年 4 月から 2016 年 9 月の期間のデータを評価データ(1,695 件)として
使用した.実験に使用したデータについて,概況テキストに日経平均株価の数値の動向を
説明する表現4 が含まれているか,含まれている場合には,その表現と取得したデータの数
値の動向が一致しているかを調査した.その統計値を表 6.2 に示す.
表 6.2: 使用したデータの統計値

Movement 動向表現
データ種類
学習データ
開発データ

なし

3,522
378

合計

あり
一致

不一致

11,172
1,346

341
35

15,035
1,759

実験設定

5 分足で収集した記事配信時刻直近の 62 個の市況データ Xshort-latest ,直近 7 取引日分の
終値データ Xlong ,および概況テキストのペアを使用する.また記事配信時刻以前のデータ
として,1 ステップ前 Xshort-1step から 6 ステップ前 Xshort-6step までを段階的に用いる.な
お,時系列株価データからテキスト中で言及された価格を適切に出力するために,Murakami
et al. (2017) と同様に,概況テキスト中の数値表現を演算タグに置換した.株価等の時系
列数値データをベクトルへ変換する各 MLP の隠れ状態の次元は 256,これらの隠れ状態
を結合した後,線形変換により次元を 256 とした.デコーダは1層の LSTM で,隠れ状態
の次元は 256,単語埋め込みベクトルの次元は 128,時間帯情報埋め込みベクトルの次元は
64,時刻情報埋め込みベクトル fk の次元は 80, 記事タグ埋め込みベクトル a の次元は 64
とした.各パラメータの最適化手法には Adam (Kingma and Ba, 2015) を使用し,学習率
は 1 × 10−4 とした.ミニバッチサイズは 100,エポック数は 150 とし,学習時に開発デー
3
4

https://hosted.datascope.reuters.com/DataScope/
上方向の動向:
「続伸,反発,上げ」,下方向の動向:「続落,反落,下げ」

6.4. 参照時間の不整合

80

タで計算された BLEU が連続して下がった場合には学習を終了し,各エポックのモデルの
中で,開発データに対する BLEU が最大となったモデルを使用して,評価を行う.

6.4.3

評価方法

評価指標には,実際の株価の概況テキストと生成されたテキストの一致度合いを測る目
的として BLEU (Papineni et al., 2002) を使用する.また,正解概況テキストおよび生成
した概況テキストの,日経平均株価の短期的・長期的な動向を説明する表現と,配信時刻直
近の数値データの動向の一致・不一致を取得して評価する方法を新たに提案する.
gold

pred

開発データの i 番目の事例とモデルの生成文を合わせて (xi , wi , wi
うに定義する:


 上方向 (w ∈ { 続伸,反発,上げ })
movetext (w) =
下方向 (w ∈ { 続落,反落,下げ })

 なし
(otherwise)


 上方向 (x の直近の数値動向 > 0)
move(x) =
下方向 (x の直近の数値動向 < 0)

 なし
(otherwise)

) とし,次のよ

Cgold = {i|movetext (wigold ) = move(xi )}
Cpred = {i|movetext (wipred ) = move(xi )}
Dgold = {i|movetext (wigold ) ̸= move(xi )}
Dpred = {i|movetext (wipred ) ̸= move(xi )}
これらを用いて,次の式により評価する:
一致precision

=

一致recall

=

不一致precision

=

不一致recall

=

|Cgold ∩ Cpred |
|Cpred |
|Cgold ∩ Cpred |
|Cgold |
|Dgold ∩ Dpred |
|Dpred |
|Dgold ∩ Dpred |
.
|Dgold |

この評価指標は,モデルが配信時刻直近の数値データの動向だけでなく,それ以前のステッ
プにアノテーションする能力の評価と見なすことができる.データセット中の概況テキス
トの動向表現と配信時刻直近の数値データの動向の一致・不一致の統計値を表 6.2 に示す.

6.4. 参照時間の不整合

81

BLEU による評価は開発データおよび評価データに対して行い,概況テキストの動向表
現と数値データとの比較による評価は開発データに対して行った.なお,学習時の seed を
0,5,10,50,100,500 の 6 種類とし,各モデルによる評価結果の平均を 6.4.4 節の実験
結果として用いた.

6.4.4

実験結果

表 6.3: BLEU (%)

ベースライン

開発

評価

開発

評価

開発

評価

21.37

21.30

-

-

-

-

Multi-timesteps
n=0
21.63
1
21.59
2
21.64
3
21.82
4
21.68
5
21.73
6
21.73

22.66
22.74
23.03
23.11
22.92
22.89
22.66

+Attention
21.33 22.38
21.43 22.25
21.20 22.47
21.02 21.94
20.59 21.71
20.71 21.74
20.51 21.62

+Copy
28.16 28.68
27.90 28.54
28.31 28.98
27.29 27.75
28.13 28.93
27.29 27.78
26.68 27.25

BLEU での評価結果を表 6.3 に,動向一致・不一致による評価結果を表 6.4 に示す.表 6.3
によると,提案手法のうち,Copy 機構を導入した場合にほとんどの場合ベースラインを上
回った.評価データセットでは,全ての場合でベースラインを上回った.特に,Copy 機構
を用いた n = 2 の場合に最も高いスコアとなり,ベースラインと比べて 7.68 ポイント高く
なった(表 6.3 の bold テキストを参照のこと).一方で,デコーダはベースラインと同じ
にし,エンコーダに注意を加える(+ Attention)だけでは,効果がないことも示している.
以上により,Attention 機構を適用しただけでは,データとテキストの対応関係を正しく得
ることはできないが,Copy 機構を適用すれば,対応関係を正しく得ることができることが
わかる.なお n = 0 から 6 の結果を比べると,大きくポイントが変わらないことから,ス
テップ数を増やしても必ずしも BLEU スコアの向上には寄与しないと言える.
さらに表 6.4 によると,提案手法のほとんどがベースラインを上回った.しかし,BLEU
での評価と同じく,ステップ数の増加はスコア向上に寄与しない.図 6.3 はコメント配信
時刻とイベント発生時刻の時間差に関する分布である.まず,データセット中の人間が書
いた市場コメントを,正規表現を用いることで定時刻のコメントか(Regular )そうでな
いか(Irregular )に分類した.定時刻のコメントの場合,その事象の発生時刻とコメント
配信時刻の時間差を 5 分単位で,例えば、0 = 0 分∼5 分のずれ、1 = 5 分∼10 分のずれで

6.4. 参照時間の不整合

82

図 6.3: コメント配信時刻とイベント発生時刻の時間差に関するデータ分布.
分類した.つまり,図 6.3 では n = 5 を用いた場合、学習データで 89.05%、検証セットで
94.07%の時間差データ(図 6.3 の Irregular 値と 0 5 の合計)をカバーしていると示してい
る.しかし,xk を多く使用するとその分ノイズが多くなるため,トレードオフの関係であ
る.表 6.3,表 6.4 および図 6.3 より,n = 3 または n = 4 を用いて,約 80% をカバーす
ることが,このデータセットでは最適な選択と考えられる.
表 6.5 に生成結果の例を示す.提案手法では,Gold のテキストと同じく,動向表現が最
新の数値を使った場合と一致しない表現が生成できた.さらに,Copy 機構を用いた場合に
は,数値を正しく生成できている.一方,流暢さには問題が残っている.例えば,“XX 円台
後半” という表現の場合,XX は 100,1,000 もしくは 10,000 などの丸め込んだ数値となる
のが自然である.しかし生成された数値は丸め込んだ数値ではなかった.動向表現は Gold
と同様の表現ができる一方,数値生成には問題が残っている.

6.4. 参照時間の不整合

83

表 6.4: 開発データでの動向一致・不一致評価 (%, P=precision, R=recall)
一致

P
Baseline
98.68

98.78

27.57

24.72

Multi-timesteps
n = 0 98.61 98.94
1
98.77 99.02
2
98.79 98.47
3
98.82 98.61
4
98.88 98.86
5
98.88 98.91
6
98.80 98.70

41.00
46.03
40.66
43.12
46.58
44.13
41.88

33.93
40.52
46.13
46.20
47.05
43.47
43.43

一致

P
n=0
1
2
3
4
5
6

98.90
98.76
98.99
98.93
98.80
98.69
98.70

R

不一致
P
R

R

不一致
P
R

+Attention
99.08 51.35
99.28 56.83
98.78 45.00
98.87 44.65
98.44 30.60
98.14 27.88
97.11 25.54

45.28
41.91
49.74
46.25
36.29
34.92
38.74

一致

P
98.85
98.81
98.71
98.73
98.68
98.57
98.46

R

不一致
P
R

+Copy
99.25 53.90
99.02 45.86
99.06 47.08
98.95 45.38
98.68 36.46
98.57 34.04
98.81 32.35

42.61
39.80
38.56
38.79
36.06
31.54
26.17

6.4. 参照時間の不整合

84

表 6.5: 直近の5分足と前日の終値との差が-48.91 円の生成テキスト例.
モデル

生成テキスト

正解文

日経平均、続伸で始まる 9 円高の 17024 円

ベースライン 日経平均、反落で始まる 16900 円台
Multi-timesteps
n=3
日経平均、小幅続伸で始まる

動向との一致

×

×

+Attention

日経平均、小幅続伸で始まる 

×

+Copy

日経平均、小幅続伸で始まる 17024円台後半

×

6.5. 予測不可能な属性

6.5

85

予測不可能な属性

Data-to-text のデータセットは実世界で得られたデータとテキストの組み合わせによって
作られるものと,実世界を模して,つまり擬似的に入出力を想定してデータやテキストを獲得
して作られるものがある.実世界を模して得られたデータセットとは,例えばクラウドソー
シングによってデータやテキストを獲得して作成されたデータセットである.このような
データセットは,入出力をコントロールして作成されている.例えば,E2E チャレンジデー
タセット (Novikova et al., 2017) の出力テキストは入力の Meaning Representation(MR)
をすべて言及するように作られている. また ToTTo (Parikh et al., 2020) は wikipedia の
テーブルをハイライト付きで与えて,1文章を生成するタスクのためのデータセットで,入
力となるデータを目的のテキストに合わせて作成してるデータセットと言える.
一方,実世界で得られたデータとテキストで作られたデータセットの場合,データやテキ
ストをそのまま利用するため,目的のテキストに合わせて入力データをコントロールできな
い.そのため,入力データから出力テキストを完全に推定できないことがある.Rotowire は
実データを用いた data-to-text のデータセットの一つである.Rotowire データセットを提
案した Wiseman et al. (2017) では,データをそのまま利用していたが,その後の研究 (Saleh
et al., 2019; Iso et al., 2019; Gong et al., 2019) では,出力テキスト生成をコントロールす
るために,入力データにはない予測不可能な属性である筆者情報を用いることで,content
selsction や correct order の精度が高くなり,生成精度が向上している.このように,実デー
タを用いた data-to-text では入力データからは予測できない属性に関する情報を追加する
ことで精度向上が見られる.
日経平均株価の概況テキストは時系列データに対して逐次作成されるテキストであり,
6.4 節に示したように,noisy なデータセットである.一方,実データを用いたデータセッ
トであるため,より実用に近い課題のデータセットである.逐次作成される市況データコ
メントは,同じ市況データを見ていても媒体によって書き方が違っていたり,市況の状態
に応じて作成される文章か,決まった時刻に作成される定時文章か,そして,今の状況のみ
を反映して作成される速報か,今後の状況まで反映して作成される文章かによって,言及
内容や文体が変わる.専門家はそれらを反映した文章を書いており,投資家もそれが反映
された文章を利用する.つまり,データセットのテキストは媒体やシチュエーションを反
映して書かれた文章である.そこで,先行研究で用いられているデータセットの入力デー
タと出力テキストとの関係性を分析し,テキストの推定に必要な追加入力ラベルを提案す
る.また,追加入力ラベルの追加タイミングについても再検討し、妥当な追加タイミング
について提案する.

6.5. 予測不可能な属性

6.5.1

86

データセット分析

ここでは先行研究 (Murakami et al., 2017; Aoki et al., 2018) で用いられたデータセッ
トについて,データセットの作成手順を説明し,それによって発生する問題を挙げ,分析
し,解決策を探る.

データセット作成手法

Murakami et al. (2017) で作成したデータセットは日経平均株価と,日経平均株価につい
て言及しているニュース記事のヘッドラインを使用した.日経平均株価は非常に短い時間
間隔(15 秒)で変動しているが,この数値データをそのまま用いると非常に多いデータ量
となるため,一般的にはより大きい間隔で区切って使用する.今回使用したデータは5分
間隔に区切ったデータ,つまり 5 分足データを用いる.この時,各間隔の代表値は区切った
時刻の最後の値を用い,その代表値からなる新しい時系列データが作成される.なお,この
ような間隔分割処理は,入力データが連続的である場合には珍しくなく,このデータセッ
ト固有の問題ではない.このように作成した時系列データを用いて,概況テキストと組み
合わせてデータセットを作成する.6.4 節で述べた通り,概況テキストにはその記事が配信
された時刻が付与されており,その時刻を基準に入力データとテキストを組み合わせてい
る.そのため,本データセットでは,ある 5 分間に複数の概況テキストが配信された場合
には,それらの入力データは同じになる.実際,検証用データセットにはり合計 1,751 件の
入出力データセットのペアが存在するが,入力データの種類は 1,176 種類にとどまり,1 対
多のアライメントが存在していることがわかる.また,データセットに含まれる概況テキ
ストには,日経平均,もしくは,東証で始まるテキストの2種類があることやある程度決
まった時刻(定時刻)に配信されるテキストが存在することも分かっている.

同じ入力データで整列した複数の概況テキストの比較
表 6.6 に,同じ入力での概況テキストの例を示す.定時刻に配信されたある概況テキス
トを基準(Pivot comment)とし,同一入力データの他の概況テキストと比較する.その結
果,他の概況テキストは少なくとも次の 4 つの点で Pivot comment と異なっていることが
分かる:

Content order: 概況テキスト中の内容表現の順序が異なる.
Lexical choice: 内容は同じだが,表現方法(単語)が異なる.
Informativeness: 情報量が異なる.
Others: 上記以外
表 6.6 は一例だが,表に記載されている違いは一般的なものである.

6.5. 予測不可能な属性

87

表 6.6: 同じ入力データで異なる概況テキストの例.
違いの種類

概況テキスト例

(Pivot comment)

日経平均、続伸で始まる。9 円高の 17024 円

Content order
Lexical choice
Informativeness
Others

日経平均、9 円高の 17024 円で続伸して始まる。
日経平均、続伸で始まる。始値は 9 円高の 17024 円
日経平均、続伸で始まる。
日経平均、上げ幅 100 円 超える。

差異を生む要因
対象のデータに含まれる概況テキストの中には,9 時,10 時,11 時 30 分,12 時 30 分,
14 時,15 時などある一定の時間帯の市場の状況を反映しているものがある.これは regular
reports である.一方,それ以外の概況テキストは,報告すべき事象が発生したときに発信
される prompt reports である.また,今回のデータセットには,
「日経平均」で始まるテキ
ストと,
「東証」から始まるテキストの 2 つの異なる書き方がある.検証用データセットで
は,62.70%の概況テキストが「日経平均」で始まり,その他は「東証」で始まる.さらに,
あるテキストは特別なトークンである ♦ から始まっており,このテキストが重要なテキス
トであることが示されている5 .これら3つの属性を regular/prompt , writing style ,およ
び supposed-importance とする.次節以降,これらの属性が概況テキストにどのような影
響を与えるかを検証する.

情報量の分析 概況テキストの長さは,概況テキストに含まれる情報量と相関があると考え,
概況テキストの平均的な長さを分析した.その結果,
「regular」概況テキストの平均トークン
数は 8.04,
「prompt」概況テキストの平均トークン数は 6.14 となり,
「regular」概況テキスト
の方がより詳細な情報を含んでいることが分かった.これは,通常の概況テキストの方がよ
り詳細な情報を含んでいることを意味する.同様に,♦ から始まる “supposed-importance”
概況テキストの平均トークン数は 8.21 であり,そうでない概況テキストの平均トークン数
は 7.24 であった。このことから,“supposed-importance” 概況テキストの方が情報量が多
いことが分かる。また, writing style は,
「日経平均」で始まる概況テキストの平均トーク
ン数が 7.96 であったのに対し,
「東証」で始まる概況テキストの平均トークン数は平均 6.99
個だった.このことから,
「日経平均」で始まる概況テキストの方が,
「東証」で始まる概況
テキストよりも情報量が多いことが分かる.

5

前処理時に削除されるため,生成は行われない.

6.5. 予測不可能な属性

88

内容と順序 時間表現を「TIME 」
,株価表現を「PRICE」
,株価変動表現を「MOVE」とし,概
況テキスト中の内容(TIME,PRICE,MOVE)とその順序を検証した.例えば,「日経平均、
続伸で始まる。17024 円の 9 円高」 は,[TIME, MOVE, PRICE, PRICE, MOVE] と置き換え
られる.
「regular」
概況テキストでは,
[MOVE, TIME, PRICE, MOVE, PRICE] が最も多く (17.23%),
次いで [TIME, MOVE] が多かった (16.34%).一方,
「prompt」テキストでは,[MOVE, PRICE]
が最も多かった (56.54%).「regular」テキストには TIME が含まれるが,臨時テキストに
は含まれない.“supposed-importance” 概況テキストには,[MOVE, TIME, PRICE, MOVE,
PRICE] が最も多く 35.65%を占めている.そうでないテキストには [MOVE, TIME, PRICE,
MOVE, PRICE] が 1,103 のうち 1 文に留まった一方,[TIME, MOVE] が最も多かった (19.95%).
regular/prompt テキストや,“supposed-importance” テキストかそうでないかの概況テキ
ストの違いは,TIME の有無や位置が異なると分かる.

writing style に着目すると,
「日経平均」で始まる 21.22%の概況テキストは [MOVE, TIME,
PRICE, MOVE, PRICE] となり,次いで 20.77%のテキストが [MOVE, PRICE] であった.一
方,
「東証」で始まる概況テキストにはこの両方がなく,最も多い内容とその順序は [TIME,
MOVE] で 28.79%を占めている.
語彙選択の分析 語彙選択の違いについて検討した. 表 6.6 の 3 番目の例では,”始値”と
いう表現が含まれているが,これは Pivot コメントには含まれていない.この 2 つのコメ
ントのような語彙選択の違いは,入力データからは捉えられないことが多く,予測できな
い属性に依存することがある.

属性予測による分析 最後に,これらの属性が市場価格データから予測可能かどうかを検
討した.表 6.7 にその結果を示す.
表 6.7: 属性予測(%)
.ベースラインは各属性の多数派がデータセットで占める割合
属性

regular/prompt
writing style
supposed-importance

ベースライン

精度

76.87
62.70
62.99

78.62
73.39
65.87

分類には, 6.5.3 の生成モデルの encoder として Murakami et al. (2017) が使用した
encoder と softmax 層からなる分類器を使用した.「regular」テキストがデータセット中で
占める割合が 76.87%(残りが「prompt」テキスト)であり,本実験の属性予測において,
regular/prompt の分類精度は 78.62%であった.regular/prompt 分類器が多数派のベース

6.5. 予測不可能な属性

89

ラインより優れていないことを示唆する.また,“supposed-importance” 概況テキストの
分類予測精度は 65.87%であり,“supposed-importance” でない概況テキストがデータセッ
ト内で占める割合の 62.99%から大きな差はない.一方,writing style の属性予測の精度は
73.39%で,大多数を占める「日経平均」で始まる概況テキストの割合 62.70%を上回った.
しかし,これは「東証」から始まる概況テキストは,その全てが「regular」テキストであ
り,時間と強く関連しているためと考えられる.「regular」テキストが参照する各時刻から
10 分後までの範囲に絞って属性予測を行ったところ,精度は 65.96%であり,ベースライン
と大きな差はなかった.
これらの結果から,属性はほぼ予測不可能であることが示唆され,今回の3つの属性に
由来する概況テキストの差異は,入力された株価の系列からは捉えることができない.

6.5.2

ラベルを用いた概況テキスト生成

6.5.1 項での分析結果を受け,本項では実験の準備として予測不可能な属性の情報をどの
ように概況テキスト生成モデルに統合するかを説明する.まず,予測できない属性を表す
ラベルとして,writing style と importance を定義する.そして,これらのラベルを追加情
報としたモデルについて説明する.なお,本実験の目的は,新しい概況テキスト生成モデ
ルを提案することではなく,予測不可能な属性の影響を示し,そのような予測不可能な属
性は入力の一部として与えられるべきであることを主張することである.

分類ラベルの設計

6.5.1 項では,概況テキストの違いには,
「regular」テキストか「prompt」テキストか,
「日経
平均」から始まるか「東証」から始まるか,元のテキストが ♦ から始まっている “supposedly
important” のテキストかどうかなどがあることを指摘した.このように概況テキストの差
異要因である,予測できない属性を反映させて作成したラベルを表 6.8 に示す.Murakami
et al. (2017); Aoki et al. (2018) のモデルで導入されている各時間の time ラベルに加え,
新たに writing style と importance の2つのラベルを作成した.
writing style ラベルは,6.5.1 項で分析した文体属性のを示しており,日経平均と,東証の
2 つのうちどちらかの値を持つ.
importance ラベルは新たに定義するラベルで,
「regular」テキストか「prompt」テキストか
の属性と,“supposedly important” テキストかどうかの属性の2種類の属性を組み合わせた
ラベルである.つまり,regular ∩ supposedly-important, prompt ∩ supposedly-important,
regular ∩ not supposedly-important, and prompt ∩ not supposedly-important の4つのう
ちのいずれかを持つラベルである.

6.5. 予測不可能な属性

90

表 6.8: 分類ラベルとその分類値
分類ラベル名

分類値

writing style

日経平均, 東証

importance

regular ∩ supposedly-important,
prompt ∩ supposedly-important,
regular ∩ not supposedly-important,
prompt ∩ not supposedly important

time

9 時台(9:00-9:59am),10 時台(10:00-10:59am), . . .
Murakami et al. (2017) によるラベル.

モデル
前項で設定したラベルをモデルに追加する場合,その追加箇所を 図 6.4 のように(a) 入力
データと同時に追加, (b) Encoder の後に追加(Decoder の直前に追加), および(c) Decoder
の各ステップに追加の3通り検討する.

図 6.4: 属性ラベルを用いた概況テキスト生成モデルの概要
ラベルの各値は,学習によって得られる埋め込みとして表現される.これを単にラベル埋
め込みと呼び,l と表記する.ネットワークの状態を計算する式を Murakami et al. (2017)
のモデルから次のように変更する.(a) の場合,式 (6.4) と (6.5) を以下のように変更する.

hlong = MLP[x′long ; l],

(6.19)

hshort = MLP[x′short ; l].

(6.20)

6.5. 予測不可能な属性

91

(b) の場合, 式 (6.6) を以下のように変更する.
m = Wm [hlong ; hshort ; l] + bm .

(6.21)

(c) の場合,式 (6.7) を以下のように変更する.
si = LSTM([wi−1 ; l], si−1 ).

(6.22)

1 つ以上のラベルを用いる場合,ラベルの埋め込みベクトルを結合して用いる.例えば,3
つのラベルを1度に使う場合, l は以下となる:
l = [ltime ; lwriting style ; limportance ]

(6.23)

このとき,ltime は time ラベル埋め込み,lwriting style は writing style ラベル埋め込み,
limportance は importance ラベル埋め込みである.

6.5.3

実験設定

前項で設定した通り,(1) time, (2) writing style, および(3) importance. の 3 つのラベル
を使用し,そのラベルの追加箇所を(a) 入力データと同時に追加, (b) Encoder の後に追加
(Decoder の直前に追加)および(c) Decoder の各ステップに追加,の3通りで実験を行う.

データセット
実験には,時系列データとして,Thomson Reuters DataScope Select6 から,2011 年 12
月から 2016 年 9 月までの期間の日経平均株価指数の時系列データを収集し,実験に使用し
た.概況テキストとして,日経 QUICK ニュース社が提供している日経平均株価に言及して
いるニュース記事のヘッドラインを使用した.なお,米国株式や外国為替などの日経平均株
価以外の記述は取り除いた.また Murakami et al. (2017) と同様に,価格に関する単語を
演算タグに変換した.2011 年 12 月から 2015 年 9 月の期間のデータを学習データ(12,391
件),2015 年 10 月から 2016 年 3 月の期間のデータを開発データ(1,751 件),2016 年 4 月
から 2016 年 9 月の期間のデータを評価データ(1,689 件)として使用した.

ハイパーパラメータ
先行研究と同様,次の設定で実験を行う.各 MLP の隠れ状態の次元は 256,Decoder の
LSTM の隠れ状態の次元は 256,短期と長期のベクトルの長さは,xlong は M = 7,xshort
6

https://hosted.datascope.reuters.com/DataScope/

6.5. 予測不可能な属性

92

は N = 62 とする.単語埋め込みベクトルは 128,3つのラベル time, writing style, および
importance の埋め込みベクトルの次元は 64 とする.ミニバッチサイズは 100,エポック数
は 150 とし,各パラメータの最適化手法には Adam (Kingma and Ba, 2015) を使用し,学
習率は 1 × 10−4 とした.学習時に開発データで計算された BLEU が連続して下がった場合
には学習を終了し,各エポックのモデルの中で,開発データに対する BLEU が最大となっ
たモデルを使用して,評価を行う.

評価指標
生成文の評価は,正解文との一致を評価可能な BLEU(Papineni et al., 2002) で行った.
また,正解文章と比較し,動向表現7 が正しく出現できているかを評価した.

6.5.4

実験結果

表 6.9: BLEU (%)

(a)

(b)

(c)

開発データ
time label
writing style label
importance label

ラベルなし: 35.82
37.42 40.78 40.44
43.51 43.52 44.28
48.78 48.50 50.18

評価データ
time label
writing style label
importance label

ラベルなし: 36.79
40.42 41.40 39.66
46.69 46.54 47.36
52.77 51.90 52.15

BLEU 評価結果を表 6.9 に示す.ラベルありの場合に,最もスコアが低かったのは (a) の
time ラベルで,Murakami et al. (2017); Aoki et al. (2018) の先行研究で使用した time ラ
ベルはラベルなしと比べてスコアの向上に貢献したものの,最も効果的なラベルとは言え
なかった. データセット解析を経て作成した writing style ラベルと importance ラベルの
使用は,スコアの向上に有意に効果があることが分かった.開発データでの 1 つのラベル
を使った場合の最高 BLEU スコアは,(c) を importance ラベルを追加した場合の 50.18%
で,ラベルなしの場合よりも 15%向上し,また (c) で time ラベルを用いた先行研究の設定
値よりも 10%以上高い値を示している. 評価データでは,(a) で important ラベルを追加し
7

続伸,反発,上げ,続落,反落,下げ

6.5. 予測不可能な属性

93

表 6.10: 開発データセットによる動作表現による評価 (%)

(a)

(b)

(c)

精度
time label
writing style label
importance label

ラベルなし: 89.27
90.26 90.88 90.96
90.61 90.64 90.68
91.40 91.27 91.40

特異度
time label
writing style label
importance label

ラベルなし: 93.25
93.86 94.05 94.08
94.06 93.97 94.04
95.27 95.08 95.29

F値
time label
writing style label
importance label

ラベルなし: 56.96
60.91 63.82 64.68
63.17 63.36 63.83
65.01 65.08 65.19

た場合に最も高いスコアが得られ,最も低かったのは先行研究の設定の (c) で time ラベル
を追加した場合だった.
表 6.10 に動向表現生成精度の評価結果を示す.ラベルを追加することで,文章生成精度
が上がるだけでなく,正しい動向表現を選べるようになっていることが分かる.BLEU と
同じく,ラベルを追加しない場合と比較して,全ての場合でラベルを追加した場合に精度が
高くなった.しかも,精度だけでなく特異度や F 値も向上していることより,出すべき時
に正しく生成できていることがわかる,特に,(c) で importance ラベルを追加すると,精
度だけでなく特異度や F 値も最も高くなった.
以上より,ラベル自体には,データの動向を表す要素は含まれていないにもかかわらず,
文体として正しい文章が生成できるだけでなく,データを正しく記述することにも貢献し
ている.
同一入力データで生成された文章を表 6.11 に示す. ラベルを全く入れない場合は生成コ
メントが変わらなかった一方,正解のテキストと同一のラベルを各々与えた場合では,全
て異なるコメントが生成できており,さらに各々正解テキストと同じようなコメントであ
ることがわかる.

6.5. 予測不可能な属性

94

表 6.11: 同一入力データでのラベル追加なし・ありの生成テキスト例
正解文
(I)
(II)
(III)

日経平均、続落 大引けは 69 円安の 17697 円
日経平均大引け、続落
東証大引け、続落

生成結果
ラベルなし
日経平均、続落 大引けは 69 円安の 17697 円
全てのラベルあり
(I)
日経平均、続落 大引けは 69 円安
(II)
日経平均大引け、続落
(III)
東証大引け、続落

6.6. まとめと今後の課題

6.6

95

まとめと今後の課題

本章では,data-to-text の時系列データと動向説明文の対応関係獲得課題を題材に問題を
2つ挙げ,分析し,解決策を探った.

1 つ目の問題は,時系列データを用いる課題で発生する特有の問題である.これは,マル
チモーダル情報の変換における適切な入出力の表現方法に関する問題とも言える.時系列
データとその時系列データの内容を逐次解説するテキストでデータセットを構築する場合,
テキストの発表時刻を基に時系列データを取得する手法が主に用いられているが,データ
のイベント発生時刻とテキスト発表時刻の不整合が起こりうる.そこで,テキスト発表時
刻はイベント発生時刻よりも遅れることに注目し,テキスト発表時刻以前のデータに対し
ても参照できる枠組みを提案した.この解決策により,時系列データを用いた data-to-text
における時刻の不整合の問題に対応できた.この手法は,入力の枠組み以外は先行研究の
枠組みを大きく変えず,簡単に導入可能である特徴がある.
2 つ目の問題は,データセットにおける予測不可能な属性の問題,つまり,入力から出力
の属性が予測できない問題である.これは,マルチモーダル情報の変換における Generative
approaches による,入力に対応する正解が複数存在しうる問題と関係が深い.時系列デー
タとその時系列データの内容を逐次解説するテキストで構築されたデータセットでは,同
一データであるが,異なるテキストとなっているデータペアが存在した.このようにデー
タセットには予測不可能な属性が存在し,このデータセットを使った場合入力から正しい
テキストを生成することができないことが判明した.データセットを分析して得られた予
測不可能な属性から 2 つのラベルを作成し,ニューラルネットワークベースモデルに新た
な入力として追加したところ,ラベルの使用によりテキストの生成性能が向上することは
もちろんのこと,ラベルの使用によりデータの内容をより正しく生成できる副次的な効果
も確認された.テキスト生成モデルを予測不可能な属性が存在する環境で学習させるので
はなく,予測不可能な属性を入力の一部として与えるべきであると示唆している.
以上,2 つの問題の解決策は,実データを用いたモダリティ間の関係性獲得には汎用的な
手法を直接使えるわけではなく,モダリティによってある程度の調整が必須であることを
示唆している. 特に,モダリティ変換を行いたい方向性がある場合,例えば専門性の高い
データや文章を扱う場合には,その方向性を制御する必要がある.
今後の課題は,入出力データの表現方法の自動獲得や,モダリティ変換の方向性の自動
獲得である.本章で扱ったデータセットには人が気付ける特徴があったため,人手による
入出力の分析により,適切な表現方法や,モダリティ変換の方向性を得ることができた.一
方暗黙知など,人が気付けない特徴も存在しうるため,それらにより入出力データが特徴
付けられていたり変換の方向性が決まる場合には,人手による分析では適切な表現方法や,
モダリティ変換の方向性を得ることができない.そのため,人手を介さないこれらの自動
獲得手法は,モダリティ変換を行う上で必須となると考えている.

96

第 7 章 結論

本論文では,言語と非言語の対応関係を捉えるタスクとして,マルチモーダル情報のモ
ダリティ変換を行う生成課題に取り組んだ.マルチモーダル情報の生成による変換手法で
は,出力データの両方のモダリティを捉えた上で,モデルを構築する必要がある.そのた
め,モダリティ変換はモダリティ毎にそれぞれモデルを作る必要がある.本論文では,言語
を中核に据えて,非言語とのモダリティ変換を 3 つ扱い,言語の特性を捉えたモダリティ
変換課題に取り組んだ.
はじめに,言語から非言語の生成課題として,自然言語理解によるロボット動作生成課
題を扱い,その手法の提案を行った.この課題では,人間とロボットが共存する場面を想
定したため,まず,ロボットが人の動作を真似て行うことができるように,基本動作を組み
合わせてひとつの行為を生成する枠組みの時系列 AAM を構築し,複数の基本動作から複
雑な行為を表現する対応関係を明確にした.従来のロボット動作構成は,関節角を直接指
示して動作を生成する必要があったため,可読性が低かったが,時系列 AAM は,基本動
作を組合せて動作構成するため,可読性が高く,人が新たな動作をロボットに指示する場
合にも容易である.また,作成動作を新たな基本動作として定義でき,複雑な動作生成へ
拡張性がある.ロボットの動作構成が可能になった上で,言葉とロボット動作の対応関係
を捉える手法として,ニューラルネットワークを基にしたモデルにより,分散表現と時系
列 AAM による動作表現を対応付ける手法を提案し,有効性を確認した.特に,分散表現
生成に大きなコーパスを用いることで,複雑な言葉と動作への対応が可能なことを確認し
た.さらに,全く新しい言葉の動作でも学習した言葉の動作から言葉の動作を推測して動
作を行えることを確認した.複数の動作生成に適用できるニューラルネットワークの構造
では,単純な構造ではなく,言葉の特徴を考慮した枠組みで高い精度を達成した.このこ
とは,異なるモダリティ間に直接的なパターンの対応関係はないことを示唆しており,対
応関係を捉えて,適切に生成を行うためには,入力特徴を考慮した枠組みにする必要があ
ると言える.またこの枠組みにより,言葉の曖昧さを動作というモダリティに限定して対
応関係を獲得することで,モダリティ変換することができた.
次に,非言語から言語の生成課題として,一般ドメイン実況生成と概況テキスト生成を
扱った.これは新たな課題の提案であり,既存のクローズドメインの実況生成では利用で
きていた分野特有のデータを使えず,映像のみからテキストを生成する必要がある課題設
定である.一方で,ドメインを限らない課題とすることで,同じ状況であっても,複数の表
現方法が考えられる,言語の広がりを許容する新たな課題の提案となった.動画中のイベ

第 7 章 結論

97

ントを抽出してテキストで説明する Dense captioning とも異なり,時間的位置,内容,ビ
デオ内のオブジェクトの相関が,ビデオ内のイベントと部分的にしか整合していない.ま
ず,様々なドメインの人間の動作を含むビデオに対して実況を収録し,新しい大規模データ
セットの構築を行い,24,000 件以上の実況データを得た.その上で,実況生成に必要なタ
イミング推定と発話生成に取り組んだ.タイミング推定では,トリミングされていないビ
デオシーケンス中の人間の活動を推定できる TAL を用い,発話生成では,テキスト生成で
有用性が示されている Transformer モデルを用いた.発話生成において,映像のみを入力
とする場合と前時刻の実況も含めて入力とする場合を比較すると,前時刻の実況も含めて
入力した場合に精度が向上した.実況が動画内のイベントと部分的にしか一致していない
という性質を持っており,動画の内容と一致しない実況を生成する必要があるときに,前
時刻の実況がモデルの決定を助け,なお,既存のクローズドメインデータセットにおいて,
分野特有のデータを用いた場合には明らかに精度が向上した.これは,映像には存在しな
い,ドメイン内情報へのアクセスの重要性を示しているが,映像にない情報へのアクセス
は,クローズドメインのみに重要なわけではなく,一般ドメインにおいても重要な点であ
る.例えば,ダーツの動画に対する実況を行う場合,矢がダーツボード,特にその中心部に
当たったかについて言及しうる.これはダーツという遊びの目的は,矢をダーツボード (特
にその中心部) に当てることであるからであるが,映像のみからなる訓練データのみから,
ダーツのルールを把握することは容易ではない.このように,今後は一般ドメインにおい
ても,なんらかの外部知識の利用が必要となると考えられる.
最後に,実世界で得られたデータやテキストを用いて対応間関係を得ようとする場合に
発生する問題に取り組んだ.これは,限られたデータから適切に目的のテキストを生成す
る手法の獲得であり,複数の解釈が可能なデータから,言葉によって解釈の方向性を決定す
る課題とも言える.特に,data-to-text の時系列データと動向説明文の対応関係獲得課題を
題材に問題を2点上げ,分析し,解決策を探った.1 つ目の問題は,時系列データを用いる
課題で発生する特有の問題である.時系列データとその時系列データの内容を逐次解説す
るテキストでデータセットを構築する場合,テキストの発表時刻を基に時系列データを取
得する手法が主に用いられているが,データのイベント発生時刻とテキスト発表時刻の不
整合が起こりうる.そこで,テキスト発表時刻はイベント発生時刻よりも遅れることに注
目し,テキスト発表時刻以前のデータに対しても参照できる枠組みを提案した.この解決
策により,時系列データを用いた data-to-text における時刻の不整合の問題に対応できた.
この手法は,入力の枠組み以外は先行研究の枠組みを大きく変えず,簡単に導入可能であ
る特徴がある.2 つ目の問題は,データセットにおける予測不可能な属性の問題,つまり,
入力から出力の属性が予測できない問題である.時系列データとその時系列データの内容
を逐次解説するテキストで構築されたデータセットでは,同一データであるが,異なるテ
キストとなっているデータペアが存在した.このようにデータセットには予測不可能な属
性が存在し,このデータセットを使った場合入力から正しいテキストを生成することがで
きないことが判明した.データセットを分析して得られた予測不可能な属性から 2 つのラ
ベルを作成し,ニューラルネットワークベースモデルに新たな入力として追加したところ,

第 7 章 結論

98

ラベルの使用によりテキストの生成性能が向上することはもちろんのこと,ラベルの使用
によりデータの内容をより正しく生成できる副次的な効果も確認された.テキスト生成モ
デルを予測不可能な属性が存在する環境で学習させるのではなく,予測不可能な属性を入
力の一部として与えるべきであると示唆している.
以上より,本論文では,実用に向けた言語と非言語のマルチモーダル情報のモダリティ
変換を行うことで,言語とロボット動作,言語と一般ドメイン動画,言語と時系列数値デー
タの各モダリティ変換手法を得ることができた.これは,各入出力データのモダリティに
適した表現方法を用いたことによる貢献も大きい.さらに,言葉と特定の非言語間のモダ
リティ変換を扱うことで,言語の曖昧さの許容や広がり,解釈の可能性を特定のモダリティ
を介して表すことができた.また,実世界で言語と非言語の対応関係を捉える課題を行う
ことで,異なるモダリティの関係性を正しく捉えるには,入出力データそれぞれの特徴を
不足なく取得した上で,関係性を捉える適切な枠組みが必要であると示唆できた.本論文
で扱った入出力データのモダリティやそれらを用いたモダリティ変換は限られた範囲であ
るため,これを直接異なるモダリティに用いることはできない.しかし,似たような特徴
を持つモダリティ変換の手掛かりとなると考えている.本研究により,異なるモダリティ
の関係性を正しく捉えるには,入出力データそれぞれの特徴を捉える必要があるとしたが,
データには暗黙知など,人が気付けない特徴も存在しうる.人が気付けない特徴により,入
出力データが特徴付けられていたり,モダリティ変換の方向性が決まる場合には,人手によ
る分析では適切な表現方法や,モダリティ変換の方向性を得ることができない.そのため,
人手を介さない入出力データの表現方法の自動獲得手法や,モダリティ変換の方向性の自
動獲得手法は,今後マルチモーダル情報のモダリティ変換を行う上で必須となると考えて
いる.

99

謝辞

本研究を進めるにあたり,多くの方々にご協力を頂きました.心より感謝致します.
まず,本論文を執筆するに辺り,ご指導下さいましたお茶の水女子大学人間文化創成科
学研究科の小林一郎教授に深謝いたします.
また,副査を担当くださいました本研究科人間文化創成科学研究科小口正人教授,戸次
大介准教授,伊藤貴之教授,五十嵐悠紀准教授,にも感謝いたします.終始適切な助言を賜
り,ご指導頂いた,統計数理研究所数理・推論研究系の持橋大地准教授,産業技術総合研究
所人工知能センターの麻生英樹氏,高村大也氏,東京大学大学院情報理工学系研究科の宮
尾祐介教授,大阪大学基礎工学研究科の長井隆行教授,電気通信大学知能機械工学専攻の
中村友昭准教授に感謝致します.
また鋭いご指摘を頂いたり,議論を交わす機会を与えてくださった産業技術総合研究所
人工知能センターの石垣達也氏,Edison Marrese-Taylor 氏,上原由衣氏,能地宏氏,Goran
Topi´c 氏に感謝いたします.
本研究の実験においてはクックパッド株式会社よりデータを提供していただきました.
ここに感謝の意を表します.
最後に,日々の研究室生活を豊かなものとしてくれた研究室のメンバー,友人の皆様に
心から感謝の意を表します.

100

参考文献

2016. Can neural machine translation do simultaneous translation? arXiv:1606.02012
[cs].
Peter Anderson, Basura Fernando, Mark Johnson, and Stephen Gould. 2016. SPICE: Semantic Propositional Image Caption Evaluation. In Computer Vision – ECCV 2016,
Lecture Notes in Computer Science, pages 382–398, Cham. Springer International Publishing.
Gabor Angeli, Percy Liang, and Dan Klein. 2010. A simple domain-independent probabilistic approach to generation. In Proceedings of the 2010 Conference on Empirical
Methods in Natural Language Processing, pages 502–512, Cambridge, MA. Association for Computational Linguistics.
Tatsuya Aoki, Akira Miyazawa, Tatsuya Ishigaki, Keiichi Goshima, Kasumi Aoki, Ichiro
Kobayashi, Hiroya Takamura, and Yusuke Miyao. 2018. Generating market comments
referring to external resources. In Proceedings of the 11th International Conference
on Natural Language Generation, pages 135–139, Tilburg University, The Netherlands.
Association for Computational Linguistics.
Rosana Ardila, Megan Branson, Kelly Davis, Michael Kohler, Josh Meyer, Michael Henretty, Reuben Morais, Lindsay Saunders, Francis Tyers, and Gregor Weber. 2020. Common voice: A massively-multilingual speech corpus. In Proceedings of the 12th Language Resources and Evaluation Conference, pages 4218–4222, Marseille, France.
European Language Resources Association.
Dzmitry Bahdanau, Kyunghyun Cho, and Yoshua Bengio. 2015. Neural machine translation by jointly learning to align and translate. In 3rd International Conference
on Learning Representations, ICLR 2015, San Diego, CA, USA, May 7-9, 2015,
Conference Track Proceedings.
Christopher Baldassano, Janice Chen, Asieh Zadbood, Jonathan W Pillow, Uri Hasson,
and Kenneth A Norman. 2017. Discovering event structure in continuous narrative
perception and memory. Neuron, 95(3):709–721.

参考文献

101

Tadas Baltruˇsaitis, Chaitanya Ahuja, and Louis-Philippe Morency. 2019. Multimodal
machine learning: A survey and taxonomy. IEEE Transactions on Pattern Analysis
and Machine Intelligence, 41(2):423–443.
Anja Belz. 2007. Probabilistic generation of weather forecast texts. In Human Language
Technologies 2007: The Conference of the North American Chapter of the Association for Computational Linguistics; Proceedings of the Main Conference, pages
164–171, Rochester, New York. Association for Computational Linguistics.
Anja Belz. 2008. Automatic generation of weather forecast texts using comprehensive
probabilistic generation-space models. Natural Language Engineering, 14(4):431–455.
Yoshua Bengio, R´ejean Ducharme, Pascal Vincent, and Christian Jauvin. 2003. A neural
probabilistic language model. Journal of machine learning research, 3(Feb):1137–1155.
Yoshua Bengio, Patrice Simard, and Paolo Frasconi. 1994. Learning long-term dependencies with gradient descent is difficult. IEEE transactions on neural networks, 5(2):157–
166.
John A Bullinaria and Joseph P Levy. 2007. Extracting semantic representations from
word co-occurrence statistics: A computational study. Behavior research methods,
39(3):510–526.
Joao Carreira and Andrew Zisserman. 2017. Quo vadis, action recognition? a new model
and the kinetics dataset. In proceedings of the IEEE Conference on Computer Vision
and Pattern Recognition, pages 6299–6308.
Xinlei Chen, Hao Fang, Tsung-Yi Lin, Ramakrishna Vedantam, Saurabh Gupta, Piotr
Dollar, and C. Lawrence Zitnick. 2015. Microsoft coco captions: Data collection and
evaluation server.
Yen-Chun Chen, Linjie Li, Licheng Yu, Ahmed El Kholy, Faisal Ahmed, Zhe Gan,
Yu Cheng, and Jingjing Liu. 2020. UNITER: UNiversal Image-TExt Representation
Learning. In Computer Vision – ECCV 2020, Lecture Notes in Computer Science,
pages 104–120, Cham. Springer International Publishing.
Heng-Tze Cheng, Feng-Tso Sun, Martin Griss, Paul Davis, Jianguo Li, and Di You. 2013.
Nuactiv: Recognizing unseen new activities using semantic attribute-based learning. In
Proceeding of the 11th annual international conference on Mobile systems, applications, and services, pages 361–374. ACM.
Andrew Chisholm, Will Radford, and Ben Hachey. 2017. Learning to generate onesentence biographies from Wikidata. In Proceedings of the 15th Conference of the

参考文献

102

European Chapter of the Association for Computational Linguistics: Volume 1, Long
Papers, pages 633–642, Valencia, Spain. Association for Computational Linguistics.
Kyunghyun Cho, Bart van Merri¨enboer, Caglar Gulcehre, Dzmitry Bahdanau, Fethi
Bougares, Holger Schwenk, and Yoshua Bengio. 2014. Learning phrase representations
using RNN encoder–decoder for statistical machine translation. In Proceedings of the
2014 Conference on Empirical Methods in Natural Language Processing (EMNLP),
pages 1724–1734, Doha, Qatar. Association for Computational Linguistics.
Ronan Collobert and Jason Weston. 2008. A unified architecture for natural language
processing: Deep neural networks with multitask learning. In Proceedings of the 25th
international conference on Machine learning, pages 160–167. ACM.
Kees van Deemter, Mariet Theune, and Emiel Krahmer. 2005. Real versus templatebased natural language generation: A false opposition? Computational Linguistics,
31:15–24.
Scott Deerwester, Susan T Dumais, George W Furnas, Thomas K Landauer, and Richard
Harshman. 1990. Indexing by latent semantic analysis. Journal of the American
society for information science, 41(6):391.
Jacob Devlin, Ming-Wei Chang, Kenton Lee, and Kristina Toutanova. 2019. BERT: Pretraining of deep bidirectional transformers for language understanding. In Proceedings
of the 2019 Conference of the North American Chapter of the Association for Computational Linguistics: Human Language Technologies, Volume 1 (Long and Short
Papers), pages 4171–4186, Minneapolis, Minnesota. Association for Computational
Linguistics.
Bernard Ghanem Fabian Caba Heilbron, Victor Escorcia and Juan Carlos Niebles. 2015.
ActivityNet: A Large-Scale Video Benchmark for Human Activity Understanding. In
Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition,
pages 961–970.
J. R. Firth. 1957. A synopsis of linguistic theory 1930-55. 1952-59:1–32.
Adam Gaier and David Ha. 2019.
weightagnostic.github.io.

Weight agnostic neural networks.

https://

Lianli Gao, Zhao Guo, Hanwang Zhang, Xing Xu, and Heng Tao Shen. 2017. Video
captioning with attention-based lstm and semantic consistency. IEEE Transactions on
Multimedia, 19(9).

参考文献

103

F.A. Gers, J. Schmidhuber, and F. Cummins. 1999. Learning to forget: continual prediction with lstm. In 1999 Ninth International Conference on Artificial Neural Networks
ICANN 99. (Conf. Publ. No. 470), volume 2, pages 850–855 vol.2.
Eli Goldberg, Norbert Driedger, and Richard I Kittredge. 1994. Using natural-language
processing to produce weather forecasts. IEEE Expert, 9(2):45–53.
Heng Gong, Xiaocheng Feng, Bing Qin, and Ting Liu. 2019. Table-to-text generation with
effective hierarchical encoder on three dimensions (row, column and time). In Proceedings of the 2019 Conference on Empirical Methods in Natural Language Processing and the 9th International Joint Conference on Natural Language Processing
(EMNLP-IJCNLP), pages 3143–3152, Hong Kong, China. Association for Computational Linguistics.
Ian Goodfellow, Jean Pouget-Abadie, Mehdi Mirza, Bing Xu, David Warde-Farley, Sherjil
Ozair, Aaron Courville, and Yoshua Bengio. 2014. Generative adversarial nets. In
Advances in Neural Information Processing Systems, volume 27. Curran Associates,
Inc.
Jiatao Gu, Zhengdong Lu, Hang Li, and Victor O.K. Li. 2016. Incorporating copying
mechanism in sequence-to-sequence learning. In Proceedings of the 54th Annual
Meeting of the Association for Computational Linguistics (Volume 1: Long Papers),
pages 1631–1640, Berlin, Germany. Association for Computational Linguistics.
Zellig S Harris. 1954. Distributional structure. Word, 10(2-3):146–162.
Geoffrey E Hinton. 1984. Distributed representations.
Sepp Hochreiter and J¨
urgen Schmidhuber. 1997. Long short-term memory. Neural Computation, 9(8):1735–1780.
Yicong Hong, Qi Wu, Yuankai Qi, Cristian Rodriguez-Opazo, and Stephen Gould. 2021.
VLN BERT: A Recurrent Vision-and-Language BERT for Navigation. In Proceedings
of the IEEE/CVF Conference on Computer Vision and Pattern Recognition, pages
1643–1653.
Andrew J Hunt and Alan W Black. 1996. Unit selection in a concatenative speech synthesis system using a large speech database. In 1996 IEEE International Conference on
Acoustics, Speech, and Signal Processing Conference Proceedings, volume 1, pages
373–376. IEEE.
Tatsuya Ishigaki, Goran Topic, Yumi Hamazono, Hiroshi Noji, Ichiro Kobayashi, Yusuke
Miyao, and Hiroya Takamura. 2021. Generating racing game commentary from vision,

参考文献

104

language, and structured data. In Proceedings of the 14th International Conference
on Natural Language Generation, pages 103–113, Aberdeen, Scotland, UK. Association for Computational Linguistics.
Hayate Iso, Yui Uehara, Tatsuya Ishigaki, Hiroshi Noji, Eiji Aramaki, Ichiro Kobayashi,
Yusuke Miyao, Naoaki Okazaki, and Hiroya Takamura. 2019. Learning to select, track,
and generate for data-to-text. In Proceedings of the 57th Annual Meeting of the Association for Computational Linguistics, pages 2102–2113, Florence, Italy. Association
for Computational Linguistics.
Armand Joulin and Tomas Mikolov. 2015. Inferring algorithmic patterns with stackaugmented recurrent nets. In C. Cortes, N. D. Lawrence, D. D. Lee, M. Sugiyama, and
R. Garnett, editors, Advances in Neural Information Processing Systems 28, pages
190–198. Curran Associates, Inc.
Mihir Kale and Abhinav Rastogi. 2020. Text-to-text pre-training for data-to-text tasks. In
Proceedings of the 13th International Conference on Natural Language Generation,
pages 97–102, Dublin, Ireland. Association for Computational Linguistics.
Byeong Jo Kim and Yong Suk Choi. 2020. Automatic baseball commentary generation
using deep learning. In Proceedings of the 35th Annual ACM Symposium on Applied
Computing, pages 1056–1065. Association for Computing Machinery, New York, NY,
USA.
Diederik P. Kingma and Jimmy Ba. 2015. Adam: A method for stochastic optimization. In
3rd International Conference on Learning Representations, ICLR 2015, San Diego,
CA, USA, May 7-9, 2015, Conference Track Proceedings.
Diederik P Kingma, Shakir Mohamed, Danilo Jimenez Rezende, and Max Welling. 2014.
Semi-supervised learning with deep generative models. In Advances in Neural Information Processing Systems, pages 3581–3589.
Diederik P Kingma and Max Welling. 2013. Auto-encoding variational bayes. arXiv
preprint arXiv:1312.6114.
Arne K¨ohn, Florian Stegen, and Timo Baumann. 2016. Mining the spoken Wikipedia for
speech data and beyond. In Proceedings of the Tenth International Conference on
Language Resources and Evaluation (LREC’16), pages 4644–4647, Portoroˇz, Slovenia.
European Language Resources Association (ELRA).
Atsuhiro Kojima, Takeshi Tamura, and Kunio Fukunaga. 2002. Natural language description of human activities from video images based on concept hierarchy of actions.
International Journal of Computer Vision, 50:171–184.

参考文献

105

Ioannis Konstas and Mirella Lapata. 2012. Unsupervised concept-to-text generation with
hypergraphs. In Proceedings of the 2012 Conference of the North American Chapter
of the Association for Computational Linguistics: Human Language Technologies,
pages 752–761, Montr´eal, Canada. Association for Computational Linguistics.
Ranjay Krishna, Kenji Hata, Frederic Ren, Li Fei-Fei, and Juan Carlos Niebles. 2017.
Dense-Captioning Events in Videos. In Proceedings of the IEEE International Conference on Computer Vision, pages 706–715.
Alex Krizhevsky, Ilya Sutskever, and Geoffrey E Hinton. 2012. Imagenet classification with
deep convolutional neural networks. In Advances in Neural Information Processing
Systems, volume 25. Curran Associates, Inc.
Karen Kukich. 1983. Design of a knowledge-based report generator. In 21st Annual
Meeting of the Association for Computational Linguistics, pages 145–150, Cambridge,
Massachusetts, USA. Association for Computational Linguistics.
Girish Kulkarni, Visruth Premraj, Vicente Ordonez, Sagnik Dhar, Siming Li, Yejin Choi,
Alexander C. Berg, and Tamara L. Berg. 2013. Babytalk: Understanding and generating simple image descriptions. IEEE Transactions on Pattern Analysis and Machine
Intelligence, 35(12):2891–2903.
R´emi Lebret, David Grangier, and Michael Auli. 2016. Neural text generation from
structured data with application to the biography domain. In Proceedings of the
2016 Conference on Empirical Methods in Natural Language Processing, pages
1203–1213, Austin, Texas. Association for Computational Linguistics.
Mike Lewis, Yinhan Liu, Naman Goyal, Marjan Ghazvininejad, Abdelrahman Mohamed,
Omer Levy, Veselin Stoyanov, and Luke Zettlemoyer. 2020. BART: Denoising sequenceto-sequence pre-training for natural language generation, translation, and comprehension. In Proceedings of the 58th Annual Meeting of the Association for Computational Linguistics, pages 7871–7880, Online. Association for Computational Linguistics.
Liunian Li and Xiaojun Wan. 2018. Point precisely: Towards ensuring the precision of
data in generated texts using delayed copy mechanism. In Proceedings of the 27th
International Conference on Computational Linguistics, pages 1044–1055, Santa Fe,
New Mexico, USA. Association for Computational Linguistics.
Percy Liang, Michael Jordan, and Dan Klein. 2009. Learning semantic correspondences
with less supervision. In 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, pages 91–99, Suntec, Singapore. Association for
Computational Linguistics.

参考文献

106

Chuming Lin, Jian Li, Yabiao Wang, Ying Tai, Donghao Luo, Zhipeng Cui, Chengjie
Wang, Jilin Li, Feiyue Huang, and Rongrong Ji. 2020. Fast Learning of Temporal
Action Proposal via Dense Boundary Generator. Proceedings of the AAAI Conference
on Artificial Intelligence, 34(07):11499–11506.
Tianyu Liu, Kexiang Wang, Lei Sha, Baobao Chang, and Zhifang Sui. 2018a. Table-to-text
generation by structure-aware seq2seq learning. In Proceedings of the Thirty-Second
AAAI Conference on Artificial Intelligence.
Tianyu Liu, Kexiang Wang, Lei Sha, Baobao Chang, and Zhifang Sui. 2018b. Tableto-text generation by structure-aware seq2seq learning. Proceedings of the AAAI
Conference on Artificial Intelligence, 32(1).
Thang Luong, Hieu Pham, and Christopher D. Manning. 2015. Effective approaches to
attention-based neural machine translation. In Proceedings of the 2015 Conference
on Empirical Methods in Natural Language Processing, pages 1412–1421, Lisbon,
Portugal. Association for Computational Linguistics.
Hongyuan Mei, Mohit Bansal, and Matthew R. Walter. 2016. What to talk about and
how? selective generation using LSTMs with coarse-to-fine alignment. In Proceedings
of the 2016 Conference of the North American Chapter of the Association for Computational Linguistics: Human Language Technologies, pages 720–730, San Diego,
California. Association for Computational Linguistics.
Tomas Mikolov, Kai Chen, Greg Corrado, and Jeffrey Dean. 2013a. Efficient estimation
of word representations in vector space. CoRR, abs/1301.3781.
Tomas Mikolov, Ilya Sutskever, Kai Chen, Greg S Corrado, and Jeff Dean. 2013b. Distributed representations of words and phrases and their compositionality. In Advances
in neural information processing systems, pages 3111–3119.
Volodymyr Mnih, Koray Kavukcuoglu, David Silver, Alex Graves, Ioannis Antonoglou,
Daan Wierstra, and Martin Riedmiller. 2013. Playing atari with deep reinforcement
learning. In NIPS Deep Learning Workshop.
Jonghwan Mun, Linjie Yang, Zhou Ren, Ning Xu, and Bohyung Han. 2019. Streamlined
Dense Video Captioning. In Proceedings of the IEEE/CVF Conference on Computer
Vision and Pattern Recognition, pages 6588–6597.
Soichiro Murakami, Akihiko Watanabe, Akira Miyazawa, Keiichi Goshima, Toshihiko
Yanase, Hiroya Takamura, and Yusuke Miyao. 2017. Learning to generate market
comments from stock prices. In Proceedings of the 55th Annual Meeting of the

参考文献

107

Association for Computational Linguistics (Volume 1: Long Papers), pages 1374–
1384, Vancouver, Canada. Association for Computational Linguistics.
Vinod Nair and Geoffrey E. Hinton. 2010. Rectified linear units improve restricted boltzmann machines. In Proceedings of the 27th International Conference on Machine
Learning (ICML-10), pages 807–814. Omnipress.
Arvind Neelakantan, Quoc V. Le, and Ilya Sutskever. 2016. Neural programmer: Inducing
latent programs with gradient descent. In 4th International Conference on Learning
Representations, ICLR 2016, San Juan, Puerto Rico, May 2-4, 2016, Conference
Track Proceedings.
Jekaterina Novikova, Ondˇrej Duˇsek, and Verena Rieser. 2017. The E2E dataset: New challenges for end-to-end generation. In Proceedings of the 18th Annual SIGdial Meeting
on Discourse and Dialogue, pages 201–206, Saarbr¨
ucken, Germany. Association for
Computational Linguistics.
Tetsuya Ogata, Masamitsu Murase, Jun Tani, Kazunori Komatani, and Hiroshi G Okuno.
2007. Two-way translation of compound sentences and arm motions by recurrent neural
networks. In Intelligent Robots and Systems, 2007. IROS 2007. IEEE/RSJ International Conference on, pages 1858–1863. IEEE.
Vassil Panayotov, Guoguo Chen, Daniel Povey, and Sanjeev Khudanpur. 2015. Librispeech: An asr corpus based on public domain audio books. In 2015 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP), pages
5206–5210.
Kishore Papineni, Salim Roukos, Todd Ward, and Wei-Jing Zhu. 2002. Bleu: a method
for automatic evaluation of machine translation. In Proceedings of the 40th Annual
Meeting of the Association for Computational Linguistics, pages 311–318, Philadelphia, Pennsylvania, USA. Association for Computational Linguistics.
Ankur Parikh, Xuezhi Wang, Sebastian Gehrmann, Manaal Faruqui, Bhuwan Dhingra,
Diyi Yang, and Dipanjan Das. 2020. ToTTo: A controlled table-to-text generation
dataset. In Proceedings of the 2020 Conference on Empirical Methods in Natural
Language Processing (EMNLP), pages 1173–1186, Online. Association for Computational Linguistics.
Wenjie Pei, Jiyuan Zhang, Xiangrong Wang, Lei Ke, Xiaoyong Shen, and Yu-Wing Tai.
2019. Memory-attended recurrent network for video captioning. In Proceedings of
the IEEE/CVF Conference on Computer Vision and Pattern Recognition, pages
8347–8356.

参考文献

108

Matthew E. Peters, Mark Neumann, Mohit Iyyer, Matt Gardner, Christopher Clark,
Kenton Lee, and Luke Zettlemoyer. 2018. Deep contextualized word representations.
In Proceedings of the 2018 Conference of the North American Chapter of the Association for Computational Linguistics: Human Language Technologies, Volume 1
(Long Papers), pages 2227–2237, New Orleans, Louisiana. Association for Computational Linguistics.
Ratish Puduppully, Li Dong, and Mirella Lapata. 2019. Data-to-text generation with
entity modeling. In Proceedings of the 57th Annual Meeting of the Association for
Computational Linguistics, pages 2023–2035, Florence, Italy. Association for Computational Linguistics.
Yevgeniy Puzikov and Iryna Gurevych. 2018. E2E NLG challenge: Neural models vs.
templates. In Proceedings of the 11th International Conference on Natural Language Generation, pages 463–471, Tilburg University, The Netherlands. Association
for Computational Linguistics.
Alec Radford, Karthik Narasimhan, Tim Salimans, Ilya Sutskever, et al. 2018. Improving
language understanding by generative pre-training.
Ehud Reiter and Robert Dale. 1997. Building applied natural language generation systems. Natural Language Engineering, 3(1):57–87.
Cristian Rodriguez-Opazo, Edison Marrese-Taylor, Basura Fernando, Hongdong Li, and
Stephen Gould. 2021. Dori: Discovering object relationships for moment localization
of a natural language query in a video. In Proceedings of the IEEE/CVF Winter
Conference on Applications of Computer Vision, pages 1079–1088.
Abdelrhman Saleh, Ramy Baly, Alberto Barr´on-Cede˜
no, Giovanni Da San Martino, Mitra
Mohtarami, Preslav Nakov, and James Glass. 2019. Team QCRI-MIT at SemEval-2019
task 4: Propaganda analysis meets hyperpartisan news detection. In Proceedings of the
13th International Workshop on Semantic Evaluation, pages 1041–1046, Minneapolis,
Minnesota, USA. Association for Computational Linguistics.
Michael Schaffrath. 2003.
Mehr als 1:0!
Bedeutung des Live-Kommentars bei
Fußball¨
ubertragungen– eine explorative Fallstudie [more than 1:0! the importance
of live commentary on football matches – an exploratory case study]. Medien und
Kommunikationswissenschaft, 51.
Abigail See, Peter J. Liu, and Christopher D. Manning. 2017. Get to the point: Summarization with pointer-generator networks. In Proceedings of the 55th Annual Meeting
of the Association for Computational Linguistics (Volume 1: Long Papers), pages
1073–1083, Vancouver, Canada. Association for Computational Linguistics.

参考文献

109

Lei Sha, Lili Mou, Tianyu Liu, Pascal Poupart, Sujian Li, Baobao Chang, and Zhifang
Sui. 2018. Order-planning neural text generation from structured data. In Proceedings
of the Thirty-Second AAAI Conference on Artificial Intelligence.
C. Shannon. 1948. A mathematical theory of communication. Bell system technical
journal, 27.
Francesca Stramandinoli, Davide Marocco, and Angelo Cangelosi. 2012. The grounding
of higher order concepts in action and language: a cognitive robotics model. Neural
Networks, 32:165–173.
Yuuya Sugita and Jun Tani. 2005. Learning semantic combinatoriality from the interaction between linguistic and behavioral processes. Adaptive Behavior, 13(1):33–52.
Ilya Sutskever, Oriol Vinyals, and Quoc V Le. 2014. Sequence to sequence learning with
neural networks. In Advances in Neural Information Processing Systems, volume 27.
Curran Associates, Inc.
Masatoshi Suzuki and Ryo Takahashi. 2021. Japanese bert.
cl-tohoku/bert-japanese.

https://github.com/

Kumiko Tanaka-Ishii, Koiti Hasida, and Itsuki Noda. 1998. Reactive content selection
in the generation of real-time soccer commentary. In 36th Annual Meeting of the
Association for Computational Linguistics and 17th International Conference on
Computational Linguistics, Volume 2, pages 1282–1288, Montreal, Quebec, Canada.
Association for Computational Linguistics.
Yasufumi Taniguchi, Yukun Feng, Hiroya Takamura, and Manabu Okumura. 2019. Generating Live Soccer-Match Commentary from Play Data. Proceedings of the AAAI
Conference on Artificial Intelligence, 33(01):7096–7103.
Du Tran, Lubomir Bourdev, Rob Fergus, Lorenzo Torresani, and Manohar Paluri. 2015.
Learning Spatiotemporal Features with 3D Convolutional Networks. In Proceedings
of the 2015 IEEE International Conference on Computer Vision (ICCV), ICCV ’15,
pages 4489–4497, USA. IEEE Computer Society.
A¨aron van den Oord, Sander Dieleman, Heiga Zen, Karen Simonyan, Oriol Vinyals, Alex
Graves, Nal Kalchbrenner, Andrew Senior, and Koray Kavukcuoglu. 2016. WaveNet: A
Generative Model for Raw Audio. In Proc. 9th ISCA Workshop on Speech Synthesis
Workshop (SSW 9), page 125.
Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N
Gomez, L ukasz Kaiser, and Illia Polosukhin. 2017. Attention is all you need. In

参考文献

110

Advances in Neural Information Processing Systems, volume 30, pages 5998–6008.
Curran Associates, Inc.
Subhashini Venugopalan, Marcus Rohrbach, Jeffrey Donahue, Raymond Mooney, Trevor
Darrell, and Kate Saenko. 2015a. Sequence to sequence – video to text. In 2015
IEEE International Conference on Computer Vision (ICCV), pages 4534–4542, Los
Alamitos, CA, USA. IEEE Computer Society.
Subhashini Venugopalan, Huijuan Xu, Jeff Donahue, Marcus Rohrbach, Raymond
Mooney, and Kate Saenko. 2015b. Translating videos to natural language using deep
recurrent neural networks. In Proceedings of the 2015 Conference of the North American Chapter of the Association for Computational Linguistics: Human Language
Technologies, pages 1494–1504, Denver, Colorado. Association for Computational Linguistics.
Oriol Vinyals, Meire Fortunato, and Navdeep Jaitly. 2015a. Pointer networks. In
C. Cortes, N. D. Lawrence, D. D. Lee, M. Sugiyama, and R. Garnett, editors, Advances
in Neural Information Processing Systems 28, pages 2692–2700. Curran Associates,
Inc.
Oriol Vinyals, Alexander Toshev, Samy Bengio, and Dumitru Erhan. 2015b. Show and
tell: A neural image caption generator. In Proceedings of the IEEE conference on
computer vision and pattern recognition, pages 3156–3164.
Bairui Wang, Lin Ma, Wei Zhang, and Wei Liu. 2018. Reconstruction network for video
captioning. In 2018 IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR), pages 7622–7631, Los Alamitos, CA, USA. IEEE Computer Society.
Teng Wang, Ruimao Zhang, Zhichao Lu, Feng Zheng, Ran Cheng, and Ping Luo. 2021.
End-to-End Dense Video Captioning With Parallel Decoding. In Proceedings of the
IEEE/CVF International Conference on Computer Vision, pages 6847–6857.
Sam Wiseman, Stuart Shieber, and Alexander Rush. 2017. Challenges in data-todocument generation. In Proceedings of the 2017 Conference on Empirical Methods
in Natural Language Processing, pages 2253–2263, Copenhagen, Denmark. Association for Computational Linguistics.
Kelvin Xu, Jimmy Ba, Ryan Kiros, Kyunghyun Cho, Aaron Courville, Ruslan Salakhudinov, Rich Zemel, and Yoshua Bengio. 2015. Show, attend and tell: Neural image caption
generation with visual attention. In International conference on machine learning,
pages 2048–2057. PMLR.

参考文献

111

Yuichi Yamashita and Jun Tani. 2008. Emergence of functional hierarchy in a multiple
timescale neural network model: a humanoid robot experiment. PLoS Comput Biol,
4(11):e1000220.
Zichao Yang, Phil Blunsom, Chris Dyer, and Wang Ling. 2017. Reference-aware language
models. In Proceedings of the 2017 Conference on Empirical Methods in Natural Language Processing, pages 1850–1859, Copenhagen, Denmark. Association for
Computational Linguistics.
Peter Young, Alice Lai, Micah Hodosh, and Julia Hockenmaier. 2014. From image descriptions to visual denotations: New similarity metrics for semantic inference over
event descriptions. Transactions of the Association for Computational Linguistics,
2:67–78.
Luowei Zhou, Chenliang Xu, and Jason J Corso. 2018a. Towards automatic learning of
procedures from web instructional videos. In AAAI Conference on Artificial Intelligence.
Luowei Zhou, Yingbo Zhou, Jason J. Corso, Richard Socher, and Caiming Xiong. 2018b.
End-to-End Dense Video Captioning With Masked Transformer. In Proceedings of the
IEEE Conference on Computer Vision and Pattern Recognition, pages 8739–8748.
仁 松原. 2020. 人工知能と認知科学. 認知科学, advpub:2020.001.

112

付 録A

A.1

発表業績

学会誌

• 濵園侑美、小林一郎、麻生英樹、中村友昭、長井隆行、持橋大地,“ヒューマノイドロ
ボットを用いた言語理解による動作生”. 知識と情報、日本知能情報ファジィ学会、32
巻 1 号 p. 632-642、2020.

A.2

査読付き国際会議

• Yumi Hamazono,Yui Uehara,Hiroshi Noji,Yusuke Miyao,Hiroya Takamura and Ichiro
Kobayashi,“Market Comment Generation from Data with Noisy Alignments”, The
13th International Conference on Natural Language Generation, Dec. 2020

• Yumi Hamazono,Tatsuya Ishigaki,Yusuke Miyao,Hiroya Takamura,Ichiro Kobayashi,
“Unpredictable Attributes in Market Comment Generation”, The 35th Pacific Asia
Conference on Language, Information and Computation, Nov. 2021

• Yumi Hamazono,Tatsuya Ishigaki,Yusuke Miyao,Hiroya Takamura,Ichiro Kobayashi,
“Unpredictable Attributes in Market Comment Generation”, The 2022 Conference
on Empirical Methods in Natural Language Processing, Dec. 2022

A.3

国内学会

• 濵園侑美, 上原由衣, 能地宏, 宮尾祐介, 高村大也, 小林一郎,“時系列データの動向説
明文生成における参照時刻の不整合解消に向けた取り組み”,言語処理学会第 26 回年
次大会,2020.

A.3. 国内学会

113

• 濵園侑美, 上原由衣, 能地宏, 宮尾祐介, 高村大也, 小林一郎,“時系列データの動向説
明文生成における参照時刻の不整合解消の精度向上にむけた取り組み”,言語処理学
会第 26 回年次大会,2020.

114

付 録B

B.1
B.1.1
1
2
3
4
5

使用したプログラム

自然言語からのロボット動作生成
動作作成プログラム

# -* - coding : utf -8 -* import sys
import string
import numpy . random as rm
import math

6
7
8
9
10
11
12

furu = [0 , 0 , 3.5 , 0.5 , 0 , 0 , -3.5 , 0.5]
furuu = [0 , 3.5 , 0 , 0.5 , 0 , -3.5 , 0 , 0.5]
itameru = [3.5 , 0 , 0 , 0.5 , -3.5 , 0 , 3 , 0.5 , 0 , 0 , -3 , 0.5]
kiru = [0 , 0 , -5 , 0.5 , 0 , 5 , 3.5 , 0.5]
mazeru = [0 , 3.5 , 0 , 0.5 , 3.5 , -3.5 , 0 , 0.5 , -3.5 , 0 , 0 , 0.5]
tsubusu = [0 , 0 , -3.5 , 0.5 , 0 , 0 , 3.5 , 0.5]

13
14
15
16
17
18
19

def degree ( bsn , adv_n ) :
num = 0
if bsn == " big ":
while num <= 4.5 + adv_n or num >= 7.5 + adv_n :
num = rm . normal (6 + adv_n , 1)
return num

20
21
22
23
24

elif bsn == " small ":
while num <= 0.5 + ( adv_n ) *0.5 or num >= 2.5 + ( adv_n ) *0.5:
num = rm . normal (1 + ( adv_n ) *0.5 , 0.8)
return num

25
26
27
28

elif bsn == " normal ":
num = 3.5
return num

29
30
31
32
33
34
35

def speed ( fsn , adv_n ) :
spd = 0
if fsn == " fast ":
while spd <= 6.5 + adv_n or spd >= 8 + adv_n :
spd = rm . normal (6 + adv_n ,1)
return spd

36
37
38
39
40

elif fsn == " slow ":
while spd <= 0.5 + ( adv_n ) *0.5 or spd >= 3 + ( adv_n ) *0.5:
spd = rm . normal (2 + ( adv_n ) *0.5 , 1)
return spd

41
42
43

elif fsn == " normal ":
spd = 5

B.1. 自然言語からのロボット動作生成
44

return spd

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

def change_num ( adv ) :
if adv >=0 and adv <=2:
num = degree (" big " , adv )
spd = speed (" fast " , adv )
elif adv == 3:
adv_n = 3 -3
num = degree (" big " , adv_n )
spd = speed (" normal " , adv_n )
elif adv >= 4 and adv <=5:
adv_n = adv - 4
num = degree (" normal " , adv_n )
spd = speed (" fast " , adv_n )
elif adv >= 6 and adv <= 8:
adv_n = adv - 6
num = degree (" small " , adv_n )
spd = speed (" normal " , adv_n )
elif adv >= 9 and adv <= 11:
adv_n = adv - 9
num = degree (" small " , adv_n )
spd = speed (" slow " , adv_n )
return round ( num , 6) , round ( spd , 6)

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

def save_list ( list , verb , adv , count ) :
k = 0
tanh_list = []
while k < len ( list ) :
nums = list [ k ]
if k % 4 == 3:
newnum = round (( math . tanh ( nums *0.2) ) , 6)
strnum = str ( newnum )
else :
newnum = round (( math . tanh ( nums *0.2) ) *0.5+0.5 , 6)
strnum = str ( newnum )
tanh_list . append ( strnum )
k +=1
if len ( tanh_list ) <=8:
act = "\ t ". join ( tanh_list )
tanh_act = act + "\ t " + act +"\ t " + act
else :
act = "\ t ". join ( tanh_list )
tanh_act = act + "\ t " + act

87
88
89
90
91
92

model = "% d_ % d_ % d . txt " % ( verb , adv , count )
# print ( model )
with open ( model , " w ") as f :
f . write ( tanh_act )
return True

93
94
95
96
97
98
99
100
101
102
103
104
105

adv_list = [[0 , 2 , 3 , 4 , 6 , 8 , 10] , [1 , 3 , 4 , 5 , 7 , 10 , 11] , [2 , 3 , 4 , 7 , 8 , 9 ,
11] , \
[1 , 2 , 3 , 5 , 6 , 9 , 10] , [0 , 1 , 3 , 4 , 6 , 7 , 9] , [0 , 3 , 5 , 7 , 8 , 9 , 11]]
# verb_list = [[0. , 0. , -1.* num , spd , 0. , 0. , num , spd ] ,\
[0. , num , 0. , spd , 0. , -1.* num , 0. , spd ] , \
[ num , 0. , 0. , spd , -1.* num , 0. , 3. , spd , 0. , 0. , -3. , spd ] ,\
[0. , 0. , -5. , spd , 0. , 5. , num , spd ] , \
[0. , num , 0. , spd , num , -1.* num , 0 , spd , -1.* num , 0 , 0 , spd ] , \
[0 , 0 , -1.* num , spd , 0 , 0 , num , spd ]]
j =0
for verb_adv in adv_list :
for adv in verb_adv :
i = 0

115

B.1. 自然言語からのロボット動作生成
while i < 100:
num , spd = change_num ( adv )
verb_list = [[0. , 0. , num , spd , 0. , 0. , -1.* num , spd ] ,\
[0. , num , 0. , spd , 0. , -1.* num , 0. , spd ] , \
[ num , 0. , 0. , spd , -1.* num , 0. , 3. , spd , 0. , 0. , -3. , spd ] ,\
[0. , 0. , -5. , spd , 0. , num , 5. , spd ] , \
[0. , num , 0. , spd , num , -1.* num , 0 , spd , -1.* num , 0 , 0 , spd ] ,\
[0 , 0 , -1.* num , spd , 0 , 0 , num , spd ]]
# furu = [0. , 0. , -1.* num , spd , 0. , 0. , num , spd ]
verb = verb_list [ j ]
save_list ( verb , j , adv , i )
i +=1

106
107
108
109
110
111
112
113
114
115
116
117
118

j +=1

B.1.2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

ロボット動作プログラム

#!/ opt / grx / bin / hrpsyspy
import os
import sys
import socket
import math
import time
import rtm
import waitInput
import bodyinfo
import java . lang . System
import org . omg . CORBA . DoubleHolder
import OpenHRP
from OpenHRP . R o b o t H a r d w a r e S e r v i c e P a c k a g e import SwitchStatus
from OpenHRP . R o b o t H a r d w a r e S e r v i c e P a c k a g e import R o b o t S t a t e H o l d e r
import sample
import test

17
18
19
20

def init ( host = ’ localhost ’) :
#
global vs , vs_svc , cvp , cvp_svc
#
global vs_head , vs_head_svc , cvp_head , cvp_head_svc

21
22

sample . init ( host )

23
24
25
26
27
28
29
30
31
32

def kugirimatome () :
ugoki = raw_input (" What is the name of ugoki ? >")
ugokilist =[]
JAD = []
while True :
putJAD = input (" get J ointAnglesD eg ? ( if fisnish , put 0) > ")
if putJAD == 0:
break
else :

33
34
35
36
37
38
39
40
41
42

JAD = sample . g e t J o i n t A n g le s De g ()
list1 = []
Body = []
ArmR = []
ArmL = []
HandR = []
HandL = []
newJAD = []# same format as bodyinfo . py

116

B.1. 自然言語からのロボット動作生成
43
44

for num in JAD :
list1 . append ( round ( num ,1) )

45
46
47
48
49
50
51
52
53
54

Body = list1 [0:3]
ArmR = list1 [3:9]
ArmL = list1 [9:15]
HandR = list1 [15:19]
HandL = list1 [19:23]
newJAD = [ Body , ArmR , ArmL , HandR , HandL ]
ttm = int ( input (" How fast ? > ") )
newugoki = [ newJAD , ttm ]
ugokilist . append ( newugoki )

55
56
57

print "% s = % r " %( ugoki , ugokilist )

58
59
60
61
62
63
64
65
66
67

def kihon ( sa ) :
ugoki = raw_input (" What is the name of kihon ? >")
ugokilist =[]
JAD = []
while True :
putJAD = input (" get J ointAnglesD eg ? ( if fisnish , put 0) > ")
if putJAD == 0:
break
else :

68
69
70
71
72
73
74
75
76

JAD = sa
list1 = []
Body = []
ArmR = []
ArmL = []
HandR = []
HandL = []
newJAD = []# same format as bodyinfo . py

77
78
79

for num in JAD :
list1 . append ( round ( num ,1) )

80
81
82
83
84
85
86
87
88
89

Body = list1 [0:3]
ArmR = list1 [3:9]
ArmL = list1 [9:15]
HandR = list1 [15:19]
HandL = list1 [19:23]
newJAD = [ Body , ArmR , ArmL , HandR , HandL ]
ttm = int ( input (" How fast ? > ") )
newugoki = [ newJAD , ttm ]
ugokilist . append ( newugoki )

90
91
92

print "% s = % r " %( ugoki , ugokilist )

93
94
95
96
97
98
99
100
101
102
103
104
105

def wake ( ugoki ) :
JAD = ugoki
Body = []
ArmR = []
ArmL = []
HandR = []
HandL = []
newJAD = []# same format as bodyinfo . py
Body = JAD [0:3]
ArmR = JAD [3:9]
ArmL = JAD [9:15]
HandR = JAD [15:19]

117

B.1. 自然言語からのロボット動作生成
106
107
108

118

HandL = JAD [19:23]
newJAD = [ Body , ArmR , ArmL , HandR , HandL ]
return newJAD

109
110
111
112
113
114
115
116

def base_use () :
fans = raw_input (" get first Join tAngle sDeg ?( yes / no ) :")
while fans !=" yes ":
fans = raw_input (" get first Join tAngle sDeg ?( yes / no ) :")
first = sample . g et J oi n t A n g l e s D e g ()

117
118
119
120
121

sans = raw_input (" get second JointAng lesDeg ?( yes / no ) :")
while sans !=" yes ":
sans = raw_input (" get second JointAng lesDeg ?( yes / no ) :")
second = sample . g e tJ o i n t A n g l e s D eg ()

122
123
124

sa =[ round (( y - x ) ,1) for (x , y ) in zip ( first , second ) ]
return sa

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

def mkaction ( s ) :
x = test . x
y = test . y
z = test . z
i =0
ugokis =[]
ugokiss =[]
ugoki = sample . g et J oi n t A n g l e s D e g ()
while i != len ( s ) :
# print s [ i ][3]
xd =[ h * s [ i ][0] for h in x ]
yd =[ j * s [ i ][1] for j in y ]
zd =[ k * s [ i ][2] for k in z ]
ugoki =[ round (( xs + ys + zs + ugoki ) ,1) for ( xs , ys , zs , ugoki ) in zip ( xd , yd , zd , ugoki )
]
ugokis = wake ( ugoki )
# print ugoki
ugokis =[ ugokis ,( s [ i ][3]) ]
ugokiss = ugokiss +[ ugokis ]
print ugokiss
i = i +1
return ugokiss

147
148
149
150
151
152
153
154
155
156

if __name__ == ’ __main__ ’ or __name__ == ’ main ’:
if len ( sys . argv ) > 1:
robotHost = sys . argv [1]
else :
robotHost = None
init ( robotHost )
# sample . s h o w J o i n t A n g l e s D e g ()
# kugirimatome ()

157
158
159
160
161
162
163

sample . goInitial ()
s =[[0 ,0 , -5 ,3] ,[0 ,0.5 ,5 ,3] ,[0 ,0 , -5 ,3]] 時系列 # で作ったものを入力とする AAM
r = mkaction ( s )
dblHolder = org . omg . CORBA . DoubleHolder ()
for p in r :
sample . s e t J o i n t A n g l e s D e g ( p [0] , p [1] , dblHolder )

164
165

sample . goInitial ()

B.1. 自然言語からのロボット動作生成

B.1.3
1
2
3
4
5

ロボット動作プログラム

# -* - coding : utf -8 -* import sys
import string
import numpy . random as rm
import math

6
7
8
9
10
11
12

furu = [0 , 0 , 3.5 , 0.5 , 0 , 0 , -3.5 , 0.5]
furuu = [0 , 3.5 , 0 , 0.5 , 0 , -3.5 , 0 , 0.5]
itameru = [3.5 , 0 , 0 , 0.5 , -3.5 , 0 , 3 , 0.5 , 0 , 0 , -3 , 0.5]
kiru = [0 , 0 , -5 , 0.5 , 0 , 5 , 3.5 , 0.5]
mazeru = [0 , 3.5 , 0 , 0.5 , 3.5 , -3.5 , 0 , 0.5 , -3.5 , 0 , 0 , 0.5]
tsubusu = [0 , 0 , -3.5 , 0.5 , 0 , 0 , 3.5 , 0.5]

13
14
15
16
17
18
19

def degree ( bsn , adv_n ) :
num = 0
if bsn == " big ":
while num <= 4.5 + adv_n or num >= 7.5 + adv_n :
num = rm . normal (6 + adv_n , 1)
return num

20
21
22
23
24

elif bsn == " small ":
while num <= 0.5 + ( adv_n ) *0.5 or num >= 2.5 + ( adv_n ) *0.5:
num = rm . normal (1 + ( adv_n ) *0.5 , 0.8)
return num

25
26
27
28

elif bsn == " normal ":
num = 3.5
return num

29
30
31
32
33
34
35

def speed ( fsn , adv_n ) :
spd = 0
if fsn == " fast ":
while spd <= 6.5 + adv_n or spd >= 8 + adv_n :
spd = rm . normal (6 + adv_n ,1)
return spd

36
37
38
39
40

elif fsn == " slow ":
while spd <= 0.5 + ( adv_n ) *0.5 or spd >= 3 + ( adv_n ) *0.5:
spd = rm . normal (2 + ( adv_n ) *0.5 , 1)
return spd

41
42
43
44

elif fsn == " normal ":
spd = 5
return spd

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

def change_num ( adv ) :
if adv >=0 and adv <=2:
num = degree (" big " , adv )
spd = speed (" fast " , adv )
elif adv == 3:
adv_n = 3 -3
num = degree (" big " , adv_n )
spd = speed (" normal " , adv_n )
elif adv >= 4 and adv <=5:
adv_n = adv - 4
num = degree (" normal " , adv_n )
spd = speed (" fast " , adv_n )
elif adv >= 6 and adv <= 8:
adv_n = adv - 6
num = degree (" small " , adv_n )

119

B.1. 自然言語からのロボット動作生成
61
62
63
64
65
66

spd = speed (" normal " , adv_n )
elif adv >= 9 and adv <= 11:
adv_n = adv - 9
num = degree (" small " , adv_n )
spd = speed (" slow " , adv_n )
return round ( num , 6) , round ( spd , 6)

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

def save_list ( list , verb , adv , count ) :
k = 0
tanh_list = []
while k < len ( list ) :
nums = list [ k ]
if k % 4 == 3:
newnum = round (( math . tanh ( nums *0.2) ) , 6)
strnum = str ( newnum )
else :
newnum = round (( math . tanh ( nums *0.2) ) *0.5+0.5 , 6)
strnum = str ( newnum )
tanh_list . append ( strnum )
k +=1
if len ( tanh_list ) <=8:
act = "\ t ". join ( tanh_list )
tanh_act = act + "\ t " + act +"\ t " + act
else :
act = "\ t ". join ( tanh_list )
tanh_act = act + "\ t " + act

87
88
89
90
91
92

model = "% d_ % d_ % d . txt " % ( verb , adv , count )
# print ( model )
with open ( model , " w ") as f :
f . write ( tanh_act )
return True

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

adv_list = [[0 , 2 , 3 , 4 , 6 , 8 , 10] , [1 , 3 , 4 , 5 , 7 , 10 , 11] , [2 , 3 , 4 , 7 , 8 , 9 ,
11] , \
[1 , 2 , 3 , 5 , 6 , 9 , 10] , [0 , 1 , 3 , 4 , 6 , 7 , 9] , [0 , 3 , 5 , 7 , 8 , 9 , 11]]
# verb_list = [[0. , 0. , -1.* num , spd , 0. , 0. , num , spd ] ,\
[0. , num , 0. , spd , 0. , -1.* num , 0. , spd ] , \
[ num , 0. , 0. , spd , -1.* num , 0. , 3. , spd , 0. , 0. , -3. , spd ] ,\
[0. , 0. , -5. , spd , 0. , 5. , num , spd ] , \
[0. , num , 0. , spd , num , -1.* num , 0 , spd , -1.* num , 0 , 0 , spd ] , \
[0 , 0 , -1.* num , spd , 0 , 0 , num , spd ]]
j =0
for verb_adv in adv_list :
for adv in verb_adv :
i = 0
while i < 100:
num , spd = change_num ( adv )
verb_list = [[0. , 0. , num , spd , 0. , 0. , -1.* num , spd ] ,\
[0. , num , 0. , spd , 0. , -1.* num , 0. , spd ] , \
[ num , 0. , 0. , spd , -1.* num , 0. , 3. , spd , 0. , 0. , -3. , spd ] ,\
[0. , 0. , -5. , spd , 0. , num , 5. , spd ] , \
[0. , num , 0. , spd , num , -1.* num , 0 , spd , -1.* num , 0 , 0 , spd ] ,\
[0 , 0 , -1.* num , spd , 0 , 0 , num , spd ]]
# furu = [0. , 0. , -1.* num , spd , 0. , 0. , num , spd ]
verb = verb_list [ j ]
save_list ( verb , j , adv , i )
i +=1
j +=1

120

B.1. 自然言語からのロボット動作生成

B.1.4
1
2
3
4
5
6
7

121

cookpad コーパス MySQL から word2vec が使える形への変換

\ begin { small }
\ begin { verbatim }
# -* - coding : utf -8 -* import mysql . connector
import re
import MeCab
import unicodedata

8
9
10

tagger = MeCab . Tagger ( ’ mecabrc -d / usr / local / lib / mecab / dic / mecab - ipadic - neologd ’)
line_list = []

11
12
13
14
15
16
17
18
19
20
21
22
23
24

def make_sentence ( line_list ) :
if not line_list [ len ( line_list ) -1][1] == 読点 "" and \
line_list [ len ( line_list ) -1][0] == 記号 "" or \
line_list [ len ( line_list ) -1][1] == 終助詞 "" or \
line_list [ len ( line_list ) -1][2] == 基本形 "" or \ 命令
"" in line_list [ len ( line_list ) -1][2] or \
line_list [ len ( line_list ) -1][0] == 名詞 "":
sentence = ""
for l in line_list :
sentence += ( l [3]) + " "
print ( sentence )
return True

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

def wakachi ( line ) :
global line_list
node = tagger . parseToNode ( line )
node = node . next
while node . next :
ftr = node . feature . split (" ,")
# print ( ftr [0] , ftr [1] , ftr [5] , ftr [6])
if ftr [6] == "*":
ftr [6] = node . surface
if ftr [0] == 名詞 ’ ’:
# print ( node . surface )
ftr [6] = node . surface
line_list . append ([ ftr [0] , ftr [1] , ftr [5] , ftr [6]])
node = node . next
# print ( line_list )
if make_sentence ( line_list ) is True :
line_list = []
# print ( line_list )

44
45
46
47

def rm_return ( line ) :
list = re . sub ( ’[\ t \ r \ f \ v ] ’ , ’’, line . strip () )
return list

48
49
50
51
52
53
54
55
56
57
58
59
60

def normalise ( s ) :
s = unicodedata . normalize ( ’ NFKC ’ , s ) 正規化する文字化け
#()
s = re . sub ( ’[\ UTF {02 D7 }\ UTF {058 A ‐ }\ UTF {2011} \
\ UTF {2012}\ UTF {2013}\ UTF {2043}\ UTF {207 B }\ UTF {208 B − }+] ’ , ’-’, s )
s = re . sub ( ’[\ UTF { FE63 }\ UTF { FF0D }^^ ef ^^ bd ^^ ――─━ー b0 ]+ ’ , ー ’’, s )
s = re . sub ( ’[~\ UTF {223 C }\ UTF {223 E ∼ }\ UTF {3030}\ UTF { FF5E }] ’ , ’’, s )
s = re . sub ( ’[\ UTF {2460} -\ UTF {2468}]+ ’ , ’’, s )
s = re . sub ℃ ( ’ ’ , 度 ’’, s )
s = re . sub , ( ’ ’ , 、 ’’, s )

B.1. 自然言語からのロボット動作生成
61
62
63
64
65
66

122

s = re . sub . ( ’ ’ , 。 ’’, s )
s = re . sub ( ’[\ UTF {266 C }\ UTF ♪ {2764}\ UTF {261 D }\ UTF {2661}\ UTF {266 B }\ UTF {263 A ◆
}\ UTF {2765}\ CID {115}] ’ , ’\n ’ , s )
s = re . sub ( ’\ UTF {273 F } ’ , ’’, s )
s = s . strip ( ’\ x00 ’)
s = s . replace ° ( ’C ’ , 度 ’ ’)
return s

67
68
69
70
71
72
73
74
75
76

def put_return ( s ) :
s = re . sub 。 ( ’ ’ , 。 ’\n ’ , s )
list = s . split ( ’\n ’)
for l in list :
l . strip ()
if not l == ’’ and not l == ’ ’:
# print ( l )
wakachi ( l )

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

def ge t_wor d_mysq l ( db_name , pw ) :
con = mysql . connector . connect ( host = ’ localhost ’ , db = db_name , user = ’ root ’ , \
passwd = pw , buffered = True )
cur = con . cursor ()
select = " select memo from steps where memo like \ 一口大
’%% ’" # where memo like 切 ’%% ’"
cur . execute ( select )
res = cur . fetchall ()
for row in res :
if not row [0] == None and not row [0] == ’ ’: # and "\ UTF {2764}" in row [0]:
# print ( row )
put_return ( rm_return ( normalise ( row [0]) ) )
cur . close
con . close

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

def get_recipe_id ( db_name , pw ) :
con = mysql . connector . connect ( host = ’ localhost ’ , db = db_name , user = ’ root ’ , \
passwd = pw , buffered = True )
cur = con . cursor ()
select = " select recipe_id from steps " # where memo like 切 ’%% ’"
cur . execute ( select )
res = cur . fetchall ()
min = ""
max = ""
for row in res :
if min == "":
min = row [0]
if max == "":
max = row [0]
else :
max = row [0]
print ( min , max )
cur . close
con . close

113
114
115
116
117

if __name__ == " __main__ ":
get_wo rd_mysql ( ’ cookpad_data ’ , pw ) # はのパスワードを入力 pwmysql
# get_recipe_id ( ’ cookpad_data ’ , pw )

B.1. 自然言語からのロボット動作生成

B.1.5

ネットワークの設計プログラム
Listing B.1: Net2

1
2
3
4

# -* - coding : utf -8 -* import chainer
import chainer . functions as F
import chainer . links as L

5
6
7
8
9
10
11
12
13
14
15
16

class act_ predic tion ( chainer . Chain ) :
def __init__ ( self , verb_in , adv_in , unit , act_out ) :
super ( act_prediction , self ) . __init__ (
verb_l1 = L . Linear ( verb_in , unit ) ,
verb_l2 = L . Linear ( unit , unit ) ,
adv_l1 = L . Linear ( adv_in , unit ) ,
adv_l2 = L . Linear ( unit , unit ) ,
l3 = L . Linear ( unit , act_out ) ,
)
def softplus ( self , x ) :
return F . log ( F . exp ( x ) + 1)

17
18
19
20

def __call__ ( self , verb , adv ) :
verb_h1 = self . softplus ( self . verb_l1 ( verb ) )
verb_h2 = self . softplus ( self . verb_l2 ( verb_h1 ) )

21
22
23

adv_h1 = self . softplus ( self . adv_l1 ( adv ) )
adv_h2 = self . softplus ( self . adv_l2 ( adv_h1 ) )

24
25

output = F . sigmoid ( self . l3 ( verb_h2 + adv_h2 ) )

26
27

return output

Listing B.2: Net3
1
2
3
4

# -* - coding : utf -8 -* import chainer
import chainer . functions as F
import chainer . links as L

5
6
7
8
9

class act_ predic tion ( chainer . Chain ) :
def __init__ ( self , verb_in , adv_in , unit , act_out ) :
super ( act_prediction , self ) . __init__ (
verb_l1 = L . Linear ( verb_in , unit ) ,

10
11

adv_l1 = L . Linear ( adv_in , unit ) ,

12
13
14
15
16
17

l2 = L . Linear ( unit , unit ) ,
l3 = L . Linear ( unit , act_out ) ,
)
def softplus ( self , x ) :
return F . log ( F . exp ( x ) + 1)

18
19
20

def __call__ ( self , verb , adv ) :
verb_h1 = self . softplus ( self . verb_l1 ( verb ) )

21
22

adv_h1 = self . softplus ( self . adv_l1 ( adv ) )

23
24
25

h2 = self . softplus ( self . l2 ( verb_h1 + adv_h1 ) )
output = F . sigmoid ( self . l3 ( h2 ) )

26
27

return output

123

B.1. 自然言語からのロボット動作生成

Listing B.3: Net4
1
2
3
4

# -* - coding : utf -8 -* import chainer
import chainer . functions as F
import chainer . links as L

5
6
7
8
9
10
11
12
13
14
15
16

class act_ predic tion ( chainer . Chain ) :
def __init__ ( self , verb_in , adv_in , unit , act_out ) :
super ( act_prediction , self ) . __init__ (
verb_l1 = L . Linear ( verb_in , unit ) ,
adv_l1 = L . Linear ( adv_in , unit ) ,
adv_verb_l2 = L . Linear ( unit , unit ) ,
l2 = L . Linear ( unit , unit ) ,
l3 = L . Linear ( unit , act_out ) ,
)
def softplus ( self , x ) :
return F . log ( F . exp ( x ) + 1)

17
18

def __call__ ( self , verb , adv ) :

19

verb_h1 = self . softplus ( self . verb_l1 ( verb ) )

20
21

adv_h1 = self . softplus ( self . adv_l1 ( adv ) )
adv_verb_h2 = self . softplus ( self . adv_verb_l2 ( verb_h1 + adv_h1 ) )

22
23
24

h2 = self . softplus ( self . l2 ( verb_h1 + adv_verb_h2 ) )
output = F . sigmoid ( self . l3 ( h2 ) )

25
26
27

return output

28

B.1.6
1

訓練プログラム

# -* - coding : utf -8 -* -

2
3
4

from __future__ import pr int_f unction
import argparse

5
6
7
8
9
10
11
12
13
14
15
16

import numpy as np
import six
# import net3 as net
# import net2 as net
import net1 as net 使うネットワークに合わせて # を考える import
import read_file
import time
import chainer
import chainer . functions as F
from chainer import optimizers
from chainer import serializers

17
18
19
20
21
22

import matplotlib
matplotlib . use (" Agg ")
import matplotlib . pyplot as plt
import os

124

B.1. 自然言語からのロボット動作生成
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

parser = argparse . Argum entPar ser ( description = ’ NN for act prediction ’)
parser . add_argument ( ’ - - gpu ’ , ’-g ’ , default = -1 , type = int ,
help = ’ GPU ID ( negative value indicates CPU ) ’)
# 数 epoch
parser . add_argument ( ’ - - epoch ’ , ’-e ’ , default =20 , type = int ,
help = ’ number of epochs to learn ’) 中間層のノード数
#
parser . add_argument ( ’ - - unit ’ , ’-u ’ , default =14 , type = int ,
help = ’ number of units ’) 動作入力層のノード数
#
parser . add_argument ( ’ - - verb_input ’ , ’-vi ’ , default =6 , type = int ,
help = ’ number of input ’) 副詞入力層のノード数
#
parser . add_argument ( ’ - - adv_input ’ , ’-ai ’ , default =12 , type = int ,
help = ’ number of input ’) バッチ数
#
parser . add_argument ( ’ - - batchsize ’ , ’-b ’ , type = int , default =100 ,
help = ’ learning minibatch size ’)

41
42
43

parser . add_argument ( ’ - - dataset_dir ’ , " - d " , default = ’ dataset1601 ’ ,
help = ’ Path to dataset ’)

44
45
46

parser . add_argument ( ’ - - save_dir ’ , " - sd " , default = ’ model ’ ,
help = ’ Path to model name ’) ネットワークの種類

47
48
49
50

#
# parser . add_argument ( ’ - - network_name ’ , " - n " , default = ’ net ’ ,
#
help = ’ Path to net name ’)

51
52
53
54
55
56
57
58
59
60
61
62

args = parser . parse_args ()
if not os . path . exists ( args . save_dir ) :
os . mkdir ( args . save_dir )
batchsize = args . batchsize # default :100
n_epoch = args . epoch
# default :20
n_units = args . unit
# default :14
verb_in = args . verb_input
# default :6
adv_in = args . adv_input
# default :12
dataset_dir = args . dataset_dir
save_dir = args . save_dir
# network = args . network_name

63
64
65
66
67
68
69

print ( ’ GPU : {} ’. format ( args . gpu ) )
print ( ’# unit : {} ’. format ( args . unit ) )
print ( ’# Minibatch - size : {} ’. format ( args . batchsize ) )
print ( ’# epoch : {} ’. format ( args . epoch ) )
print ( ’ ’) データ準備

70
71
72
73
74
75
76
77
78
79
80

#
print ( ’ load dataset ... ’)
all_verb , all_adv , all_act = read_file . read_file ( dataset_dir )
print ( ’ Done ’)
# print ( len ( all_verb ) )
N = 3800
train_verb = all_verb [: N ]
train_adv = all_adv [: N ]
train_act = all_act [: N ]

81
82
83
84
85

test_verb = all_verb [ N :]
test_adv = all_adv [ N :]
test_act = all_act [ N :]

125

B.1. 自然言語からのロボット動作生成
86

N_test = len ( test_act ) モデルセット

87
88
89

#
mlp = net . act_predi ction ( verb_in , adv_in , n_units , 24)

90
91
92
93
94
95
96

# GPU を使う場合
if args . gpu >= 0:
chainer . cuda . get_device ( args . gpu ) . use ()
mlp . to_gpu () 「
# は xp , なら CPUnp , ならとする」というお得意の呪文 GPUcupychain er
xp = np if args . gpu < 0 else chainer . cuda . cupy

97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

# Setup optimizer
optimizer = optimizers . Adam ()
# optimizer = optimizers . SGD ( lr =0.001) # 最適化関数はを使用 Adam
optimizer . setup ( mlp ) # optimizer に model をセット
# Learning loop
train_loss = []
test_loss = []
for epoch in six . moves . range (1 , n_epoch + 1) :
# print ( ’ epoch ’ , epoch )
### training ###
perm = np . random . permutation ( N ) # 個の数字をランダムな順に並べる N ( shuffle )
sum_loss = 0
start = time . time () # 計算時間計測開始
for i in six . moves . range (0 , N , batchsize ) :
verb = chainer . Variable ( xp . asarray ( train_verb [ perm [ i : i + batchsize ]]) )
adv = chainer . Variable ( xp . asarray ( train_adv [ perm [ i : i + batchsize ]]) )
act = chainer . Variable ( xp . asarray ( train_act [ perm [ i : i + batchsize ]]) )

115
116
117
118
119
120
121
122

optimizer . zero_grads ()
# output , loss = mlp ( verb , adv , act )
loss = F . m e a n _ s q u a r e d _ e r r o r ( mlp ( verb , adv ) , act )
loss . backward ()
optimizer . update ()
sum_loss += float ( loss . data ) * len ( act . data )
end = time . time ()

123
124
125
126
127
128

elapsed_time = end - start
throughput = N / elapsed_time
train_loss . append ( sum_loss / N )
# print ( ’ train mean loss = {} , throughput = {} ,\
images / sec ’. format ( sum_loss /N , throughput ) )

129
130
131
132
133
134
135
136
137
138
139
140
141

# test
sum_loss = 0
for i in six . moves . range (0 , N_test , batchsize ) :
verb = chainer . Variable ( xp . asarray ( train_verb [ perm [ i : i + batchsize ]]) ,\
volatile = ’ on ’) # したくないときは dorpouton
adv = chainer . Variable ( xp . asarray ( train_adv [ perm [ i : i + batchsize ]]) ,\
volatile = ’ on ’)
act = chainer . Variable ( xp . asarray ( train_act [ perm [ i : i + batchsize ]]) ,\
volatile = ’ on ’)
loss = F . m e a n _ s q u a r e d _ e r r o r ( mlp ( verb , adv ) , act )
# とだけ計算 forwardloss , の必要なし backward

142
143
144
145
146
147
148

sum_loss += float ( loss . data ) * len ( act . data )
# sum_accuracy += float ( model . accuracy . data ) * len ( t . data )
# print ( ’ test mean loss ={} , \
accuracy ={} ’. format ( sum_loss / N_test , sum_accuracy / N_test ) )
test_loss . append ( sum_loss / N_test )
# print ( ’ test mean loss ={} ,\

126

B.1. 自然言語からのロボット動作生成
149

throughput ={} images / sec ’. format ( sum_loss / N_test , throughput ) )

150
151
152
153
154

if epoch % 1000 == 0:
model_path = "% s / a c t _ I n _ v e rb_ a dv_ % d . model " % ( save_dir , epoch )
# with open ( model_path , " w ") as f :
serializers . save_npz ( model_path , mlp )

155

state_path = "% s / a c t _ I n _ v e rb_ a dv_ % d . state " % ( save_dir , epoch )
# with open ( state_path , " w ") as f :
serializers . save_npz ( state_path , optimizer )

156
157
158
159
160
161
162
163
164
165

# Save the model and the optimizer
print ( ’ save the model ’)
model_path = "% s / a c t _ I n _ v e r b _ a d v _ % d . model " % ( save_dir , epoch )
# with open ( model_path , " w ") as f :
serializers . save_npz ( model_path , mlp )

166
167
168
169
170

print ( ’ save the optimizer ’)
state_path = "% s / a c t _ I n _ v e r b _ a d v _ % d . state " % ( save_dir , epoch )
# with open ( state_path , " w ") as f :
serializers . save_npz ( state_path , optimizer )

171
172
173
174
175
176
177
178
179

plt . figure ( figsize =(8 ,12) )
plt . subplot (2 , 1 , 1)
plt . title (" Loss of Train Data Recognition .")
plt . ylim ( ymax = round ( train_loss [0] ,1) )
plt . plot ( range ( len ( train_loss ) ) , train_loss )
plt . text ( len ( train_loss ) -1 , train_loss [ -1] ,\
round ( train_loss [ -1] , 6) , ha = ’ right ’ , va = ’ bottom ’)

180
181
182
183
184
185
186
187
188
189

plt . subplot (2 , 1 , 2)
plt . title (" Loss of Test Data Recognition .")
# plt . yscale (" log ")
plt . ylim ( ymax =0.1)
plt . plot ( range ( len ( test_loss ) ) , test_loss )
plt . text ( len ( test_loss ) -1 , test_loss [ -1] , \
round ( test_loss [ -1] , 6) , ha = ’ right ’ , va = ’ bottom ’)
plt . tight_layout ()
plt . savefig ("% s / loss . png " %( save_dir ) )

B.1.7
1
2
3
4

3D 描写プログラム

from mpl_toolkits . mplot3d import Axes3D
import numpy as np
import matplotlib . pyplot as plt
# を取得 Axes3DSubplot

5
6
7
8
9
10
11
12
13
14

def make_fig (x , y , z , name ) :
fig = plt . figure ()
ax = fig . gca ( projection = ’3d ’)
Xz , Yz = np . meshgrid ( np . arange (0 , 8 , 7) , np . arange ( -7 , 8 , 7) )
Zz = 0
ax . plot_surface ( Xz , Zz , Yz , rstride =1 , cstride =1 , alpha = 0.1)
ax . plot_surface ( Zz , Xz , Yz , rstride =1 , cstride =1 , alpha = 0.1)
line , = ax . plot (x , y , z , zdir = ’z ’)
ax . view_init (15.0 , 30.0)

127

B.1. 自然言語からのロボット動作生成
15
16
17

plt . axis ( ’ scaled ’)
fig_name = name + ". png "
fig . savefig ( fig_name )

B.1.8
1

評価プログラム

# -* - coding : utf -8 -* -

2
3
4

from __future__ import pr int_f unction
import argparse

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

import numpy as np
import six
import os
import time
import chainer
import chainer . functions as F
from chainer import optimizers
from chainer import serializers
import matplotlib . pyplot as plt
import math
import mkfig #3 に描写 D
import mkdefact_0112 as mkdefact デフォルトの動作を作成 #
import read_file
# import net1 as net ネットワークに合わせて選ぶ #
# import net2 as net
# import net3 as net

22
23
24
25
26
27
28
29

parser = argparse . Argum entPar ser ( description = ’ NN for act prediction ’)
parser . add_argument ( ’ - - gpu ’ , ’-g ’ , default = -1 , type = int ,
help = ’ GPU ID ( negative value indicates CPU ) ’)
# 数 epoch
# parser . add_argument ( ’ - - epoch ’ , ’-e ’ , default =20 , type = int ,
#
help = ’ number of epochs to learn ’) 中間層のノード数

30
31
32
33
34
35
36
37
38
39

#
parser . add_argument ( ’ - - unit ’ , ’-u ’ , default =14 , type = int ,
help = ’ number of units ’) 動作入力層のノード数
#
parser . add_argument ( ’ - - verb_input ’ , ’-vi ’ , default =6 , type = int ,
help = ’ number of input ’) 副詞入力層のノード数
#
parser . add_argument ( ’ - - adv_input ’ , ’-ai ’ , default =12 , type = int ,
help = ’ number of input ’) 学習モデル

40
41
42
43

#
parser . add_argument ( ’ - - model ’ , " - m " , default = ’mlp ’ ,
help = ’ Path to trained all movement model ’) ネットワークの種類

44
45
46
47

#
# parser . add_argument ( ’ - - network_name ’ , " - n " , default = ’ net ’ ,
#
help = ’ Path to net name ’)

48
49
50
51
52

args = parser . parse_args ()
if not os . path . exists ( args . model ) :
os . mkdir ( args . model )
# batchsize = args . batchsize # default :100

128

B.1. 自然言語からのロボット動作生成
53
54
55
56
57

# n_epoch = args . epoch
# default :20
n_units = args . unit
# default :1000
verb_in = args . verb_input
# default :6
adv_in = args . adv_input
# default :12
model = args . model + ". model "

58
59
60
61
62
63

print ( ’ GPU : {} ’. format ( args . gpu ) )
print ( ’# unit : {} ’. format ( args . unit ) )
# print ( ’# Minibatch - size : {} ’. format ( args . batchsize ) )
# print ( ’# epoch : {} ’. format ( args . epoch ) )
print ( ’ ’)

64
65
66
67
68
69
70
71
72

if " share "
import
elif " hid "
import
elif " sig "
import
elif " sft "
import

in model :
net_share as net
in model :
net_hid2 as net
in model :
net_sig as net
in model :
net_softplus as net

73
74
75

mlp = net . act_predi ction ( verb_in , adv_in , n_units , 24)
serializers . load_npz ( model , mlp )

76
77
78

loss_path = "% s / loss_result . txt " % ( args . model )
fl = open ( loss_path , " w ")

79
80
81
82
83
84

# GPU を使う場合
if args . gpu >= 0:
chainer . cuda . get_device ( args . gpu ) . use ()
mlp . to_gpu () 「

85
86
87

# は xp , なら CPUnp , ならとする」というお得意の呪文 GPUcupychain er
xp = np if args . gpu < 0 else chainer . cuda . cupy

88
89
90
91
92
93
94
95
96
97
98
99
100

verb_ja = ふる ["" , ふるう "" , 炒める "" , 切る "" , 混ぜる "" , つぶす ""]
adv_ja = さっと ["" , ざっと "" , ザクザク "" , たっぷり "" , 手早い "" , \ 一気に
"" , 少し "" , 細かい "" , ちょっと "" , しっかり "" , きちんと "" , じっくり ""]
defomove = mkdefact . mkdef ()
# print ( defomove )
su m_ t ra in d _l oss = 0
sum_non_loss = 0
sum_loss = 0
adv_list = [[0 , 2 , 3 , 4 , 6 , 8 , 10] , [1 , 3 , 4 , 5 , 7 , 10 , 11] , [2 , 3 , 4 , 7 , 8 , 9 ,
11] ,\
[1 , 2 , 3 , 5 , 6 , 9 , 10] , [0 , 1 , 3 , 4 , 6 , 7 , 9] , [0 , 3 , 5 , 7 , 8 , 9 , 11]]
str_list , vec_list = read_file . r ead_word_file ( word_file )
# word_file = で作ったベクトルを保存したファイル word2vec

101
102
103
104
105
106
107
108
109
110
111
112
113
114

for i in range ( len ( verb_ja ) ) :
# np_verb = np . array ([0.] * verb_in , dtype = np . float32 )
# np_verb [ i ] = 1.
result_path = "% s /% d % s_result . txt " % ( args . model , i , verb_ja [ i ])
f = open ( result_path , " w ")
v_sum_loss = 0
for j in range ( len ( adv_ja ) ) :
# np_adv = np . array ([0.] * adv_in , dtype = np . float32 )
# np_adv [ j ] = 1.
verb_vec = read_file . str_to_vec ( str_list , vec_list , verb_ja [ i ])
adv_vec = read_file . str_to_vec ( str_list , vec_list , adv_ja [ j ])
verb = chainer . Variable ( xp . asarray ([ verb_vec ]) , volatile = ’ on ’)
adv = chainer . Variable ( xp . asarray ([ adv_vec ]) , volatile = ’ on ’)

129

B.1. 自然言語からのロボット動作生成
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

130

out = mlp ( verb , adv )
l = ( list ( out . data ) )
for k in l :
num = list ( k )
t = 0
sum = 0
while t < len ( num ) :
if t % 4 == 3:
num [ t ] = round (0.25* math . log ((1+( float ( num [ t ]) ) ) / \
(1 -( float ( num [ t ]) ) ) ) ,2)
else :
num [ t ] = round (2.5* math . log ((1+(( float ( num [ t ]) -0.5) *2) ) \
/(1 -(( float ( num [ t ]) -0.5) *2) ) ) , 2)
if i == 2 or i == 4:
loss = defomove [ j ][ i ][ t %12] - num [ t ]
else :
loss = defomove [ j ][ i ][ t %8] - num [ t ]
loss_mean = loss * loss
sum += loss_mean
t += 1
# print (i , j )
rms = round ( math . sqrt ( sum / t ) , 4)
if j in adv_list [ i ]:
su m_ t ra in d _l o ss += rms
else :
sum_non_loss += rms
sum_loss += rms
v_sum_loss += rms
# print ( verb_ja [ i ] , adv_ja [ j ] , rms )
# print ([ num [ r : r +4] for r in range (0 , len ( num ) , 4) ])

145
146

num_list = [ num [ r : r +4] for r in range (0 , len ( num ) , 4) ]

147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163

x = [0.]
y = [0.]
z = [0.]
countss =0
if i == 2 or i == 4:
while countss < 3:
x . append ( x [ countss ]
y . append ( y [ countss ]
z . append ( z [ countss ]
countss +=1
else :
while countss < 2:
x . append ( x [ countss ]
y . append ( y [ countss ]
z . append ( z [ countss ]
countss +=1

+ num_list [ countss ][0])
+ num_list [ countss ][1])
+ num_list [ countss ][2])

+ num_list [ countss ][0])
+ num_list [ countss ][1])
+ num_list [ countss ][2])

164
165
166
167
168
169
170
171
172
173
174
175
176

mkfig . make_fig (x , y , z , args . model +"/"+ str ( i ) +" _ "+ str ( j ) + verb_ja [ i ]+ adv_ja [
j ])
result_path = "% s / result . txt " % ( args . model )
# with open ( result_path , " a ") as f :
f . write ( verb_ja [ i ] + "\ t "+ adv_ja [ j ] + "\ n ")
f . write ( str ( rms ) +"\ n ")
f . write ( str ( num_list ) + "\ n ")
fl . write ( str ( i ) +"\ t "+ str ( j ) +"\ t "+ str ( rms ) +"\ n ")
f . close ()
fl . write ( str ( i ) +"\ t "+ str ( round ( v_sum_loss /12 , 4) ) + "\ n ")
fl . write ("\ n " + " all_loss \ t "+ str ( round ( sum_loss /12/6 , 4) ) + "\ n ")
fl . write (" traind_loss \ t "+ str ( round ( su m _trai nd _lo ss /7/6 , 4) ) + "\ n ")
fl . write (" n ontraind_los s \ t "+ str ( round ( sum_non_loss /5/6 , 4) ) + "\ n ")

B.2. 一般ドメイン実況生成
177

131

fl . close ()

B.2
B.2.1

一般ドメイン実況生成
実況コメント録音 UI
Listing B.4: Recording

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

< script src =" https :// sdk . amazonaws . com / js / aws - sdk -2.142.0. min . js " > < script
src =" https :// ajax . googleapis . com / ajax / libs / jquery /3.2.1/ jquery . min . js " > >
< link href =" https :// s3 . amazonaws . com / mturk - public / bs30 / css / bootstrap . min . css " rel ="
stylesheet " / >
< link href =" https :// fonts . googleapis . com / icon ? family = Material + Icons " rel ="
stylesheet " / >
< style type =" text / css " > fieldset {
padding : 10 px ;
background : # fbfbfb ;
border - radius : 5 px ;
margin - bottom : 5 px ;
}
. f i l e U p l o a d F i e l d s e t . record_button {
display : none ;
}
.d - flex {
display : flex ;
}
. ytplayer . nocontrol {
pointer - events : none ;
}
. recordway {
display : none ;
}

< section class =" container " id =" Other " style =" margin - bottom :15 px ; padding : 10 px 10 px
; font - family : Verdana , Geneva , sans - serif ; color :#333333; font - size :0.9 em ;" >
< div class =" row col - xs -12 col - md -12" >
< fieldset > < label > Read the Instructions
< div class =" panel panel - primary " >
< div class =" panel - heading " > < strong > Instructions

28
29
30
31

< div class =" panel - body " >

Watch the videos , < span class =" recordway " > and record live commentaries
< span class =" uploadway " > , and upload recorded files
link in our code later -->

32
33
34
35


  • This survey gathers live commentaries of videos . < br / >
    < span class =" uploadway " > You need some recording tools . < br / >

    B.2. 一般ドメイン実況生成
    36
    37
    38
    39

    40
    41
    42
    43
    44
    45
    46
    47
    48
    49

    50
    51
    52
    53
    54
    55
    56
    57
    58

    59
    60

    132

    You will be shown 2 videos .
    < br / >
  • This HIT & nbsp ; allows for repeat participation if the videos are different . li >
  • Before starting , please make sure that following & nbsp ; < strong > Video1
    and < strong > Video2 & nbsp ; videos appear as shown in < strong > Example strong >. We have checked the videos & nbsp ; before creating this & nbsp ; HIT , but
    depending on the timing or your situation , the video may not play . If you
    cannot watch the video , please do not work on this HIT ( You will not be able
    to submit it ) .
  • Please record a live commentary twice for each of the video .

    • Record a live commentary while watching a video .
    • Record a live commentary again while watching the same video .
      < li class =" uploadway " > Upload two recording files .
      < li class =" recordway " > The video will start playing as you click the record
      button .
      Please make sure the time length of each recorded commentary is
      within its video ’ s time .
      -->
      < li class =" recordway " > You will not be able to stop recording before the video
      finishes . The recording will automatically shut off 60 seconds after the
      video ends , if you don ' t stop it sooner .
      You cannot refer to any word in the video .
      - - > Use only English in your live commentaries .
    • Keep talking and recording the commentary until the video is over . li >
    • Please ignore any written text you see in the video , and describe the video
      in your own words .
      -->
    • The audio of the video is muted .
    • When recording starts , < strong >( recorded XX : XX / XX : XX ) will be
      displayed next to < strong > First commentary : or < strong > Second
      commentary : . If not , your environment is not compatible with this
      HIT , and you should stop working on it .
    • Important ! ( Check them all )
      < div class =" checkbox " > < label > < input name =" Ch e c k _ i m p o r t a n t 1 " required ="" type ="
      checkbox " value =" check_ok " / > Keep talking and recording the commentary
      until the video is over .

      61
      62

      < div class =" checkbox " > < label > < input name =" Ch e c k _ i m p o r t a n t 2 " required ="" type ="
      checkbox " value =" check_ok " / > Please ignore any written text you see in the
      video , and describe the video in your own words .

      63
      64

      < div class =" checkbox " > < label > < input name =" Ch e c k _ i m p o r t a n t 3 " required ="" type ="
      checkbox " value =" check_ok " / > Use only English in your live commentaries . label >

      65
      66

      < div class =" checkbox " > < label > < input name =" Ch e c k _ i m p o r t a n t 4 " required ="" type ="
      checkbox " value =" check_ok " / > Please do not start with the phrases like >& quot ; OK , this is the second recoding & quot ; , just describe what is on
      the video .

      67
      68

      < div class =" checkbox " > < label > < input name =" Ch e c k _ i m p o r t a n t 5 " required ="" type ="
      checkbox " value =" check_ok " / > If an ad is played while recording , say &
      quot ; ad starts & quot ; when the ad starts , and & quot ; ad ends & quot ; em > when it ends .

      69
      70

      < div class =" checkbox " > < label > < input name =" Ch e c k _ i m p o r t a n t 6 " required ="" type ="
      checkbox " value =" check_ok " / > Please check your recordings before

      B.2. 一般ドメイン実況生成

      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91

      133

      submission . The auto - recognition function may reject it when your voice is
      too quiet , there is too much noise , or the total time of the commentary
      audio part only is less than 60% of the video duration .



    • Also answer the questionnaire about the videos .

      • How difficult was it to record a live commentary ? and why ?
      • How many scene cuts are there in this video ?
        How fast is each scene cut ?
      • How many events are there in each scene cut ?
        -->


      • Finally answer the questionnaire about your background .

        • The country you are living in
        • The language ( s ) you can speak fluently
        • Your familiarity with : Sports , Music ,... etc




          92
          93
          94
          95
          96
          97

          < section >
          < div class =" checkbox " > < label > < input name =" Check " required ="" type =" checkbox " value
          =" check_ok " / > Have you checked the instructions ?




          98
          99
          100

          < div class =" panel panel - primary " >
          < div class =" panel - heading " > < strong > Example

          101
          102
          103

          < div class =" panel - body d - flex " >
          < div class =" ytplayer " data - id =" H6hb3SIqdL4 " >& nbsp ;

          104
          105
          106
          107


          < fieldset class =" f il e U p l o a d F i e l d s e t " > < label > First commentary ( sample audio ) : > < br / >
          < input class =" fileUpload " disabled =" disabled " single ="" type =" file " / > < button class
          =" record_button " disabled =" disabled " > < i class =" material - icons " > mic

          108
          109
          110

          < audio class =" playback " controls ="" data - loc =" sample / sample_c1 . mp3 " disabled ="
          disabled " >& nbsp ;


          111
          112
          113

          < fieldset class =" f il e U p l o a d F i e l d s e t " > < label > Second commentary ( sample audio ) : label > < br / >
          < input class =" fileUpload " disabled =" disabled " single ="" type =" file " / > < button class
          =" record_button " disabled =" disabled " > < i class =" material - icons " > mic

          114
          115
          116
          117
          118
          119
          120
          121
          122

          < audio class =" playback " controls ="" data - loc =" sample / sample_c2 . mp3 " disabled ="
          disabled " >& nbsp ;






          < input id =" audiomethod " name =" method "
          type =" hidden " value =" uploaded " / >

          B.2. 一般ドメイン実況生成
          123

          134

          < fieldset > < label > Video

          124
          125
          126

          < div class =" panel panel - primary " >
          < div class =" panel - heading " > < strong > Video 1

          127
          128
          129
          130

          131
          132
          133

          < div class =" panel - body d - flex " >
          < div class =" ytplayer " data - id =" $ { VideoId1 }" data - set =" $ { Datatype1 }" >& nbsp ;
          Datatype1 }" >& nbsp ; -->< input class =" videoDuration " name =" v1d " type ="
          hidden " / >

          < fieldset class =" f il e U p l o a d F i e l d s e t " > < label > First commentary < span class =" timer " >: span > < br / >
          < input class =" audioinput fileUpload " single ="" type =" file " / > < button class ="
          audioinput record_button " disabled =" disabled " > < i class =" material - icons " > mic >

          134
          135
          136
          137
          138
          139

          < audio class =" playback " controls ="" disabled =" disabled " >& nbsp ;
          < input class =" duration " data - cid ="1" name =" v1c1d " type =" hidden " / > < input class ="
          filekey " data - cid ="1" name =" v1c1 " type =" hidden " / >
          < div class =" status " >& nbsp ;
          Did any ads play while the video was playing ? < br / >
          < input checked =" checked " name =" v1c1cm " required ="" type =" radio " value ="0" / > No &
          nbsp ; < input name =" v1c1cm " type =" radio " value ="1" / > Yes

          140
          141
          142

          < fieldset class =" f il e U p l o a d F i e l d s e t " > < label > Second commentary < span class =" timer
          " >: < br / >
          < input class =" audioinput fileUpload " single ="" type =" file " / > < button class ="
          audioinput record_button " disabled =" disabled " > < i class =" material - icons " > mic >

          143
          144
          145
          146
          147
          148
          149
          150

          < audio class =" playback " controls ="" disabled =" disabled " >& nbsp ;
          < input class =" duration " data - cid ="2" name =" v1c2d " type =" hidden " / > < input class ="
          filekey " data - cid ="2" name =" v1c2 " type =" hidden " / >
          < div class =" status " >& nbsp ;
          Did any ads play while the video was playing ? < br / >
          < input checked =" checked " name =" v1c2cm " required ="" type =" radio " value ="0" / > No &
          nbsp ; < input name =" v1c2cm " type =" radio " value ="1" / > Yes



          151
          152
          153

          < div class =" panel - body " >

          Questionnaire about Video 1



          154
          155
          156
          157

          158
          159
          160
          161

          162


          • How difficult was it to record a live commentary with this video ? (1: Easy &
            larr ; & rarr ; 5: Difficult ) < br / >
            < input name =" v1_difficulty " required ="" type =" radio " value ="1" / > 1 & nbsp ; < input
            name =" v1_difficulty " type =" radio " value ="2" / > 2 & nbsp ; < input name ="
            v1_difficulty " type =" radio " value ="3" / > 3 & nbsp ; < input name =" v1_difficulty "
            type =" radio " value ="4" / > 4 & nbsp ; < input name =" v1_difficulty " type =" radio "
            value ="5" / > 5& nbsp ;
          • Why was it difficult ?

            • Speed (1: Too slow & larr ; & rarr ;5: Too fast ; Check 3 if you answered ☆
              as 1: Easy ) < br / >
              < input name =" v1_speed " required ="" type =" radio " value ="1" / >1 & nbsp ; < input name
              =" v1_speed " type =" radio " value ="2" / > 2 & nbsp ; < input name =" v1_speed " type ="
              radio " value ="3" / > 3 & nbsp ; < input name =" v1_speed " type =" radio " value ="4"
              / > 4 & nbsp ; < input name =" v1_speed " type =" radio " value ="5" / > 5& nbsp ;
            • Event changing in each scene cuts (1: Too few to continue describing & larr ; &
              rarr ;5: Too many to describe in time ; Check 3 if you answered ☆
              as 1: Easy ) < br / >

              B.2. 一般ドメイン実況生成
              163

              164
              165

              166
              167

              168
              169
              170
              171
              172
              173

              174
              175
              176
              177

              178
              179
              180

              181
              182
              183

              135

              < input name =" v1_event " required ="" type =" radio " value ="1" / >1 & nbsp ; < input name
              =" v1_event " type =" radio " value ="2" / > 2 & nbsp ; < input name =" v1_event " type ="
              radio " value ="3" / > 3 & nbsp ; < input name =" v1_event " type =" radio " value ="4"
              / > 4 & nbsp ; < input name =" v1_event " type =" radio " value ="5" / > 5& nbsp ;
            • Video content ( situation , object , event ,... etc ) < br / >
              < input name =" v1_content " required ="" type =" radio " value =" unknown " / >& nbsp ;
              Unknown & nbsp ;& nbsp ; < input name =" v1_content " type =" radio " value =" known " / >&
              nbsp ; Known & nbsp ;& nbsp ; < input name =" v1_content " required ="" type =" radio "
              value =" familiar " / >& nbsp ; Familiar & nbsp ;& nbsp ;

            • Other < br \ > < input class =" form - control " id =" v1_other " name =" v1_other "
              placeholder =" e . g . ’ The screen shakes so much that it is difficult to grasp
              the situation ’" type =" text " / >




              How fast is each scene cut ? < br / >
              (1: Scene cuts are too long , 3: Best speed for recording the commentary , 5:
              Scene cuts are too fast ) < br / >
              < input name =" v1q3 " required ="" type =" radio " value ="1" / > 1 & nbsp ; < input name ="
              v1q3 " type =" radio " value ="2" / > 2 & nbsp ; < input name =" v1q3 " type =" radio " value
              ="3" / > 3 & nbsp ; < input name =" v1q3 " type =" radio " value ="4" / > 4 & nbsp ; < input
              name =" v1q3 " type =" radio " value ="5" / > 5& nbsp ;
            • How many events are there in each scene cut ? < br / >
              (1: The events do not change * at all within one scene cut , 3: Best amount for
              recording the commentary , 5: Too many events within one scene cut ) < br / >
              * Event changing is such as a change in the behavior of a person or a change in
              an object in the video . < br / >
              < input name =" v1q4 " required ="" type =" radio " value ="1" / > 1 & nbsp ; < input name ="
              v1q4 " type =" radio " value ="2" / > 2 & nbsp ; < input name =" v1q4 " type =" radio " value
              ="3" / > 3 & nbsp ; < input name =" v1q4 " type =" radio " value ="4" / > 4 & nbsp ; < input
              name =" v1q4 " type =" radio " value ="5" / > 5& nbsp ;
              - - >
            • How many scene cuts are there in this video ? < br / >
              < input name =" v1_scenecuts " required ="" type =" radio " value ="1" / > 1 & nbsp ; < input
              name =" v1_scenecuts " type =" radio " value ="2 -4" / > 2 -4 & nbsp ; < input name ="
              v1_scenecuts " type =" radio " value ="5 -8" / > 5 -8 & nbsp ; < input name ="
              v1_scenecuts " type =" radio " value ="9 -14" / > 9 -14 & nbsp ; < input name ="
              v1_scenecuts " type =" radio " value =" over15 " / > over 15 -& nbsp ;




              184
              185
              186

              < div class =" panel panel - primary " >
              < div class =" panel - heading " > < strong > Video 2

              187
              188
              189
              190
              191
              192
              193

              < div class =" panel - body d - flex " >
              < div class =" ytplayer " data - id =" $ { VideoId2 }" data - set =" $ { Datatype2 }" >& nbsp ;
              < input class =" videoDuration " name =" v2d " type =" hidden " / >

              < fieldset class =" f il e U p l o a d F i e l d s e t " > < label > First commentary < span class =" timer " >: span > < br / >
              < input class =" audioinput fileUpload " single ="" type =" file " / > < button class ="
              audioinput record_button " disabled =" disabled " > < i class =" material - icons " > mic >

              194
              195
              196
              197
              198
              199

              < audio class =" playback " controls ="" disabled =" disabled " >& nbsp ;
              < input class =" duration " data - cid ="1" name =" v2c1d " type =" hidden " / > < input class ="
              filekey " data - cid ="1" name =" v2c1 " type =" hidden " / >
              < div class =" status " >& nbsp ;
              Did any ads play while the video was playing ? < br / >
              < input checked =" checked " name =" v2c1cm " required ="" type =" radio " value ="0" / > No &
              nbsp ; < input name =" v2c1cm " type =" radio " value ="1" / > Yes

              B.2. 一般ドメイン実況生成

              136

              200
              201
              202

              < fieldset class =" f il e U p l o a d F i e l d s e t " > < label > Second commentary < span class =" timer
              " >: < br / >
              < input class =" audioinput fileUpload " single ="" type =" file " / > < button class ="
              audioinput record_button " disabled =" disabled " > < i class =" material - icons " > mic >

              203
              204
              205
              206
              207
              208
              209
              210

              < audio class =" playback " controls ="" disabled =" disabled " >& nbsp ;
              < input class =" duration " data - cid ="2" name =" v2c2d " type =" hidden " / > < input class ="
              filekey " data - cid ="2" name =" v2c2 " type =" hidden " / >
              < div class =" status " >& nbsp ;
              Did any ads play while the video was playing ? < br / >
              < input checked =" checked " name =" v2c2cm " required ="" type =" radio " value ="0" / > No &
              nbsp ; < input name =" v2c2cm " type =" radio " value ="1" / > Yes



              211
              212
              213

              < div class =" panel - body " >

              Questionnaire about Video 2



              214
              215
              216
              217

              218
              219
              220
              221

              222

              223

              224
              225

              226
              227

              228
              229
              230
              231
              232

              233
              234


              • How difficult was it to record a live commentary with this video ? (1: Easy &
                larr ; & rarr ; 5: Difficult ) < br / >
                < input name =" v2_difficulty " required ="" type =" radio " value ="1" / > 1 & nbsp ; < input
                name =" v2_difficulty " type =" radio " value ="2" / > 2 & nbsp ; < input name ="
                v2_difficulty " type =" radio " value ="3" / > 3 & nbsp ; < input name =" v2_difficulty "
                type =" radio " value ="4" / > 4 & nbsp ; < input name =" v2_difficulty " type =" radio "
                value ="5" / > 5& nbsp ;
              • Why was it difficult ?

                • Speed (1: Too slow & larr ; & rarr ;5: Too fast ; Check 3 if you answered ☆
                  as 1: Easy ) < br / >
                  < input name =" v2_speed " required ="" type =" radio " value ="1" / >1 & nbsp ; < input name
                  =" v2_speed " type =" radio " value ="2" / > 2 & nbsp ; < input name =" v2_speed " type ="
                  radio " value ="3" / > 3 & nbsp ; < input name =" v2_speed " type =" radio " value ="4"
                  / > 4 & nbsp ; < input name =" v2_speed " type =" radio " value ="5" / > 5& nbsp ;
                • Event changing in each scene cuts (1: Too few to continue describing & larr ; &
                  rarr ;5: Too many to describe in time ; Check 3 if you answered ☆
                  as 1: Easy ) < br / >
                  < input name =" v2_event " required ="" type =" radio " value ="1" / >1 & nbsp ; < input name
                  =" v2_event " type =" radio " value ="2" / > 2 & nbsp ; < input name =" v2_event " type ="
                  radio " value ="3" / > 3 & nbsp ; < input name =" v2_event " type =" radio " value ="4"
                  / > 4 & nbsp ; < input name =" v2_event " type =" radio " value ="5" / > 5& nbsp ;
                • Video content ( situation , object , event ,... etc ) < br / >
                  < input name =" v2_content " required ="" type =" radio " value =" unknown " / >& nbsp ;
                  Unknown & nbsp ;& nbsp ; < input name =" v2_content " type =" radio " value =" known " / >&
                  nbsp ; Known & nbsp ;& nbsp ; < input name =" v2_content " required ="" type =" radio "
                  value =" familiar " / >& nbsp ; Familiar & nbsp ;& nbsp ;

                • Other < br \ > < input class =" form - control " id =" v2_other " name =" v2_other "
                  placeholder =" e . g . ’ The screen shakes so much that it is difficult to grasp
                  the situation ’" type =" text " / >





                • How many scene cuts are there in this video ? < br / >
                  < input name =" v2_scenecuts " required ="" type =" radio " value ="1" / > 1 & nbsp ; < input
                  name =" v2_scenecuts " type =" radio " value ="2 -4" / > 2 -4 & nbsp ; < input name ="
                  v2_scenecuts " type =" radio " value ="5 -8" / > 5 -8 & nbsp ; < input name ="
                  v2_scenecuts " type =" radio " value ="9 -14" / > 9 -14 & nbsp ; < input name ="
                  v2_scenecuts " type =" radio " value =" over15 " / > over 15 -& nbsp ;



                  B.2. 一般ドメイン実況生成
                  235
                  236

                  137




                  237
                  238

                  < fieldset > < label > Questionnaire

                  239
                  240
                  241

                  < div class =" panel panel - primary " >
                  < div class =" panel - heading " > < strong > Questionnaire about your background div >

                  242
                  243
                  244

                  < div class =" panel - body " >

                  The country you are living in < br \ > < input class =" form - control " id =" livingplace "
                  name =" livingplace " placeholder =" e . g . UK " required ="" type =" text " / >



                  245
                  246

                  The language ( s ) you can speak fluently < br \ > < input class =" form - control " id ="
                  language " name =" language " placeholder =" e . g . English , German ,... etc " required =""
                  type =" text " / >



                  247
                  248

                  Your familiarity with :

                  249
                  250
                  251

                  252

                  253

                  254
                  255
                  256
                  257
                  258
                  259
                  260


                  • Sports : football , basketball , skating , ... < br \ > < input class =" form - control "
                    id =" sports " name =" sports " placeholder =" football , cricket ,... etc or NONE "
                    required ="" type =" text " / >
                  • Music ( instrument , genre ) : guitar , piano , rock , jazz , ... < br \ > < input class ="
                    form - control " id =" music " name =" music " placeholder =" violin , classical ,... etc
                    or NONE " required ="" type =" text " / >
                  • Other < br \ > < input class =" form - control " id =" other " name =" other " placeholder ="
                    computer science , video game ,... etc or NONE " required ="" type =" text " / > \ >





                    < script >
                    const d i s a bl e Mi c ro p ho n e = false ;

                    261
                    262
                    263
                    264
                    265
                    266

                    const config = {
                    region : ’ap - northeast -1 ’ ,
                    pool : ’ap - northeast -1: eaad08ff -2455 -4 c54 - a19b -0 cd9b21347f7 ’ ,
                    bucket : ’ nedo3 - amt - worker - uploads ’
                    }

                    267
                    268
                    269
                    270
                    271
                    272
                    273
                    274

                    AWS . config . region = config . region ;
                    // Configure the credentials provider to use your identity pool
                    AWS . config . credentials = new AWS . C o g n i t o I d e n t i t y C r e d e n t i a l s ({
                    IdentityPool Id : config . pool ,
                    RoleArn : ’ arn : aws : iam :: 6 46 640 37 4441: role /
                    Cognito_AMT_upload_files_poolUnauth_Role ’,
                    AccountId : ’646640374441 ’ ,
                    }) ;

                    275
                    276
                    277
                    278
                    279
                    280
                    281
                    282
                    283
                    284
                    285
                    286

                    // XXX DEBUG - for testing outside AMT HIT without actual uploaing
                    if (! window . turkGetParam ) {
                    window . turkGetParam = () = > 0;
                    window . AWS = {
                    S3 : function () {
                    return {
                    upload : function (x , f ) {
                    console . log ("[ fake ] uploading :" , x )

                    B.2. 一般ドメイン実況生成
                    f ( null , "") ;
                    },
                    getObject : function (x , f ) {
                    console . log ("[ fake ] downloading :" , x )
                    f ( null , {
                    ContentType : ’ audio / mp3 ’ ,
                    Data : new Uint8Array () ,
                    }) ;
                    },

                    287
                    288
                    289
                    290
                    291
                    292
                    293
                    294
                    295

                    };
                    },
                    config : {} ,
                    C o g n i t o I d e n t i t y C r e d e n t i a l s : function () {} ,

                    296
                    297
                    298
                    299

                    };

                    300
                    301

                    }

                    302
                    303
                    304
                    305
                    306
                    307
                    308
                    309
                    310
                    311
                    312
                    313
                    314
                    315
                    316
                    317
                    318
                    319

                    const ytplayers = {};
                    window . o n Y o u T u b e I f r a m e A P I R e a d y = function () {
                    $ ( ’. ytplayer ’) . each ( function ( index , div ) {
                    const $player = $ ( div ) ;
                    const videoId = $player . data ( ’ id ’) ;
                    const player = new YT . Player ( div , {
                    width : 640 ,
                    height : 390 ,
                    videoId : videoId ,
                    events : {
                    onReady : ytReady ,
                    onStateChange : ytStateChange ,
                    },
                    }) ;
                    ytplayers [ videoId ] = player ;
                    }) ;
                    }

                    320
                    321
                    322
                    323
                    324

                    const ytTag = document . createElement ( ’ script ’) ;
                    ytTag . src = " https :// www . youtube . com / iframe_api ";
                    const firstScrip tTag = document . g e t E l e m e n t s B y T a g N a m e ( ’ script ’) [0];
                    firstS criptT ag . parentNode . insertBefore ( ytTag , firstS criptT ag ) ;

                    325
                    326
                    327
                    328
                    329
                    330

                    function ytReady ( evt ) {
                    evt . target . mute () ;
                    $ ( ’. audioinput . record_button ’) . prop ( ’ disabled ’ , false ) ;
                    }

                    331
                    332
                    333
                    334
                    335
                    336
                    337

                    let
                    let
                    let
                    let
                    let
                    let

                    $ c u r r e n t R e c B u t t o n = null ;
                    currentPlayer = null ;
                    stopRecTimer = null ;
                    t i m e rU pd at eT im er = null ;
                    recStart = null ;
                    videoDuration = null ;

                    338
                    339
                    340
                    341
                    342
                    343
                    344
                    345
                    346
                    347
                    348
                    349

                    function ytStateChange ( evt ) {
                    if ( evt . data == YT . PlayerState . ENDED ) {
                    videoDuration = evt . target . getDuration () ;
                    if ( $ c ur r en t Re c Bu t t o n ) {
                    $ c u r r e n t R e c B u t t o n . prop ( ’ disabled ’ , false ) ;
                    stopRecTimer = setTimeout ( function () {
                    $ c u r r e n t R e c B u t t o n . click () ;
                    } , 60 * 1000) ;
                    }
                    }
                    }

                    138

                    B.2. 一般ドメイン実況生成

                    139

                    350
                    351
                    352
                    353
                    354
                    355
                    356
                    357
                    358

                    function s u p p o r t s D y n a m i c I m p o r t () {
                    try {
                    new Function ( ’ import ("") ’) ;
                    return true ;
                    } catch ( err ) {
                    return false ;
                    }
                    }

                    359
                    360
                    361
                    362
                    363
                    364
                    365

                    function minsec ( time ) {
                    const min = Math . floor ( time
                    const sec = Math . round ( time
                    const filler = sec > 9 ? ’’
                    return min + ":" + filler +
                    }

                    / 60) ;
                    - min * 60) ;
                    : ’0 ’;
                    sec ;

                    366
                    367
                    368
                    369
                    370
                    371
                    372

                    function updateTimer () {
                    const duration = Math . round ( currentPlayer . getDuration () ) ;
                    const position = Math . round (( new Date () - recStart ) / 1000) ;
                    const displayText = " ( recorded " + minsec ( position ) + " / " + minsec ( duration )
                    + ") ";
                    $ c u r r e n t R e c B u t t o n . closest ( ’ fieldset ’) . find ( ’. timer ’) . text ( displayText ) ;
                    }

                    373
                    374
                    375
                    376
                    377

                    const r e co rd e rP r om is e = new Promise ( function ( resolve , reject ) {
                    if ( d i s a b le M ic r o ph o n e || ! navigator . permissions ) {
                    reject () ;
                    }

                    378
                    379
                    380
                    381
                    382
                    383
                    384
                    385
                    386
                    387
                    388
                    389
                    390
                    391
                    392
                    393
                    394
                    395
                    396
                    397
                    398
                    399
                    400
                    401
                    402
                    403
                    404

                    navigator . permissions . query ({ name : ’ microphone ’ })
                    . then ( function ( permissions ) {
                    const micStatus = permissions . state ;
                    if ( micStatus == ’ prompt ’ || micStatus == ’ granted ’) {
                    if ( s u p p o r t s D y n a m i c I m p o r t () ) {
                    const vmsgURL = " https :// cdn . jsdelivr . net / npm / vmsg@0 .3.6/"
                    import ( vmsgURL + " vmsg . js ")
                    . then ( function ( vmsg ) {
                    if ( vmsg && vmsg . Recorder ) {
                    const Recorder = vmsg . Recorder . bind ( null , {
                    wasmURL : vmsgURL + " vmsg . wasm " ,
                    shimURL : vmsgURL + " wasm - polyfill . js " ,
                    }) ;
                    resolve ( Recorder ) ;
                    } else {
                    reject () ;
                    }
                    }) ;
                    } else {
                    reject () ;
                    }
                    } else {
                    reject () ;
                    }
                    }) ;
                    }) ;

                    405
                    406
                    407
                    408
                    409

                    const s3 = new AWS . S3 ({
                    apiVersion : "2006 -03 -01" ,
                    params : { Bucket : config . bucket }
                    }) ;

                    410
                    411

                    const workerId = turkGetParam (" workerId ") ;

                    B.2. 一般ドメイン実況生成
                    412
                    413

                    140

                    const assignmentId = turkGetParam (" assignmentId ") ;
                    const hitId = turkGetParam (" hitId ") ;

                    414
                    415
                    416
                    417

                    $ ( ’ audio [ data - loc ] ’) . each ( function () {
                    const $this = $ ( this ) ;
                    const fileKey = $this . data ( ’ loc ’) ;

                    418
                    419
                    420
                    421
                    422
                    423
                    424
                    425
                    426
                    427
                    428
                    429
                    430
                    431
                    432
                    433
                    434
                    435
                    436
                    437
                    438
                    439

                    s3 . getObject (
                    {
                    Key : fileKey ,
                    },
                    function ( err , data ) {
                    if ( err ) {
                    console . error ( err )
                    } else {
                    const mimeType = data . ContentType ;
                    const buffer = data . Body . buffer ;
                    const blob = new Blob ([ buffer ] , { type : mimeType })
                    const audioURL = URL . cr e at eObje c tURL ( blob ) ;
                    $ ( ’ < source > ’) . attr ({
                    src : audioURL ,
                    type : mimeType ,
                    }) . appendTo ( $this ) ;
                    $this . prop ( ’ disabled ’ , false ) ;
                    }
                    }
                    );
                    }) ;

                    440
                    441
                    442
                    443

                    function upload_file ( file , videoId , commentaryId , videoSet ) {
                    const extension = mimeTypes [ file . type ];
                    const fileKey = hitId + " _ " + assignmentId + " _ " + workerId + " _ " + videoId + "
                    _ " + commentaryId + " _ " + videoSet + "." + extension ;

                    444

                    return new Promise ( function ( resolve , reject ) {
                    s3 . upload (
                    {
                    Key : fileKey ,
                    Body : file ,
                    ContentType : file . type ,
                    ACL : " bucket - owner - full - control "
                    },
                    function ( err , data ) {
                    if ( err ) {
                    reject ( err ) ;
                    } else {
                    resolve ( fileKey ) ;
                    }
                    }
                    );
                    })

                    445
                    446
                    447
                    448
                    449
                    450
                    451
                    452
                    453
                    454
                    455
                    456
                    457
                    458
                    459
                    460
                    461
                    462

                    }

                    463
                    464
                    465
                    466
                    467

                    function d o_ i np u t_ up l oa d ( evt ) {
                    const $fieldset = $ ( evt . target ) . closest (" fieldset ") ;
                    const $fileinput = $fieldset . find (". fileUpload ") ;
                    const $status = $fieldset . find (". status ") ;

                    468
                    469
                    470
                    471
                    472
                    473

                    const file = $fileinput . prop (" files ") [0];
                    if (! file ) {
                    $status . text ("") ;
                    return ;
                    }

                    B.2. 一般ドメイン実況生成

                    141

                    const mimeType = file . type ;
                    const extension = mimeTypes [ mimeType ];

                    474
                    475
                    476

                    if ( extension ) {
                    receiveAudio ( file , $fieldset ) ;
                    } else {
                    $status . text (" Please only upload MP3 or M4A files .") . addClass ( ’ text - error ’) .
                    removeClass ( ’ text - success ’) ;
                    }

                    477
                    478
                    479
                    480
                    481
                    482

                    };

                    483
                    484
                    485
                    486
                    487

                    $ (". fileUpload ") . on (" input " , do _ inp ut _uplo ad ) ;
                    $ ( function () {
                    $ ("# submitButton ") . prop (" disabled " , true ) ;
                    }) ;

                    488
                    489
                    490
                    491
                    492
                    493
                    494
                    495

                    const mimeTypes = {
                    ’ audio / webm ; codecs = opus ’: ’ webm ’ ,
                    ’ audio / ogg ; codecs = opus ’: ’ogg ’ ,
                    ’ audio / mpeg ’: ’ mp3 ’ ,
                    ’ audio /x - m4a ’: ’m4a ’ ,
                    // TODO check uploaded mimetypes on other browsers ( above is for Chrome )
                    };

                    496
                    497
                    498
                    499
                    500
                    501
                    502
                    503
                    504
                    505
                    506

                    function receiveAudio ( blob , $fieldset ) {
                    const $status = $fieldset . find (". status ") ;
                    const $filekey = $fieldset . find (". filekey ") ;
                    const $duration = $fieldset . find (". duration ") ;
                    const $audioinputs = $fieldset . find (". audioinput ") ;
                    const commentaryId = $filekey . data (" cid ") ;
                    const $player = $fieldset . closest (". panel - body ") . find (". ytplayer ") ;
                    const $videoD uratio n = $fieldset . closest (". panel - body ") . find (". videoDuration ") ;
                    const videoId = $player . data (" id ") ;
                    const videoSet = $player . data (" set ") ;

                    507
                    508
                    509

                    $status . text (" Uploading ...") ;
                    $audioinputs . prop (" disabled " , true ) ;

                    510
                    511
                    512
                    513
                    514
                    515
                    516
                    517

                    const audioURL = URL . cr e at eO b jec tU RL ( blob ) ;
                    const $audio = $fieldset . find ( ’. playback ’) . empty () . prop ( ’ disabled ’ , false ) ;
                    const audio = $audio [0];
                    $ ( ’ < source > ’) . attr ({
                    src : audioURL ,
                    type : blob . type ,
                    }) . appendTo ( $audio ) ;

                    518
                    519
                    520
                    521
                    522
                    523

                    const displayError = function ( error ) {
                    $status . text ( error ) . addClass ( ’ text - danger ’) . removeClass ( ’ text - success ’) ;
                    $filekey . val ("") ;
                    $audioinputs . prop (" disabled " , false ) ;
                    }

                    524
                    525
                    526
                    527
                    528
                    529
                    530
                    531
                    532
                    533
                    534
                    535

                    audio . o n lo ad ed me ta d a t a = function a u d i o L o a d e d M e t a d a t a () {
                    const duration = audio . duration ;
                    if ( videoDuration === null ) {
                    displayError (" Please watch the video .") ;
                    return ;
                    }
                    if ( duration < videoDuration ) {
                    displayError (" Please commentate the entire video .") ;
                    return ;
                    }
                    $duration . val ( duration ) ;

                    B.2. 一般ドメイン実況生成

                    142

                    $videoDuratio n . val ( videoDuration ) ;

                    536
                    537

                    upload_file ( blob , videoId , commentaryId , videoSet )
                    . then ( function ( fileKey ) {
                    $status . text (" Success .") . removeClass ( ’ text - danger ’) . addClass ( ’ text - success
                    ’) ;
                    $filekey . val ( fileKey ) ;
                    $audioinputs . prop (" disabled " , false ) ;
                    const $noComment = $ ( ’. f i l e U p l oa d Fi e l d s e t . filekey : not ([ value ]) ’) ;
                    if (! $noComment . length ) {
                    // all comments uploaded , allow form submission
                    $ ("# submitButton ") . prop (" disabled " , false ) ;
                    }
                    })
                    . catch ( function () {
                    displayError (" Failed to upload .") ;
                    }) ;

                    538
                    539
                    540
                    541
                    542
                    543
                    544
                    545
                    546
                    547
                    548
                    549
                    550
                    551

                    };

                    552
                    553

                    audio . onerror = function audioError ( evt ) {
                    displayError (" Audio file not valid .") ;
                    }

                    554
                    555
                    556
                    557

                    audio . load () ;

                    558
                    559

                    }

                    560
                    561
                    562
                    563
                    564
                    565

                    function g e t P l a y e r F o r S e c t i o n ( evt ) {
                    const $audio = $ ( evt . target ) ;
                    const videoId = $audio . closest ( ’. panel - body ’) . find ( ’. ytplayer ’) . data ( ’ id ’) ;
                    return ytplayers [ videoId ];
                    }

                    566
                    567
                    568
                    569
                    570
                    571
                    572
                    573
                    574
                    575
                    576
                    577
                    578
                    579
                    580

                    function onAudioPlay ( evt ) {
                    evt . target . ignorePause = true ;
                    $ ( ’ audio ’) . not ( evt . target ) . each ( function () {
                    this . ignorePause = true ;
                    this . pause () ;
                    }) ;
                    ignorePause = false ;
                    const time = evt . target . currentTime ;
                    const player = ge t P l a y e r F o r S e c t i o n ( evt ) ;
                    player . seekTo ( time ) ;
                    $ c u r r e n t R e c B u t t o n = null ;
                    videoDuration = null ;
                    player . playVideo () ;
                    }

                    581
                    582
                    583
                    584
                    585
                    586
                    587
                    588
                    589

                    function onAudioPause ( evt ) {
                    if ( evt . target . ignorePause ) {
                    delete evt . target . ignorePause ;
                    return ;
                    }
                    const player = ge t P l a y e r F o r S e c t i o n ( evt ) ;
                    player . pauseVideo () ;
                    }

                    590
                    591
                    592
                    593
                    594
                    595
                    596
                    597

                    function e na b le R ec or d in g ( flag ) {
                    if ( flag !== false ) {
                    $ ( ’. ytplayer ’) . addClass ( ’ nocontrol ’) ;
                    $ ( ’. f il e U p l oa d F i e l d s e t . fileupload , . uploadway ’) . hide () ;
                    $ ( ’. f il e U p l oa d F i e l d s e t . record_button , . recordway ’) . show () ;
                    $ ( ’# audiomethod ’) . val ( ’ recorded ’) ;
                    } else {

                    B.2. 一般ドメイン実況生成
                    $ ( ’. ytplayer ’) . removeClass ( ’ nocontrol ’) ;
                    $ ( ’. f il e U p l oa d F i e l d s e t . fileupload , . uploadway ’) . show () ;
                    $ ( ’. f il e U p l oa d F i e l d s e t . record_button , . recordway ’) . hide () ;
                    $ ( ’# audiomethod ’) . val ( ’ uploaded ’) ;

                    598
                    599
                    600
                    601

                    }

                    602
                    603

                    143

                    }

                    604
                    605
                    606
                    607

                    $ ( ’ audio ’)
                    . on ( ’ play ’ , onAudioPlay )
                    . on ( ’ pause ’ , onAudioPause ) ;

                    608
                    609
                    610
                    611

                    re co r de rP r om i se
                    . then ( function ( Recorder ) {
                    let recorder ;

                    612
                    613

                    en ab l eR eco rdi ng () ;

                    614
                    615
                    616
                    617
                    618
                    619
                    620
                    621
                    622
                    623
                    624
                    625
                    626
                    627
                    628

                    function do_record ( evt ) {
                    const $recButton = $ ( evt . target ) . closest ( ’ button ’) ;
                    const $fieldset = $ ( evt . target ) . closest ( ’. fileUploadFieldset ’) ;
                    const videoId = $fieldset . closest ( ’. panel - body ’) . find ( ’. ytplayer ’) . data ( ’ id ’)
                    ;
                    currentPlayer = ytplayers [ videoId ];
                    const recording = $fieldset . data ( ’ recording ’) ;
                    if ( recorder ) {
                    recorder . stopRecording ()
                    . then ( function ( blob ) {
                    clearTimeout ( stopRecTimer ) ;
                    stopRecTimer = null ;
                    clearTimeout ( t i m e r U p d a t e Tim e r ) ;
                    ti me r Up da te Ti m e r = null ;
                    updateTimer () ;

                    629

                    currentPlayer . stopVideo () ;
                    receiveAudio ( blob , $fieldset ) ;
                    $recButton . html ( ’ < i class =" material - icons " > mic ’) ;
                    $ ( ’. fileUploadFieldset ’) . not ( $fieldset ) . find ( ’. record_button ’) . prop ( ’
                    disabled ’ , false ) ;
                    recorder = null ;
                    }) ;
                    } else {
                    stopRecTimer = null ;

                    630
                    631
                    632
                    633
                    634
                    635
                    636
                    637
                    638

                    $recButton . html ( ’ < i class =" material - icons " > stop ’) ;
                    $ c u r r e n t R e c B u t t o n = $recButton ;
                    $ ( ’. fileUploadFieldset ’) . find ( ’. record_button ’) . prop ( ’ disabled ’ , true ) ;
                    const chunks = [];
                    recorder = new Recorder () ;
                    recorder . initAudio ()
                    . then ( function () { return recorder . initWorker () })
                    . then ( function () {
                    currentPlayer . playVideo () ;
                    recStart = new Date () ;
                    videoDuration = null ;
                    ti me r Up da te Ti m e r = setInterval ( updateTimer , 1000) ;
                    return recorder . star tRecording () ;
                    })
                    . catch ( function (... args ) {
                    en ab l eR ec o rd in g ( false ) ;
                    }) ;

                    639
                    640
                    641
                    642
                    643
                    644
                    645
                    646
                    647
                    648
                    649
                    650
                    651
                    652
                    653
                    654
                    655

                    }
                    return false ;

                    656
                    657
                    658

                    }

                    B.2. 一般ドメイン実況生成
                    659
                    660
                    661

                    144

                    $ (". record_button ") . on (" click " , do_record ) ;
                    })


                    B.2.2

                    コメント修正 UI
                    Listing B.5: Transcribe

                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13
                    14
                    15
                    16
                    17
                    18
                    19
                    20
                    21
                    22
                    23
                    24
                    25
                    26
                    27
                    28
                    29
                    30
                    31
                    32
                    33
                    34
                    35
                    36
                    37
                    38
                    39
                    40
                    41
                    42
                    43
                    44
                    45
                    46
                    47

                    < script src =" https :// sdk . amazonaws . com / js / aws - sdk -2.142.0. min . js " >
                    < script src =" https :// ajax . googleapis . com / ajax / libs / jquery /3.2.1/ jquery . min . js " > script >
                    < link href =" https :// s3 . amazonaws . com / mturk - public / bs30 / css / bootstrap . min . css " rel ="
                    stylesheet " / >
                    < link href =" https :// fonts . googleapis . com / icon ? family = Material + Icons " rel ="
                    stylesheet " / >
                    < style type =" text / css " >
                    /* https :// css - tricks . com / auto - growing - inputs - textareas / */
                    . input - sizer {
                    display : inline - grid ;
                    vertical - align : top ;
                    align - items : center ;
                    position : relative ;
                    /* border : solid 1 px ; */
                    /* padding : 0.25 em 0.5 em ; */
                    margin : 5 px ;
                    }
                    . input - sizer . stacked {
                    /* padding : 0.5 em ; */
                    align - items : stretch ;
                    }
                    . input - sizer . stacked :: after ,
                    . input - sizer . stacked input ,
                    . input - sizer . stacked textarea {
                    grid - area : 2/1;
                    }
                    . input - sizer :: after ,
                    . input - sizer input ,
                    . input - sizer textarea {
                    width : auto ;
                    min - width : 1 em ;
                    grid - area : 1/2;
                    font : inherit ;
                    padding : 0.25 em ;
                    margin : 0;
                    resize : none ;
                    background : none ;
                    appearance : none ;
                    border : none ;
                    }
                    . input - sizer span {
                    padding : 0.25 em ;
                    }
                    . input - sizer :: after {
                    content : attr ( data - value ) " ";
                    visibility : hidden ;
                    white - space : pre - wrap ;
                    }
                    /*

                    B.2. 一般ドメイン実況生成
                    48
                    49
                    50
                    51
                    52
                    53
                    54
                    55
                    56
                    57
                    58
                    59
                    60

                    . input - sizer : focus - within {
                    outline : solid 1 px blue ;
                    box - shadow : 4 px 4 px 0 px blue ;
                    }
                    . input - sizer : focus - within > span {
                    color : blue ;
                    }
                    */
                    . input - sizer : focus - within textarea : focus ,
                    . input - sizer : focus - within input : focus {
                    outline : none ;
                    }
                    /* end input - sizer */

                    61
                    62
                    63
                    64
                    65
                    66

                    . players {
                    position : sticky ;
                    top : 20 px ;
                    padding - right : 20 px ;
                    }

                    67
                    68
                    69
                    70

                    . ytplayer {
                    pointer - events : none ;
                    }

                    71
                    72
                    73
                    74

                    audio {
                    outline : none ;
                    }

                    75
                    76
                    77
                    78

                    . no - bold - labels label {
                    font - weight : normal ;
                    }

                    79
                    80
                    81
                    82

                    .d - flex {
                    display : flex ;
                    }

                    83
                    84
                    85
                    86

                    . align - items - start {
                    align - items : start ;
                    }

                    87
                    88
                    89
                    90

                    . flex - row {
                    flex - direction : row ;
                    }

                    91
                    92
                    93
                    94

                    . flex - grow -1 {
                    flex - grow : 1;
                    }

                    95
                    96
                    97
                    98
                    99
                    100
                    101
                    102
                    103
                    104

                    blockquote . example {
                    border : 0;
                    padding : 0;
                    margin : 0;
                    }
                    blockquote . example : before {
                    content : " e . g . ";
                    color : # bbbbbb ;
                    }

                    105
                    106
                    107
                    108
                    109
                    110

                    fieldset {
                    padding : 10 px ;
                    background : # fbfbfb ;
                    border - radius : 5 px ;
                    margin - bottom : 5 px ;

                    145

                    B.2. 一般ドメイン実況生成
                    111

                    146

                    }

                    112
                    113
                    114
                    115

                    . material - icons . smaller {
                    margin : -3 px ;
                    }

                    116
                    117
                    118
                    119

                    . align - self - center {
                    align - self : center ;
                    }

                    120
                    121
                    122
                    123
                    124

                    . form - check - inline {
                    display : inline - block ;
                    margin - right : 10 px ;
                    }

                    125
                    126
                    127
                    128

                    .w -100 {
                    width : 100%;
                    }

                    129
                    130
                    131
                    132

                    . mb -10 {
                    margin - bottom : 10 px ;
                    }

                    133
                    134
                    135
                    136

                    . mb -20 {
                    margin - bottom : 20 px ;
                    }

                    137
                    138
                    139
                    140

                    textarea : required : invalid {
                    border : 2 px solid # ff0000 ;
                    }

                    141
                    142
                    143
                    144

                    fieldset . required {
                    border : 2 px solid transparent ;
                    }

                    145
                    146
                    147
                    148
                    149

                    fieldset . required : invalid {
                    border - bottom : 2 px solid # ff0000 ;
                    border - radius : 0;
                    }

                    150
                    151
                    152
                    153
                    154

                    form : invalid input [ type =" submit "] {
                    pointer - events : none ;
                    opacity : 0.38;
                    }

                    155
                    156
                    157
                    158
                    159
                    160
                    161
                    162
                    163

                    kbd {
                    font - weight : bold ;
                    }

                    < main class =" container " id =" Other " style =" margin - bottom :15 px ; padding : 10 px 10 px ;
                    font - family : Verdana , Geneva , sans - serif ; color :#333333; font - size :0.9 em ;" >
                    < fieldset > < label > Read the Instructions
                    < div class =" panel panel - primary " >
                    < div class =" panel - heading " > < strong > Instructions

                    164
                    165
                    166
                    167
                    168

                    < div class =" panel - body " >
                    This is a qualification test for the task explained below . -->
                    You can accept the actual HIT after you pass this qualification
                    task !

                    -->
                    This HIT is a task of listening to audio and correcting the
                    transcription .

                    169
                    170

                    There are two audios , so correct those tra nscrip tions .

                    B.2. 一般ドメイン実況生成

                    147

                    171
                    172
                    173

                    If you do not follow the rules below , your job will be rejected . div > -->
                    Please follow the instructions below to do both of the following "
                    Transcription correction " and " Transcription review " .

                    174
                    175
                    176

                    Please check your work before submission , you cannot redo this HIT
                    after submission .
                    The reward of this task is determined by the number of chars in the
                    pre - transcription and the audio time .

                    177
                    178
                    179
                    180

                    Transcription correction fields

                    • Please add an appropriate punctuation mark ("." , "?" etc .) at the end
                      , if you find the sentence is ending .

                      181
                      182

                    • Please input "( UNKNOWN ) " in places where you can ’ t hear or
                      recognise what was said .

                      183
                      184
                      185
                      186
                      187
                      188
                      189
                      190
                      191
                      192
                      193
                      194
                      195
                      196
                      197
                      198

                    • Please correct any part where the automatic transcription text
                      differs from the audio .
                      < blockquote class =" example " >
                      " So it z there a burning man ?" & rarr ; " So is there a burning man ?"


                    • Please write out any numbers using words as it
                      is .
                      < blockquote class =" example " >
                      "1" & rarr ; " one "

                      < blockquote class =" example " >
                      "1234" & rarr ; " one thousand two hundred and thirty four "

                      < blockquote class =" example " >
                      "1 st ,2 nd " & rarr ; " first , second "


                      199
                      200
                      201




                      202
                      203
                      204

                      205
                      206

                      207
                      208
                      209
                      210
                      211
                      212
                      213
                      214
                      215
                      216
                      217
                      218
                      219

                      Transcription review fields

                      In the transcription review fields , please perform all the corrections
                      listed for the Transcription correction fields , as well as the
                      following additional ones .

                        In the transcription review fields , please perform all the
                        corrections listed for the Transcription correction fields , as well as
                        the following additional ones . -->
                      • Please change the "( UNKNOWN ) " to appropriate word or > remove for natural sentence .

                      • Please correct any incorrect grammar .
                        < blockquote class =" example " >
                        " They is talking ." & rarr ; " They are talking ."

                        < blockquote class =" example " >
                        " There are two mouses ." & rarr ; " There are two mice ."



                      • Please remove rephrasing .
                        < blockquote class =" example " >

                        B.2. 一般ドメイン実況生成
                        220
                        221
                        222
                        223
                        224
                        225

                        226
                        227
                        228

                        148

                        " and I think oh it seems one of them , he threw three darts ," & rarr ; "
                        He threw three darts ."



                      • Please remove any repr es entat i on s of fillers * words or
                        hesitation markers .
                        < br / > * fillers : < a href =" https :// en . wikipedia . org / wiki / Filler_ (
                        linguistics ) " target =" _blank " > > https :// en . wikipedia . org / wiki /
                        Filler_ ( linguistics )
                        < blockquote class =" example " >
                        fillers : Mmm , Uh , uh , OK , Yeah ... etc


                        229
                        230
                        231
                        232
                        233
                        234
                        235
                        236

                        < blockquote class =" example " >
                        " uh Let ’ s see uh there ’ s a man , there ’ s a man throwing darts ." & rarr ;
                        " There ’ s a man throwing darts ."

                        < blockquote class =" example " >
                        " Mmm , is there a burning man ?" & rarr ; " Is there a burning man ?"



                        237
                        238
                        239
                        240
                        241
                        242
                        243
                        244
                        245
                        246
                        247
                        248
                        249
                        250
                        251

                      • If the field ends up as empty after such deletions , please input >"( NONE ) " .


                        < section >
                        < fieldset class =" required " >
                        < label >
                        < input name =" Check " required type =" checkbox " value =" check_ok " / >
                        Have you checked the instructions ?







                        252
                        253



                        254
                        255
                        256

                        < fieldset class =" task " >
                        < label > Task

                        257
                        258
                        259

                        < div class =" panel panel - primary " >
                        < div class =" panel - heading " > < strong > Audio Clip

                        260
                        261
                        262
                        263
                        264
                        265
                        266
                        267
                        268
                        269
                        270
                        271
                        272
                        273
                        274
                        275
                        276

                        < div class =" panel - body d - flex align - items - start " >
                        < div class =" players " style =" width : 480 px ; padding : 0" >
                        < audio controls =" controls " class =" mb -20 w -100" >
                        < div class =" ytplayer mb -20" >
                        < table class =" mb -10" >

                        < kbd class =" modkey " > < kbd >I :
                        Play sentence from start


                        < kbd class =" modkey " > < kbd >B :
                        Rewind one second


                        < kbd class =" modkey " > < kbd >U :
                        Pause and unpause

                        B.2. 一般ドメイン実況生成



                        < br / > * Instructions : < a href =" https :// material - analyzer . airc .
                        aist . go . jp / I n s t ru c tio n sHe l p . html " target =" _blank " > > Help

                        277
                        278
                        279
                        280
                        281
                        282

                        149

                        < br / >
                        < small style =" border - top : 0.5 px solid #000000" >( Only when cursor is in a
                        subtitle editing field )


                        283
                        284
                        285
                        286
                        287
                        288
                        289
                        290
                        291
                        292
                        293
                        294
                        295
                        296
                        297
                        298
                        299
                        300
                        301
                        302
                        303
                        304
                        305
                        306
                        307
                        308
                        309
                        310
                        311
                        312
                        313
                        314
                        315
                        316
                        317
                        318
                        319
                        320
                        321
                        322
                        323
                        324
                        325
                        326
                        327

                        < div class =" sentences flex - grow -1" >



                        < section class =" panel - body panel - primary " >
                        < div class =" panel - heading d - flex flex - row " >
                        Questionnaire about this task

                        < div class =" panel - body no - bold - labels " >

                        Could you understand what was said ?

                        < fieldset class =" required " >
                        < div class =" form - check form - check - inline " >
                        < input required class =" form - check - input " type =" radio " id ="2
                        _understood_y " name ="2 _understood " value ="1" >
                        < label class =" form - check - label " for =" understood_y " > Yes

                        < div class =" form - check form - check - inline " >
                        < input required class =" form - check - input " type =" radio " id ="2
                        _understood_n " name ="2 _understood " value ="0" >
                        < label class =" form - check - label " for =" understood_n " > No



                        If not , why ?

                        < fieldset >
                        < div class =" form - check form - check - inline " >
                        < input class =" form - check - input " type =" checkbox " id ="2 _low_volume "
                        name ="2 _problems " value =" low_volume " >
                        < label class =" form - check - label " for ="2 _low_volume " > Low volume

                        < div class =" form - check form - check - inline " >
                        < input class =" form - check - input " type =" checkbox " id ="2 _too_fast " name
                        ="2 _problems " value =" too_fast " >
                        < label class =" form - check - label " for ="2 _too_fast " > Too fast

                        < div class =" form - check form - check - inline " >
                        < input class =" form - check - input " type =" checkbox " id ="2 _ u n k n o w n _ m e a n i n g
                        " name ="2 _problems " value =" unkn o wn _m e an in g " >
                        < label class =" form - check - label " for ="2 _ u n k n o w n _ m e a n i n g " > Words of
                        unknown meaning

                        < div class =" form - check form - check - inline " >
                        < input class =" form - check - input " type =" checkbox " id ="2 _not_english "
                        name ="2 _problems " value =" not_english " >
                        < label class =" form - check - label " for ="2 _not_english " > Not English label >

                        < div class =" form - check form - check - inline " >
                        < input class =" form - check - input " type =" checkbox " id ="2 _t oo _ mu c h_ no i se "
                        name ="2 _problems " value =" t oo_muc h_nois e " >

                        B.2. 一般ドメイン実況生成
                        328
                        329
                        330
                        331
                        332
                        333
                        334
                        335
                        336
                        337
                        338
                        339
                        340
                        341
                        342
                        343
                        344
                        345
                        346
                        347
                        348
                        349
                        350
                        351
                        352
                        353
                        354
                        355
                        356
                        357
                        358
                        359
                        360
                        361
                        362
                        363
                        364
                        365
                        366

                        150

                        < label class =" form - check - label " for ="2 _t oo _ mu ch _ no i se " > Too much noise


                        < div class =" form - check form - check - inline " >
                        < input class =" form - check - input " type =" checkbox " id ="2 _other " name ="2
                        _problems " value =" other " >
                        < label class =" form - check - label " for ="2 _other " > Other



                        Did the audio match the video ?

                        < fieldset class =" required " >
                        < div class =" form - check form - check - inline " >
                        < input required class =" form - check - input " type =" radio " id ="2 _matched_y
                        " name ="2 _matched " value ="1" >
                        < label class =" form - check - label " for =" matched_y " > Yes

                        < div class =" form - check form - check - inline " >
                        < input required class =" form - check - input " type =" radio " id ="2 _matched_n
                        " name ="2 _matched " value ="0" >
                        < label class =" form - check - label " for =" matched_n " > No



                        Was there any inappropriate language ?

                        < fieldset class =" required " >
                        < div class =" form - check form - check - inline " >
                        < input required class =" form - check - input " type =" radio " id ="2
                        _appro priate _y " name ="2 _appropriate " value ="0" >
                        < label class =" form - check - label " for =" appropriate_y " > Yes

                        < div class =" form - check form - check - inline " >
                        < input required class =" form - check - input " type =" radio " id ="2
                        _appro priate _n " name ="2 _appropriate " value ="1" >
                        < label class =" form - check - label " for =" appropriate_n " > No







                        < input name =" resultJSON " id =" resultJSON " type =" hidden "/ >

                        367
                        368
                        369
                        370
                        371

                        372
                        373
                        374

                        < script id =" realdata " type =" text / json " > $ { json }
                        < script id =" sampledata " type =" text / json " >
                        {" sentences ":[" uh Let ’ s see uh there ’ s a man , there ’ s a man throwing darts " , " and
                        I think oh it seems one of them , he threw three darts ," , " and I think 11 of
                        them hit the center , didn ’ t it ?."] , " d e f i l l e r _ s e n t e n c e s ":[" Let ’ s see ... there
                        ’ s a man , there ’ s a man throwing darts " , " and I think ... it seems one of them
                        , he threw three darts ," , " and I think 11 of them hit the center , didn ’ t it
                        ?."] , " timestamps ":[[0.54 ,6.35] ,[6.35 ,10.01] ,[10.01 ,14.364]] , " audio_s3_key
                        ":" sample / s a m p le _ w i t h _ e r r o r s . mp3 "}

                        < script id =" testdata " type =" text / json " >
                        {" sentences ":[" All right ." ," So it z there a burning man ? It ’ s a man and a woman
                        ." ," Man has some bongos ." ," Um , the woman has incentive for and feeds braided
                        hair with beads in it ." ," They ’ re having some kind of , ah , conversation ." ," She
                        wants to see him do something on his his bongos ." ," He ’ s got 12345 bongos ." ,"
                        Another one comes in and taste the , uh uh , container ." ," Okay , so he ’ s the man

                        B.2. 一般ドメイン実況生成

                        375

                        151

                        is playing on the bongos ." ," He got a bicyclist , uh , in an odd costume I was
                        walking about ." ," She ’ s dancing ." ," She ’ s got a uh huh And tiny barely there in
                        little skirt in a very tight little T shirt ." ," And she is now dancing to his
                        his bongo playing ." ," And he has , ah , she ’ s doing some unique moves ." ," Her
                        her derriere is really hanging out of her out of her costume ." ," And behind
                        them , there ’s , um , Kintz there in the desert ." ," Looks like that there got
                        some tents behind them with a bunch of bicycles just lined up ." ," And she ’ s
                        just dancing away to hiss bongo playing ." ," And he looks like he has attempt
                        behind him that is in the shape of a drum ." ," Bongo ." ," Possibly ." ," And she ’ s
                        clapping ." ," She ’ s She ’ s pleased with his bongo playing ."] ," d e f i l l e r _ s e n t e n c e s
                        ":[" All right ." ," So it z there a burning man ? It ’ s a man and a woman ." ," Man
                        has some bongos ." ," The woman has incentive for and feeds braided hair with
                        beads in it ." ," They ’ re having some kind of ... conversation ." ," She wants to
                        see him do something on his his bongos ." ," He ’ s got 12345 bongos ." ," Another
                        one comes in and taste the ... container ." ," Okay , so he ’ s the man is playing
                        on the bongos ." ," He got a bicyclist ... in an odd costume I was walking about
                        ." ," She ’ s dancing ." ," She ’ s got a ... And tiny barely there in little skirt in
                        a very tight little T shirt ." ," And she is now dancing to his his bongo
                        playing ." ," And he has ... she ’ s doing some unique moves ." ," Her her derriere is
                        really hanging out of her out of her costume ." ," And behind them , there ’ s ...
                        Kintz there in the desert ." ," Looks like that there got some tents behind them
                        with a bunch of bicycles just lined up ." ," And she ’ s just dancing away to
                        hiss bongo playing ." ," And he looks like he has attempt behind him that is in
                        the shape of a drum ." ," Bongo ." ," Possibly ." ," And she ’ s clapping ." ," She ’ s She ’ s
                        pleased with his bongo playing ."] ," timestamps
                        ":[[2.34 ,2.82] ,[2.82 ,7.36] ,[7.36 ,8.96] ,[9.34 ,15.56] ,[16.54 ,18.85] ,[20.44 ,24.35] ,[24.74 ,26.75] ,[
                        audio_s3_key ":" Batch_4345895 / Approved /3
                        UDTAB6HID6XCUM4XL77KBQ5G7L90G_3C6FJU71TY0VG13MT6I8XJ3Q86UUYX_A44ODU03OP0D9_ -v e K G 7 3 D i 4 _ 1 _ t r a i n . mp3 "}


                        376
                        377
                        378

                        < script >
                        " use strict ";

                        379
                        380
                        381
                        382
                        383

                        const config = {
                        region : ’ap - northeast -1 ’ ,
                        bucket : ’ nedo3 - amt - worker - uploads ’ ,
                        };

                        384
                        385
                        386
                        387
                        388
                        389

                        const
                        const
                        const
                        const
                        const

                        realJson = $ ( ’# realdata ’) . text () ;
                        testJson = $ ( ’# testdata ’) . text () ;
                        sampleJson = $ ( ’# sampledata ’) . text () ;
                        data = JSON . parse ( realJson === ’$ ’ + ’{ json } ’ ? testJson : realJson ) ;
                        sampleData = JSON . parse ( sampleJson ) ;

                        390
                        391
                        392
                        393

                        const searchParams = ( new URL ( document . URL ) ) . searchParams ;
                        const workerId = searchParams . get ( ’ workerId ’) ;
                        const assignmentId = searchParams . get ( ’ assignmentId ’) ;

                        394
                        395
                        396
                        397
                        398

                        const audioURL = " https ://" + config . bucket + ". s3 -" + config . region + ".
                        amazonaws . com /" + data . audio_s3_key ;
                        const videoID = data . audio_s3_key . match (/ _ (.{11}) _ [^ _ ]+ _ [^ _ ]+\. mp3 $ /) [1];
                        const sampleAudi oURL = " https ://" + config . bucket + ". s3 -" + config . region + ".
                        amazonaws . com /" + sampleData . audio_s3_key ;
                        const sampleVideoID = " H6hb3SIqdL4 ";

                        399
                        400
                        401
                        402
                        403
                        404
                        405
                        406

                        const ytAPIPromise = new Promise (( resolve , reject ) = > {
                        window . o n Y o u T u b e I f r a m e A P I R e a d y = resolve ;
                        const ytTag = document . createElement ( ’ script ’) ;
                        ytTag . src = " https :// www . youtube . com / iframe_api ";
                        const firs tScri ptTag = document . g e t E l e m e n t s B y T a g N a m e ( ’ script ’) [0];
                        firstS criptTag . parentNode . insertBefore ( ytTag , firstS criptT ag ) ;

                        B.2. 一般ドメイン実況生成
                        407

                        152

                        }) ;

                        408
                        409
                        410
                        411
                        412
                        413
                        414
                        415
                        416
                        417
                        418
                        419
                        420
                        421
                        422
                        423
                        424
                        425

                        function m a k e Y T P l a y e r P r o m i s e ( wrapper , options ) {
                        return ytAPIPromise . then (() = >
                        new Promise (( resolve , reject ) = > {
                        const ytPlayer = new YT . Player ( wrapper , {
                        ... options ,
                        events : {
                        ...( options . events ?? {}) ,
                        onReady : () = > {
                        ytPlayer . mute () ;
                        resolve ( ytPlayer ) ;
                        },
                        }
                        })
                        return ytPlayer ;
                        })
                        )
                        }

                        426
                        427
                        428
                        429
                        430
                        431
                        432
                        433
                        434
                        435
                        436
                        437
                        438
                        439
                        440
                        441

                        let modKey ;
                        if ( navigator . platform === ’ MacIntel ’) {
                        $ ( ’ kbd . modkey ’) . html ( ’^^ e2 ^^8 c ^^98 ’)
                        modKey = ’ metaKey ’;
                        } else {
                        $ ( ’ kbd . modkey ’) . text ( ’ Ctrl ’) . after ( ’ - ’) ;
                        modKey = ’ ctrlKey ’;
                        }
                        const keys = {
                        play : ’i ’ ,
                        back : ’b ’ ,
                        pause : ’u ’ ,
                        enter : ’ Enter ’ ,
                        };
                        const backJump = 1; // seconds

                        442
                        443
                        444
                        445
                        446
                        447

                        $ ( ’ form # mturk_form ’) . submit ( evt = > {
                        const $invalid = $ ( ’ main . container ’) . find ( ’: invalid ’) ;
                        if ( $invalid . length ) {
                        return false ;
                        }

                        448
                        449
                        450
                        451
                        452
                        453
                        454
                        455
                        456
                        457
                        458
                        459
                        460
                        461
                        462
                        463
                        464
                        465

                        const sampleBoxes = {} , actualBoxes = {};
                        $ ( ’. task . sample input [ type =" radio "]: checked ’) . get () . forEach ( el = > sampleBoxes [
                        el . name . substr (2) ] = !!+ el . value ) ;
                        $ ( ’. task . sample input [ type =" checkbox "] ’) . get () . forEach ( el = > ( sampleBoxes [ el .
                        name . substr (2) ] ??= {}) [ el . value ] = el . checked ) ;
                        $ ( ’. task . actual input [ type =" radio "]: checked ’) . get () . forEach ( el = > actualBoxes [
                        el . name . substr (2) ] = !!+ el . value ) ;
                        $ ( ’. task . actual input [ type =" checkbox "] ’) . get () . forEach ( el = > ( actualBoxes [ el .
                        name . substr (2) ] ??= {}) [ el . value ] = el . checked ) ;
                        const result = {
                        actual : {
                        correction : $ ( ’. task . actual . input - correction ’) . get () . map ( el = > el . value ) ,
                        review : $ ( ’. task . actual . input - review ’) . get () . map ( el = > el . value ) ,
                        boxes : actualBoxes ,
                        },
                        sample : {
                        correction : $ ( ’. task . sample . input - correction ’) . get () . map ( el = > el . value ) ,
                        review : $ ( ’. task . sample . input - review ’) . get () . map ( el = > el . value ) ,
                        boxes : sampleBoxes ,
                        },
                        };

                        B.2. 一般ドメイン実況生成
                        466
                        467
                        468

                        $ ( ’# resultJSON ’) . val ( JSON . stringify ( result ) ) ;
                        // no prev entDefault
                        }) ;

                        469
                        470
                        471
                        472
                        473
                        474
                        475
                        476
                        477
                        478

                        function makeTask ( $task , which , audioURL , videoID , data ) {
                        function playSentence ( evt , back =0) {
                        const $element = $ ( evt . target ) . closest ( ’ section ’) ;
                        const startTime = $element . data ( ’ from ’) ;
                        const newTime = back
                        ? Math . max ( startTime , audio . currentTime - back )
                        : startTime ;

                        479

                        audio . currentTime = newTime ;
                        audio . play () ;

                        480
                        481
                        482

                        };

                        483
                        484

                        $task . addClass ( which ) ;

                        485
                        486
                        487
                        488
                        489
                        490
                        491
                        492
                        493
                        494
                        495
                        496
                        497

                        const y t Pl ay e rP r om is e = m a k e Y T P l a y e r P r o m i s e ( $task . find ( ’. ytplayer ’) [0] , {
                        width : 480 ,
                        height : 292 ,
                        videoId : videoID ,
                        playerVars : {
                        autoplay : 0 ,
                        controls : 0 ,
                        disablekb : 1 ,
                        modest brandi ng : 1 ,
                        fs : 0 ,
                        },
                        }) ;

                        498
                        499
                        500
                        501
                        502
                        503
                        504
                        505

                        const $audio = $task . find ( ’ audio ’) ;
                        const audio = $audio [0];
                        console . log ( audio ) ;
                        const audioPromise = new Promise (( resolve , reject ) = > {
                        audio . a d d E v e n t L i s t e n e r ( ’ canplaythrough ’ , () = > resolve ( audio ) ) ;
                        $audio . attr ( ’ src ’ , audioURL ) ;
                        }) ;

                        506
                        507

                        Promise . all ([ ytPlayerPromise , audioPromise ]) . then (([ ytPlayer , audio ]) = > {

                        508
                        509
                        510
                        511
                        512
                        513
                        514
                        515
                        516

                        audio . a d d E v e n t L i s t e n e r ( ’ seeked ’ , evt = > {
                        ytPlayer . seekTo ( audio . currentTime ) ;
                        if ( audio . paused ) {
                        ytPlayer . pauseVideo () ;
                        } else {
                        ytPlayer . playVideo () ;
                        }
                        }) ;

                        517
                        518
                        519
                        520

                        audio . a d d E v e n t L i s t e n e r ( ’ pause ’ , evt = > {
                        ytPlayer . pauseVideo () ;
                        }) ;

                        521
                        522
                        523
                        524

                        audio . a d d E v e n t L i s t e n e r ( ’ play ’ , evt = > {
                        ytPlayer . playVideo () ;
                        }) ;

                        525
                        526
                        527
                        528

                        const $sentences = $task . find ( ’. sentences ’) ;
                        $sentences
                        . on ( ’ click ’ , ’. reset - button ’ , ( evt ) = > {

                        153

                        B.2. 一般ドメイン実況生成
                        529
                        530
                        531
                        532
                        533
                        534
                        535
                        536
                        537
                        538
                        539
                        540
                        541
                        542
                        543
                        544
                        545
                        546
                        547
                        548
                        549
                        550
                        551
                        552
                        553
                        554
                        555
                        556
                        557
                        558
                        559

                        154

                        const $input = $ ( evt . target ) . closest ( ’. sentbox ’) . find ( ’ textarea ’) ;
                        $input . val ( $input . data ( ’ original ’) ) ;
                        })
                        . on ( ’ click ’ , ’. play - button ’ , playSentence )
                        . on ( ’ keydown ’ , ’ textarea ’ , ( evt ) = > {
                        let handled = false ;
                        if ( evt . key == keys . enter ) {
                        evt . pre ventDe fault () ;
                        return ;
                        }
                        if ( evt [ modKey ]) {
                        if ( evt . key == keys . play ) {
                        playSentence ( evt ) ;
                        handled = true ;
                        } else if ( evt . key == keys . back ) {
                        playSentence ( evt , backJump ) ;
                        handled = true ;
                        } else if ( evt . key == keys . pause ) {
                        if ( audio . paused ) {
                        audio . play () ;
                        } else {
                        audio . pause () ;
                        }
                        handled = true ;
                        }
                        }
                        if ( handled ) {
                        evt . s t op P ro pa g at io n () ;
                        evt . pre ventDe fault () ;
                        }
                        }) ;

                        560
                        561
                        562
                        563
                        564
                        565
                        566
                        567
                        568
                        569
                        570
                        571
                        572
                        573
                        574
                        575
                        576
                        577
                        578
                        579
                        580
                        581
                        582
                        583
                        584
                        585
                        586
                        587

                        data . timestamps . forEach (([ from , to ] , i ) = > {
                        const sentence = data . sentences [ i ];
                        const d ef il le rS e n t e n c e = data . d ef i ll e r _ s e n t e n c e s [ i ];
                        const $template = $ ( ’ < div / > ’) . html ( ‘
                        < section class =" panel - body panel - primary " >
                        < div class =" panel - heading d - flex flex - row " >
                        < div class =" align - self - center " >
                        < span class =" from " > s & nbsp ;& mdash ;& nbsp ; < span class =" to " > span > s

                        < div class =" flex - grow -1" >
                        play_arrow

                        < div class =" panel - body " >
                        < div class =" w -100 sentbox " >
                        < label > Transcription correction
                        < div class =" d - flex flex - row " >
                        < div class =" input - sizer stacked flex - grow -1 align - self - start " >
                        < textarea class =" input - correction form - control w -100 h -100"
                        rows ="1" value ="" required / >


                        replay


                        < br / >
                        < div class =" w -100 sentbox " >
                        < label > Transcription review :
                        < div class =" d - flex flex - row " >
                        < div class =" input - sizer stacked flex - grow -1 align - self - start " >

                        B.3. 概況テキスト生成

                        155

                        < textarea class =" input - review form - control w -100 h -100" rows
                        ="1" value ="" required / >


                        replay





                        588
                        589
                        590
                        591
                        592
                        593
                        594

                        ‘) ;
                        const $element = $template . children ( ’: first ’) ;
                        $sentences . append ( $element ) ;
                        $element . data ( ’ from ’ , from ) ;
                        $element . find ( ’. from ’) . text ( from ) ;
                        $element . find ( ’. to ’) . text ( to ) ;
                        $element . find ( ’. input - correction ’) . val ( sentence ) . data ( ’ original ’ , sentence )
                        . parent () . attr ( ’ data - value ’ , sentence ) ;
                        $element . find ( ’. input - review ’) . attr ( ’ placeholder ’ , d e f i l l e r S e n t e n c e ) . data ( ’
                        original ’ , ’ ’) . parent () . attr ( ’ data - value ’ , d e f i l l e r S e n t e n c e ) ;
                        $element . find ( ’. input - sizer > textarea ’) . on ( ’ input ’ , evt = > {
                        evt . target . parentNode . dataset . value = evt . target . value || evt . target .
                        placeholder ;
                        }) ;
                        }) ;

                        595
                        596
                        597
                        598
                        599
                        600
                        601
                        602
                        603
                        604
                        605
                        606
                        607
                        608
                        609
                        610
                        611
                        612
                        613
                        614

                        }) ;
                        }
                        const task_els = $ ( ’. task ’) . get () ;
                        ) ; -->

                        makeTask ( $ ( task_els [0]) , ’ actual ’ , audioURL , videoID , data ) ;


                        B.3

                        概況テキスト生成
                        Listing B.6: Recording

                        1
                        2
                        3
                        4
                        5

                        import argparse
                        import warnings
                        from datetime import datetime
                        from functools import reduce
                        from pathlib import Path

                        6
                        7

                        import torch

                        8
                        9
                        10
                        11
                        12
                        13
                        14

                        from n e t w o r k _a t te n ti o n import (
                        AttnDecoder as Decoder ,
                        En co d er _no nHi gh as Encoder ,
                        EncoderDecoder ,
                        se tu p _a tte nti on

                        B.3. 概況テキスト生成
                        15
                        16
                        17
                        18
                        19
                        20
                        21
                        22
                        23

                        )
                        from
                        from
                        from
                        from
                        from
                        from
                        from
                        from

                        train import run
                        po stproc essing . bleu import calc_bleu
                        po stproc essing . export import e x p o r t _ r e s u l t s _ t o _ c s v
                        preprocessing . dataset import create_dataset
                        util . config import Config
                        util . constant import Phase , SpecialToken , SeqType
                        util . logging import create_logger
                        preprocessing . prepro import prepro

                        24
                        25
                        26

                        def parse_args () -> argparse . Namespace :

                        27
                        28
                        29
                        30
                        31
                        32
                        33
                        34
                        35
                        36
                        37
                        38
                        39
                        40
                        41
                        42
                        43
                        44
                        45
                        46
                        47
                        48
                        49
                        50
                        51
                        52
                        53

                        parser = argparse . Argum entPa rser ( prog = ’ reporter ’)
                        parser . add_argument ( ’ - - device ’ ,
                        type = str ,
                        metavar = ’ DEVICE ’ ,
                        default = ’ cpu ’ ,
                        help = ’ ‘ cuda :n ‘ where ‘n ‘ is an integer , or ‘cpu ‘ ’)
                        parser . add_argument ( ’ - - debug ’ ,
                        dest = ’ is_debug ’ ,
                        action = ’ store_true ’ ,
                        default = False ,
                        help = ’ show detailed messages while execution ’)
                        parser . add_argument ( ’ - - config ’ ,
                        type = str ,
                        dest = ’ dest_config ’ ,
                        metavar = ’ FILENAME ’ ,
                        default = ’ config . toml ’ ,
                        help = ’ specify config file ( default : ‘ config . toml ‘) ’)
                        parser . add_argument ( ’ -m ’ ,
                        ’-- model ’ ,
                        type = str ,
                        metavar = ’ FILENAME ’)
                        parser . add_argument ( ’ -o ’ ,
                        ’-- output - subdir ’ ,
                        type = str ,
                        metavar = ’ DIRNAME ’)
                        return parser . parse_args ()

                        54
                        55
                        56

                        def main () -> None :

                        57
                        58

                        args = parse_args ()

                        59
                        60
                        61

                        if not args . is_debug :
                        warnings . simplefilter ( action = ’ ignore ’ , category = FutureWarning )

                        62
                        63

                        config = Config ( args . dest_config )

                        64
                        65
                        66
                        67
                        68
                        69
                        70
                        71
                        72
                        73
                        74
                        75
                        76
                        77

                        device = torch . device ( args . device )
                        """
                        now = datetime . today () . strftime ( ’ reporter -% Y -% m -% d -% H -% M -% S ’)
                        dest_dir = config . dir_output / Path ( now ) \
                        if args . output_subdir is None \
                        else config . dir_output / Path ( args . output_subdir )
                        """
                        now = datetime . today () . strftime ( ’ reporter -% Y -% m -% d -% H -% M -% S ’)
                        folder_name = " test "
                        dest_dir = config . dir_output / Path ( folder_name ) \
                        if args . output_subdir is None \
                        else config . dir_output / Path ( args . output_subdir )
                        dest_log = dest_dir / Path ( now + ’_ ’ + ’ reporter . log ’)

                        156

                        B.3. 概況テキスト生成

                        157

                        78
                        79
                        80
                        81
                        82
                        83
                        84

                        """
                        now = " reporter -2019 -09 -11 -11 -36 -21"
                        dest_dir = config . dir_output / Path ( now ) \
                        if args . output_subdir is None \
                        else config . dir_output / Path ( args . output_subdir )
                        """

                        85
                        86

                        # dest_log = dest_dir / Path ( ’ reporter . log ’)

                        87
                        88
                        89

                        logger = create_logger ( dest_log , is_debug = args . is_debug )
                        config . write_log ( logger )

                        90
                        91
                        92

                        message = ’ start main ( is_debug : {} , device : {}) ’. format ( args . is_debug , args .
                        device )
                        logger . info ( message )

                        93
                        94
                        95
                        96
                        97
                        98

                        # === Alignment ===
                        h a s _ a l l _ al i g n m en t s = \
                        reduce ( lambda x , y : x and y ,
                        [( config . dir_output / Path ( ’ alignment -{}. json ’. format ( phase . value ) ) )
                        . exists ()
                        for phase in list ( Phase ) ])

                        99
                        100
                        101
                        102
                        103

                        # がなければ,作る alignment
                        if not ha s _ a l l_ a l i g n m e n t s :
                        print (" not exist alignment file ")
                        prepro ( config , logger )

                        104
                        105
                        106

                        # === Dataset ===
                        ( vocab , train , valid , test ) = create_dataset ( config , device )

                        107
                        108
                        109
                        110
                        111
                        112
                        113
                        114
                        115
                        116
                        117
                        118
                        119
                        120
                        121
                        122
                        123
                        124
                        125

                        vocab_size = len ( vocab )
                        dest_vocab = dest_dir / Path ( ’ reporter . vocab ’)
                        with dest_vocab . open ( mode = ’ wb ’) as f :
                        torch . save ( vocab , f )
                        seqtypes = [ SeqType . NormMovRefLong ,
                        SeqType . NormMovRefShort ,
                        SeqType . StdLong ,
                        SeqType . StdShort ] \
                        if config . u s e _ s t a n d a r d i z a t i o n \
                        else [ SeqType . NormMovRefLong ,
                        SeqType . N or m Mo v Re fS h ort ]
                        attn = s etu p_a tte nt io n ( config , seqtypes )
                        encoder = Encoder ( config , device )
                        decoder = Decoder ( config , vocab_size , attn , device )
                        model = Encod erDeco der ( encoder , decoder , device )
                        optimizer = torch . optim . Adam ( model . parameters () , lr = config . learning_rate )
                        criterion = torch . nn . NLLLoss ( reduction = ’ elementwise_mean ’ ,
                        ignore_index = vocab . stoi [ SpecialToken . Padding . value
                        ])

                        126
                        127
                        128
                        129
                        130
                        131
                        132
                        133
                        134
                        135
                        136
                        137

                        # === Train ===
                        dest_model = dest_dir / Path ( ’ reporter . model ’)
                        pr ev _ va lid _bl eu = 0.0
                        max_bleu = 0.0
                        best_epoch = 0
                        e a r l y _ s t op _ c o u nt e r = 0
                        for epoch in range ( config . n_epochs ) :
                        logger . info ( ’ start epoch {} ’. format ( epoch ) )
                        train_result = run ( train ,
                        vocab ,
                        model ,

                        B.3. 概況テキスト生成
                        optimizer ,
                        criterion ,
                        Phase . Train ,
                        logger , "")
                        train_bleu = calc_bleu ( train_result . gold_sents , train_result . pred_sents )
                        valid_result = run ( valid ,
                        vocab ,
                        model ,
                        optimizer ,
                        criterion ,
                        Phase . Valid ,
                        logger , "")
                        valid_bleu = calc_bleu ( valid_result . gold_sents , valid_result . pred_sents )

                        138
                        139
                        140
                        141
                        142
                        143
                        144
                        145
                        146
                        147
                        148
                        149
                        150
                        151

                        s = ’ | ’. join ([ ’ epoch : {0:4 d } ’. format ( epoch ) ,
                        ’ training loss : {:.2 f } ’. format ( train_result . loss ) ,
                        ’ training BLEU : {:.4 f } ’. format ( train_bleu ) ,
                        ’ validation loss : {:.2 f } ’. format ( valid_result . loss ) ,
                        ’ validation BLEU : {:.4 f } ’. format ( valid_bleu ) ])
                        logger . info ( s )

                        152
                        153
                        154
                        155
                        156
                        157
                        158

                        if max_bleu < valid_bleu :
                        torch . save ( model . state_dict () , str ( dest_model ) )
                        max_bleu = valid_bleu
                        best_epoch = epoch

                        159
                        160
                        161
                        162
                        163

                        e a rl y _ s t op _ c o u n t e r = e a r l y _s t o p _ c o u nt e r + 1 \
                        if p rev _va li d _b le u > valid_bleu \
                        else 0
                        if e a r l y _ s t o p _ c o u n t e r == config . patience :
                        logger . info ( ’ EARLY STOPPING ’)
                        break
                        pr ev _va lid _ble u = valid_bleu

                        164
                        165
                        166
                        167
                        168
                        169
                        170
                        171
                        172
                        173
                        174
                        175
                        176
                        177
                        178
                        179
                        180
                        181
                        182

                        # === Test ===
                        with dest_model . open ( mode = ’ rb ’) as f :
                        model . l oa d _s ta t e_ d ic t ( torch . load ( f ) )
                        test_result = run ( test ,
                        vocab ,
                        model ,
                        optimizer ,
                        criterion ,
                        Phase . Test ,
                        logger , dest_dir )
                        test_bleu = calc_bleu ( test_result . gold_sents , test_result . pred_sents )

                        183
                        184
                        185
                        186
                        187

                        s = ’ | ’. join ([ ’ epoch : {:04 d } ’. format ( best_epoch ) ,
                        ’ Test Loss : {:.2 f } ’. format ( test_result . loss ) ,
                        ’ Test BLEU : {:.10 f } ’. format ( test_bleu ) ])
                        logger . info ( s )

                        188
                        189

                        e x p o r t _ r e s u l t s _ t o _ c s v ( dest_dir , test_result )

                        190
                        191
                        192
                        193

                        if __name__ == ’ __main__ ’:
                        main ()

                        B.3.1

                        訓練プログラム

                        158

                        B.3. 概況テキスト生成

                        159
                        Listing B.7: Transcribe

                        1
                        2

                        from logging import Logger
                        from typing import Dict , List

                        3
                        4
                        5
                        6
                        7
                        8

                        import numpy
                        import torch
                        from nltk . translate . bleu_score import SmoothingFunction , sentence_bleu
                        from torchtext . data import Iterator
                        from torchtext . vocab import Vocab

                        9
                        10
                        11
                        12
                        13
                        14
                        15
                        16
                        17
                        18
                        19

                        from n e t w o r k _a t te n ti o n import Attention , En coderD ecoder
                        from operation import (
                        get_latest_closing_vals ,
                        replace_tags_with_vals
                        )
                        from po stproc essing . text import remove_bos
                        from util . constant import SEED , Code , Phase , SeqType , SpecialToken
                        from util . conversion import s t r i n g i f y _ r i c _ s e q t y p e
                        from util . tool import takeuntil
                        from pathlib import Path

                        20
                        21
                        22
                        23
                        24
                        25
                        26
                        27
                        28
                        29

                        class RunResult :
                        def __init__ ( self ,
                        loss : float ,
                        article_ids : List [ str ] ,
                        gold_sents : List [ List [ str ]] ,
                        gold_se nts_n um : List [ List [ str ]] ,
                        pred_sents : List [ List [ str ]] ,
                        pred_se nts_n um : List [ List [ str ]]) :

                        30
                        31
                        32
                        33
                        34
                        35
                        36

                        self . loss = loss
                        self . article_ids = article_ids
                        self . gold_sents = gold_sents
                        self . gold_sent s_num = gold _sents_num
                        self . pred_sents = pred_sents
                        self . pred_sent s_num = pred _sents_num

                        37
                        38
                        39
                        40
                        41
                        42

                        import matplotlib . pyplot as plt
                        import j a p a n i z e _ m a t p l o t l i b
                        plt . swi tch_ba ckend ( ’ agg ’)
                        import matplotlib . ticker as ticker

                        43
                        44
                        45
                        46
                        47
                        48
                        49
                        50

                        def showAttention ( input , output_words , attentions , save_file ) :
                        # Set up figure with colorbar
                        fig = plt . figure ( figsize =(60 , 40) )
                        ax = fig . add_subplot (111)
                        cax = ax . matshow ( attentions , cmap = ’ bone ’)
                        fig . colorbar ( cax )

                        51
                        52
                        53
                        54
                        55
                        56
                        57

                        # Set up axes
                        # print ( input )
                        # print ( input . cpu () )
                        ax . s et _ xtic kla bel s ([ ’ ’] + [ str ( round (s , 3) ) for s in input . cpu () . numpy () . tolist
                        () ] + [ ’ ’] , rotation =90)
                        # ax . s et _x t ic k la be l s ([ ’ ’] + input . split ( ’ ’) +[ ’ < EOS > ’] , rotation =90)
                        ax . s et _ ytic kla bel s ([ ’ ’] + output_words )

                        58
                        59
                        60

                        # Show label at every tick
                        ax . xaxis . s e t_ m aj o r _ l o c a t o r ( ticker . M ultip le Loc at o r (1) )

                        B.3. 概況テキスト生成
                        61

                        160

                        ax . yaxis . s e t_ m aj o r _ l o c a t o r ( ticker . M ultip le Loc at o r (1) )

                        62
                        63
                        64

                        plt . savefig ( save_file )
                        plt . close ()

                        65
                        66
                        67
                        68
                        69
                        70
                        71
                        72
                        73
                        74

                        def run ( X : Iterator ,
                        vocab : Vocab ,
                        model : EncoderDecoder ,
                        optimizer : Dict [ SeqType , torch . optim . Optimizer ] ,
                        criterion : torch . nn . modules . Module ,
                        phase : Phase ,
                        logger : Logger ,
                        dest_dir ) -> RunResult :

                        75
                        76
                        77
                        78
                        79

                        if phase in [ Phase . Valid , Phase . Test ]:
                        model . eval ()
                        else :
                        model . train ()

                        80
                        81

                        numpy . random . seed ( SEED )

                        82
                        83
                        84
                        85
                        86
                        87
                        88
                        89

                        accum_loss = 0.0
                        al l_ a rt icl e_i ds = []
                        all_go ld_sents = []
                        all_pr ed_sents = []
                        a l l _ g o l d _ s e n t s _ w i t h _ n u m b e r = []
                        a l l _ p r e d _ s e n t s _ w i t h _ n u m b e r = []
                        attn_weights = []

                        90
                        91

                        for batch in X :

                        92
                        93
                        94
                        95
                        96
                        97
                        98
                        99
                        100

                        article_ids = batch . article_id
                        times = batch . time
                        tokens = batch . token
                        ra w_ sho rt_ fiel d = s t r i n g i f y _ r i c _ s e q t y p e ( Code . N225 . value , SeqType . RawShort )
                        latest_vals = [ x for x in getattr ( batch , r aw _ sh or t _f ie l d ) . data [: , 0]]
                        raw_lo ng_fie ld = s t r i n g i f y _ r i c _ s e q t y p e ( Code . N225 . value , SeqType . RawLong )
                        l a t e s t _ c l o s i n g _ v a l s = g e t _ l a t e s t _ c l o s i n g _ v a l s ( batch , raw_long_field , times )
                        max_n_tokens , _ = tokens . size ()

                        101
                        102
                        103
                        104
                        105
                        106

                        # Forward
                        if phase == Phase . Test :
                        loss , pred , attn_weight , input_data = model ( batch , batch . batch_size ,
                        tokens , times , criterion , phase )
                        else :
                        loss , pred , attn_weight = model ( batch , batch . batch_size , tokens , times ,
                        criterion , phase )

                        107
                        108
                        109
                        110
                        111

                        if phase == Phase . Train :
                        optimizer . zero_grad ()
                        loss . backward ()
                        optimizer . step ()

                        112
                        113
                        114
                        115

                        if isinstance ( model . decoder . attn , Attention ) :
                        attn_weight = numpy . array ( list ( zip (* attn_weight ) ) )
                        attn_weights . extend ( attn_weight )

                        116
                        117

                        al l_ art icl e_id s . extend ( article_ids )

                        118
                        119
                        120

                        i_eos = vocab . stoi [ SpecialToken . EOS . value ]
                        # Recover words from ids removing BOS and EOS from gold sentences for
                        evaluation

                        B.3. 概況テキスト生成

                        161

                        gold_sents = [ remove_bos ([ vocab . itos [ i ] for i in takeuntil ( i_eos , sent ) ])
                        for sent in zip (* tokens . cpu () . numpy () ) ]
                        all_go ld_sen ts . extend ( gold_sents )

                        121
                        122
                        123
                        124

                        pred_sents = [ remove_bos ([ vocab . itos [ i ] for i in takeuntil ( i_eos , sent ) ])
                        for sent in zip (* pred ) ]
                        all_pr ed_sen ts . extend ( pred_sents )

                        125
                        126
                        127

                        if phase == Phase . Test :
                        z_iter = zip ( article_ids , gold_sents , pred_sents , latest_vals ,
                        latest_closing_vals , attn_weights , input_data )
                        for ( article_id , gold_sent , pred_sent , latest_val , latest_closing_val ,
                        att_we , input_d ) in z_iter :

                        128
                        129
                        130
                        131

                        bleu = sentence_bleu ([ gold_sent ] ,
                        pred_sent ,
                        s m oo t h i n g _ f u n c t i o n = S m o o t h i n g F u n c t i o n () . method1
                        )

                        132
                        133
                        134
                        135

                        gold_sent_num = r e p l a c e _ t a g s _ w i t h _ v a l s ( gold_sent ,
                        latest_closing_val , latest_val )
                        a l l _ g o l d _ s e n t s _ w i t h _ n u m b e r . append ( gold_sent_num )

                        136
                        137
                        138

                        pred_sent_num = r e p l a c e _ t a g s _ w i t h _ v a l s ( pred_sent ,
                        latest_closing_val , latest_val )
                        a l l _ p r e d _ s e n t s _ w i t h _ n u m b e r . append ( pred_sent_num )

                        139
                        140
                        141

                        description = \
                        ’\n ’. join ([ ’=== {} === ’. format ( phase . value . upper () ) ,
                        ’ Article ID : {} ’. format ( article_id ) ,
                        ’ Gold ( tag ) : {} ’. format ( ’ , ’. join ( gold_sent ) ) ,
                        ’ Gold ( num ) : {} ’. format ( ’ , ’. join ( gold_sent_num ) ) ,
                        ’ Pred ( tag ) : {} ’. format ( ’ , ’. join ( pred_sent ) ) ,
                        ’ Pred ( num ) : {} ’. format ( ’ , ’. join ( pred_sent_num ) ) ,
                        ’ BLEU : {:.5 f } ’. format ( bleu ) ,
                        ’ Loss : {:.5 f } ’. format ( loss . item () / max_n_tokens ) ,
                        ’ Latest : {:.2 f } ’. format ( latest_val ) ,
                        ’ Closing : {:.2 f } ’. format ( l a t e s t _ c l o s i n g _ v a l ) ])
                        showAttention ( input_d , pred_sent , att_we , dest_dir / Path (
                        article_id + ". png ") )
                        logger . info ( description ) # TODO : info → debug in release

                        142
                        143
                        144
                        145
                        146
                        147
                        148
                        149
                        150
                        151
                        152
                        153
                        154
                        155

                        accum_loss += loss . item () / max_n_tokens

                        156
                        157
                        158
                        159
                        160
                        161
                        162
                        163

                        return RunResult ( accum_loss ,
                        all_article_ids ,
                        all_gold_sents ,
                        all_gold_sents_with_number ,
                        all_pred_sents ,
                        all_pred_sents_with_number )

                        B.3.2

                        ネットワーク構成
                        Listing B.8: Transcribe

                        1
                        2
                        3

                        import itertools
                        from collections import OrderedDict
                        from typing import List , Tuple , Union

                        B.3. 概況テキスト生成

                        162

                        4
                        5
                        6
                        7

                        import torch
                        from torch import Tensor , nn
                        from torchtext . data import Batch

                        8
                        9
                        10
                        11
                        12
                        13
                        14
                        15
                        16
                        17
                        18

                        from util . config import Config
                        from util . constant import (
                        GENERATION_LIMIT ,
                        N_LONG_TERM ,
                        N_SHORT_TERM ,
                        TIMESLOT_SIZE ,
                        Phase ,
                        SeqType
                        )
                        from util . conversion import s t r i n g i f y _ r i c _ s e q t y p e

                        19
                        20
                        21
                        22
                        23

                        class Attention ( nn . Module ) :
                        ’’’ This implement ation is based on ‘ Luong et al . (2015) < https :// arxiv . org / abs
                        /1508.04025 > ‘ _ .
                        ’’’

                        24
                        25
                        26

                        def __init__ ( self ) :
                        super ( Attention , self ) . __init__ ()

                        27
                        28
                        29

                        def forward ( self , h_t : Tensor , h_s : Tensor ) -> Tensor :
                        return self . align ( h_t , h_s )

                        30
                        31
                        32
                        33
                        34
                        35
                        36
                        37
                        38
                        39
                        40
                        41
                        42
                        43
                        44
                        45
                        46
                        47
                        48
                        49
                        50

                        def align ( self , h_t : Tensor , h_s : Tensor ) -> Tensor :
                        r’’’
                        .. math :
                        a_ { ij } =
                        \ frac {%
                        \ exp \ left (
                        \ operatorname { score }\ left (
                        \ boldsymbol { h }^\ text { target } _j , \ boldsymbol { h }^\ text {
                        source } _i
                        \ right )
                        \ right )
                        }{%
                        \ sum_ {\ iota = 1}^ I
                        \ exp \ left (
                        \ operatorname { score }\ left (
                        \ boldsymbol { h }^\ text { target } _j , \ boldsymbol { h }^\
                        text { source } _ \ iota
                        \ right )
                        \ right )
                        }
                        ’’’
                        return nn . functional . softmax ( self . score ( h_t , h_s ) , dim =1)

                        51
                        52
                        53

                        def score ( self , h_t : Tensor , h_s : Tensor ) -> Tensor :
                        raise N o t I m p l e m e n t e d E r r o r

                        54
                        55
                        56

                        class G e n e r a l A t t e n t i o n ( Attention ) :

                        57
                        58
                        59
                        60
                        61
                        62
                        63

                        def __init__ ( self , h_t_size : int , h_s_size : int ) :
                        super ( Attention , self ) . __init__ ()
                        r’’’
                        Args :
                        h_t_size ( int ) : the size of target hidden state
                        h_s_size ( int ) : the size of source hidden state

                        B.3. 概況テキスト生成

                        163

                        64
                        65
                        66
                        67
                        68
                        69
                        70
                        71

                        This calculates scores by
                        .. math :
                        \ boldsymbol { h }^{ target } _j
                        \ cdot
                        \ boldsymbol { W }^\ text { attn } \ boldsymbol { h }^\ text { source } _i .
                        ’’’
                        self . w_a = nn . Linear ( h_s_size , h_t_size , bias = False )

                        72
                        73
                        74

                        def score ( self , h_t : Tensor , h_s : Tensor ) -> Tensor :
                        return torch . bmm ( self . w_a ( h_s ) , h_t . transpose (1 , 2) )

                        75
                        76
                        77

                        def se t up _a t ten tion ( config : Config , seqtypes : List [ SeqType ]) -> Union [ None ,
                        Attention ]:

                        78
                        79
                        80
                        81
                        82
                        83
                        84
                        85

                        # e n c _ t i m e _ h i d d e n _ s i z e = config . tim e_ embe d_ siz e * len ( seqtypes )
                        e n c _ t i m e _ h i d d e n _ s i z e = 138
                        if config . attn_type == ’ general ’:
                        # h_t ^^ c2 ^^ b7 ( W_a h_s )
                        return G e n e r a l A t t e n t i o n ( config . dec_hidden_size , e n c _ t i m e _ h i d d e n _ s i z e )
                        else :
                        return None

                        86
                        87
                        88
                        89

                        class E n co de r_n onH igh ( nn . Module ) :
                        def __init__ ( self , config : Config , device : torch . device ) :

                        90
                        91
                        92
                        93
                        94
                        95
                        96
                        97
                        98
                        99
                        100
                        101
                        102
                        103
                        104
                        105
                        106
                        107
                        108
                        109
                        110
                        111

                        super ( Encoder_nonHigh , self ) . __init__ ()
                        self . used_seqtypes = [ SeqType . StdLong ,
                        SeqType . StdShort ,
                        SeqType . NormMovRefLong ,
                        SeqType . Nor m MovRe fS h or t ] \
                        if config . u s e _ s t a n d a r d i z a t i on \
                        else [ SeqType . NormMovRefLong ,
                        SeqType . N or m Mo v Re fShor t ]
                        self . used_rics = config . rics
                        self . use_extra _rics = len ( self . used_rics ) > 1
                        # self . base_ric = config . base_ric
                        # self . extra_rics = [ ric for ric in self . used_rics if ric != self . base_ric ]
                        self . extra_rics = [ ric for ric in self . used_rics ]
                        self . b a s e _ r i c _ h i d d e n _ s i z e = config . b a s e _ r i c _ h i d d e n _ s i z e
                        self . ri c_hi dde n _s iz e = config . ric_ hi dden _s iz e
                        self . hidden_size = config . en c_ hidde n _size
                        self . n_layers = config . enc_n_layers
                        # self . prior_ encod ing = int ( self . base_ric in self . used_rics )
                        self . dropout = config . use_dropout
                        self . device = device
                        self . attn_vec_type = config . attn_vec_type

                        112
                        113
                        114

                        self . use_dropout = config . use_dropout
                        # self . r i c _ s e q t y p e _ t o _ m l p = dict ()

                        115
                        116
                        117
                        118
                        119
                        120
                        121
                        122
                        123
                        124

                        for ( ric , seqtype ) in itertools . product ( self . used_rics , self . used_seqtypes )
                        :
                        input_size = N_LONG_TERM \
                        if seqtype . value . endswith ( ’ long ’) \
                        else N_SHORT_TERM
                        """
                        output_size = self . b a s e _ r i c _ h i d d e n _ s i z e \
                        if ric == self . base_ric \
                        else self . r ic _h i dd en_si z e
                        """

                        B.3. 概況テキスト生成
                        125
                        126
                        127
                        128
                        129
                        130
                        131
                        132

                        164

                        output_size = input_size
                        """
                        mlp = MLP ( input_size ,
                        self . hidden_size ,
                        output_size ,
                        n_layers = self . n_layers ) . to ( self . device )
                        self . r i c _ s e q t y p e _ t o _ m l p [( ric , seqtype ) ] = mlp
                        """

                        133
                        134
                        135
                        136
                        137
                        138
                        139
                        140
                        141
                        142
                        143
                        144
                        145
                        146
                        147
                        148
                        149
                        150
                        151
                        152
                        153
                        154

                        lengths = [ N_LONG_TERM if seqtype . value . endswith ( ’ long ’) else N_SHORT_TERM
                        for (_ , seqtype ) in itertools . product ( self . used_rics , self .
                        used_seqtypes ) ]
                        self . total_length = sum ( lengths )
                        self . ca t_hi dde n _s iz e = \
                        self . total_length if len ( self . used_rics ) == 1 \
                        else 1 # self . pri or_enc oding * len ( self . used_seqtypes ) * self .
                        base_ric_hidden_size + \
                        #( len ( lengths ) - self . prior_encoding * len ( self . used_seqtypes ) ) * self .
                        ri c_h id de n _s i ze
                        """
                        self . ca t_hi dde n _s iz e = \
                        total_length + self . pr ior_en coding * len ( self . used_seqtypes ) * self .
                        base_ric_hidden_size \
                        if len ( self . used_rics ) == 1 \
                        else self . prior_ encodi ng * len ( self . used_seqtypes ) * self .
                        base_ric_hidden_size + \
                        ( len ( lengths ) - self . p rior_encoding * len ( self . used_seqtypes ) ) * self .
                        ri c_h id de n _s i ze
                        """
                        self . dense = nn . Linear ( self . cat_hidden_size , self . hidden_size )
                        if self . attn_vec_type == " concat ":
                        self . attn_linear = nn . Linear (1 , self . hidden_size )
                        elif self . attn_vec_type == " cnn ":
                        self . window = 3
                        self . move = 1
                        self . attn_linear = nn . Linear ( self . window , self . hidden_size )

                        155
                        156
                        157

                        if self . use_dropout :
                        self . drop = nn . Dropout ( p =0.30)

                        158
                        159
                        160
                        161

                        def forward ( self ,
                        batch : Batch ,
                        mi ni _ ba tc h _s i ze : int ) -> Tuple [ Tensor , Tensor ]:

                        162
                        163

                        L = OrderedDict ()

                        # low - level rep resentation

                        164
                        165

                        attn_vector = []

                        166
                        167

                        for ( ric , seqtype ) in itertools . product ( self . used_rics , self . used_seqtypes )
                        :

                        168
                        169

                        vals = getattr ( batch , s t r i n g i f y _ r i c _ s e q t y p e ( ric , seqtype ) ) . to ( self .
                        device )

                        170
                        171
                        172
                        173
                        174
                        175
                        176
                        177
                        178

                        if seqtype in [ SeqType . NormMovRefLong , SeqType . N o rm M ov Re f Sh or t ]:
                        # Switch the source to one which is not normalized
                        # to make our imp lemen tation compatible with Murakami 2017
                        L_seqtype = SeqType . MovRefLong \
                        if seqtype == SeqType . No rmMovR efLon g \
                        else SeqType . MovRefShort
                        L [( ric , seqtype ) ] = getattr ( batch , s t r i n g i f y _ r i c _ s e q t y p e ( ric ,
                        L_seqtype ) ) . to ( self . device )
                        else :

                        B.3. 概況テキスト生成
                        179
                        180
                        181
                        182
                        183
                        184
                        185
                        186
                        187
                        188
                        189
                        190
                        191
                        192
                        193

                        165

                        L [( ric , seqtype ) ] = vals
                        """
                        for ric in self . used_rics :
                        attn_vector . extend ([ num for num in [ L [( ric , seq ) ] for seq in self .
                        used_seqtypes ]])
                        """
                        if self . attn_vec_type == " concat ":
                        attn_vector = torch . cat ( list ( L . values () ) , 1)
                        elif self . attn_vec_type == " cnn ":
                        head = 0
                        for ric in self . used_rics :
                        seq_vec_list = [ L [( ric , seq ) ] for seq in self . used_seqtypes ]
                        while head + self . window <= len ( seq_vec_list ) :
                        attn_vector . extend ([ vec for vec in seq_vec_list [ head : head + self .
                        window ]])
                        self . head += self . move
                        head = 0

                        194
                        195

                        org_en c_hidd en = torch . cat ( list ( L . values () ) , 1)

                        # Murakami model

                        196
                        197

                        enc_hidden = self . dense ( org_e nc_hid den )

                        198
                        199
                        200
                        201
                        202

                        if self . use_dropout :
                        enc_hidden = self . drop ( enc_hidden )
                        org_en c_hidd en = self . drop ( org _enc_hidden )
                        attn_vector = self . drop ( attn_vector )

                        203
                        204
                        205
                        206
                        207
                        208
                        209
                        210
                        211
                        212

                        if len ( attn_vector ) > 0:
                        # attn_vector = torch . cat ( attn_vector , 1)
                        if self . attn_vec_type == " concat ":
                        attn_vector = attn_vector . view ( mini_batch_size , self . total_length ,
                        1)
                        elif self . attn_vec_type == " cnn ":
                        org_enc _hidd en = attn_vector
                        attn_vector = torch . cat ( attn_vector , 1)
                        attn_vector = attn_vector . view ( mini_batch_size , -1 , self . window )
                        attn_vector = self . attn_linear ( attn_vector )

                        213
                        214

                        return ( org_enc_hidden , enc_hidden , attn_vector )

                        215
                        216
                        217
                        218
                        219
                        220
                        221
                        222
                        223

                        class AttnDecoder ( nn . Module ) :
                        def __init__ ( self ,
                        config : Config ,
                        o u t p u t _ v o c a b _ s i z e : int ,
                        attn : Union [ None , Attention ] ,
                        device : torch . device ) :

                        224
                        225

                        super ( AttnDecoder , self ) . __init__ ()

                        226
                        227
                        228
                        229
                        230
                        231

                        self . device = device
                        self . de c_hi dde n _s iz e = config . dec_ hi dden _s iz e
                        self . wo rd_e mbe d _s iz e = config . word _e mbed _s iz e
                        self . ti me_e mbe d _s iz e = config . time _e mbed _s iz e
                        self . attn = attn

                        232
                        233
                        234
                        235
                        236
                        237

                        self . w or d_ em be d _ l a y e r = nn . Embedding ( output_vocab_size , self .
                        word_embed_size , padding_idx =0)
                        self . t im e_ em be d _ l a y e r = nn . Embedding ( TIMESLOT_SIZE , self . ti me _ em b ed _s i ze )
                        self . output_layer = nn . Linear ( self . dec_hidden_size , o u t p u t _ v o c a b _ s i z e )
                        self . softmax = nn . LogSoftmax ( dim =1)

                        B.3. 概況テキスト生成
                        238
                        239
                        240

                        166

                        self . de c_hi dde n _s iz e = self . de c _hidd en _si ze
                        self . i n pu t _h i dd e n _ s i z e = self . t ime_e m bed_s iz e + self . wo r d_ e mb ed _ si ze
                        self . re curr ent _ la ye r = nn . LSTMCell ( self . input_hidden_size , self .
                        de c_h idde n_s i ze )

                        241
                        242
                        243
                        244

                        self . en c_hi dde n _s iz e = config . enc_ hi dden _s iz e
                        attn_size = self . e n c_ hi d de n_s iz e + self . de c _h id d en _ si ze
                        self . linear_attn = nn . Linear ( attn_size , self . d e c_ h id de n _s iz e )

                        245
                        246
                        247
                        248
                        249
                        250

                        def init_hidden ( self , batch_size : int ) -> Tuple [ Tensor , Tensor ]:
                        zeros = torch . zeros ( batch_size , self . dec_hidden_size , device = self . device )
                        self . h_n = zeros
                        self . c_n = zeros
                        return ( self . h_n , self . c_n )

                        251
                        252
                        253
                        254
                        255
                        256

                        def forward ( self ,
                        word : Tensor ,
                        time : Tensor ,
                        seq_ric _tens or : Tensor ,
                        batch_size : int ) -> Tuple [ Tensor , Tensor ]:

                        257
                        258
                        259
                        260
                        261

                        weight = 0.0
                        word_embed = self . w o r d _ e m b e d_l a yer ( word ) . view ( batch_size , self .
                        wo rd_ embe d_s i ze )
                        time_embed = self . t i m e _ e m b e d_l a yer ( time ) . view ( batch_size , self .
                        ti me_ embe d_s i ze )
                        stream = torch . cat (( word_embed , time_embed ) , 1)

                        262
                        263
                        264

                        self . h_n , self . c_n = self . recu r rent_ la yer ( stream , ( self . h_n , self . c_n ) )
                        output , hidden = self . c_n , self . h_n

                        265
                        266
                        267
                        268
                        269
                        270
                        271
                        272
                        273
                        274

                        if isinstance ( self . attn , Attention ) :
                        _ , num_copy , _ = seq_r ic_ten sor . size ()
                        copied_hidden = hidden . unsqueeze (1)
                        weight = self . attn ( copied_hidden , seq _ric_t ensor )
                        weighted_ric = torch . bmm ( weight . view ( batch_size , -1 , num_copy ) ,
                        seq_ric_tens or . view ( batch_size , num_copy , -1) )
                        weighted_ric = weighted_ric . squeeze ()
                        hidden = torch . tanh ( self . linear_attn ( torch . cat (( hidden , weighted_ric ) ,
                        1) ) )
                        self . h_n = hidden

                        275
                        276
                        277

                        output = self . softmax ( self . output_layer ( hidden ) )
                        return ( output , weight )

                        278
                        279
                        280
                        281
                        282
                        283
                        284
                        285
                        286
                        287
                        288

                        class MLP ( nn . Module ) :
                        def __init__ ( self ,
                        input_size : int ,
                        mid_size : int ,
                        output_size : int ,
                        n_layers : int = 3 ,
                        a c t i v a t i o n _ f u n c t i on : str = ’ tanh ’) :
                        ’’’ Multi - Layer Perceptron
                        ’’’

                        289
                        290
                        291

                        super ( MLP , self ) . __init__ ()
                        self . n_layers = n_layers

                        292
                        293

                        assert ( n_layers >= 1)

                        294
                        295
                        296

                        if a c t i v a t i o n _ f u n c t i o n == ’ tanh ’:
                        self . a c t i v a t i o n _ f u n c t i o n = nn . Tanh ()

                        B.3. 概況テキスト生成
                        297
                        298
                        299
                        300

                        167

                        elif a c t i v a t i o n _ f u n c t i o n == ’ relu ’:
                        self . a c t i v a t i o n _ f u n c t i o n = nn . ReLU ()
                        else :
                        raise N o tI m p l e m e n t e d E r r o r

                        301
                        302
                        303
                        304
                        305
                        306
                        307
                        308
                        309

                        self . MLP = nn . ModuleList ()
                        if n_layers == 1:
                        self . MLP . append ( nn . Linear ( input_size , output_size ) )
                        else :
                        self . MLP . append ( nn . Linear ( input_size , mid_size ) )
                        for _ in range ( n_layers - 2) :
                        self . MLP . append ( nn . Linear ( mid_size , mid_size ) )
                        self . MLP . append ( nn . Linear ( mid_size , output_size ) )

                        310
                        311
                        312
                        313
                        314
                        315
                        316

                        def forward ( self , x : Tensor ) -> Tensor :
                        out = x
                        for i in range ( self . n_layers ) :
                        out = self . MLP [ i ]( out )
                        out = self . a c t i v a t i o n _f u n c t i o n ( out )
                        return out

                        317
                        318
                        319
                        320
                        321
                        322
                        323
                        324

                        class Enco derDec oder ( nn . Module ) :
                        def __init__ ( self ,
                        encoder : Encoder_nonHigh ,
                        decoder : AttnDecoder ,
                        device : torch . device ) :
                        super ( EncoderDecoder , self ) . __init__ ()

                        325
                        326
                        327
                        328

                        self . device = device
                        self . encoder = encoder . to ( self . device )
                        self . decoder = decoder . to ( self . device )

                        329
                        330

                        self . weight_lambda = 10 ** 0

                        # for supervised attention

                        331
                        332
                        333
                        334
                        335
                        336
                        337
                        338

                        def forward ( self ,
                        batch : Batch ,
                        mi ni _ ba tc h _s i ze : int ,
                        tokens : Tensor ,
                        time_em beddi ng : Tensor ,
                        criterion : nn . NLLLoss ,
                        phase : Phase ) -> Tuple [ nn . NLLLoss , Tensor , Tensor ]:

                        339
                        340
                        341

                        self . decoder . init_hidden ( mini_ ba tch_s i ze )
                        concated_input , self . decoder . h_n , attn_vector = self . encoder ( batch ,
                        mi ni_ batc h_s i ze )

                        342
                        343
                        344
                        345
                        346

                        loss = 0.0
                        n_tokens , _ = tokens . size ()
                        decoder_input = tokens [0]
                        time_e mbeddi ng = t ime_em beddin g . squeeze ()

                        347
                        348
                        349
                        350

                        pred = []
                        attn_weight = []
                        pred . append ( decoder_input . cpu () . numpy () )

                        351
                        352
                        353
                        354
                        355
                        356
                        357

                        if phase == Phase . Train :
                        for i in range (1 , n_tokens ) :
                        decoder_output , weight = \
                        self . decoder ( decoder_input , time_embedding , attn_vector ,
                        mi ni _ ba tc h _siz e )
                        loss += criterion ( decoder_output , tokens [ i ])

                        B.3. 概況テキスト生成
                        358
                        359
                        360
                        361
                        362

                        topv , topi = deco der_ou tput . data . topk (1)
                        pred . append ([ t [0] for t in topi . cpu () . numpy () ])
                        if self . decoder . attn :
                        weight = weight . squeeze ()
                        attn_weight . append ( weight )

                        363
                        364

                        decoder_input = tokens [ i ]

                        365
                        366
                        367
                        368
                        369
                        370
                        371

                        else :
                        for i in range (1 , G E N E RA T ION _ LIM I T ) :
                        decoder_output , weight = \
                        self . decoder ( decoder_input , time_embedding , attn_vector ,
                        mi ni _ ba tc h _siz e )
                        if i < n_tokens :
                        loss += criterion ( decoder_output , tokens [ i ])

                        372
                        373
                        374
                        375
                        376
                        377

                        topv , topi = deco der_ou tput . detach () . topk (1)
                        pred . append ([ t [0] for t in topi . cpu () . numpy () ])
                        if self . decoder . attn :
                        weight = weight . squeeze (2) . cpu () . detach () . numpy ()
                        attn_weight . append ( weight )

                        378
                        379
                        380
                        381
                        382
                        383

                        decoder_input = topi . squeeze ()
                        if phase == Phase . Test :
                        return ( loss , pred , attn_weight , concated_ input )
                        else :
                        return ( loss , pred , attn_weight )

                        168

                        この論文で使われている画像

全国の大学の
卒論・修論・学位論文

一発検索!

この論文の関連論文を見る