掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板2

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.29276

単純パーセプトロンの学習
投稿者---mie(2006/12/22 16:44:11)


単純パーセプトロンの学習をシミュレーションさせるプログラムを作りたく、いろいろとソースを探したり、自分でもいろいろとしてみたのですが、どうもうまくいきません。
ファイル名を指定してくださいというエラーが出て実行ができません。
どなたかわかるかたは教えていただけないでしょうか?
お願いします。

コンパイラはbcpad231\bcpadです。
ソースは
<pre>/******************************/
/* Perceptronクラスの定義 */
/******************************/
class Perceptron {
long max;
long n;
long p;
long *W_p;
long *W;
long **E;
long *C;
public:
Perceptron(long, long, long, long);
~Perceptron();
long Bunrui();
void Input(char *);
void Learn(int, char *name = &quot;&quot;);
long Pocket(long *);
};


/**********************/
/* コンストラクタ */
/**********************/
#include &lt;stdlib.h&gt;


void srand48(long);

Perceptron::Perceptron(long max_i, long n_i, long p_i, long seed)
{
long i1;
/*
設定
*/
max = max_i;
n = n_i;
p = p_i;

srand48(seed);
/*
領域の確保
*/
E = new long * [n];
for (i1 = 0; i1 &lt; n; i1++)
E[i1] = new long [p+1];

W_p = new long [p+1];
W = new long [p+1];
C = new long [n];
}

/********************/
/* デストラクタ */
/********************/


Perceptron::~Perceptron()
{
int i1;

for (i1 = 0; i1 &lt; n; i1++)
delete [] E[i1];
delete [] E;

delete [] W_p;
delete [] W;
delete [] C;
}

/**********************************************/
/* 訓練例の分類 */
/* return : 正しく分類した訓練例の数 */
/**********************************************/


long Perceptron::Bunrui()
{
long i1, i2, num = 0, s;

for (i1 = 0; i1 &lt; n; i1++) {
s = 0;
for (i2 = 0; i2 &lt;= p; i2++)
s += W[i2] * E[i1][i2];
if ((s &gt; 0 &amp;&amp; C[i1] &gt; 0) || (s &lt; 0 &amp;&amp; C[i1] &lt; 0))
num++;
}

return num;
}


/******************************/
/* 学習データの読み込み */
/* name : ファイル名 */
/******************************/
#include &lt;stdio.h&gt;


void Perceptron::Input(char *name)
{
long i1, i2;
FILE *st;

st = fopen(name, &quot;r&quot;);

fscanf(st, &quot;%*s&quot;);

for (i1 = 0; i1 &lt; n; i1++) {
E[i1][0] = 1;
for (i2 = 1; i2 &lt;= p; i2++)
fscanf(st, &quot;%ld&quot;, &amp;E[i1][i2]);
fscanf(st, &quot;%ld&quot;, &amp;C[i1]);
}

fclose(st);
}

/*************************************/
/* 学習と結果の出力 */
/* pr : =0 : 画面に出力 */
/* =1 : ファイルに出力 */
/* name : 出力ファイル名 */
/*************************************/
#include &lt;stdio.h&gt;


void Perceptron::Learn(int pr, char *name)
{
long i1, i2, n_tri, num, s;
FILE *out;

n_tri = Pocket(&amp;num);

if (pr == 0)
out = stdout;
else
out = fopen(name, &quot;w&quot;);

fprintf(out, &quot;重み\n&quot;);
for (i1 = 0; i1 &lt;= p; i1++)
fprintf(out, &quot;%5ld&quot;, W_p[i1]);
fprintf(out, &quot;\n&quot;);

fprintf(out,&quot;分類結果\n&quot;);
for (i1 = 0; i1 &lt; n; i1++) {
s = 0;
for (i2 = 0; i2 &lt;= p; i2++)
s += E[i1][i2] * W_p[i2];
if (s &gt; 0)
s = 1;
else
s = (s &lt; 0) ? -1 : 0;
for (i2 = 1; i2 &lt;= p; i2++)
fprintf(out, &quot;%2ld&quot;, E[i1][i2]);
fprintf(out, &quot; Cor %2ld Res %2ld\n&quot;, C[i1], s);
}

if (n == num)
printf(&quot; !!すべてを分類(試行回数:%ld)\n&quot;, n_tri);
else
printf(&quot; !!%ld 個を分類\n&quot;, num);
}

