IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 手搓全连接层神经网络识别手写数字 -> 正文阅读

[人工智能]手搓全连接层神经网络识别手写数字

需要对28x28的灰度数字图像进行数字识别。
输入层 28x28个输入节点,分别代表像素点上的灰度大小
输出层10个输出,分别代表0-1的概率

使用sigmoid函数

由于求导过于繁琐,因此这里仅添加了一层隐藏层。

代码如下

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;

char file[]="train-images-idx3-ubyte";
char lc;
#define gc() (lc=getchar())
//#define gc() (lc=(Cs>=Ms?(fread(buf,Ms,1,stdin),Cs=0,buf[Cs++]):buf[Cs++]))

#define sigmoid(x) (1/(1+exp(x)))


int read(int&x)
{
	x=0;
	char c;
	do c=gc();while((c!=EOF)&&(c<'0'||c>'9')&&(c<'a'||c>'z')&&(c<'A'||c>'Z'));
	if (lc==EOF)
	{
		x=-1;
		return -1;
	}
	while(!((c<'0'||c>'9')&&(c<'a'||c>'z')&&(c<'A'||c>'Z')))
	{
		x=x*10+c-'0';
		c=gc();
	}
	return 1;
}








int n_lay1=28*28;
double w1[28*28][20];
double dw1[28*28][20];
double b1[20];
double db1[20];

double x1[28*28];
double sig1[28*28];

int n_lay2=20;
double w2[20][10];
double dw2[20][10];
double b2[10];
double db2[10];





double mid[60001][20];
double dmid[20];
double out[60001][10];



double train[60001][28*28];

double label[60001][10];
int train_N;



double get_loss(const int &train_n)
{

		double loss=0;
		for(int i=0;i<train_n;i++)
		{
			for(int j=0;j<20;j++)
				mid[i][j]=b1[j];

			for(int j=0;j<28*28;j++)
				for(int k=0;k<20;k++)
					{
						mid[i][k]=mid[i][k]+w1[j][k]*train[i][j];
						//printf("%d  %lf   %lf\n",train[i][j],w1[j][k], mid[i][k]);
					}
			//puts("mid");
			for(int j=0;j<20;j++)
				mid[i][j]=sigmoid(mid[i][j]);//,printf("%lf, ",mid[i][j]);
			//puts("");

			for(int j=0;j<10;j++)
				out[i][j]=b2[j];
			for(int j=0;j<20;j++)
				for(int k=0;k<10;k++)
					out[i][k]=out[i][k]+w2[j][k]*mid[i][j];

			//puts("out");
			for(int j=0;j<10;j++)
				out[i][j]=sigmoid(out[i][j]);//,printf("%lf, ",out[i][j]);
			//puts("");
			for(int j=0;j<10;j++)
			{
				loss=loss+0.5*(label[i][j]-out[i][j])*(label[i][j]-out[i][j]);
				if(isnan(loss))
				{
					printf("NAN!!!\n");
					printf("i:%d  j:%d   label:%lf out:%lf",i,j,label[i][j],out[i][j]);
					return 0;
				}
			}	
		}
		puts("loss_ok");
		return loss;

}

