私はニューラルネットの専門家ではありませんが、以下の点が参考になると思います。いくつかの素晴らしい投稿もあります。たとえば、これは隠しユニットにあります。このサイトで、ニューラルネットがどのように役立つかについて検索することができます。
1大きなエラー:例がまったく機能しなかった理由
なぜエラーが非常に大きく、なぜすべての予測値がほぼ一定なのですか?
これは、ニューラルネットワークが指定された乗算関数を計算できずy
、に関係なくの範囲の真ん中に定数を出力することがx
トレーニング中のエラーを最小限に抑えるための最良の方法だったためです。(58749は、1から500までの2つの数値を掛け合わせる平均にかなり近いことに注意してください。)
ニューラルネットワークが乗算関数を賢明な方法で計算する方法を確認することは非常に困難です。ネットワーク内の各ノードが以前に計算された結果をどのように組み合わせるかを考えてください。前のノードからの出力の重み付き合計を取得します(そして、シグモイド関数をそれに適用します。たとえば、はじめにニューラルネットワークを参照して、出力を切り詰めます)および)。2つの入力の乗算を行うために加重和をどのように取得しますか?(ただし、非常に工夫された方法で乗算を機能させるために、多数の隠れ層を使用できる可能性があると思います。)− 11
2極小値:理論的に合理的な例が機能しない理由
ただし、追加しようとしても、例では問題が発生します。ネットワークが正常にトレーニングされません。これは2番目の問題、つまりトレーニング中に極小値を取得することが原因であると思います。実際、加算の場合、5つの非表示ユニットの2つのレイヤーを使用することは、加算を計算するには非常に複雑です。非表示のユニットがないネットワークは、完全に適切にトレーニングします。
x <- cbind(runif(50, min=1, max=500), runif(50, min=1, max=500))
y <- x[, 1] + x[, 2]
train <- data.frame(x, y)
n <- names(train)
f <- as.formula(paste('y ~', paste(n[!n %in% 'y'], collapse = ' + ')))
net <- neuralnet(f, train, hidden = 0, threshold=0.01)
print(net) # Error 0.00000001893602844
もちろん、ログを取ることで元の問題を追加の問題に変換することもできますが、これはあなたが望むことではないと思うので、その後...
3推定するパラメーターの数と比較したトレーニング例の数
では、元々あった5つの非表示ユニットの2つのレイヤーでニューラルネットをテストするための妥当な方法は何でしょうか。ニューラルネットは分類によく使用されるため、が問題の合理的な選択であるかどうかを判断します。私はと。学習すべきパラメータがいくつかあることに注意してください。X ⋅ K >CK =(1、2、3、4、5)c = 3750
以下のコードでは、トレーニングセットの50の例と500のサンプルを使用して2つのニューラルネットをトレーニングすることを除いて、非常に似たアプローチをとっています。
library(neuralnet)
set.seed(1) # make results reproducible
N=500
x <- cbind(runif(N, min=1, max=500), runif(N, min=1, max=500), runif(N, min=1, max=500), runif(N, min=1, max=500), runif(N, min=1, max=500))
y <- ifelse(x[,1] + 2*x[,1] + 3*x[,1] + 4*x[,1] + 5*x[,1] > 3750, 1, 0)
trainSMALL <- data.frame(x[1:(N/10),], y=y[1:(N/10)])
trainALL <- data.frame(x, y)
n <- names(trainSMALL)
f <- as.formula(paste('y ~', paste(n[!n %in% 'y'], collapse = ' + ')))
netSMALL <- neuralnet(f, trainSMALL, hidden = c(5,5), threshold = 0.01)
netALL <- neuralnet(f, trainALL, hidden = c(5,5), threshold = 0.01)
print(netSMALL) # error 4.117671763
print(netALL) # error 0.009598461875
# get a sense of accuracy w.r.t small training set (in-sample)
cbind(y, compute(netSMALL,x)$net.result)[1:10,]
y
[1,] 1 0.587903899825
[2,] 0 0.001158500142
[3,] 1 0.587903899825
[4,] 0 0.001158500281
[5,] 0 -0.003770868805
[6,] 0 0.587903899825
[7,] 1 0.587903899825
[8,] 0 0.001158500142
[9,] 0 0.587903899825
[10,] 1 0.587903899825
# get a sense of accuracy w.r.t full training set (in-sample)
cbind(y, compute(netALL,x)$net.result)[1:10,]
y
[1,] 1 1.0003618092051
[2,] 0 -0.0025677656844
[3,] 1 0.9999590121059
[4,] 0 -0.0003835722682
[5,] 0 -0.0003835722682
[6,] 0 -0.0003835722199
[7,] 1 1.0003618092051
[8,] 0 -0.0025677656844
[9,] 0 -0.0003835722682
[10,] 1 1.0003618092051
がnetALL
はるかに優れていることは明らかです!どうしてこれなの?plot(netALL)
コマンドで何が得られるか見てみましょう:
トレーニング中に推定される66個のパラメーターを作成します(11個のノードのそれぞれに5つの入力と1つのバイアス入力)。50のトレーニング例で66のパラメーターを確実に推定することはできません。この場合、ユニットの数を減らすことで、推定するパラメータの数を減らすことができると思います。また、ニューラルネットワークを構築してさらに実行すると、トレーニング中に問題が発生する可能性が低くなることがわかります。
ただし、機械学習(線形回帰を含む)の原則として、推定するパラメーターよりも多くのトレーニング例を用意する必要があります。