多層パーセプトロン
ディープラーニングのチュートリアル
http://deeplearning.net/tutorial/intro.html
今回はMultilayer perceptron を読んでいきます。
http://deeplearning.net/tutorial/mlp.html
多層パーセプトロン
今回扱うのは、隠れ変数の層が一つある多層パーセプトロン。
隠れ変数間や観測変数間の接続はないものとする。
これは、入力に非線形変換が施されたロジスティック回帰とみなせる。
なんで非線形変換なんかするかって言うと、線形分離可能にするため。
ロジスティック回帰から多層パーセプトロンへ
ここからは実装の話
入力をで変換して、
その結果をロジスティック回帰の入力にしてやるのだからまず
ここで、重みの初期値はの範囲からランダムにとるとうまくいくってことが知られているのでそれに従う。
class HiddenLayer(object): def __init__(self, rng, input, n_in, n_out, activation=T.tanh): self.input = input # 初期値の設定 W_values = numpy.asarray(rng.uniform( low=-numpy.sqrt(6. / (n_in + n_out)), high=numpy.sqrt(6. / (n_in + n_out)), size=(n_in, n_out)), dtype=theano.config.floatX) if activation == theano.tensor.nnet.sigmoid: W_values *= 4 self.W = theano.shared(value=W_values, name='W') b_values = numpy.zeros((n_out), dtype=theano.config.floatX) self.b = theano.shared(value=b_values, name='b') # W, b と inputと outputの関係を定義 self.output = activation(T.dot(input, self.W) + self.b) self.params = [self.W, self.b] class MLP(object): def __init__(self, rng, input, n_in, n_hidden, n_out): # 入力を一旦h(x)で変換 self.hiddenLayer = HiddenLayer(rng = rng, input = input, n_in = n_in, n_out = n_hidden, activation = T.tanh) # h(x)で変換されたものを入力としてロジスティック回帰を行う self.logRegressionLayer = LogisticRegression( input=self.hiddenLayer.output, n_in=n_hidden, n_out=n_out)
ここで行っているのはあくまでもTheanoのシンボル同士の関係性を定義しているだけ。
そして、ここではL1とL2制約を用いる。
これは過学習を抑えるためだとおもう
self.L1 = abs(self.hiddenLayer.W).sum() \ + abs(self.logRegressionLayer.W).sum() self.L2_sqr = (self.hiddenLayer.W ** 2).sum() \ + (self.logRegressionLayer.W ** 2).sum() self.negative_log_likelihood = self.logRegressionLayer.negative_log_likelihood self.errors = self.logRegressionLayer.errors self.params = self.hiddenLayer.params + self.logRegressionLayer.params
前回のロジスティック回帰では、負の対数尤度を最小化したが、今回は負の対数尤度 + L1制約 + L2制約を最小化する
"ロジスティック回帰に一段隠れ変数の層を加えたのはその変換によって線形分離可能にするため"
であったはずで、その結果の学習方法が
"ロジスティック回帰の負の対数尤度 + L1制約 + L2制約の最小化"
というのがちょっとピンとこない
単純に、"隠れ変数の層への変換で線形分離可能"になれば、負の対数尤度関数は小さくなるだろうし、モデルの自由度が増えた分、過学習しやすくなっているから制約条件を入れるって言うのもわかるけどあとでちゃんと確認した方が良さそう
ということで学習部分
gparams = [] for param in classifier.params: gparam = T.grad(cost, param) gparams.append(gparam) updates = [] for param, gparam in zip(classifier.params, gparams): updates.append((param, param - learning_rate * gparam)) train_model = theano.function(inputs=[index], outputs=cost, updates=updates, givens={ x: train_set_x[index * batch_size:(index + 1) * batch_size], y: train_set_y[index * batch_size:(index + 1) * batch_size]})
おわりに
前回は問題自体も解法自体も初めて扱ったのでやることが多かったけれど、今回はアルゴリズムがちょこっと変わっただけだったので前回の内容が理解できていれば比較的理解しやすかったのではないかと思いました。