質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Jupyter

Jupyter (旧IPython notebook)は、Notebook形式でドキュメント作成し、プログラムの記述・実行、その実行結果を記録するツールです。メモの作成や保存、共有、確認などもブラウザ上で行うことができます。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1642閲覧

シンプルな多層パーセプトロンにおける役に立たない中間層のニューロンの再利用について

picker413

総合スコア18

Jupyter

Jupyter (旧IPython notebook)は、Notebook形式でドキュメント作成し、プログラムの記述・実行、その実行結果を記録するツールです。メモの作成や保存、共有、確認などもブラウザ上で行うことができます。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/11/12 08:03

前提・実現したいこと

以前はscikit-learnなどを使っていましたが、現在研究テーマのためにライブラリーを用いらずにシンプルな多層パーセプトロンを誤差逆伝搬によって学習させています。

深層学習(MLP出版)やゼロから作るDeepLeaningなどを参考に作ったプログラムに試しにorタスクを学習させてみたのですが、学習はできたものの中間層のニューロンを10個ほど用意しておかないと学習が進まないという問題に直面しました。

自分で各ニューロンの出力を確認してみると、適当に重みを割り振った時に有用な中間層のニューロンがあった場合学習は進みますが、なかった場合、入力に対する中間層の出力は一向に変化せず、使えないニューロンはいつまでたっても使えないままという状態です。

機械学習を学び始めて数か月しかたっていないのでよくわからないですが、中間層の状態に有用なニューロンがなければ大きな誤差の勾配が伝わり有用なニューロンが現れると思っています。しかし、今のネットワークでは無益なニューロンは無益なままです。orのタスクは理論的には2つのニューロン(そもそも中間層が必要ない)でいいと思うので3,4個中間層のニューロンがあればいいと思うのですが・・・

今後はもっと複雑なタスクをやらせすつもりですし、RNN化するつもりなので重みの初期値に頼る今の状態は改善したいです。

ちなみに、学習率は固定で0.1~0.01を試したのですがダメでした。

こういう風にすればいいという漠然とした意見でもいいので、アドバイスを頂ければと思います。

コードはここに上げてあります。

もし、読んでいただけるのでしたら、これ以外のもんだでも突っ込んでいただけたら幸いです。

該当のソースコード

ネットワークの定義

python

1class test_network: 2 def __init__(self, I, H, O, W01_size, W12_size): 3 # 重みとバイアスの定義 4 W01 = W01_size*np.random.rand(I, H)-W01_size/2 5 W12 = W12_size*np.random.rand(H, O)-W12_size/2 6 b1 = np.zeros(H) 7 b2 = np.zeros(O) 8 9 # モデルの生成 10 self.Seccond_layer = BPneuron(W01, b1) 11 self.Third_layer = BPneuron(W12, b2) 12 self.test_loss_layer = Loss() 13 14 self.loss_memo = [] 15 self.dx_memo = np.empty(0) 16 self.bo_memo = np.empty(0) 17 self.dbo_memo = np.empty(0) 18 self.W12_memo = np.empty(0) 19 20 def traning(self, test_data, target_data, epoch): 21 # 学習に使う配列の決定 22 for i in range(epoch): 23 test_number = np.random.randint(target_data.shape[0]) 24 x = np.array([test_data[test_number]]) 25 t = np.array([target_data[test_number]]) 26 27 out1, container1 = self.Seccond_layer.forward(x) 28 out2, container2 = self.Third_layer.forward(out1) 29 W, b, x, y, z = container1 30 W, b, x, y, z = container2 31 32 loss = self.test_loss_layer.forward(out2, t) 33 dout = self.test_loss_layer.backward() 34 if i % 500 == 0: 35 print("loss:", dout, "epoch:", i) 36 print("_________") 37 print("b:", b) 38 print("_________") 39 40 if i % 5000 == 0: 41 clear_output() 42 43 self.loss_memo.append(dout[0][0]) 44 dx, containe = self.Third_layer.backward(dout) 45 dinput, containe = self.Seccond_layer.backward(dx) 46 self.dx_memo = np.append(self.dx_memo, dx) 47 self.bo_memo = np.append(self.bo_memo, b) 48 self.W12_memo = np.append(self.W12_memo, W) 49 50 return self.loss_memo 51 52 def dx(self): 53 return self.dx_memo 54 55 def bo(self): 56 return self.bo_memo 57 58 def W_12(self): 59 return self.W12_memo 60

各層の定義

python

1lr = 0.1 2class Loss: 3 def __init__(self): 4 self.Loss = None 5 self.dout = None 6 7 def forward(self, out, t): 8 self.Loss = 1/2 * np.sum((out - t)**2) 9 self.dout = out - t 10 return self.Loss 11 12 def backward(self): 13 return self.dout 14 15 16class BPneuron: 17 def __init__(self, W, b): 18 # 引数として受けた重みとバイアスをself.aramsに格納 19 self.params = [W, b] 20 # 更新前に勾配をまとめてオプティマイザーに送るための入れ物(中身はparamsに対応している必要あり) 21 self.grads = [np.zeros_like(W), np.zeros_like(b)] 22 # クラス外へ中身を持っていくための入れ物 23 self.container = np.empty(0) 24 25 def forward(self, x): 26 # クラスの初期化時に格納した重みとバイアスの取り出し 27 W, b = self.params 28 # yはニューロン内部の値 29 y = np.dot(x, W)+b 30 # Zが出力 31 z = sigmoid(y) 32 self.container = [W, b, x, y, z] 33 return z, self.container 34 35 def backward(self, dz): 36 W, b, x, y, z = self.container 37 # 出力部の逆伝搬(シグモイド版) 38 dy = sigmoid_back(z, dz) 39 db = dy 40 dW = np.dot(x.T, dy) 41 dx = np.dot(dy, W.T) 42 43 # self.gradsに更新に行かう勾配を格納 44 self.grads[0][...] = dW 45 self.grads[1][...] = db 46 47 # オプティマイザーによりself.paramsの値を更新 48 self.params = optimizer_SGD(lr, self.params, self.grads) 49 # すべての結果をself.containerに格納 50 self.container = [dy, db, dW, dx] 51 52 return dx, self.container

その他の関数

python

1 2def sigmoid(x): 3 return 1 / (1 + np.exp(-x)) 4 5 6def sigmoid_grad(z): 7 return sigmoid(z) * (1 - sigmoid(z)) 8 9 10def sigmoid_back(z, dz): 11 return dz*sigmoid(z) * (1 - sigmoid(z)) 12 13def optimizer_SGD(lr, params, grads): 14 for i in range(len(params)): 15 params[i] -= lr * grads[i] 16 17 return params 18

よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

学習が進むかどうか逆伝搬時に勾配の情報が正しく伝わるかどうかなので、初期化の仕方が結構重要だと思います。

一様分布でなく、一般的に広く使われている Xavier や He の初期化を試してみればどうでしょうか?

投稿2018/11/12 11:52

tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

picker413

2018/11/19 07:32

初期化に関するアルゴリズムは全く知らないので紹介していただいたXavier や Heを勉強してみようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問