回答編集履歴

6

完全なパラメータの追記

2017/11/27 01:14

投稿

yag1kaz
yag1kaz

スコア253

test CHANGED
@@ -296,6 +296,8 @@
296
296
 
297
297
 
298
298
 
299
+ 既に不要かもしれませんが、完全な学習ができたハイパーパラメータを記載しておきます。
300
+
299
301
  ```Python
300
302
 
301
303
  X = numpy.array([[0, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0],[0, 0, 1,1], # 入力の記号:0がマイナス、1がプラス
@@ -324,64 +326,14 @@
324
326
 
325
327
  input_size = X.shape[1]
326
328
 
327
- hidden_size = 2 # 2
329
+ hidden_size = 6 # 2
328
330
 
329
331
  output_size = 4 # 2
330
332
 
331
- epsilon = 0.1 # 0.1
333
+ epsilon = 0.3 # 0.1
332
334
 
333
335
  mu = 0.5 # 0.9
334
336
 
335
- epoch = 200000 # 10000
336
-
337
- ```
338
-
339
-
340
-
341
- 残念ながら、[1,1,1,1]の符号判定だけは誤学習していました。パラメータとチューニングすればいけそうな感触です。
342
-
343
-
344
-
345
- 追記4
346
-
347
- 既に不要かもしれませんが、完全な学習ができたハイパーパラメータを記載しておきます。
348
-
349
- ```Python
350
-
351
- X = numpy.array([[0, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0],[0, 0, 1,1], # 入力の記号:0がマイナス、1がプラス
352
-
353
- [0, 1, 0, 0], [0, 1, 0, 1], [0, 1, 1, 0], [0, 1, 1, 1],
354
-
355
- [1, 0, 0, 0], [1, 0, 0, 1], [1, 0, 1, 0], [1, 0, 1, 1],
356
-
357
- [1, 1, 0, 0], [1, 1, 0, 1], [1, 1, 1, 0], [1, 1, 1, 1]])
358
-
359
- T = numpy.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], [1, 0, 0, 0], # 答えの符号:1個目が1ならプラス、
360
-
361
- [0, 1, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [0, 1, 0, 0], # 2個目が1ならマイナス
362
-
363
- [0, 1, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [0, 1, 0, 0],
364
-
365
- [1, 0, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], [1, 0, 0, 0]])
366
-
367
- # X = numpy.array([[0, 0], [0, 1], [1, 0], [1, 1]]) # 入力の記号:0がマイナス、1がプラス
368
-
369
- # T = numpy.array([[1, 0], [0, 1], [0, 1], [1, 0]]) # 答えの符号:1個目が1ならプラス、2個目が1ならマイナス
370
-
371
- N = X.shape[0] # number of data
372
-
373
-
374
-
375
- input_size = X.shape[1]
376
-
377
- hidden_size = 6 # 2
378
-
379
- output_size = 4 # 2
380
-
381
- epsilon = 0.3 # 0.1
382
-
383
- mu = 0.5 # 0.9
384
-
385
337
  epoch = 100000 # 10000
386
338
 
387
339
  ```

5

正解パラメータの追加

2017/11/27 01:14

投稿

yag1kaz
yag1kaz

スコア253

test CHANGED
@@ -423,3 +423,75 @@
423
423
  [1 1 1 1][ 9.91126091e-01 8.87614458e-03 2.20889172e-05 2.87712893e-05]0
424
424
 
