回答編集履歴

3

d

2018/11/10 16:37

投稿

tiitoi
tiitoi

スコア21954

test CHANGED
@@ -221,3 +221,127 @@
221
221
  print(np.allclose(loss1, loss2))
222
222
 
223
223
  ```
224
+
225
+
226
+
227
+ ## 追記
228
+
229
+
230
+
231
+ 各処理がなにをやっているのか簡単な例を追加しました。
232
+
233
+ TensorFlow のテンソルに対して、numpy の indexing のような操作ができないようなので、少々わかりづらいやり方を取らざる得なくなっています。
234
+
235
+
236
+
237
+ ```python
238
+
239
+ import tensorflow as tf
240
+
241
+
242
+
243
+ with tf.Session() as sess:
244
+
245
+ label_dim = 6
246
+
247
+ labels = tf.constant([[1, 2, 3, 4, 5, 6],
248
+
249
+ [7, 8, 9, 10, 11, 12],
250
+
251
+ [13, 14, 15, 16, 17, 18]])
252
+
253
+
254
+
255
+ # ラベルから Y_true を抽出する。
256
+
257
+ mask = tf.tile([True, True, False], (label_dim // 3,))
258
+
259
+ print(mask.eval()) # [ True True False True True False]
260
+
261
+
262
+
263
+ # 各サンプルの 1, 2, 4, 5 列目を抜き出している。
264
+
265
+ Y_true = tf.boolean_mask(labels, mask, axis=1)
266
+
267
+ print(Y_true.eval())
268
+
269
+ # [[ 1 2 4 5]
270
+
271
+ # [ 7 8 10 11]
272
+
273
+ # [13 14 16 17]]
274
+
275
+
276
+
277
+ # ラベルから重み係数を抽出する。
278
+
279
+ mask = tf.math.logical_not(mask)
280
+
281
+ print(mask.eval()) # [False False True False False True]
282
+
283
+
284
+
285
+ # 各サンプルの 3, 6 列目を抜き出している。
286
+
287
+ coeff = tf.boolean_mask(labels, mask, axis=1)
288
+
289
+ print(coeff.eval())
290
+
291
+ # [[ 3 6]
292
+
293
+ # [ 9 12]
294
+
295
+ # [15 18]]
296
+
297
+
298
+
299
+ # 末尾に次元を1つ追加している。ones のほうも同様
300
+
301
+ print(tf.shape(coeff).eval()) # [3 2]
302
+
303
+ print(tf.shape(coeff[..., tf.newaxis]).eval()) # [3 2 1]
304
+
305
+
306
+
307
+ # 次元を1つ増やし、axis=-1 で結合している。
308
+
309
+ ones = tf.ones_like(coeff)
310
+
311
+ concat = tf.concat([ones[..., tf.newaxis], coeff[..., tf.newaxis]], axis=-1)
312
+
313
+ print(concat.eval())
314
+
315
+ # [[[ 1 3]
316
+
317
+ # [ 1 6]]
318
+
319
+ # [[ 1 9]
320
+
321
+ # [ 1 12]]
322
+
323
+ # [[ 1 15]
324
+
325
+ # [ 1 18]]]
326
+
327
+
328
+
329
+ # [3 2 2] を [3, 4] に戻している。
330
+
331
+ W = tf.reshape(concat, [tf.shape(ones)[0], -1])
332
+
333
+ print(tf.shape(concat).eval()) # [3 2 2]
334
+
335
+ print(tf.shape(W).eval()) # [3 4]
336
+
337
+
338
+
339
+ print(W.eval())
340
+
341
+ # [[ 1 3 1 6]
342
+
343
+ # [ 1 9 1 12]
344
+
345
+ # [ 1 15 1 18]]
346
+
347
+ ```

2

d

2018/11/10 16:37

投稿

tiitoi
tiitoi

スコア21954

test CHANGED
@@ -8,101 +8,199 @@
8
8
 
9
9
 
10
10
 
11
- 簡単にするため、バッチ次元及び最後の2つの次元は除いています。
11
+ BatchSize=30, LabelDim=75, OutputDim=50
12
-
13
-
14
-
12
+
13
+
14
+
15
- モデルの入力データ X: (InputDims) の numpy 配列
15
+ モデルの入力 data: (BatchSize, 16, 16, 1) の配列
16
-
16
+
17
- モデルの出力データ Y_pred: (InputDims // 3 * 2) の numpy 配列
17
+ モデルの出力 Y_pred: (BatchSize, OutputDim) の配列
18
-
19
-
20
-
21
- まず入力データ X を MSE を計算する際の正解データと重み係数に分解します。
18
+
22
-
23
- 配列 X のうち、1, 2, 4, 5, 7, 8, ... というように3の倍数以外のインデックスの要素を抽出した部分配列を作り、
24
-
25
- これを Y_true とします。
26
-
27
- また配列 X のうち、3, 6, 9, ... というように3の倍数のインデックスの要素を抽出した部分配列を作り、W とします。
28
-
29
-
30
-
31
- W の要素に w_1, w_2, w_3, ... に交互に1を加えて、
19
+ ラベル labels: (BatchSize, LabelDim) の配列
32
-
33
- W = [1, w_1, 1, w_2, ...] とします。
20
+
34
-
35
-
36
-
37
- すると、サンプル1つの損失関数は以下のように表せます。
21
+
38
-
39
-
40
-
41
- mean((Y_true - Y_pred) ** 2 * W)
22
+
42
-
43
-
44
-
45
- ## numpy のサンプルコード
23
+ ## サンプルコード
24
+
25
+
26
+
27
+ ### テスト用に入力及びラベルを作成する。
46
28
 
47
29
 
48
30
 
49
31
  ```python
50
32
 
51
- batch_size = 30
52
-
53
- input_dim = 75
54
-
55
- assert 75 % 3 == 0 # input_dim は3で割り切れないとおかしい
56
-
57
- output_dim = input_dim // 3 * 2
58
-
59
-
60
-
61
- # ダミーの入力データ及び出力データを作成する。
62
-
63
- input_tensor = np.random.randn(batch_size, input_dim, 1, 1)
64
-
65
- Y_pred = np.random.randn(batch_size, output_dim, 1, 1)
66
-
67
- print('input_tensor.shape', input_tensor.shape) # input_tensor.shape (30, 75, 1, 1)
68
-
69
- print('Y_pred.shape', output_tensor.shape) # Y_pred.shape (3, 8, 1, 1)
70
-
71
-
72
-
73
- # 入力データ X を MSE を計算する際の正解データと重み係数に分解
74
-
75
- ##############################################################
76
-
77
-
78
-
79
- # 1, 2, 4, 5, 7, 8, ... というよう3の倍数以外が True のマスク
80
-
81
- Y_true_indices = np.mod(np.arange(input_dim) + 1, 3) != 0
82
-
83
- print(Y_true_indices)
84
-
85
- # [ True True False True True False True True False True True False]
86
-
87
-
88
-
89
- # 3, 6, 9, ... というように3の倍数が True のマスク
90
-
91
- W_indices = np.logical_not(Y_true_indices)
92
-
93
- # [False False True False False True False False True False False True]
94
-
95
- print(W_indices)
96
-
97
-
98
-
99
- Y_true = input_tensor[:, Y_true_indices, ...]
100
-
101
- coeff = input_tensor[:, W_indices, ...]
102
-
103
- print('Y_true.shape', Y_true.shape) # Y_true.shape (30, 50, 1, 1)
104
-
105
- print('coeff.shape', coeff.shape) # coeff.shape (30, 25, 1, 1)
33
+ import numpy as np
34
+
35
+
36
+
37
+ batch_size = 30 # バッチサイズ
38
+
39
+ input_shape = (16, 16, 1) # モデルの入力サイズ
40
+
41
+ label_dim = 75 # ラベルの次元数
42
+
43
+ output_dim = 50 # 出力の次元数
44
+
45
+
46
+
47
+ # ダミーの入力データ及びラベルを作成する。
48
+
49
+ data = np.random.randn(batch_size, *input_shape) # データ
50
+
51
+ labels = np.random.randn(batch_size, label_dim) # ラベル
52
+
53
+ print('data.shape', data.shape) # data.shape (30, 16, 16, 1)
54
+
55
+ print('labels.shape', labels.shape) # labels.shape (30, 75)
56
+
57
+ ```
58
+
59
+
60
+
61
+ ### テスト用簡単なモデルを作成する。
62
+
63
+
64
+
65
+ ```python
66
+
67
+ import tensorflow as tf
68
+
69
+ from keras.models import Sequential
70
+
71
+ from keras.layers import Conv2D, GlobalMaxPooling2D
72
+
73
+
74
+
75
+ # 入力が (BatchSize, 16, 16, 1) で出力が (BatchSize, 50) のダミーのモデルを作成する。
76
+
77
+ model = Sequential()
78
+
79
+ model.add(Conv2D(output_dim, kernel_size=(3, 3), input_shape=input_shape))
80
+
81
+ model.add(GlobalMaxPooling2D())
82
+
83
+ model.summary()
84
+
85
+ ```
86
+
87
+
88
+
89
+ ```
90
+
91
+ _________________________________________________________________
92
+
93
+ Layer (type) Output Shape Param #
94
+
95
+ =================================================================
96
+
97
+ conv2d_1 (Conv2D) (None, 14, 14, 50) 500
98
+
99
+ _________________________________________________________________
100
+
101
+ global_max_pooling2d_1 (Glob (None, 50) 0
102
+
103
+ =================================================================
104
+
105
+ Total params: 500
106
+
107
+ Trainable params: 500
108
+
109
+ Non-trainable params: 0
110
+
111
+ _________________________________________________________________
112
+
113
+ ```
114
+
115
+
116
+
117
+ ### 損失関数の定義
118
+
119
+
120
+
121
+ ```python
122
+
123
+ def custom_loss(labels, Y_pred):
124
+
125
+ # ラベルから Y_true を抽出する。
126
+
127
+ mask = tf.tile([True, True, False], (label_dim // 3,))
128
+
129
+ Y_true = tf.boolean_mask(labels, mask, axis=1)
130
+
131
+
132
+
133
+ # ラベルから重み係数を抽出する。
134
+
135
+ mask = tf.math.logical_not(mask)
136
+
137
+ coeff = tf.boolean_mask(labels, mask, axis=1)
138
+
139
+
140
+
141
+ # 重み係数を作成する。
142
+
143
+ ones = tf.ones_like(coeff)
144
+
145
+ W = tf.reshape(
146
+
147
+ tf.concat([ones[..., tf.newaxis], coeff[..., tf.newaxis]], axis=-1),
148
+
149
+ [tf.shape(ones)[0], -1])
150
+
151
+
152
+
153
+ return tf.reduce_mean((Y_true - Y_pred) ** 2 * W)
154
+
155
+ ```
156
+
157
+
158
+
159
+ ### 損失関数の値計算
160
+
161
+
162
+
163
+ ```
164
+
165
+ model.compile(loss=custom_loss, optimizer='adam')
166
+
167
+ model.fit(data, labels, epochs=3)
168
+
169
+ loss1 = model.evaluate(data, labels)
170
+
171
+ print(loss1) # 0.6780742406845093
172
+
173
+ ```
174
+
175
+
176
+
177
+ ### numpy での計算
178
+
179
+
180
+
181
+ ```
182
+
183
+ # モデルの出力
184
+
185
+ Y_pred = model.predict(data)
186
+
187
+
188
+
189
+ # ラベルから Y_true を抽出する。
190
+
191
+ mask = np.ones(labels.shape[1], dtype=bool)
192
+
193
+ mask[2::3] = False
194
+
195
+ Y_true = labels[:, mask]
196
+
197
+
198
+
199
+ # ラベルから重み係数を抽出する。
200
+
201
+ mask = np.logical_not(mask)
202
+
203
+ coeff = labels[:, mask]
106
204
 
107
205
 
108
206
 
@@ -110,26 +208,16 @@
110
208
 
111
209
  W = np.ones_like(Y_true)
112
210
 
113
- W[:, 1::2, ...] = coeff
211
+ W[:, 1::2] = coeff
114
-
115
- print('W.shape', W.shape) # W.shape (30, 50, 1, 1)
212
+
116
-
117
-
118
-
119
- # 重み付き2乗誤差
213
+
120
-
214
+
121
- loss = np.mean((Y_true - Y_pred) ** 2 * W)
215
+ loss2 = np.mean((Y_true - Y_pred) ** 2 * W)
216
+
217
+
218
+
122
-
219
+ # 計算した値が numpy と TensorFlow で一致するか
220
+
123
- print(loss)
221
+ print(np.allclose(loss1, loss2))
124
-
222
+
125
- ```
223
+ ```
126
-
127
-
128
-
129
- ## Keras でこれと同じことを行うには
130
-
131
-
132
-
133
- Keras の Lambda 関数内では TensorFlow の関数を利用できます。
134
-
135
- numpy でできることは TensorFlow の関数を使ってもできるので、同じ方針で作りましょう。

1

d

2018/11/10 14:24

投稿

tiitoi
tiitoi

スコア21954

test CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
 
6
6
 
7
- ## 問題設定とその理解
7
+ ## 問題設定
8
8
 
9
9
 
10
10