続きは次に載せます。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:単純パーセプトロンの学習 29277 mie 2006/12/22 16:45:46


No.29277

Re:単純パーセプトロンの学習
投稿者---mie(2006/12/22 16:45:46)


つづきです。

/************************************************/
/*     Pocket Algorith with Ratcet              */
/*          num_p : 正しく分類した訓練例の数    */
/*          return : =0 : 最大学習回数          */
/*                   >0  : すべてを分類(回数) */
/************************************************/
#include <stdlib.h>


double drand48();

long Perceptron::Pocket(long *num_p)
{
    long count = 0, i1, k, num, run = 0, run_p = 0, s, sw = -1;
/*
     初期設定
*/
    *num_p = 0;

    for (i1 = 0; i1 <= p; i1++)
        W[i1] = 0;
/*
     実行
*/
    while (sw < 0) {

        count++;
        if (count > max)
            sw = 0;

        else {
                    
            k = (long)(drand48() * n);
            if (k >= n)
                k = n - 1;
                
            s = 0;
            for (i1 = 0; i1 <= p; i1++)
                s += W[i1] * E[k][i1];
                    
            if ((s > 0 && C[k] > 0) || (s < 0 && C[k] < 0)) {
                run++;
                if (run > run_p) {
                    num = Bunrui();
                    if (num > *num_p) {
                        *num_p = num;
                        run_p  = run;
                        for (i1 = 0; i1 <= p; i1++)
                            W_p[i1] = W[i1];
                        if (num == n)
                            sw = count;
                    }
                }
            }
                    // 誤った分類
            else {
                run = 0;
                for (i1 = 0; i1 <= p; i1++)
                    W[i1] += C[k] * E[k][i1];
            }
        }
    }

    return sw;
}


/***************************************/
/*     パーセプトロン学習              */
/*     (Pocket Algorith with Ratcet) */
/*          coded by Y.Suganuma        */
/***************************************/
#include <stdio.h>
#include <stdlib.h>


/**********************/
/*     乱数の初期設定 */
/**********************/
void srand48(long seed)
{
    srand((int)seed);
}

/**********************************/
/*     [0, 1]区間の一様乱数の発生 */
/*          rerutn : 乱数         */
/**********************************/
double drand48()
{
    double x;

    while ((x = (double)rand() / RAND_MAX) == 0.0)
        ;

    return x;
}

/********************/
/*     main program */
/********************/
int main(int argc, char *argv[])
{
    long max, n, p, seed;
    char name[100];
    FILE *st;

    if (argc > 1) {
                
        st = fopen(argv[1], "r");
        fscanf(st, "%*s %ld %*s %ld %*s %ld %*s %ld",
               &max, &p, &n, &seed);
        fscanf(st, "%*s %s", name);
        fclose(st);
                    
        Perceptron net(max, n, p, seed);
        net.Input(name);
                
        if (argc == 2)
            net.Learn(0);
        else
            net.Learn(1, argv[2]);
    }

    else {
        printf("***error   入力データファイル名を指定して下さい\n");
        exit(1);
    }

    return 0;
}




この投稿にコメントする

削除パスワード

No.29278

Re:単純パーセプトロンの学習
投稿者---~(2006/12/22 16:57:59)


>ファイル名を指定してくださいというエラー

エラーメッセージは、正確にこの内容ですか?
「***error 入力データファイル名を指定して下さい」ではなく?

ところで、どんな風に実行していますか?
実行手順を教えてください。



この投稿にコメントする

削除パスワード

No.29306

Re:単純パーセプトロンの学習
投稿者---mie(2006/12/24 13:44:49)


エラーメッセージは「***error 入力データファイル名を指定して下さい」でした。すみません。

もう少し分かりやすいというものを見つけたのですが、バックプロバゲーションのプログラムなのですが、余分なものを削ると単純パーセプトロンのプログラムになるとあったのですが、どこを削ればよいのかいまいち分かりません。
ころころ変わって申し訳ないのですが、教えていただけないでしょうか?
よろしくお願いします。

ソースは、
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<time.h>
#include"ranran48.h"

#define INPUT 2     /*入力層*/
#define HIDDEN 2    /*中間層*/
#define OUTPUT 1    /*出力層*/
#define PATTERN 4   /*入力パターン数*/
#define PR 100      /*途中結果出力のタイミング(100回ごと)*/
#define MAX_T 10000 /*学習回数の上限*/