425
425
  ```
426
+
427
+
428
+
429
+ mkgreiさんとのコメント欄でのやり取りで、興味がでたので、XNORを出力するMLPの重み付けパラメータの一例を記載しておきます。
430
+
431
+
432
+
433
+ 入力層+隠れ層(一層)+出力層の形での解の一例示です。
434
+
435
+
436
+
437
+ ```
438
+
439
+ <イメージ図>(※注:\はバックスラッシュ)
440
+
441
+ 入力層 隠れ層 出力層
442
+
443
+ (w11)
444
+
445
+ x1 ― ― h1
446
+
447
+ (w21)\ / (v1)
448
+
449
+ X    o1
450
+
451
+ (w12)/ \ /(v2)
452
+
453
+ x2 ― ― h2
454
+
455
+ (w22)
456
+
457
+ ```
458
+
459
+
460
+
461
+ h1 = f(w11 * x1 + w12 * x2 + b1)
462
+
463
+ h2 = f(w12 * x1 + w22 * x2 + b2)
464
+
465
+ o1 = f(v1 * h1 + v2 * h2 + b3)
466
+
467
+
468
+
469
+ fはシグモイド関数です。上記の形でMLPを表すことができます。
470
+
471
+
472
+
473
+ このときにXORを実現するパラメータの組み合わせは以下です。
474
+
475
+
476
+
477
+ w11 = 2
478
+
479
+ w12 = 2
480
+
481
+ w21 = -2
482
+
483
+ w22 = -2
484
+
485
+ b1 = -1
486
+
487
+ b2 = 3
488
+
489
+ v1 = -2
490
+
491
+ v2 = -2
492
+
493
+ b3 = 3
494
+
495
+
496
+
497
+ ここに負数があるのでreluではだめなんでしょうね。

4

完全収束したパラメータを追加

2017/11/25 10:08

投稿

yag1kaz
yag1kaz

スコア253

test CHANGED
@@ -272,7 +272,7 @@
272
272
 
273
273
  追記2
274
274
 
275
- 手元で確認しましたら、
275
+ 手元で確認しましたら、2値入力の符号計算については、
276
276
 
277
277
  epsilon = 0.1
278
278
 
@@ -339,3 +339,87 @@
339
339
 
340
340
 
341
341
  残念ながら、[1,1,1,1]の符号判定だけは誤学習していました。パラメータとチューニングすればいけそうな感触です。
342
+
343
+
344
+
345
+ 追記4
346
+
347
+ 既に不要かもしれませんが、完全な学習ができたハイパーパラメータを記載しておきます。
348
+
349
+ ```Python
350
+
351
+ X = numpy.array([[0, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0],[0, 0, 1,1], # 入力の記号:0がマイナス、1がプラス
352
+
353
+ [0, 1, 0, 0], [0, 1, 0, 1], [0, 1, 1, 0], [0, 1, 1, 1],
354
+
355
+ [1, 0, 0, 0], [1, 0, 0, 1], [1, 0, 1, 0], [1, 0, 1, 1],
356
+
357
+ [1, 1, 0, 0], [1, 1, 0, 1], [1, 1, 1, 0], [1, 1, 1, 1]])
358
+
359
+ T = numpy.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], [1, 0, 0, 0], # 答えの符号:1個目が1ならプラス、
360
+
361
+ [0, 1, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [0, 1, 0, 0], # 2個目が1ならマイナス
362
+
363
+ [0, 1, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [0, 1, 0, 0],
364
+
365
+ [1, 0, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], [1, 0, 0, 0]])
366
+
367
+ # X = numpy.array([[0, 0], [0, 1], [1, 0], [1, 1]]) # 入力の記号:0がマイナス、1がプラス
368
+
369
+ # T = numpy.array([[1, 0], [0, 1], [0, 1], [1, 0]]) # 答えの符号:1個目が1ならプラス、2個目が1ならマイナス
370
+
371
+ N = X.shape[0] # number of data
372
+
373
+
374
+
375
+ input_size = X.shape[1]
376
+
377
+ hidden_size = 6 # 2
378
+
379
+ output_size = 4 # 2
380
+
381
+ epsilon = 0.3 # 0.1
382
+
383
+ mu = 0.5 # 0.9
384
+
385
+ epoch = 100000 # 10000
386
+
387
+ ```
388
+
389
+ 学習結果は以下となります。
390
+
391
+ ```
392
+
393
+ [0 0 0 0][ 0.9946526 0.00533347 0.00283314 0.00259751]0
394
+
395
+ [0 0 0 1][ 3.35769941e-03 9.96644302e-01 5.56622699e-04 6.70592964e-04]1
396
+
397
+ [0 0 1 0][ 3.33927080e-03 9.96660884e-01 5.59857461e-04 6.70702223e-04]1
398
+
399
+ [0 0 1 1][ 9.96596879e-01 3.40821671e-03 2.22956843e-04 3.25614771e-04]0
400
+
401
+ [0 1 0 0][ 3.27048326e-03 9.96728618e-01 5.64677142e-04 6.74756067e-04]1
402
+
403
+ [0 1 0 1][ 9.96570795e-01 3.43393502e-03 2.23697557e-04 3.26314940e-04]0
404
+
405
+ [0 1 1 0][ 9.96504986e-01 3.49893558e-03 2.25097803e-04 3.27462076e-04]0
406
+
407
+ [0 1 1 1][ 5.66155206e-03 9.94335298e-01 9.34340392e-05 9.24230822e-05]1
408
+
409
+ [1 0 0 0][ 3.31009107e-03 9.96690587e-01 5.56904682e-04 6.68238304e-04]1
410
+
411
+ [1 0 0 1][ 9.96573108e-01 3.43220946e-03 2.22530928e-04 3.25064048e-04]0
412
+
413
+ [1 0 1 0][ 9.96511494e-01 3.49322967e-03 2.23526919e-04 3.25795278e-04]0
414
+
415
+ [1 0 1 1][ 5.66332128e-03 9.94333992e-01 9.32042942e-05 9.22570059e-05]1
416
+
417
+ [1 1 0 0][ 9.96481951e-01 3.52230033e-03 2.24429722e-04 3.26645683e-04]0
418
+
419
+ [1 1 0 1][ 5.66085770e-03 9.94336166e-01 9.33024233e-05 9.23137346e-05]1
420
+
421
+ [1 1 1 0][ 5.65317314e-03 9.94343241e-01 9.34888288e-05 9.24102042e-05]1
422
+
423
+ [1 1 1 1][ 9.91126091e-01 8.87614458e-03 2.20889172e-05 2.87712893e-05]0
424
+
425
+ ```

3

4値入力である程度うまくいくパターンを記載

2017/11/22 01:59

投稿

yag1kaz
yag1kaz

スコア253

test CHANGED
@@ -287,3 +287,55 @@
287
287
  [1 0][ 0.05249829 0.94820941]1
288
288
 
289
289
  [1 1][ 0.94447755 0.05472062]0
290
+
291
+
292
+
293
+ 追記3(2017/11/20 19:25)
294
+
295
+ 上記は2値入力でしたので4値入力でうまくいくパターンを見つけましたので、追記しておきます。
296
+
297
+
298
+
299
+ ```Python
300
+
301
+ X = numpy.array([[0, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0],[0, 0, 1,1], # 入力の記号:0がマイナス、1がプラス
302
+
303
+ [0, 1, 0, 0], [0, 1, 0, 1], [0, 1, 1, 0], [0, 1, 1, 1],
304
+
305
+ [1, 0, 0, 0], [1, 0, 0, 1], [1, 0, 1, 0], [1, 0, 1, 1],
306
+
307
+ [1, 1, 0, 0], [1, 1, 0, 1], [1, 1, 1, 0], [1, 1, 1, 1]])
308
+
309
+ T = numpy.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], [1, 0, 0, 0], # 答えの符号:1個目が1ならプラス、
310
+
311
+ [0, 1, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [0, 1, 0, 0], # 2個目が1ならマイナス
312
+
313
+ [0, 1, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [0, 1, 0, 0],
314
+
315
+ [1, 0, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], [1, 0, 0, 0]])
316
+
317
+ # X = numpy.array([[0, 0], [0, 1], [1, 0], [1, 1]]) # 入力の記号:0がマイナス、1がプラス
318
+
319
+ # T = numpy.array([[1, 0], [0, 1], [0, 1], [1, 0]]) # 答えの符号:1個目が1ならプラス、2個目が1ならマイナス
320
+
321
+ N = X.shape[0] # number of data
322
+
323
+
324
+
325
+ input_size = X.shape[1]
326
+
327
+ hidden_size = 2 # 2
328
+
329
+ output_size = 4 # 2
330
+
331
+ epsilon = 0.1 # 0.1
332
+
333
+ mu = 0.5 # 0.9
334
+
335
+ epoch = 200000 # 10000
336
+
337
+ ```
338
+
339
+
340
+
341
+ 残念ながら、[1,1,1,1]の符号判定だけは誤学習していました。パラメータとチューニングすればいけそうな感触です。

2

Python2->3対応分の修正とPython3で良好な結果を得るためのパラメータ検証の追記

2017/11/20 10:31

投稿

yag1kaz
yag1kaz

スコア253

test CHANGED
@@ -258,12 +258,32 @@
258
258
 
259
259
 
260
260
 
261
- print x
261
+ print(x)
262
-
262
+
263
- print y
263
+ print(y)
264
-
264
+
265
- print c
265
+ print(c)
266
-
266
+
267
- print ""
267
+ print("")
268
268
 
269
269
  ```
