C言語について質問

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
peke

C言語について質問

#1

投稿記事 by peke » 2年前

以前質問した内容と同じなのですがお願いします。
URL: http://blog.livedoor.jp/rtabaladi_58/ar ... 58901.html
上のページを参考に単一ニューロンの学習をc言語で行いたいのですが、Haskellが分からず自分なりにやってみたのでsがページ道理の結果になりません。
どうかアドバイスをお願いします。

コード:

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

//ディスプレイに仕切りを表示する関数
void partition(void)
{
	int i;

	for(i=0; i<20; i++){
		printf("*");
	}

	printf("\n");
}

//ニューロンの学習させるためのシグモイド関数
double sigmoid_1(int N, int l, double alpha, double *omega, double *dt[])
{
    int i;
    double s = 0;

    for(i=0; i<=N; i++){
        s += omega[i]*dt[l][i];
    }

    return 1/(1 + exp(-alpha*s));
}

//学習させたニューロンを移用する際のシグモイド関数
double sigmoid_2(int N, int l, double alpha, double theta, double *omega, double *dt[])
{
    int i;
    double s = 0;

    for(i=0; i<N; i++){
        s += omega[i + 1]*dt[l][i];
    }

    return 1/(1 + exp(-alpha*(s - theta)));
}

//ニューロンの学習
int neuron_learning(int N, int num, double alpha, double epsilon, double omega[],  double *dt[])
{
    int i, k, count;//count:学習回数
    int count_MAX = pow(10, 6);//count_MAX:学習回数の上限
    double grad, d_sigm;
    double *initial_omega;
    double convergence_value = pow(10, -6);//収束条件

    initial_omega = (double *)malloc(sizeof(double)*N);

    //重みωの初期値を決定
    srand((unsigned)time(NULL));
    for(i=0; i<N+1; i++){
        omega[i] = (((double)rand() / ((double)RAND_MAX + 1))*2.0 - 1.0)*0.01;   
    }

    for(i=0; i<N+1; i++){
        printf("初期重み\nω[%i] = %f\n", i, omega[i]);  
    }

    for(i=0; i<=N; i++){
        count = 0;
        do{
            for(k=0; k<num; k++){
                d_sigm = alpha* sigmoid_1(N, k, alpha, omega, dt)*(1 - sigmoid_1(N, k, alpha, omega, dt));
                grad = -2*(dt[k][N + 1] - sigmoid_1(N, k, alpha, omega, dt))*d_sigm*dt[k][i];
                omega[i] -= epsilon*grad;
                count ++;
            }
        if(count>count_MAX)break;          
        }while(fabs(grad) >= convergence_value);
    } 

    return 0;
}

//学習されたニューロンを使用する関数
int use_of_neurons(int N, int num, double alpha, double omega[],  double *dt_in[], double dt_out[])
{
    int i, k;

    for(i=0; i<num; i++){
        dt_out[i] = sigmoid_2(N, i, alpha, -omega[0], omega, dt_in);
    }

    for(i=0; i<num; i++){
        printf("y_%d = %f\n", i+1, dt_out[i]);
    }

    return 0;
}

//メイン関数
int main(void)
{
    int i, k, num, choice;//num:訓練データのセット数
    double eps;//学習率
    double **data_set, **input, *output;
    //data_set:訓練データ, input:学習したニューロンを使用するときの入力, output:学習したニューロンの出力
    
    int N;//ニューロンの入力数
    int check = 1;//ニューロンの学習を行ったか判定
    double alpha;//シグモイド関数のゲイン
    double *omega;//重み係数
    
    do{    
        partition();
        printf("[1] ニューロンの学習\n[2] 学習したニューロンの使用\n[0] 戻る\n");
        partition();
        printf("機能を選択してください : ");
        scanf("%d", &choice);
        partition();
        
        switch (choice) {
        case 1:
            printf("学習率 ε を決定してください.\nε = ");
            scanf("%lf", &eps);
            partition();
            printf("シグモイド関数のゲイン α を決定してください.\nα = ");
            scanf("%lf", &alpha);
            partition();
            printf("入力数 N を決定してください.\nN = ");
            scanf("%d", &N);
            partition();
            printf("訓練データの数を入力してください.:");
            scanf("%d", &num);
            partition();

            omega = (double *)malloc(sizeof(double)*(N + 1));   
            data_set = (double **)malloc(sizeof(double *)*num); 
            for (i=0;i<num;i++) {
                data_set[i] = (double *)malloc(sizeof(double)*(N + 2));
            }

            printf("訓練用データセットを決定してください.\n");
            for(i=0; i<num; i++){
                printf("%d つ目\n", i + 1);
                data_set[i][0] = 1;

                for(k=1; k<=N; k++){
                    printf("x_%d = ", k);
                    scanf("%lf", &data_set[i][k]);                
                }

                printf("  y = ");
                scanf("%lf", &data_set[i][N+1]);
                printf("\n");
            }

            neuron_learning(N, num, alpha, eps, omega, data_set);
            check = 0; 

            for(i=0; i<N+1; i++){
                printf("重み\nω[%i] = %f\n", i, omega[i]);  
            }	

            for (i=0;i<num;i++) free(data_set[i]);
            free(data_set);
            break;

        case 2:
            if(check == 0){
                printf("入力データの数を入力してください");
                scanf("%d", &num);
                partition();

                input = (double **)malloc(sizeof(double *)*num);
                for (i=0;i<num;i++) {
                    input[i] = (double *)malloc(sizeof(double)*N);
                }
                output = (double *)malloc(sizeof(double )*num);

                printf("入力データセットを決定してください.\n");
                for(i=0; i<num; i++){
                    printf("%d つ目\n", i+1);
                    for(k=0; k<N; k++){
                        printf("x_%d = ", k+1);
                        scanf("%lf", &input[i][k]);                
                    }
                }

                use_of_neurons(N, num, alpha, omega, input, output);

                for (i=0;i<num;i++) free(input[i]);
                free(input);
            }
            else if(check == 1){
                printf("ニューロンの学習を行ってください\n");
            }
            else{
                printf("想定されていない動作が発生しました.\n");
            }

            break;

        case 0:
            break;

        default:
            printf("Unexpected characters were entered.\n");
        }
        
        partition();

    }while(choice != 0);

    free(omega);
    
    return 0;
}


box
記事: 2002
登録日時: 13年前

Re: C言語について質問

#2

投稿記事 by box » 2年前

質問者さんの疑問が解決するかどうかはわかりませんが、

コード:

    srand((unsigned)time(NULL));
このコードはmain関数の先頭で「1回だけ」実行すればいいのではないでしょうか。
neuron_learning関数で、毎回乱数の種を初期化する必要はどこにあるのでしょうか。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: C言語について質問

#3

投稿記事 by みけCAT » 2年前

複雑ですぐにはわからなそうなので、とりあえず作った入力データを置いておきます。

コード:

1
0.5
4
2
6
0 1 0
1 0 0
0 0 0
1 3 1
2 1 1
1.5 2 1
2
6
0 1
1 0
0 0
1 3
2 1
1.5 2
0
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

返信

“C言語何でも質問掲示板” へ戻る