#define eta 2.4     /*学習率*/
#define eps 1.0e-4  /*終了判定*/
#define alpha 0.8
#define beta 0.8    /*シグモイド関数パラメータ*/
#define W0 0.5      /*結合荷重の初期値*/

double xi[INPUT+1],v[HIDDEN+1],o[OUTPUT],zeta[OUTPUT];
double w1[HIDDEN][INPUT+1],w2[OUTPUT][HIDDEN+1];
double d_w1[HIDDEN][INPUT+1],d_w2[OUTPUT][HIDDEN+1];
double pre_dw1[HIDDEN][INPUT+1],pre_dw2[OUTPUT][HIDDEN+1];
double data[PATTERN][INPUT],t_data[PATTERN][OUTPUT];

void load_data(char *filename);
void back_propagation();
void w_init();
double ranran();
void dw_init();
void xi_set(long int t, int p);
void forward(long int t);
void backward();
double calc_error();
void modify_w();
void w_print();
double sigmoid(double u);

main(int argc, char *argv[])
{
    load_data(*++argv);

    back_propagation();
    
    w_print();
}

void load_data(char *filename)/*データの読み込み*/
{
    int p,k,i;
    double value;
    FILE *fp;

    fp = fopen("bpdata4.txt","r");
    if( fp == NULL ) {
        fprintf(stderr,"File Open Error!\n");
        exit(0);
    }

    for( p=0 ; p < PATTERN ; p++ ){
        for( k=0 ; k < INPUT ; k++ ){
            fscanf(fp," %lf",&value);
            data[p][k] = value;
        }
        for( i=0 ; i < OUTPUT ; i++ ){
            fscanf(fp," %lf",&value);
            t_data[p][i] = value;
        }
    }
    fclose(fp);

    printf("入力       出力\n");
        for( p=0 ; p<PATTERN ; p++ ){
                printf("{");
                for( k=0 ; k<INPUT ; k++ )
                        printf(" %.0lf ",data[p][k]);
                printf("} -> {");
                for( i=0 ; i<OUTPUT ; i++)
                        printf(" %.0lf ",t_data[p][i]);
                printf("}\n");
        }
    putchar('\n');

}

void back_propagation()/*バックプロバゲーション処理*/
{
    long int t;
    int p;
    double E,Esum;

    w_init();

    for( t=0 ; t < MAX_T ; t++ ){

        dw_init();

        for( p=0, Esum=0 ; p < PATTERN ; p++ ){
            xi_set(t,p);
            forward(t);/*前進処理*/
            backward();/*フィードバック*/
            Esum += calc_error();
        }

        modify_w();

        E = Esum / (OUTPUT * PATTERN);
        if( t%PR == 0 )
            printf("学習回数%d エラー %e\n",t,E);

        if( E < eps )/*終了判定*/
            break;
    }

    printf("\n総学習回数 = %ld",t);/*総学習回数の表示*/
    if( t == MAX_T )
        printf(" (MAX) もう一度!");
    putchar('\n');

    for( p=0 ; p < PATTERN ; p++ ){
        xi_set(0,p);
        forward(0);
    }

    printf("E = %e\n",E);/*最終的なエラー値の表示*/
}






この投稿にコメントする

削除パスワード

No.29307

Re:単純パーセプトロンの学習
投稿者---mie(2006/12/24 13:46:04)


つづきです。
void w_init()
{
    int i,j,k;
    long time_t;

    time_t = time(NULL);
    srand48(time_t);
    
    for( j=0 ; j < HIDDEN ; j++ )
        for( k=0 ; k <INPUT+1 ; k++ ){
            w1[j][k] = ranran();/*入力から隠れ層への結合荷重の変更*/
            d_w1[j][k] = 0.0;
        }
    for( i=0 ; i < OUTPUT ; i++ )
        for( j=0 ; j < HIDDEN+1 ; j++ ){
            w2[i][j] = ranran();/*隠れ層から出力層への結合荷重の変更*/
            d_w2[i][j] = 0.0;
        }
}

double ranran()/*乱数の生成*/
{
    double r;

    r = drand48();
    r = r * 2*W0 - W0;
    
    return r;
}

