从服务器的角落翻出来的,纯C写了个感知器,纪念下刚学深度学习的那段时光。
代码简单到不需要注释了吧 ^_^
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef float (*activator_fun)(float);
typedef void (*status_fun)(void *);
typedef struct {
activator_fun activator;
float *weights;
int weight_num;
float bias;
status_fun print_stat;
} PERCEPTRON;
static float predict(PERCEPTRON *P, float *x, int n);
static void train(PERCEPTRON *P, float *input, float *labels, int m_group, int iteration, float rate);
static void update_weights(PERCEPTRON *P, float *input, float tmp_output, float label, float rate);
void print_stat(void *P)
{
PERCEPTRON *p = P;;
printf("* P->bias: %f\n", p->bias);
int i;
for (i = 0; i < p->weight_num; i++)
printf(" P->weights[%d]: %f\n", i, p->weights[i]);
}
float activator(float x)
{
if (x > 0)
return 1;
else
return 0;
}
static float predict(PERCEPTRON *P, float *x, int n)
{
int i;
float s = 0;
if (n > P->weight_num)
n = P->weight_num;
for (i = 0; i < n; i ++)
{
s = x[i] * P->weights[i] + s;
}
return P->activator(s + P->bias);
}
/*
* m_group: 样例数
* iteration: 训练次数
* rate: 步长
*/
static void train(PERCEPTRON *P, float *input, float *labels, int m_group, int iteration, float rate)
{
int i, n, m, n_x = P->weight_num;
float tmp_output = 0;
for (i = 0; i < iteration; i++)
{
for(m = 0; m < m_group; m++)
{
printf("[%d-%d]:\n", i, m);
tmp_output = predict(P, input + m * n_x, n_x);
update_weights(P, input + m * n_x, tmp_output, labels[m], rate);
}
}
}
static void update_weights(PERCEPTRON *P, float *input, float tmp_output, float label, float rate)
{
int i;
float delta = label - tmp_output;
printf("label[%f] - tmp_output[%f] = delta:[%f]\n", label, tmp_output, delta);
print_stat(P);
for (i = 0; i < P->weight_num; i++)
{
printf("x[%d] = %f\n", i, input[i]);
P->weights[i] += rate * delta * input[i];
}
P->bias += rate * delta;
print_stat(P);
}
int main()
{
PERCEPTRON perceptron = {
.activator = activator,
.weights = NULL,
.weight_num = 0,
.bias = 0,
};
int i, N = 2;
perceptron.weight_num = N;
perceptron.weights = (float *)malloc(sizeof(float) * N);
memset((void *)perceptron.weights, 0x00, sizeof(float) * N);
float input_vecs[4][2] = {{1, 1}, {1, 0}, {0, 1}, {0, 0}};
float labels[4] = {1, 0, 0, 0};
train(&perceptron, (float *)input_vecs, labels, 4, 6, 0.1);
for (i = 0; i < N; i++)
printf("weights[%d]: %f\n", i, perceptron.weights[i]);
printf("bias: %f\n\n", perceptron.bias);
for (i = 0; i < 4; i++)
{
printf("[%.2f] [%.2f] -> [%.2f]\n",
input_vecs[i][0], input_vecs[i][1],
predict(&perceptron, input_vecs[i], 2));
}
free(perceptron.weights);
return 0;
}