int main()
{

	char tmp;
	int cnt=0;
	int test_set=1;
	
	freopen("train_data.in","r",stdin);
		
	read(train_N);
	int n,m;
	read(n),read(m);

	int train_n=train_N;
	printf("train_n=%d\n",train_n);
	int tmpt;
	for(int i=0;i<train_n;i++)
		for (int j=0;j<n*m;j++)
			read(tmpt),train[i][j]=tmpt/256.0;//,printf("%d,",train[i][j]);

	
	freopen("train_label.in","r",stdin);
	
	read(n);
	for(int i=0;i<train_n;i++)
	{
		int l;
		read(l);
		label[i][l]=1;
	}
	//return 0;

	srand(100);
	for(int i=0;i<28*28;i++)
		for(int j=0;j<20;j++)
			w1[i][j]=((rand()&2)-1)*0.05*log((1+log(rand()))),b1[j]=((rand()&2)-1)*0.01*log((1+log(rand())));


	for(int i=0;i<20;i++)
		for(int j=0;j<10;j++)
			w2[i][j]=((rand()&2)-1)*0.05*log((1+log(rand()))),b2[j]=((rand()&2)-1)*0.01*log((1+log(rand())));
	
	/*freopen("train_model.out","r",stdin);
	
	for(int i=0;i<28*28;i++)
		for(int j=0;j<20;j++)
			scanf("%lf,",&w1[i][j]);//,printf("%lf",w1[i][j]);
	for(int j=0;j<20;j++)
		scanf("%lf,",&b1[j]);
			
	for(int i=0;i<20;i++)
		for(int j=0;j<10;j++)
			scanf("%lf,",&w2[i][j]);
	for(int j=0;j<10;j++)
		scanf("%lf,",&b2[j]);
	fclose(stdin);*/

	double new_los=0;
	double old_loss=1e100;
	double loss=0;
	double best_loss=old_loss;
	double alpha=1;

	while(alpha>=1e-7)
	{
		//calc
		loss=get_loss(train_n);
		printf("%lf\n",loss);
		
		if(loss>old_loss)
			alpha=alpha/2;
		else if(loss<best_loss)
		{
			best_loss=loss;
			FILE*fout;
			fout=fopen("train_model.out","w");
			for(int i=0;i<28*28;i++,fprintf(fout,"\n"))
				for(int j=0;j<20;j++)
					fprintf(fout,"%lf,",w1[i][j]);
			for(int j=0;j<20;j++)
				fprintf(fout,"%lf,",b1[j]);
			fprintf(fout,"\n");
			
			for(int i=0;i<20;i++,fprintf(fout,"\n"))
				for(int j=0;j<10;j++)
					fprintf(fout,"%lf,",w2[i][j]);
			for(int j=0;j<10;j++)
				fprintf(fout,"%lf,",b2[j]);
			fprintf(fout,"\n");
			fclose(fout);
		}
		old_loss=loss;

		//derive for layer 2
		
		//db2
		for(int j=0;j<10;j++)
		{
			db2[j]=0;
			for(int i=0;i<train_n;i++)
				db2[j]+=(label[i][j]-out[i][j])*(1/out[i][j]-1)*out[i][j]*out[i][j];
			//printf("%lf ",db2[j]);
		}
		puts("db2 ok");
		//dw2
		for(int j=0;j<10;j++)
			for(int k=0;k<20;k++)
			{
				dw2[k][j]=0;
				for(int i=0;i<train_n;i++)
					dw2[k][j]+=(label[i][j]-out[i][j])*(1/out[i][j]-1)*mid[i][k]*out[i][j]*out[i][j];
				//printf("%lf ",dw2[k][j]);
			}

		puts("dw2 ok");
		
		//dx2
		/*for(int k=0;k<20;k++)
		{

			dmid[k]=0;
			for(int j=0;j<10;j++)
			{
				for(int i=0;i<train_n;i++)
					dmid[k]-=(label[i][j]-out[i][j])*(1/out[i][j]-1)*w2[k][j]*out[i][j]*out[i][j];
			}

		}*/

		//derive for layer1
		//dw1

		for (int t=0;t<28*28;t++)
			for(int k=0;k<20;k++)
				dw1[t][k]=0;


		double tmp_ij=0,tmp_ijk;
		for(int j=0;j<10;j++)
		{
			for(int i=0;i<train_n;i++)
			{
				tmp_ij=(label[i][j]-out[i][j])*(1/out[i][j]-1)*out[i][j]*out[i][j];
				for(int k=0;k<20;k++)
				{
					tmp_ijk=tmp_ij*w2[k][j]*(1/mid[i][k]-1)*mid[i][k]*mid[i][k];
					for (int t=0;t<28*28;t+=4)
					{
						dw1[t][k]-=tmp_ijk*train[i][t];
						dw1[t+1][k]-=tmp_ijk*train[i][t+1];
						dw1[t+2][k]-=tmp_ijk*train[i][t+2];
						dw1[t+3][k]-=tmp_ijk*train[i][t+3];
					}
				}
//						dw1[t][k]-=(label[i][j]-out[i][j])*(1/out[i][j]-1)*w2[k][j]*out[i][j]*out[i][j] 
//								*train[i][t]*(1/mid[i][k]-1)*mid[i][k]*mid[i][k];
			}
		}
				
			


		puts("dw1 ok");
		//for(int k=0;k<1;k++,puts(""))
		//	for(int t=0;t<28*28;t++)
		//		printf("%lf ",dw1[t][k]);
		//db1
		for (int k=0;k<20;k++)
		{
			db1[k]=0;
			for(int j=0;j<10;j++)
			{
				for(int i=0;i<train_n;i++)
					db1[k]-=(label[i][j]-out[i][j])*(1/out[i][j]-1)*w2[k][j]*out[i][j]*out[i][j]
							*(1/mid[i][k]-1)*(mid[i][k]*mid[i][k]);

			}
		}

		puts("db1 ok");

		int cnt_i=28*10+10;

		double dw=w1[cnt_i][2]*1e-2;
		w1[cnt_i][2]+=dw;
		double dLoss=get_loss(train_n)-loss;
		printf("dw1:%lf   dLoss:%lf   div:%lf  derive:%lf\n",dw,dLoss,dLoss/dw,dw1[cnt_i][2]);
		w1[cnt_i][2]-=dw;

		
		dw=w2[10][2]*1e-2;
		w2[10][2]+=dw;
		dLoss=get_loss(train_n)-loss;
		printf("dw2:%lf   dLoss:%lf   div:%lf  derive:%lf\n",dw,dLoss,dLoss/dw,dw2[10][2]);
		w2[10][2]-=dw;


		double db=b1[10]*1e-2;
		b1[10]+=db;
		dLoss=get_loss(train_n)-loss;
		printf("db1:%lf   dLoss:%lf   div:%lf  derive:%lf\n",db,dLoss,dLoss/db,db1[10]);
		b1[10]-=db;

		db=b2[5]*1e-6;
		b2[5]+=db;
		dLoss=get_loss(train_n)-loss;
		printf("db2:%lf   dLoss:%lf   div:%lf  derive:%lf\n",db,dLoss,dLoss/db,db2[5]);
		b2[5]-=db;



		double tmp=0;
		for(int i=0;i<28*28;i++)
			for(int j=0;j<20;j++)
				tmp+=dw1[i][j]*dw1[i][j];
		for(int j=0;j<20;j++)
			tmp+=db1[j]*db1[j];


		for(int i=0;i<20;i++)
			for(int j=0;j<10;j++)
				tmp+=dw2[i][j]*dw2[i][j];
		for(int j=0;j<10;j++)
			tmp+=db2[j]*db2[j];

		double dif=0.0001*alpha;

		printf("       dif:%lf\n",dif);
		printf("       tmp:%lf\n",tmp);
		for(int i=0;i<28*28;i++)
			for(int j=0;j<20;j++)
				w1[i][j]-=dif*dw1[i][j];//,printf("%lf\n",dif*dw1[i][j]);
		for(int j=0;j<20;j++)
			b1[j]-=dif*db1[j];//,printf("%lf\n",dif*db1[j]);


		for(int i=0;i<20;i++)
			for(int j=0;j<10;j++)
				w2[i][j]-=dif*dw2[i][j];//,printf("%lf\n",dif*dw2[i][j]);
		for(int j=0;j<10;j++)
			b2[j]-=dif*db2[j];//,printf("%lf\n",dif*db1[2]);
		

		{
			FILE*fout;
			fout=fopen("tmp3.out","w");
			for(int i=0;i<28*28;i++,fprintf(fout,"\n"))
				for(int j=0;j<20;j++)
					fprintf(fout,"%lf,",w1[i][j]);
			for(int j=0;j<20;j++)
				fprintf(fout,"%lf,",b1[j]);
			fprintf(fout,"\n");
			
			for(int i=0;i<20;i++,fprintf(fout,"\n"))
				for(int j=0;j<10;j++)
					fprintf(fout,"%lf,",w2[i][j]);
			for(int j=0;j<10;j++)
				fprintf(fout,"%lf,",b2[j]);
			fprintf(fout,"\n");
			fclose(fout);
		}

	}
	
	return 0;
}

由于机器实在太差,没有GPU,于是在代码中进行了一些小优化。
如减少 t m p i j k tmp_{ijk} tmpijk? t m p i j tmp_{ij} tmpij?的计,同时通过循环重构,压榨了一下多核性能。

不得不说,看着自己的深度智障慢慢的会认字了,还是很开心的。

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-11-29 16:19:21  更:2021-11-29 16:19:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 4:01:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码