●パーセプトロン
簡易な機械学習の原理を模擬したコードを構築して 原理を研究していく。
このコードは、100ビットの信号を入力として 処理する。
#include
#include
#include
#include
#include
using namespace std;
extern float fx(float(*x)[10]);
extern float fx1(float(*xi)[10], float *x, float *set);
extern float fx2(float *x, float(*y)[10]);
extern float ex(float *x, float *y);
extern float relu(float(*x)[10]);
extern float dx(float(*x)[10], float *(ax), float *(bx), float *(cx), float *(dx), float *(ct));
extern float dx1(float x, float y, float x2, float y2, float *(ax));
extern float memo(float(*x)[10], float *(ax), float *(bx) ,float *(cx));
float fx(float(*x)[10])
{
int i = 0, j = 0, k = 0;
float d = 0;
char ax[10][10] = { { 0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,1,1,0,0,0,0 },
{ 0,0,0,1,1,1,1,0,0,0 },
{ 0,0,0,1,0,0,1,0,0,0 },
{ 0,0,1,1,0,0,1,1,0,0 },
{ 0,0,1,1,0,0,1,1,0,0 },
{ 0,1,1,1,1,1,1,1,1,0 },
{ 0,1,1,1,1,1,1,1,1,0 },
{ 1,1,0,0,0,0,0,0,1,1 },
{ 1,1,0,0,0,0,0,0,1,1 } };
srand((unsigned)time(NULL));
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
x[i][j] = ax[i][j];
if (x[i][j] > 0.9) { ax[i][j] = '*'; }
if (x[i][j] < 0.9) { ax[i][j] = ' '; }
printf("%c ", ax[i][j]); k++;
if (k % 10 == 0) printf("\n");
d += ax[i][j];
}
}
return d;
}
float fx1(float(*xi)[10], float *x, float *set)
{
int i = 0, j = 0, k = 0;
float d = 0;
float dx = 0;
float ax[10][10];
float bx[10][10];
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
xi[i][j] = xi[i][j] * ex(x, set); d=relu(xi);
if (xi[i][j] > 1) {xi[i][j] = 0;
}
}
}
return d;
}
float fx2(float *x, float(*y)[10])
{
int i = 0, j = 0, k = 0;
float d = 0;
float w = 0;
float ax[10][10];
d = *x;
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
y[i][j] = y[i][j]* ex(x,x);
w=relu(y);
}
}
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
if (ax[i][j] < 1) { y[i][j] = 1.1; }
w += y[i][j];
}
}
if (w - d < w) { *x = w - d; }
if (d - w < d) { *x = d - w; }
if (*x != 0) { if (*x < 0.1) { *x += -0.1; } }
else *x += 0.1;
return *x;
}
float ex(float *x, float *y)
{
int i = 0, j = 0, k = 0;
float d = 0;
float w = 0;
srand((unsigned)time(NULL));
d = rand() % 100;
w = rand() % 100;
return (-d + w) / 100;
}
float relu(float(*x)[10])
{
int i = 0, j = 0, k = 0;
float d = 0;
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
if (x[i][j] > 1) { x[i][j] = x[i][j]; }
else if (x[i][j] < 1) {
d+=x[i][j] = 0;
}
}
}
return d;
}
float mem(float(*x)[100], float *y)
{
int i = 0, j = 0, k = 0;
float d = 0;
float w = 0;
for (i = 0; i < 100; i++) {
for (j = 0; j < 100; j++) {
x[i][j] = x[i][j];
}
}
return *y;
}
int main(void)
{
int i = 0, j = 0, k = 0, pc = 10;
char xe[10][10] = { 0 };
float xc[10][10] = { 0 };
float xi[10][10] = { 0 };
float ax[20] = { 0 };
float bx[20] = { 0 };
float cx[20] = { 0 };
float dex[20] = { 0 };
float ct[20] = { 0 };
float x = 0.1, y = 0, yi = 0, zi = 0, set = 0.1;
float ul = 0, ad = 0;
int switch_on = 0;
y = fx(xi);
//機械学習ルーチン導入部
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
xc[i][j] = xi[i][j];
}
}
printf("内部動作確認 なら1 確認しない 2 を入力 ");
cin >> switch_on;
switch (switch_on)
{
case 1:
x = fx2(&y, xi);
y = fx1(xi, &x, &set);
break;
case 2:while (y == 0)
{
x = fx2(&y, xi);
y = fx1(xi, &x, &set);
}
break;
}
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
k++;
printf("%d x= %f\n", k, xi[i][j]);
}
}
k = 0;
ul = y;
printf("xi=%f\n", ul);
printf("\n");
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
if (xi[i][j] > 0.9) { xe[i][j] = '*'; }
if (xi[i][j] < 0.9) { xe[i][j] = ' '; }
printf("%c ", xe[i][j]); k++;
if (k % 10 == 0) printf("\n");
}
}
k = 0;
printf("\n");
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
if (xc[i][j] > 0.9) { xe[i][j] = ' '; }
if (xc[i][j] < 0.9) { xe[i][j] = '*'; }
printf("%c ", xe[i][j]); k++;
if (k % 10 == 0) printf("\n");
}
}
printf("dx=%f \n", dx(xi,ax,bx,cx,dex,ct));
printf("\n");
cin >> pc;
}
上記のコードに線形分析関数 DX と 記憶関数 memoを追加して 修正する。
線形分析関数DXで入力の図形の外側の線分を抽出する。
線形1次関数DX1で1次関数y=として データを記憶する。
記憶関数memoで線形分析した図形のパターンと一致する割合を照合する。
float memo(float(*x)[10], float *(ax), float *(bx),float *(cx))
{
int i = 0, j = 0, k = 0;
float d = 0;
float w = 0;
char m[256];
FILE * fp;
errno_t error;
error = fopen_s(&fp, "mem.txt","a+");
if (error != 0)
{
printf("ERROR:書き込み失敗");
}
fprintf(fp, "y=%fx", cx[0]);
fprintf(fp, "%f ", cx[1]);
fclose(fp);
return 1;
}
float dx(float(*x)[10], float *(ax), float *(bx), float *(cx), float *(dx), float *(ct))
{
int i = 0, j = 0, k = 0,m=0,s=0,c=0,d=0,a=0,b=0;
float w = 0,v=0;
float xi[10][10] = { 0 };
char xa[10][10] = { 0 };
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
xi[i][j] = x[i][j];
if (x[i][j] == 0 && x[i][j + 1] != 0) {
m++; xi[i][j] = 2;
}
if (x[i][j] == 0 && x[i][j - 1] != 0) {
s++; xi[i][j] = 3;
}
printf("%f ", xi[i][j]); k++;
if (k % 10 == 0) printf("\n");
}
}
printf("\n"); k = 0;
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
if (xi[i][j] == 1) { xa[i][j] = '+'; }
if (xi[i][j] == 2) { ax[a] = 10-i; a++; bx[b] = j; b++; xa[i][j] = '*'; }
if (xi[i][j] == 3) { cx[c] = 10-i; c++; dx[d] = j; d++; xa[i][j] = '@'; }
printf("%c ", xa[i][j]); k++;
if (k % 10 == 0) printf("\n");
}
}
dx1(ax[1], bx[1], ax[2], bx[2], ct);
memo(xi, ax, bx, ct);
printf("\n");
dx1(cx[1], dx[1], cx[2], dx[2], ct);
memo(xi, cx, dx, ct);
for (i = 0; i < 10; i++) { printf("%f ", ax[i]); }printf("\n");
for (i = 0; i < 10; i++) { printf("%f ", bx[i]); }printf("\n");
for (i = 0; i < 10; i++) { printf("%f ", cx[i]); }printf("\n");
for (i = 0; i < 10; i++) { printf("%f ", dx[i]); }printf("\n");
return m+s;
}
float dx1(float x, float y, float x2, float y2, float *(ax))
{
int i = 0, j = 0, k = 0;
float a = 0, b = 0, c = 0, d = 0;
a=(y2 - y) / (x2 - x);
b = a*(x2);
c = y2-b;
ax[0] = b;
ax[1] = c;
printf("y=%f x %f", b,c); printf("\n");
return a;
}
以下にここまでの完成している段階のプリコンパイル済み動作プログラムを掲載している。
GCCなどでコンパイル出来ないか 面倒な場合 ここに掲載のコードをプリコンパイル済みにした
ファイルであるので動作確認をする事が出来る。※このプログラムの不具合によるいかなる障害も保証は出来ない。
配列の前後16バイトは、読み込む可能性が数%〜50%ある。書き込む可能性は、殆ど無い。
2021・7・31 製造
動作テスト用プリコンパイル済みファイル