自分で書いたニューラルネットワークを使ってsine()関数を近似しようとしています。単純なOCR問題でニューラルネットワークをテストしましたが、機能しましたが、近似sine()に適用するのに問題があります。私の問題は、トレーニング中にエラーが正確に50%に収束するため、完全にランダムだと推測していることです。
入力(0からPI)に1つの入力ニューロンを使用し、結果に1つの出力ニューロンを使用しています。ニューロンの数を変えることができる単一の隠れ層がありますが、現在は6〜10個程度を試しています。
Sine()の出力が-1から1の間であるのに対し、0から1の間だけを出力するシグモイド伝達関数(私のアプリケーションの要件)を使用しているため、問題があると感じています。これは、出力に2を掛けてから、1を引いてみましたが、問題は解決しませんでした。これを機能させるには、どこかで何らかの変換を行う必要があると思います。
何か案は?
線形出力ユニットを使用します。
[〜#〜] r [〜#〜] を使用した簡単な例を次に示します。
set.seed(1405)
x <- sort(10*runif(50))
y <- sin(x) + 0.2*rnorm(x)
library(nnet)
nn <- nnet(x, y, size=6, maxit=40, linout=TRUE)
plot(x, y)
plot(sin, 0, 10, add=TRUE)
x1 <- seq(0, 10, by=0.1)
lines(x1, predict(nn, data.frame(x=x1)), col="green")
ネットワークをトレーニングするときは、ターゲット(sin関数)を[0,1]の範囲に正規化する必要があります。そうすれば、シグモイド伝達関数を維持できます。
sin(x) in [-1,1] => 0.5*(sin(x)+1) in [0,1]
Train data:
input target target_normalized
------------------------------------
0 0 0.5
pi/4 0.70711 0.85355
pi/2 1 1
...
ターゲットをマッピングしたことに注意してくださいbefore training。ネットワークをトレーニングしてシミュレートしたら、ネットの出力をマップバックできます。
以下は、説明するためのMATLABコードです。
%% input and target
input = linspace(0,4*pi,200);
target = sin(input) + 0.2*randn(size(input));
% mapping
[targetMinMax,mapping] = mapminmax(target,0,1);
%% create network (one hidden layer with 6 nodes)
net = newfit(input, targetMinMax, [6], {'tansig' 'tansig'});
net.trainParam.epochs = 50;
view(net)
%% training
net = init(net); % init
[net,tr] = train(net, input, targetMinMax); % train
output = sim(net, input); % predict
%% view prediction
plot(input, mapminmax('reverse', output, mapping), 'r', 'linewidth',2), hold on
plot(input, target, 'o')
plot(input, sin(input), 'g')
hold off
legend({'predicted' 'target' 'sin()'})
バニラ最急降下法を使用した場合も同じ動作になります。別のトレーニングアルゴリズムを使用してみてください。
Javaアプレットに関する限り、興味深いことに気づきました。「双極シグモイド」を使用し、ランダムでない重み(からの結果など)から始めると収束します。二次関数を使用した以前のトレーニング)。
ネットワークが機能しない理由はありませんが、6は正弦波を近似するためのローサイドです。私は少なくとも10、多分20を試してみます。
それがうまくいかない場合は、システムについてさらに詳しく説明する必要があると思います。つまり、学習アルゴリズム(バックプロパゲーション?)、学習率などです。