void dw_init()
{
    int i,j,k;

    for( j=0 ; j < HIDDEN ; j++)
        for( k=0 ; k < INPUT+1 ; k++ ){
            pre_dw1[j][k] = d_w1[j][k];/*前回のw1の変更量*/

            d_w1[j][k] = 0.0;
        }
    for( i=0 ; i <OUTPUT ; i++ )
        for( j=0 ; j < HIDDEN+1 ; j++ ){
            pre_dw2[i][j] = d_w2[i][j];/*前回のw2の変更量*/

            d_w2[i][j] = 0.0;
        }
}

void xi_set(long int t, int p)
{
    int i,k;
    
    if( t%PR == 0 ) printf("入力(IN)  ");

    for( k=0 ; k < INPUT ; k++ ){
        xi[k] = data[p][k];
        if( t%PR == 0 ) printf(" %.0lf ",xi[k]);
    }

    xi[INPUT] = 1.0;

    if( t%PR == 0 ) putchar('(');

    for( i=0 ; i < OUTPUT ; i++ ){
        zeta[i] = t_data[p][i];
        if( t%PR == 0 ) printf(" %.0lf ",zeta[i]);
    }

    if( t%PR == 0 ) printf(")\n");
}

void forward(long int t)/*前進処理*/
{
    int i,j,k;
    double sum;
    
    for( j=0 ; j < HIDDEN ; j++ ){
        for( k=0, sum=0 ; k < INPUT+1 ; k++ )
            sum += xi[k] * w1[j][k];
        v[j] = sigmoid(sum);
    }

    if( t%PR == 0 ) printf("出力(OUT)  ");

    v[HIDDEN] = 1.0;

    for( i=0 ; i < OUTPUT ; i++ ){
        for( j=0, sum=0 ; j < HIDDEN+1 ; j++ )
            sum += v[j] * w2[i][j];
        o[i] = sigmoid(sum);
        if( t%PR == 0 ) printf(" %.4lf",o[i]);
    }
    if(t %PR == 0 ) putchar('\n');
}

void backward()/*フィードバック処理*/
{
    int i,j,k;
    double delta2[OUTPUT],delta1[HIDDEN+1],sum;
    
    for( i=0 ; i < OUTPUT ; i++ )
        delta2[i] = beta * o[i] * (1-o[i]) * (zeta[i]-o[i]);

    for( j=0 ; j < HIDDEN ; j++){
        for( i=0, sum=0 ; i < OUTPUT ; i++ )
            sum += w2[i][j] * delta2[i];
        delta1[j] = beta * v[j] * (1-v[j]) * sum;
    }

    for( i=0 ; i < OUTPUT ; i++ )
        for( j=0 ; j < HIDDEN+1 ; j++)
            d_w2[i][j] += delta2[i] * v[j];

    for( j=0 ; j < HIDDEN ; j++ )
        for( k=0 ; k < INPUT+1 ; k++ )
            d_w1[j][k] += delta1[j] * xi[k];
}

double calc_error()/*エラーのカウント*/
{
    double E=0;
    int i;
    
    for( i=0 ; i < OUTPUT ; i++ )
        E += (zeta[i]-o[i]) * (zeta[i]-o[i]);

    return E;
}

void modify_w()
{
    int i,j,k;
    
    for( i=0 ; i < OUTPUT ; i++ )
        for( j=0 ; j < HIDDEN+1 ; j++ ){
            d_w2[i][j] = eta * d_w2[i][j] + alpha * pre_dw2[i][j];
            w2[i][j] = w2[i][j] + d_w2[i][j];
        }

    for( j=0 ; j < HIDDEN ; j++)
        for( k=0 ; k < INPUT+1 ; k++ ){
            d_w1[j][k] = eta * d_w1[j][k] + alpha * pre_dw1[j][k];
            w1[j][k] = w1[j][k] + d_w1[j][k];
        }
}

void w_print()/*学習終了後の重みと閾値の表示*/
{
    int i,j,k;
    
    printf("Weight\n");
    for(j =0 ; j < HIDDEN ; j++ ){
        printf("w1[%d]={",j);
        for( k=0 ; k < INPUT ; k++ ){
            if( k != 0 )
                putchar(',');
            printf("%.6lf",w1[j][k]);
        }
        printf("} シータ1[%d]=%.6lf\n",j,w1[j][k]);
    }

    for( i=0 ; i < OUTPUT ; i++ ){
        printf("w2[%d]={",i);
        for( j=0 ; j < HIDDEN ;j ++ ){
            if( j != 0 )
                putchar(',');
            printf("%.6lf",w2[i][j]);
        }
        printf("} シータ2[%d]=%.6lf\n",i,w2[i][j]);
    }
}

