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 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 全连接神经网络用C语言实现 -> 正文阅读

[人工智能]全连接神经网络用C语言实现

关于参数的获取:已经在上篇博客中提出,请参照相关链接请点击

一、分析输入输出

1、手写体输入为28x28的黑白图片,所以输入为784个x
2、输出为识别0-9的数字的概率,所以有10个输出
3、输入只能是-1~1的小数,主要是防止计算溢出

二、分析神经网络层数

如果只是一层,输入784,输出10,中间能记录的神经元只能是10个,很难达到识别0-9这10个数字,所以2层比较合适

三、分析神经元数量

隐藏层神经元数量没有特定的计算方法,主要是靠经验测试,当然设置过多会导致参数太多训练比较困难,太少会达不到识别效果

1、第一层:第一层的神经元没有绝对,这里给64,主要是方便后面上fpga使用

2、第二层:因为一个神经元只有一个输出,而输出的数量是0-9的数字概率,所以第二层神经元为10

四、分析参数数量

1、第一层:因为输入层28x28图片,所以一个神经元有784个w,1个b,64个神经元对应64x784个w,64个b

2、第二层:第一层的64个神经元对应64个输出,第二层输入则为64,所以第二层一个神经元有64个w,1个b,64个神经元对应64x10个w,10个b

五、分析传递过程连接方式

1、第一层:单神经元计算,每个像素点w0x0+w1x1…w783x783+b经过激活函数输出a1,然后拓展给第一层所有神经元

2、第二层:第一层输出a0,a1…a63,单神经元计算,每个像素点w0a0+w1a1…w63a63+b经过激活函数输出a2,然后拓展给第二层所有神经元

注意:推理一般是为了拿到推理结果,不关心概率,所以为了节省运行时间,我们把最后一层激活函数省略

六、代码框架

代码框架:
输入 图片数组,第一层权重,第一层偏置,第二层权重,第二层偏置
输出 推理结果
实现逻辑:
第一层神经网络计算
第二层神经网络计算
查询最大概率的结果输出
//全连接推理
//传入图片大小img 2828
//第一层的权重参数784
64 偏置参数64个 输出64个
//第二层的权重参数64*10 偏置参数10
//找到最大值结果,并返回0-9

int my_predict(float *img, float *w1, float *b1, float *w2, float *b2)
{
	//第一层64个神经元 x 28x28 w 784*64个 b 64个 输出 64个输出 
	//w1x1+w2x2 ... wnxn+b

	//第二层 10个特征0-9 10个神经元  输入连接第一层的输出 64 w 64x10个 b 10个 输出10个 
	//w1x1+w2x2 ... wnxn+b

	//查询那个特征值的概率最大,返回
}

七、完整代码实现:

#include <stdio.h>
#include <time.h>
//导入图片
#include "input_0.h"
#include "input_1.h"
#include "input_2.h"
#include "input_3.h"
#include "input_4.h"
#include "input_5.h"
#include "input_6.h"
#include "input_7.h"
#include "input_8.h"
#include "input_9.h"

#include <windows.h>
//导入权重w和偏置b
#include "layer1_weight.h"
#include "layer1_bais.h"
#include "layer2_weight.h"
#include "layer2_bais.h"

//输入图片  28*28 
//layer1 神经元 64个  w:784*64   b:64
//layer2 神经元 10    w:64*10    b:10
//计算概率最大的值并返回

int predict(float *img,float *w1,float *b1,float *w2,float *b2)
{
    int i,j;
    float y;
    float a1[64],a2[10];
    int ret;
    //第一层计算
    //多个神经元计算
    for(i=0;i<64;i++)
    {
        //单个神经元计算
        //y=w0*x0+w1*x1+w2*x2+...+w783*x783 + b
        y = 0.0;
        for(j=0;j<784;j++)
        {
            y =  y + w1[j*64+i]*img[j]; 
        }
        //加偏置
        y = y + b1[i];
        //加激活  relu  将线性转化为非线性
        y = y > 0?y:0;

        a1[i] = y;    //将单个神经元的值保存下来
        // y = 0.0;
    }
    //y = 0.0;
    //第二层计算
    //多个神经元计算
    for(i=0;i<10;i++)
    {
        y = 0.0;
        for(j=0;j<64;j++)
        {
            //单点计算  
            //y=w0*x0+w1*x1+w2*x2+...+w63*x63 + b
            y = y + w2[i+10*j]*a1[j];
        }
        //加偏置
        y = y + b2[i];
        a2[i] = y;
    }
    y = 0.0;
    //计算概率最大值
    for(i=0;i<10;i++)
    {
        if(a2[i] > y)
        {
            y = a2[i];
            ret = i;
        }
    }
    return ret;
}

void full_connect_test()
{
    int ret;
    float *imgx[10]={
        input_0,
        input_1,
        input_2,       
        input_3,
        input_4,
        input_5,
        input_6,
        input_7,
        input_8,
        input_9
    };
    
    double run_time;
    LARGE_INTEGER time_start;	//开始时间
	LARGE_INTEGER time_over;	//结束时间
	double dqFreq;		//计时器频率
	LARGE_INTEGER f;	//计时器频率
	QueryPerformanceFrequency(&f);
	dqFreq=(double)f.QuadPart;
    
    for(int i=0;i<10;i++)
    {
        
	    QueryPerformanceCounter(&time_start);	//计时开始
	    ret = predict(imgx[i],layer1_weight,layer1_bais,layer2_weight,layer2_bais);
	    QueryPerformanceCounter(&time_over);	//计时结束
	    run_time=1000000*(time_over.QuadPart-time_start.QuadPart)/dqFreq;
	    //乘以1000000把单位由秒化为微秒,精度为1000 000/(cpu主频)微秒
	    printf("\nrun_time:%fus\n",run_time);

        //clock_t start = clock();
        //ret = predict(imgx[i],layer1_weight,layer1_bais,layer2_weight,layer2_bais);
        //clock_t end = clock();
        //double runtime = (double)(end - start) / CLOCKS_PER_SEC;
        //printf("runtime:%f s ",runtime);

        printf("input is %d ,predict:%d\n",i,ret);
    }
}
int main()
{
    full_connect_test();
    return 0;
}

运行结果如下:
在这里插入图片描述

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-11-01 11:35:03  更:2021-11-01 11:35:18 
 
开发: 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 6:18:34-

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