こんにちはHabr。
ハブで書いたものを読んで、彼らは人工知能についてもっとシンプルで面白い言語で話したかった。 アイデアは、第一に、ニューラルネットワークの基礎に関する一連の記事を書くことであり、第二に、すべてのwebdvanolに固有の双方向性とニューラルネットワークの学習能力を組み合わせた興味深いプロジェクトのアイデアがいくつかありますが、これは後のことです。
はじめに
この記事では、ニューロンや連想記憶などの基本概念を分析します。実際、これは一般的に人工知能と呼ばれるもののほとんどの基礎です。
ニューラルネットワークに関する講義をコピーアンドペーストすることはせず、すぐに仕事に取りかかることはありません。 このニューロンは誰なのか、数学的にどのように記述されているのか、何のためにあるのか、適切な程度の関心を持つ人なら誰でも自分で読むと思います。 さらに、単一のニューロンで構成され、結合操作を実装するニューラルネットワークの最も単純なJavaScript実装を提案します(ただし、この操作は、ネットワーク学習マトリックスを置き換えることで簡単に置き換えることができます)。
したがって、このクラスはニューラルネットワークのすべての機能を実装します。
//Globals weights
var weights = new Array();
var defaultWeight = -1;
//Our small Neuron Class=)
with (NeuronClass = new Function){
prototype.tsum = 0;
prototype.prilly = 0;
prototype.view = '' ;
prototype.vec = new Array();
//Sum all inputs
prototype.sum = function (x){
this .tsum = 0;
for ( var k = 0; k < 4;k++) {
this .tsum += weights[k] * x[k];
}
this .tsum += defaultWeight;
if ( this .tsum < 0) {
return 0;
}
else {
return 1;
}
}
//Teach function
prototype.teach = function (i, d, k){
this .prilly = 0;
this .prilly = 0.1 * (1 + Math.sin(0.01 * k * d * i));
return this .prilly;
}
//Check job our neoron
prototype.check = function (vector){
this .vec = vector.split( ',' );
this .view += this .sum( this .vec);
$( "#out_2" ).html( 'Result: ' + this .view);
this .view = '' ;
}
}
* This source code was highlighted with Source Code Highlighter .
コードは美しいふりをせず、ひざの上で書かれたものであり、「完璧なコード」のためではありません。 機能を分析しましょう。
ニューロンには4つの入力があり、フォームの単純な加算器が内部に実装されています
そして、sumメソッドによって実装され、週末には、このメソッドの値はしきい値アクティベーション関数に「設定」されます(これらの恐ろしい言葉はすべて
if ( this .tsum < 0) {
return 0;
}
else {
return 1;
}
)
* This source code was highlighted with Source Code Highlighter .
ティーチ方法は、ネットワーク学習、つまり ニューラルネットワークから受け取った値と式によって得られた値(明らかに真)の不一致に応じて、ニューロンの各入力の重み係数を変更します。
また、ネットワークをトレーニングした後、どのように学習したかをチェックするためのチェック方法が必要です。
ここで、連結トレーニングマトリックスでネットワークトレーニングを実施します。
var i, j, k, Yt, Yv, d, ms;
var biasing = new Array();
var x = new Array();
var values = new Array();
var view = '' ;
var Neuron = new NeuronClass();
check = function (vector){
Neuron.check(vector);
}
for (k = 0; k < 4; k++) {
weights[k] = Math.random();
biasing[k] = Math.random();
}
view += 'Start : ' + weights[0] + ' ' + weights[1] + ' ' + weights[2] + ' ' + weights[3] + '<br />' ;
i = 0;
while (i <= 200) {
j = Math.round(Math.random() * 10);
switch (j) {
case 1:{
x[0] = 1;
x[1] = 1;
x[2] = 0;
x[3] = 1;
Yv = 0;
break ;
}
case 2:{
x[0] = 1;
x[1] = 1;
x[2] = 1;
x[3] = 0;
Yv = 0;
break ;
}
case 3:{
x[0] = 1;
x[1] = 1;
x[2] = 1;
x[3] = 1;
Yv = 1;
break ;
}
case 4:{
x[0] = 1;
x[1] = 1;
x[2] = 0;
x[3] = 0;
Yv = 0;
break ;
}
case 5:{
x[0] = 1;
x[1] = 0;
x[2] = 1;
x[3] = 1;
Yv = 0;
break ;
}
case 6:{
x[0] = 1;
x[1] = 0;
x[2] = 1;
x[3] = 0;
Yv = 0;
break ;
}
case 7:{
x[0] = 1;
x[1] = 0;
x[2] = 0;
x[3] = 1;
Yv = 0;
break ;
}
case 8:{
x[0] = 1;
x[1] = 0;
x[2] = 0;
x[3] = 0;
Yv = 0;
break ;
}
case 9:{
x[0] = 0;
x[1] = 1;
x[2] = 1;
x[3] = 1;
Yv = 0;
break ;
}
case 10:{
x[0] = 0;
x[1] = 0;
x[2] = 0;
x[3] = 0;
Yv = 0;
break ;
}
}
Yt = Neuron.sum(x);
d = Yv - Yt;
for (k = 0; k < 4; k++)
values[k] = Neuron.teach(i, d, biasing[k]);
for (k = 0; k < 4; k++)
weights[k] = weights[k] + values[k] * d * x[k];
i++;
}
view += 'Stop : ' + weights[0] + ' ' + weights[1] + ' ' + weights[2] + ' ' + weights[3] + '<br />' ;
$( "#out" ).html(view);
* This source code was highlighted with Source Code Highlighter .
スイッチのすべては、学習マトリックス、つまりです。 入力の値と出力を設定する必要があります。もちろん、すべてのオプションがトレーニングマトリックスにあるわけではありません。そうでない場合、ニューラルネットワークを使用して問題を解決します(ただし、この場合、パフォーマンス上の理由から使用すべきではありませんが、これは単なる例です、および最初)。
行
Yt = Neuron.sum(x);
d = Yv - Yt;
for (k = 0; k < 4; k++)
values[k] = Neuron.teach(i, d, biasing[k]);
for (k = 0; k < 4; k++)
weights[k] = weights[k] + values[k] * d * x[k];
* This source code was highlighted with Source Code Highlighter .
些細なことですが、それでも、ここでは、「結果」がどのように予想から「なくなっている」かを確認し、これに応じて、ネットワーク入力ごとに学習機能を呼び出します。
次に、ネットワークがどれだけ正しくトレーニングされたかを確認します。これは、係数の初期値から始まる多くの要因に依存します。係数は、この些細なケースでは単純にランダムに選択され、学習の反復回数に依存します。
例http://bnet.su/dvl/nn1/
ソースhttp://bnet.su/dvl/nn1/nn1.zip
ホップフィールドネットワーク
次に、Hopfieldネットワークについて説明します。 このネットワークは自動連想メモリを実装しており、サンプルを復元する機能の点で興味深いものです。 サイズはn * nの(n次元)行列のベクトルを受け取ったので、すべてが単純で、歪んだベクトルをネットワークの「入力」に送信できます。その結果、元のベクトルを取得できます。これはネットワークの非常に有用な特性です。 ウィキにはこの主題に関する多くの理論的情報がありますので、ここでやめることはありません。また、他の目標もあります。
言葉からコードへ。 MemClassクラスは、ネットワークで作業するために必要なすべてのメソッドを実装します。
with (MemClass = new Function){
prototype.global_matrix = new Array();
prototype.sign = function (value){
return (parseFloat(value) > 0) ? '1' : '-1' ;
}
prototype.searchW = function (vector){
var vec = new Array();
var returned = new Array();
var tmp = new Array();
vec = vector.split( ',' );
this .ViewerW( this .getW( this .getTmp(vec))[1]);
}
prototype.getTmp = function (vec){
var tmp = new Array();
var count = 0;
count = vec.length;
for ( var i = 0; i < count; i++) {
tmp[i] = parseFloat(2 * vec[i] - 1);
}
return tmp;
}
prototype.getW = function (tmp){
var view = '' ;
var returned = new Array();
var count = 0;
count = tmp.length;
returned[0] = new Array();
for ( var i = 0; i < count; i++) {
for ( var j = 0; j < count; j++) {
//alert(returned[i]);
if (j == 0)
returned[i] = new Array();
returned[i][j] = parseFloat(tmp[i] * tmp[j]);
if (i == j)
returned[i][j]--;
if (returned[i][j] >= 0)
view += ' ' ;
view += returned[i][j];
}
view += '<br />' ;
}
this .global_matrix = returned;
//tmp
return Array(returned, view);
}
prototype.check = function (vector, j){
var sum = 0;
for ( var i = 0; i < vector.length; i++) {
sum = sum + parseFloat(vector[i]) * parseFloat( this .global_matrix[j][i]);
}
return sum;
}
prototype.checkMatrix = function (vector){
var view = '' ;
var vec = new Array();
vector = vector.split( ',' );
for ( var i = 0; i < vector.length; i++) {
vec[i] = this .sign( this .check(vector, i));
view += vec[i];
}
this .ViewerCheck(view);
prototype.ViewerW = function (matrix){
$( "#matrix" ).html(matrix);
$( "#form_second" ).css({
display: "block"
});
}
}
prototype.ViewerCheck = function (vector){
$( "#check_vector" ).html(vector);
}
prototype.ViewerW = function (view) {
$( "#matrix" ).html(view);
$( "#matrix" ).show( "drop" , {
direction: "right"
}, 500);
$( "#form_second" ).css({display: 'block' });
}
* This source code was highlighted with Source Code Highlighter .
何が何であるかを理解しましょう。 記憶するベクトルを入力すると、最終的にgetWメソッドが呼び出され、次の関数が実装されます ここで、Iはサイズn * nの単位行列です。 数学はそこで終わりません。ベクターを復元するとき、操作のトレースが使用されます(checkMatrixメソッドによって実装されます) 。 さて、それは事実上すべてです。今では、バイナリベクトルが何であっても覚えており、あらゆる方法でそれを変更することにより、ネットワークが「Fu!」
さて、jQueryを使ったちょっとした魔法で、これで完了です
$( function (){
$( '#form_first label' ).tooltip({
track: true ,
delay: 100,
showBody: '::' ,
opacity: 0.85,
bodyHandler: function (){
return ' , "1" "-1" ( ) ( =))' ;
}
});
$( '#form_second label' ).tooltip({
track: true ,
delay: 100,
showBody: '::' ,
opacity: 0.85,
bodyHandler: function (){
return ' , , ( )' ;
}
});
$( '#matrix' ).tooltip({
track: true ,
delay: 100,
showBody: '::' ,
opacity: 0.85,
bodyHandler: function (){
return ' ' ;
}
});
$( '#check_vector' ).tooltip({
track: true ,
delay: 100,
showBody: '::' ,
opacity: 0.85,
bodyHandler: function (){
return ' ' ;
}
});
});
* This source code was highlighted with Source Code Highlighter .
理解を深めるために、このツールチップにjQueryプラグインを使用して、ヒントをハングアップします。
例http://bnet.su/dvl/nn2/ 。
ソースhttp://bnet.su/dvl/nn2/nn2.zip
おわりに
この記事では、ニューラルネットワークの基本の基礎を検証しました。数学者にとっては根拠がなく、理不尽ではなく、プログラマにとってはあまりにも乾燥していて退屈ではないことを願っています。 次の記事では、いわゆる「遺伝的」アルゴリズムと、実際にWebがニューラルネットワークを必要とする理由について説明します。
私のブログの記事のミラーはhttp://bnet.su/blog/?p=30です。