C

时间:2018-03-08 22:57:58

标签: c naivebayes

我已经实现了朴素贝叶斯,但我在静态内存分配中实现了它。 我想转变为动态但我的小脑子无法做到这一点。

#define COLS 4 //including class label
#define BINS 100 
#define CLASS_COL 0
#define CLASS 2

我们的想法是从配置文件中获取上述值,然后进行设置。

struct each_col //Probability for each feature based on classes
{
    double col_PB[BINS][CLASS];
};  
struct NB_Class_Map
{
    char label[250];
    unsigned int label_value;
    double class_PB;
};
struct NB //Proabability for entire feature
{
    struct NB_Class_Map classes[CLASS];
    struct each_col cols[COLS];
};
NB nb = {0}; //gloabal value

训练NB的功能:

long strhash(const char *str)
{
    long hash = 5381;
    int c;
    printf("IN: %s ",str);
    while (c = *str++)
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */

     printf("OUT: %ld  ||",hash);
    return hash;
}

int setup_train_NB(vector<vector<string> > &data)
{
    //Finding the feature count
    static int class_label = -1;
    for(unsigned int i=0;i<data.size();i++)
    {
        unsigned int Class;
        printf("\n===========New ROW==============\n");
        int k;
        for(k=0;k<CLASS;k++)
        {
            if(strcmp(data[i][CLASS_COL].c_str(), nb.classes[k].label) == 0)
            {
                printf("MATCHED\n");
                Class = nb.classes[k].label_value;
                break;
            }
        }
        if(k==CLASS)
        {
            printf("NOT MATCHED\n");
            class_label++;
            nb.classes[class_label].label_value = class_label;
            strcpy( nb.classes[class_label].label, data[i][CLASS_COL].c_str());
            Class = nb.classes[class_label].label_value;
        }

        printf("Class: %d  ||\n", Class);

        for(unsigned j=0;j<data[0].size();j++)
        {
            printf("\n===========New COLUMN==============\n");
            if(j == CLASS_COL)
            {
                nb.classes[Class].class_PB++;
                continue;
            }
            unsigned int bin = strhash((data[i][j].c_str()))%BINS;

            printf("Bin: %d  ||", bin);
            printf("Class: %d  ||\n", Class);
            nb.cols[j].col_PB[bin][Class]++; //[feature][BINS][CLASS]
        }
    }

    //Finding the feature PB
    for(unsigned int i=0;i<COLS;i++)
    {
        if(i==CLASS_COL)
            continue;
        for(unsigned j=0;j<BINS;j++)
        {
            for(unsigned k=0;k<CLASS;k++)
            {
//              nb.cols[i].col_PB[j][k] /= nb.classes[k].class_PB; //without laplacian smoothing
                nb.cols[i].col_PB[j][k] = (nb.cols[i].col_PB[j][k] + 1) / (nb.classes[k].class_PB + COLS - 1); //with laplace smoothing
            }
        }
    }

    int k = 0;
    int sum = 0;
    while(k<CLASS)
    {
        sum += nb.classes[k].class_PB;
        k++;
    }

//Finding the class PB
    k = 0;
    while(k<CLASS)
    {
        nb.classes[k].class_PB /= sum;
        k++;
    }
return 0;
}

该程序应该用C语言编写,但目前我使用vector从CSV文件中获取数据。请暂时忽略它。实际的问题是如何删除那些硬编码的定义值并仍然声明我的结构。

虽然没关系,但CSV文件看起来像这样,它可能会改变cols和标签。第一行被忽略,不会被放入数据中。

Person,height,weight,foot
male,654,180,12
female,5,100,6
female,55,150,8
female,542,130,7
female,575,150,9

我实际上在做什么,因为每个值被放入一个bin,然后对于每个值,我发现CLASS /标签的可预测性,即male = 0,female = 1

2 个答案:

答案 0 :(得分:1)

基本上:

  • 定义变量而不是预处理器宏常量:size_t cols; size_t bins;等。
  • 用指针(初始化为NULL!)和长度变量替换1维固定大小的数组。或者,您可以使用struct mytype_span { size_t length; mytype* data; }
  • 用“1维”指针替换你的2维修复大小数组(当然也初始化为NULL)并将维度变量配对。同样,您可以使用结构。
  • 用“线性化”访问替换你的2-d数组访问a[x][y],即a[x * row_length_of_a + y](或者你可以在带有相关参数的内联函数中执行此操作,或者{{1} })
  • 当您从以下位置读取配置值时,无论何处 - 设置相关的长度变量(见上文)。
  • 使用struct mytype_span库函数分配正确的空间量;在使用指针值之前,请记得检查malloc()返回值以确保它不为空!

答案 1 :(得分:0)

你对struct的使用可能是错误的,除了struct NB_Class_Map。你不应该在将大数组放在同一个变量中的目标中使用struct。除此之外,您应该为每个数组定义变量,而不是将其放在结构中,而不是使用数组,而是用指针替换它。然后,您可以为指针分配内存。例如:

struct mydata {
    type1 field1;
    type2 field2;
    etc...
    } *myarray;
myarray = calloc(number_of_record_you_need, sizeof(struct mydata));
// here, error checking code, etc.

现在,如果你真的想要,你可以把你的不同指针放到一个全局结构中,但你的每个表都应该单独分配。

编辑(关于你的变量): NB作为一种结构并没有真正的兴趣。这只是你粘在一起的两个变量:

struct NB_Class_Map classes[CLASS];
struct each_col cols[COLS];

NB.Cols实际上不是一个结构。它只是一个三维数组

double cols[COLS][BINS][CLASS];

唯一真正的结构是

struct NB_Class_Map
{
    char label[250];
    unsigned int label_value;
    double class_PB;
};

所以你只需要替换

struct NB_Class_Map classes[CLASS];

struct NB_Class_Map *classes;

double cols[COLS][BINS][CLASS];

double *cols[BINS][CLASS];

或者如果你想要一个类型名称:

typedef double each_col[BINS][CLASS];
each_cols *cols;

并使用classescollscalloc分配内存空间。

现在,如果你真的想要这个struct NB

typedef double each_col[BINS][CLASS];

struct NB
{
    struct NB_Class_Map *classes;
    each_col *cols;
};