270
+
271
+
272
+
273
+ 追記2
274
+
275
+ 手元で確認しましたら、
276
+
277
+ epsilon = 0.1
278
+
279
+ mu = 0.5
280
+
281
+ で10000回で良好な結果が得られました。
282
+
283
+ [0 0][ 0.94077065 0.05854585]0
284
+
285
+ [0 1][ 0.05252437 0.94818359]1
286
+
287
+ [1 0][ 0.05249829 0.94820941]1
288
+
289
+ [1 1][ 0.94447755 0.05472062]0

1

実際のサンプルコードが存在するサイトへのリンクとサンプルコードを追記しました。

2017/11/20 05:08

投稿

yag1kaz
yag1kaz

スコア253

test CHANGED
@@ -3,3 +3,267 @@
3
3
 
4
4
 
5
5
  同一NNの各層に追加の符号学習専用の入力層、中間層、出力層を用意する、といいかえてもよいと思います。
6
+
7
+
8
+
9
+ <追記>
10
+
11
+ 以下の記事が参考になると思います。
12
+
13
+ https://qiita.com/ta-ka/items/bcdfd2d9903146c51dcb
14
+
15
+ リンク先ページの削除されていると参考にできなくなるとおもいますので、コード部分のみ転記しておきます。(記載先の例で示されている学習率で十分かどうかは確認をお願いいたします。)
16
+
17
+
18
+
19
+ neuralnetwork.py
20
+
21
+ ```python
22
+
23
+ import numpy
24
+
25
+ import math
26
+
27
+ import random
28
+
29
+ from matplotlib import pyplot
30
+
31
+
32
+
33
+ class Neural:
34
+
35
+
36
+
37
+ # constructor
38
+
39
+ def __init__(self, n_input, n_hidden, n_output):
40
+
41
+ self.hidden_weight = numpy.random.random_sample((n_hidden, n_input + 1))
42
+
43
+ self.output_weight = numpy.random.random_sample((n_output, n_hidden + 1))
44
+
45
+ self.hidden_momentum = numpy.zeros((n_hidden, n_input + 1))
46
+
47
+ self.output_momentum = numpy.zeros((n_output, n_hidden + 1))
48
+
49
+
50
+
51
+
52
+
53
+ # public method
54
+
55
+ def train(self, X, T, epsilon, mu, epoch):
56
+
57
+ self.error = numpy.zeros(epoch)
58
+
59
+ N = X.shape[0]
60
+
61
+ for epo in range(epoch):
62
+
63
+ for i in range(N):
64
+
65
+ x = X[i, :]
66
+
67
+ t = T[i, :]
68
+
69
+
70
+
71
+ self.__update_weight(x, t, epsilon, mu)
72
+
73
+
74
+
75
+ self.error[epo] = self.__calc_error(X, T)
76
+
77
+
78
+
79
+
80
+
81
+ def predict(self, X):
82
+
83
+ N = X.shape[0]
84
+
85
+ C = numpy.zeros(N).astype('int')
86
+
87
+ Y = numpy.zeros((N, X.shape[1]))
88
+
89
+ for i in range(N):
90
+
91
+ x = X[i, :]
92
+
93
+ z, y = self.__forward(x)
94
+
95
+
96
+
97
+ Y[i] = y
98
+
99
+ C[i] = y.argmax()
100
+
101
+
102
+
103
+ return (C, Y)
104
+
105
+
106
+
107
+
108
+
109
+ def error_graph(self):
110
+
111
+ pyplot.ylim(0.0, 2.0)
112
+
113
+ pyplot.plot(numpy.arange(0, self.error.shape[0]), self.error)
114
+
115
+ pyplot.show()
116
+
117
+
118
+
119
+
120
+
121
+ # private method
122
+
123
+ def __sigmoid(self, arr):
124
+
125
+ return numpy.vectorize(lambda x: 1.0 / (1.0 + math.exp(-x)))(arr)
126
+
127
+
128
+
129
+
130
+
131
+ def __forward(self, x):
132
+
133
+ # z: output in hidden layer, y: output in output layer
134
+
135
+ z = self.__sigmoid(self.hidden_weight.dot(numpy.r_[numpy.array([1]), x]))
136
+
137
+ y = self.__sigmoid(self.output_weight.dot(numpy.r_[numpy.array([1]), z]))
138
+
139
+
140
+
141
+ return (z, y)
142
+
143
+
144
+
145
+ def __update_weight(self, x, t, epsilon, mu):
146
+
147
+ z, y = self.__forward(x)
148
+
149
+
150
+
151
+ # update output_weight
152
+
153
+ output_delta = (y - t) * y * (1.0 - y)
154
+
155
+ _output_weight = self.output_weight
156
+
157
+ self.output_weight -= epsilon * output_delta.reshape((-1, 1)) * numpy.r_[numpy.array([1]), z] - mu * self.output_momentum
158
+
159
+ self.output_momentum = self.output_weight - _output_weight
160
+
161
+
162
+
163
+ # update hidden_weight
164
+
165
+ hidden_delta = (self.output_weight[:, 1:].T.dot(output_delta)) * z * (1.0 - z)
166
+
167
+ _hidden_weight = self.hidden_weight
168
+
169
+ self.hidden_weight -= epsilon * hidden_delta.reshape((-1, 1)) * numpy.r_[numpy.array([1]), x]
170
+
171
+ self.hidden_momentum = self.hidden_weight - _hidden_weight
172
+
173
+
174
+
175
+
176
+
177
+ def __calc_error(self, X, T):
178
+
179
+ N = X.shape[0]
180
+
181
+ err = 0.0
182
+
183
+ for i in range(N):
184
+
185
+ x = X[i, :]
186
+
187
+ t = T[i, :]
188
+
189
+
190
+
191
+ z, y = self.__forward(x)
192
+
193
+ err += (y - t).dot((y - t).reshape((-1, 1))) / 2.0
194
+
195
+
196
+
197
+ return err
198
+
199
+
200
+
201
+ ```
202
+
203
+
204
+
205
+ main.py
206
+
207
+ ```python
208
+
209
+ from neuralnetwork import *
210
+
211
+
212
+
213
+ if __name__ == '__main__':
214
+
215
+
216
+
217
+ X = numpy.array([[0, 0], [0, 1], [1, 0], [1, 1]])
218
+
219
+ T = numpy.array([[1, 0], [0, 1], [0, 1], [1, 0]])
220
+
221
+ N = X.shape[0] # number of data
222
+
223
+
224
+
225
+ input_size = X.shape[1]
226
+
227
+ hidden_size = 2
228
+
229
+ output_size = 2
230
+
231
+ epsilon = 0.1
232
+
233
+ mu = 0.9
234
+
235
+ epoch = 10000
236
+
237
+
238
+
239
+ nn = Neural(input_size, hidden_size, output_size)
240
+
241
+ nn.train(X, T, epsilon, mu, epoch)
242
+
243
+ nn.error_graph()
244
+
245
+
246
+
247
+ C, Y = nn.predict(X)
248
+
249
+
250
+
251
+ for i in range(N):
252
+
253
+ x = X[i, :]
254
+
255
+ y = Y[i, :]
256
+
257
+ c = C[i]
258
+
259
+
260
+
261
+ print x
262
+
263
+ print y
264
+
265
+ print c
266
+
267
+ print ""
268
+
269
+ ```