背景
工作之余研究一下时下大热的人工神经网络,因工作原因本人对C语言使用较为顺手于是用C撸了一个神经元
特点
本实现有以下特点
- 以基于对象的方式实现;
- 树突使用链表实现;
- 树突在连接两个神经元时自动创建。
代码
废话不多说,直接上代码
代码的使用,该部分用实现好的神经元模拟了与或非逻辑门
//main.c
#include <stdio.h>
#include <stdlib.h>
#include "neure.h"
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
//阶梯形隶属函数
double ladder(double x)
{
return ((x>0)?1:0);
}
//sigmoid隶属函数
double sigmoid(double x)
{
return (1/(1+exp(-x)));
}
int main(int argc, char *argv[])
{
double d_x=1;
double d_y=1;
//简单模拟与逻辑门
neure_t* node1=creat_neure(1.5,ladder);//创建一个神经元 阀值为1.5
neure_connectIn(&d_x,node1,1);//连接到输入x 系数为1
neure_connectIn(&d_y,node1,1);//连接到输入y 系数为1
printf("%f and %f=%f\n",d_x,d_y,neure_output(node1)); //输出运算结果
//简单模拟或逻辑门
neure_t* node2=creat_neure(0.5,ladder);//创建一个神经元 阀值为0.5
neure_connectIn(&d_x,node2,1);//连接到输入x 系数为1
neure_connectIn(&d_y,node2,1);//连接到输入y 系数为1
printf("%f or %f=%f\n",d_x,d_y,neure_output(node2)); //输出运算结果
//简单模拟非逻辑门
neure_t* node3=creat_neure(-0.5,ladder);//创建一个神经元 阀值为-0.5
neure_connectIn(&d_x,node3,-1);//连接到输入x 系数为-1
printf("%f not =%f\n",d_x,neure_output(node3)); //输出运算结果
//连接与门和非门模拟与非门
neure_connect(node1,node3,-1);//连接两个神经元系数为-1
printf("%f andnot %f =%f\n",d_x,d_y,neure_output(node3)); //输出运算结果
return 0;
}
neure.h是接口
//neure.h
#ifndef _FILE_NEURE_H_
#define _FILE_NEURE_H_
typedef double (*transferFunc_t)(double);
typedef struct neure neure_t;
//typedef struct input input_t;
/*功能:创建神经元,无树突,树突在连接两个神经元或连接神经元与输入时自动创建
参数:v阀值 pf_tsf隶属函数
返回值:指向被创建的神经元的指针 */
neure_t* creat_neure(double v,transferFunc_t pf_tsf);
//连接两个神经元,并设置系数
int neure_connect(neure_t* pNeureFirst,neure_t* pNeureNext,double w);
//连接神经元到输入,并设置系数
int neure_connectIn(double* pd_x,neure_t* pNeureNext,double w);
//计算神经元的输出 该函数自动调用所依赖的前置神经元
float neure_output(neure_t *pNeure);
#endif
重点来了neure.c部分是实现
//neure.c
//author :1084541514@qq.com
#include <stdio.h>
#include <stdlib.h>
#include "neure.h"
typedef struct input input_t;
//创建输入节点
input_t* creat_input(neure_t* pLastNeure,double* pd_x,double w);
typedef double (*transferFunc_t)(double);
//神经元
struct neure
{
input_t* inputHead;//树突链表 ,因树突个数不定所以用链表实现
double v; //阀值
transferFunc_t tsf;//传递函数 ,隶属函数
};
//树突
struct input
{
neure_t * pNeure;//输入神经元
double* pd_x; //输入值指针,未连接神经元时值要外部设置
double w;//权重
input_t * next;//下一输入项
};
//连接两个神经元,如果后置的神经元没有树突则自动创建
int neure_connect(neure_t* pNeureFirst,neure_t* pNeureNext,double w)
{
input_t* pNextInput=NULL;
input_t* pLastInput=NULL;
if((pNeureFirst==NULL)||(pNeureNext==NULL))
{
return -1;
}
pLastInput=pNeureNext->inputHead;
pNextInput=pNeureNext->inputHead;
while(NULL!=pNextInput)//遍历树突
{
if(NULL==pNextInput->pNeure)//判断树突是否空闲
{
pNextInput->pNeure=pNeureFirst;
pNextInput->w=w;
return 0;//连接成功
}
pLastInput=pNextInput;
pNextInput=pNextInput->next;//查看下个树突
}
if(NULL==pNeureNext->inputHead)//没有树突
{
pNeureNext->inputHead=creat_input(pNeureFirst,NULL,w);
if(NULL==pNeureNext->inputHead)return -2;//创建新树突分配内存失败
}
else //有树突但没有空闲树突
{
pLastInput->next=creat_input(pNeureFirst,NULL,w);
if(NULL==pNeureNext->inputHead)return -2;//创建新树突分配内存失败
}
}
int neure_connectIn(double* pd_x,neure_t* pNeureNext,double w)
{
input_t* pNextInput=NULL;
input_t* pLastInput=NULL;
if((pd_x==NULL)||(pNeureNext==NULL))
{
return -1;
}
pLastInput=pNeureNext->inputHead;
pNextInput=pNeureNext->inputHead;
while(NULL!=pNextInput)//遍历树突
{
if(NULL==pNextInput->pNeure)//判断树突是否空闲
{
if(NULL==pNextInput->pd_x)
{
pNextInput->pd_x=pd_x;
pNextInput->w=w;
return 0;//连接成功
}
}
pLastInput=pNextInput;
pNextInput=pNextInput->next;//查看下个树突
}
if(NULL==pNeureNext->inputHead)//没有树突
{
pNeureNext->inputHead=creat_input(NULL,pd_x,w);
if(NULL==pNeureNext->inputHead)
return -2;//创建新树突分配内存失败
return 0;
}
else //有树突但没有空闲树突
{
pLastInput->next=creat_input(NULL,pd_x,w);
if(NULL==pNeureNext->inputHead)
return -2;//创建新树突分配内存失败
return 0;
}
}
//神经元输出计算函数
float neure_output(neure_t *pNeure)
{
double sum=0;
input_t* pNextInput=pNeure->inputHead;
//求输入和
while(NULL!=pNextInput)
{
if(NULL!=pNextInput->pNeure)//输入神经元非空
{
sum+=neure_output(pNextInput->pNeure)*(pNextInput->w);//递归计算前神经元的输出
}
else//输入没有接神经元
{
sum+=*(pNextInput->pd_x)*pNextInput->w;//debug
}
pNextInput=pNextInput->next;
}
return(pNeure->tsf(sum-pNeure->v));//使用隶属函数计算输出
}
//创建无树突的神经元
neure_t* creat_neure(double v,transferFunc_t pf_tsf)
{
neure_t* pNeure=(neure_t*)malloc(sizeof(neure_t));
if(pNeure==NULL)return NULL;//内存分配错误
pNeure->inputHead=NULL;//新创建的神经元没有树突
pNeure->v=v;
pNeure->tsf=pf_tsf;
return pNeure;
}
//创建树突
input_t* creat_input(neure_t* pLastNeure,double* pd_x,double w)
{
input_t * pInput=(input_t*)malloc(sizeof(input_t));
if(NULL==pInput)return NULL;
pInput->pNeure=pLastNeure;
pInput->w=w;
pInput->pd_x=pd_x;
pInput->next=NULL;
return pInput;
}
代码未完善,未实现删除。
代码未经充分测试仅供参考
谢谢