double sigmoid(double u)/*シグモイド関数*/
{
    return 1.0 / (1.0+exp(-beta*u));
}






この投稿にコメントする

削除パスワード

No.29309

Re:単純パーセプトロンの学習
投稿者---ぽへぇ(2006/12/24 16:10:40)


>もう少し分かりやすいというものを見つけたのですが、
>バックプロバゲーションのプログラムなのですが、
>余分なものを削ると単純パーセプトロンのプログラムに
>なるとあったのですが、どこを削ればよいのかいまいち
>分かりません。

参考になるかどうかわかりませんが。
http://mars.elcom.nitech.ac.jp/java-cai/neuro/menu.html



この投稿にコメントする

削除パスワード

No.29310

Re:単純パーセプトロンの学習
投稿者---mie(2006/12/24 16:14:10)


参考ありがとうございます。

理論的にはなんとなく分かっているのですが、プログラムにするといまいち分からなくなってしまいます。

プログラムの分で単純パーセプトロンの部分を示している部分だけでも教えていただけると助かります。
お願いします。


この投稿にコメントする

削除パスワード

No.29312

Re:単純パーセプトロンの学習
投稿者---ぽへぇ(2006/12/24 20:20:26)


>プログラムの分で単純パーセプトロンの部分を示している部分だけ
>でも教えていただけると助かります。

考え方が逆ではないでしょうか。
サンプルプログラムがバックプロバゲーション型で、
欲しいものが単純パーセプトロン型ですよね?
バックプロバゲーション型と単純パーセプトロン型の違いは何か、
というところから始めて、プログラムでバックプロバゲーション型の
部分を削るか変更することを考えましょう。

理論的には解っているということなので、ヒントだけ。

void backward() と
void modify_w()



この投稿にコメントする

削除パスワード

No.29313

Re:単純パーセプトロンの学習
投稿者---mie(2006/12/24 23:12:01)


返信ありがとうございます。

違いを探して考えてみたのですが、
まず、フィードバック処理はパーセプトロンのほうにはないのでbackward()を削って、あとsigmoid関数も使わないので、削り、渡した2つの値を比較し、1か0をかえすステップ関数にして、

modify_w()の中身を
void modify_w()/*結合荷重の修正値の計算*/
{
int i,j;
    for( i=0 ; i < OUTPUT ; i++ )
        for( j=0 ; j < HIDDEN+1 ; j++ ){
            d_w2[i][j]= eta * (zeta[j] -o[j] )*v[j]
            w2[i][j] = w2[i][j] + d_w2[i][j];
        }
}

という風に変えたらいいのでしょうか?
もし間違っていたら、どう違うかということも教えていただけるとうれしいです。
よろしくお願いします。



この投稿にコメントする

削除パスワード

No.29314

Re:単純パーセプトロンの学習
投稿者---mie(2006/12/25 02:01:43)


もうひとつ教えてほしいのですが、
出力結果だけをテキストに書き出そうと思ってソノ部分を付け足したのですが、

なぜか最終的な結果しか表示されません。
どこが違っているのか教えていただけないでしょうか?
お願いします。
ソースは
void forward(long int t)/*前進処理*/
{
    int i,j,k;
    double sum;
    FILE *fp;
    

    for( j=0 ; j < HIDDEN ; j++ ){
        for( k=0, sum=0 ; k < INPUT+1 ; k++ )
            sum += xi[k] * w1[j][k];
        v[j] = sigmoid(sum);
    }

    if( t%PR == 0 ) printf("出力(OUT)  ");

    v[HIDDEN] = 1.0;

    for( i=0 ; i < OUTPUT ; i++ ){
        for( j=0, sum=0 ; j < HIDDEN+1 ; j++ )
            sum += v[j] * w2[i][j];
        o[i] = sigmoid(sum);
        if( t%PR == 0 ){
         printf("ここです %.4lf",o[i]);
            if((fp=fopen("syuturyoku.txt","w"))==NULL){
        printf("error\n");}
        
            else{fprintf(fp,"%.4lf\n",o[j]);}
        }
        fclose(fp);
        
    }
    if(t %PR == 0 ) putchar('\n');
}




