バックプロパゲーション学習をMATLABとCで
XORを解く
最初の雛形
matlabファイル
入力2ユニット出力1ユニットは決まっているので,中間層のユニット数は実行時に変えられるようにしたい.
XORの入力と出力パターンは4通りのみ.
コントロール出来る擬似乱数にしたいので,しょぼくていいのでシードでコントロールできる乱数をつくっちゃいましょう.
もしくはsrand系で.
バイアスニューロンはXORに必須なので,その数も可変にします.
なので,コードを以下のようにしてみた.
kyoshi_input=[0,0; 0,1; 1,0; 1,1]; kyoshi_output=[0,1,1,0]; %bp(kyoshi_input, kyoshi_output, hidden_num,seed,bias_num); [w1 w2] = bp(kyoshi_input, kyoshi_output, 10, 0.5, 1);
Cコード
を以下のようにする
#include <stdio.h> #include <math.h> #include "mex.h" #define PI 3.1415 int *prdims0, *prdims1, *pldims0, *pldims1; int pattern, input_num, output_num, hidden_num, i, j, k, randomcount, bias_num; double *kyoshi_input, *kyoshi_output, *w1, *w2; double seed; randomcount=0; double sigmoid(double x){ return 1/(1 + exp(-x)); } void random(){ double a, b, c, d, e; a = seed * PI + 0.5; b = a * PI; c = b * PI; d = c * PI; e = d * PI; randomcount++; if(randomcount%2==0){ seed = e - (int)e; }else{ seed = -(e - (int)e); } } void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){ //入力処理 prdims0 = (int*)mxGetDimensions(prhs[0]); pattern = prdims0[0]; input_num = prdims0[1] + bias_num; kyoshi_input = mxGetPr(prhs[0]); prdims1 = (int*)mxGetDimensions(prhs[1]); output_num = prdims1[0]; kyoshi_output = mxGetPr(prhs[1]); hidden_num = (int)mxGetScalar(prhs[2]) + bias_num; seed = (double)mxGetScalar(prhs[3]); bias_num = (int)mxGetScalar(prhs[4]); printf(" %s%d\n %s%d\n %s%d\n %s%d\n", "pattern:", pattern, "input_num:", input_num, "hidden_num:", hidden_num, "output_num:", output_num, "seed:", seed ); //出力処理 pldims0 = (int*)mxCalloc(2, sizeof(double)); pldims0[0] = input_num; pldims0[1] = hidden_num; plhs[0] = mxCreateNumericArray(2, pldims0, mxDOUBLE_CLASS, mxREAL); w1 = mxGetPr(plhs[0]); pldims1 = (int*)mxCalloc(1, sizeof(double)); pldims1[0] = hidden_num; plhs[1] = mxCreateNumericArray(1, pldims1, mxDOUBLE_CLASS, mxREAL); w2 = mxGetPr(plhs[1]); //w1と2の初期化 for(i=0;i<input_num;i++){ for(j=0;j<hidden_num;j++){ random(); w1[i + j*input_num] = seed; } } for(j=0;j<hidden_num;j++){ random(); w2[j]=seed; } }
mex後に実行するとちゃんとw1とw2が初期化されていることが分かります