-
Notifications
You must be signed in to change notification settings - Fork 12
/
dialogue.ipynb
327 lines (327 loc) · 11.5 KB
/
dialogue.ipynb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
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
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Introduction\n",
"[Chainer](http://chainer.org/) とはニューラルネットの実装を簡単にしたフレームワークです。\n",
"\n",
"* 今回は対話にニューラルネットを適用してみました。\n",
"\n",
"![](./pictures/Chainer.jpg)\n",
"\n",
"* 今回は対話モデルの構築を行っていただきます。\n",
"\n",
"\n",
"対話モデルは人間の発言に対して応答して返すモデルです。\n",
"\n",
"対話モデルにはいくつか種類があるのでここでも紹介しておきます。\n",
"\n",
"* POMDP\n",
" * [POMDP](https://github.com/pybrain/pybrain/blob/master/pybrain/rl/environments/mazes/tasks/pomdp.py)対話モデルの一般的な機械学習のモデルです。\n",
"* End TO End ニューラル対話モデル\n",
" * 入力をユーザーの入力、出力をシステム側の出力として機械翻訳と同じ枠組みで対応しているモデル\n",
"\n",
"以下では、このChainerを利用しデータを準備するところから実際にNN対話モデルを構築し学習・評価を行うまでの手順を解説します。\n",
"\n",
"<A HREF=#1.各種ライブラリ導入 >1.各種ライブラリ導入</A><br>\n",
"<A HREF=#2.対話のクラス >2.対話のクラス</A><br>\n",
"<A HREF=#3.各値を設定 >3.各値を設定</A><br>\n",
"<A HREF=#4.実行 >4.実行</A><br>\n",
"<A HREF=#5.学習したモデルの動作テスト >5.学習したモデルの動作テスト</A><br>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## <A NAME=1.各種ライブラリ導入 /> 1.各種ライブラリ導入"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Chainerの言語処理では多数のライブラリを導入します。\n",
"Ctrl → m → lをコードの部分で入力すると行番号が出ます。ハンズオンの都合上、行番号があった方が良いので対応よろしくお願いします。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#表示用に使用しています。\n",
"from util.functions import trace\n",
"import numpy as np\n",
"\n",
"from chainer import Chain, Variable, cuda, functions, links, optimizer, optimizers, serializers\n",
"import chainer.links as L\n",
"\n",
"from EncoderDecoderModel import EncoderDecoderModel\n",
"import subprocess\n",
"\n",
"from word2vec.word2vec_load import SkipGram,SoftmaxCrossEntropyLoss\n",
"\n",
"unit = 300\n",
"vocab = 5000\n",
"loss_func = SoftmaxCrossEntropyLoss(unit, vocab)\n",
"w2v_model = SkipGram(vocab, unit, loss_func)\n",
"serializers.load_hdf5(\"word2vec/word2vec_chainer.model\", w2v_model)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`導入するライブラリの代表例は下記です。\n",
"\n",
"* `numpy`: 行列計算などの複雑な計算を行なうライブラリ\n",
"* `chainer`: Chainerの導入\n",
"* `util`:今回の処理で必要なライブラリが入っています。\n",
"* `w2v_model`:初期値の設定にWord2vecを使用して初期値の最適化を行なっています。\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## <A NAME=2.対話のクラス /> 2.対話のクラス"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"下記の論文を参考にしてforward処理を記述しています。\n",
"\n",
"http://arxiv.org/pdf/1507.04808.pdf\n",
"\n",
"\n",
"下記を設定しています。\n",
"* ニューラルネットを用いて対話用のモデルを構成しています。\n",
"\n",
"全体構成\n",
"\n",
"![](./pictures/NN_machine_translation.png)\n",
"\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"class EncoderDecoderModelForward(EncoderDecoderModel):\n",
" \n",
" def forward(self, src_batch, trg_batch, src_vocab, trg_vocab, encdec, is_training, generation_limit):\n",
" batch_size = len(src_batch)\n",
" src_len = len(src_batch[0])\n",
" trg_len = len(trg_batch[0]) if trg_batch else 0\n",
" src_stoi = src_vocab.stoi\n",
" trg_stoi = trg_vocab.stoi\n",
" trg_itos = trg_vocab.itos\n",
" encdec.reset(batch_size)\n",
"\n",
" x = self.common_function.my_array([src_stoi('</s>') for _ in range(batch_size)], np.int32)\n",
" encdec.encode(x)\n",
" for l in reversed(range(src_len)):\n",
" x = self.common_function.my_array([src_stoi(src_batch[k][l]) for k in range(batch_size)], np.int32)\n",
" encdec.encode(x)\n",
"\n",
" t = self.common_function.my_array([trg_stoi('<s>') for _ in range(batch_size)], np.int32)\n",
" hyp_batch = [[] for _ in range(batch_size)]\n",
"\n",
" if is_training:\n",
" loss = self.common_function.my_zeros((), np.float32)\n",
" for l in range(trg_len):\n",
" y = encdec.decode(t)\n",
" t = self.common_function.my_array([trg_stoi(trg_batch[k][l]) for k in range(batch_size)], np.int32)\n",
" loss += functions.softmax_cross_entropy(y, t)\n",
" output = cuda.to_cpu(y.data.argmax(1))\n",
" for k in range(batch_size):\n",
" hyp_batch[k].append(trg_itos(output[k]))\n",
" return hyp_batch, loss\n",
"\n",
" else:\n",
" while len(hyp_batch[0]) < generation_limit:\n",
" y = encdec.decode(t)\n",
" output = cuda.to_cpu(y.data.argmax(1))\n",
" t = self.common_function.my_array(output, np.int32)\n",
" for k in range(batch_size):\n",
" hyp_batch[k].append(trg_itos(output[k]))\n",
" if all(hyp_batch[k][-1] == '</s>' for k in range(batch_size)):\n",
" break\n",
"\n",
" return hyp_batch"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## <A NAME=3.各値を設定 /> 3.各値を設定"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"各値を設定\n",
"\n",
"* ユーザーの発言の設定(学習データ)\n",
"* システム応答結果の設定(学習データ)\n",
"* ユーザーの発言の設定(テストデータ)\n",
"* システム応答結果の設定(テストデータ)\n",
"* 語彙の設定\n",
"* 潜在空間の設定\n",
"* 隠れ層の設定\n",
"* 学習回数の設定\n",
"* ミニバッチサイズの設定\n",
"* 最大予測言語数の設定\n",
"ベストな調整方法は経験則か力技です。グリッドサーチ、ランダムサーチ、データから推定など。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"parameter_dict = {}\n",
"train_path = \"data/\"\n",
"parameter_dict[\"source\"] = train_path + \"player_1_wakati\"\n",
"parameter_dict[\"target\"] = train_path + \"player_2_wakati\"\n",
"parameter_dict[\"test_source\"] = train_path + \"player_1_wakati\"\n",
"parameter_dict[\"test_target\"] = train_path + \"player_2_test\"\n",
"#--------Hands on 2----------------------------------------------------------------\n",
"\n",
"\"\"\"\n",
"下記の値が大きいほど扱える語彙の数が増えて表現力が上がるが計算量が爆発的に増えるので大きくしない方が良いです。\n",
"\"\"\"\n",
"parameter_dict[\"vocab\"] = 5000\n",
"\n",
"\"\"\"\n",
"この数が多くなればなるほどモデルが複雑になります。この数を多くすると必然的に学習回数を多くしないと学習は\n",
"収束しません。\n",
"語彙数よりユニット数の数が多いと潜在空間への写像が出来ていないことになり結果的に意味がない処理になります。\n",
"\"\"\"\n",
"parameter_dict[\"embed\"] = 300\n",
"\n",
"\"\"\"\n",
"この数も多くなればなるほどモデルが複雑になります。この数を多くすると必然的に学習回数を多くしないと学習は\n",
"収束しません。\n",
"\"\"\"\n",
"parameter_dict[\"hidden\"] = 500\n",
"\n",
"\"\"\"\n",
"学習回数。基本的に大きい方が良いが大きすぎると収束しないです。\n",
"\"\"\"\n",
"parameter_dict[\"epoch\"] = 20\n",
"\n",
"\"\"\"\n",
"ミニバッチ学習で扱うサイズです。この点は経験的に調整する場合が多いが、基本的に大きくすると学習精度が向上する\n",
"代わりに学習スピードが落ち、小さくすると学習精度が低下する代わりに学習スピードが早くなります。\n",
"\"\"\"\n",
"parameter_dict[\"minibatch\"] = 64\n",
"\n",
"\"\"\"\n",
"予測の際に必要な単語数の設定。長いほど多くの単語の翻訳が確認できるが、一般的にニューラル翻訳は長い翻訳には\n",
"向いていないので小さい数値がオススメです。\n",
"\"\"\"\n",
"parameter_dict[\"generation_limit\"] = 256\n",
"\n",
"parameter_dict[\"word2vec\"] = w2v_model\n",
"\n",
"parameter_dict[\"word2vecFlag\"] = True\n",
"\n",
"\n",
"parameter_dict[\"encdec\"] = \"\"\n",
"\n",
"#--------Hands on 2----------------------------------------------------------------#"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## <A NAME=4.実行 /> 4.実行"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"trace('initializing ...')\n",
"\n",
"encoderDecoderModel = EncoderDecoderModelForward(parameter_dict)\n",
"encoderDecoderModel.train()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## <A NAME=5.学習したモデルの動作テスト /> 5.学習したモデルの動作テスト"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"学習したモデルを使用してテスト\n",
"\n",
"* 学習したモデルを利用して学習データに対して対応を変えす。\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"model_name = \"ChainerDialogue.021\"\n",
"trace('initializing ...')\n",
"\n",
"encoderDecoderModel = EncoderDecoderModelForward(parameter_dict)\n",
"encoderDecoderModel.test()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
""
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3.0
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.4.1"
}
},
"nbformat": 4,
"nbformat_minor": 0
}