この投稿にコメントする

削除パスワード

No.29316

Re:単純パーセプトロンの学習
投稿者---ぽへぇ(2006/12/25 07:22:35)




>backward()を削って、
>あとsigmoid関数も使わないので、削り、渡した2つの値を比較し、
>1か0をかえすステップ関数にして、
>modify_w()の中身を

元のコードをそのまま利用して(forループ p の外)でこのmodify_w()
を呼ぶような形は駄目ですね。
modify_w()を削って、backward() をこの修正版にすべきでしょう。


気付いた点をいくつか。

> d_w2[i][j] = eta * (zeta[j] -o[j] )*v[j]
> w2[i][j] = w2[i][j] + d_w2[i][j];

d_w2[i][j] を使う予定がないなら w2[i][j] += eta * (zeta[i] -o[i]) * v[j];で十分。
(注)zeta, o は j を使っちゃぁいけませんね。

私もよく知りませんが、リンク先を読んだ限りでは
パーセプトロンはw1へのフィードバック処理がないようです。
w1[][]の初期値によっては収束しないかも。
下手に乱数で初期化するよりは決め打ちの方が良いでしょう。

>No.29314
>もうひとつ教えてほしいのですが
>なぜか最終的な結果しか表示されません。
>どこが違っているのか教えていただけないでしょうか?
>お願いします。
void forward(long int t) が呼ばれる毎に(上書きモードで)
fopenしてcloseしてたら、そうなるでしょう。


この投稿にコメントする

削除パスワード

No.29317

Re:単純パーセプトロンの学習
投稿者---mie(2006/12/25 11:28:50)


>元のコードをそのまま利用して(forループ p の外)でこのmodify_w()
>を呼ぶような形は駄目ですね。
>modify_w()を削って、backward() をこの修正版にすべきでしょう。
>
>
>気付いた点をいくつか。
>
>> d_w2[i][j] = eta * (zeta[j] -o[j] )*v[j]
>> w2[i][j] = w2[i][j] + d_w2[i][j];

>これでいいのでしょうか?
void backward()
{
    int i,j,k;
    
    for( i=0 ; i < OUTPUT ; i++ )
        for( j=0 ; j < HIDDEN+1 ; j++ ){
        w2[i][j] += eta * (zeta[i] -o[i]) * v[j];
        
        }

    for( j=0 ; j < HIDDEN ; j++)
        for( k=0 ; k < INPUT+1 ; k++ ){
        w1[i][j] += eta * (zeta[j] -o[j]) * v[k];
            
        }
}

でいいのでしょうか?

>void forward(long int t) が呼ばれる毎に(上書きモードで)
>fopenしてcloseしてたら、そうなるでしょう。

main関数内でファイルをopen,closeを行い、foward()関数の中で
fprintf(fp,"%.4lf\n",o[i]);

と書きこむようにしたのですが、
途中で処理が止まってしまい強制終了してしまいます。
どうしてなのでしょうか?
ネット上でも調べてみたのですが、基本的な書き方しか乗っていなく分かりませんでした。すみませんが、教えていただけないでしょうか?



この投稿にコメントする

削除パスワード

No.29319

Re:単純パーセプトロンの学習
投稿者---ぽへぇ(2006/12/25 18:50:51)


>ネット上でも調べてみたのですが、基本的な書き方しか
>乗っていなく分かりませんでした。すみませんが、
>教えていただけないでしょうか?

以下、お手本とは言いがたいですが、こちらで動かしている
ソースを貼ります。
こちらの環境に合わせて書き換えた部分がありますが、
読み替えてください。

#include    <stdio.h>
#include    <math.h>
#include    <stdlib.h>
#include    <time.h>

#define INPUT 2     /*入力層*/
#define HIDDEN 2    /*中間層*/
#define OUTPUT 1    /*出力層*/
#define PATTERN 4   /*入力パターン数*/
#define PR 100      /*途中結果出力のタイミング(100回ごと)*/
#define MAX_T 10000 /*学習回数の上限*/

#define eta 2.4     /*学習率*/
#define eps 1.0e-4  /*終了判定*/
#define alpha 0.8
#define beta 0.8    /*シグモイド関数パラメータ*/
#define W0 0.5      /*結合荷重の初期値*/

