単一ニューロンの学習

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

単一ニューロンの学習

#1

投稿記事 by peke » 2年前

単一ニューロンを逐次更新で学習するプログラムを作っているのですが,重みωの更新がうまくいきません.
参考にしたページに訓練データや結果や詳しいことが載っています.URL:http://blog.livedoor.jp/rtabaladi_58/ar ... 58901.html

コード:

 
 #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;
    int count_MAX = pow(10, 6);
    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;
    double eps;
    double **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;
}
  

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