double xi[INPUT+1],v[HIDDEN+1],o[OUTPUT],zeta[OUTPUT];
double w1[HIDDEN][INPUT+1],w2[OUTPUT][HIDDEN+1];
double data[PATTERN][INPUT],t_data[PATTERN][OUTPUT];

FILE*   outFile;

void load_data(char *filename);
void back_propagation();
void w_init();
double ranran();
void xi_set(long int t, int p);
void forward(long int t);
void backward();
double calc_error();
void modify_w();
void w_print();
double sigmoid(double u);

int main(int argc, char *argv[])
{
    load_data(*++argv);

    back_propagation();
    
    w_print();
    return  0;
}

void load_data(char *filename)/*データの読み込み*/
{
    int p,k,i;
    double value;
    FILE *fp;

    fp = fopen("bpdata4.txt","r");
    if( fp == NULL ) {
        fprintf(stderr,"File Open Error!\n");
        exit(0);
    }

    for( p=0 ; p < PATTERN ; p++ ){
        for( k=0 ; k < INPUT ; k++ ){
            fscanf(fp," %lf",&value);
            data[p][k] = value;
        }
        for( i=0 ; i < OUTPUT ; i++ ){
            fscanf(fp," %lf",&value);
            t_data[p][i] = value;
        }
    }
    fclose(fp);

    printf("入力       出力\n");
        for( p=0 ; p<PATTERN ; p++ ){
                printf("{");
                for( k=0 ; k<INPUT ; k++ )
                        printf(" %.0lf ",data[p][k]);
                printf("} -> {");
                for( i=0 ; i<OUTPUT ; i++)
                        printf(" %.0lf ",t_data[p][i]);
                printf("}\n");
        }
    putchar('\n');

}

void back_propagation()/*バックプロバゲーション処理*/
{
    long int t;
    int p;
    double E,Esum;

    if( (outFile = fopen("syuturyoku.txt","w"))==NULL) {
        printf("error\n");
        exit(-1);
    }

    w_init();

    for( t=0 ; t < MAX_T ; t++ ){
        for( p=0, Esum=0 ; p < PATTERN ; p++ ){
            xi_set(t,p);
            forward(t);/*前進処理*/
            backward();/*フィードバック*/
            Esum += calc_error();
        }

        E = Esum / (OUTPUT * PATTERN);
        if( t%PR == 0 )
            printf("学習回数%d エラー %e\n",t,E);

        if( E < eps )/*終了判定*/
            break;
    }

    printf("\n総学習回数 = %ld",t);/*総学習回数の表示*/
    if( t == MAX_T )
        printf(" (MAX) もう一度!");
    putchar('\n');

    for( p=0 ; p < PATTERN ; p++ ){
        xi_set(0,p);
        forward(0);
    }

    printf("E = %e\n",E);/*最終的なエラー値の表示*/

    fclose(outFile);
}



この投稿にコメントする

削除パスワード

No.29320

Re:単純パーセプトロンの学習
投稿者---ぽへぇ(2006/12/25 18:52:48)


続き

void w_init()
{
    int i,j,k;

    srand( (unsigned long)time(NULL));
    
    for( j=0 ; j < HIDDEN ; j++ )
        for( k=0 ; k <INPUT+1 ; k++ ){
            /*入力から隠れ層への結合荷重の変更(決め打ち)*/
            w1[j][k] = 0.5;
        }

    for( i=0 ; i < OUTPUT ; i++ )
        for( j=0 ; j < HIDDEN+1 ; j++ ){
            w2[i][j] = ranran();/*隠れ層から出力層への結合荷重の変更*/
        }
}

double ranran()/*乱数の生成*/
{
    double r;

    r = rand()/(RAND_MAX+1.);
    r = r * 2*W0 - W0;
    
    return r;
}

void xi_set(long int t, int p)
{
    int i,k;
    
    if( t%PR == 0 ) printf("入力(IN)  ");

    for( k=0 ; k < INPUT ; k++ ){
        xi[k] = data[p][k];
        if( t%PR == 0 ) printf(" %.0lf ",xi[k]);
    }

    xi[INPUT] = 1.0;

    if( t%PR == 0 ) putchar('(');

    for( i=0 ; i < OUTPUT ; i++ ){
        zeta[i] = t_data[p][i];
        if( t%PR == 0 ) printf(" %.0lf ",zeta[i]);
    }

    if( t%PR == 0 ) printf(")\n");
}

void forward(long int t)/*前進処理*/
{
    int i,j,k;
    double sum;
    
    for( j=0 ; j < HIDDEN ; j++ ){
        for( k=0, sum=0 ; k < INPUT+1 ; k++ )
            sum += xi[k] * w1[j][k];
        v[j] = sigmoid(sum);
    }

    if( t%PR == 0 ) printf("出力(OUT)  ");

    v[HIDDEN] = 1.0;

    for( i=0 ; i < OUTPUT ; i++ ){
        for( j=0, sum=0 ; j < HIDDEN+1 ; j++ )
            sum += v[j] * w2[i][j];
        o[i] = sigmoid(sum);

        if( t%PR == 0 ) {
            printf(" %.4lf",o[i]);
            fprintf(outFile, "%.4lf\n", o[i]);
        }
    }
    if(t %PR == 0 ) putchar('\n');
}

void backward()/*フィードバック処理*/
{
    int i,j;
    for( i=0 ; i < OUTPUT ; i++ )
        for( j=0 ; j < HIDDEN+1 ; j++ ) {
            w2[i][j] += eta * (zeta[i] -o[i] )*v[j];
        }

}

double calc_error()/*エラーのカウント*/
{
    double E=0;
    int i;
    
    for( i=0 ; i < OUTPUT ; i++ )
        E += (zeta[i]-o[i]) * (zeta[i]-o[i]);

    return E;
}

void w_print()/*学習終了後の重みと閾値の表示*/
{
    int i,j,k;
    
    printf("Weight\n");
    for(j =0 ; j < HIDDEN ; j++ ){
        printf("w1[%d]={",j);
        for( k=0 ; k < INPUT ; k++ ){
            if( k != 0 )
                putchar(',');
            printf("%.6lf",w1[j][k]);
        }
        printf("} シータ1[%d]=%.6lf\n",j,w1[j][k]);
    }

    for( i=0 ; i < OUTPUT ; i++ ){
        printf("w2[%d]={",i);
        for( j=0 ; j < HIDDEN ;j ++ ){
            if( j != 0 )
                putchar(',');
            printf("%.6lf",w2[i][j]);
        }
        printf("} シータ2[%d]=%.6lf\n",i,w2[i][j]);
    }
}

double sigmoid(double u)/*シグモイド関数*/
{
    return 1.0 / (1.0+exp(-beta*u));
}




この投稿にコメントする

削除パスワード

No.29321

Re:単純パーセプトロンの学習
投稿者---mie(2006/12/26 01:35:39)


わざわざありがとうございます。

ただ一つ気になったのが、パーセプトロンではsigmoid関数は使わないみたいなのですが、ここはどうなのでしょうか?



この投稿にコメントする

削除パスワード

No.29323

Re:単純パーセプトロンの学習
投稿者---ぽへぇ(2006/12/26 06:23:43)


>ただ一つ気になったのが、パーセプトロンではsigmoid関数は
>使わないみたいなのですが、ここはどうなのでしょうか?

好きにしたら?

http://mars.elcom.nitech.ac.jp/java-cai/neuro/neuro3.html
>出力関数にはここで用いた階段関数のほかに、線形ランプ関数や
>シグモイド関数 を用いることもあります。

っつーかすでにC言語の範疇ではない



この投稿にコメントする

削除パスワード

No.29315

Re:単純パーセプトロンの学習
投稿者---mie(2006/12/25 02:06:47)


何度もすみません。
返信をいただいてから色々と試してみたりしたのですが、学習が収束しなくなったり、やはりどうしてもうまくいきません。

自分でも考えているのですが、どうしても答えが出てきません。
本当に申し訳ないのですが、どこを削ればパーセプトロンのプログラムになるかということを教えていただけないでしょうか?

ずうずうしいことばかりいってすみません。できればでいいのでよろしくお願いします。





この投稿にコメントする

削除パスワード

No.29308

Re:単純パーセプトロンの学習
投稿者---~(2006/12/24 14:44:11)


当方にはニューラルネットワークの知識がありませんので、
どなたか他の方々からの回答をお待ちください。
すみません。


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