Feedforward Neural Network Language Model(NNLM)c++核心代码实现

本文详细介绍了如何使用c++实现Feedforward Neural Network Language Model(NNLM),包括CLex、CInput、CHidden、COutput及CAlgorithm类的设计与实现,用于自然语言处理中的语言模型训练和测试。
摘要由CSDN通过智能技术生成

本文来自CSDN博客,转载请注明出处:http://blog.csdn.net/a635661820/article/details/44730507


参考文献: A Neural Probabilistic Language Model


   参照我另一篇NNLM学习介绍的博客, 这一篇是对NNLM的简要实现, 自己简化了一些,输入层到输出层没有连接(加上直连边的真在原论文中没有明显的提高),并且没有并行算法。下面贴上自己的一些核心代码。总体来说,我用了c++面向对象来设计该算法,大概分为6个类,如下: 

  1. CLex类:用来处理文本的一个类
  2. CInput类:输入层类, 包含相关量
  3. CHidden类:隐层类,包含相关量
  4. COutput类:输出层类,包含相关变量
  5. CAlgothrim类:算法类,涉及前向算法以及反向更新算法,将前面3个类串起来
  6. CForeCast类:测试类,训练好模型后对模型进行测试的相关操作

关于网络中的各个手动设定的参数在macroDefinition.h,包括隐层神经元个数、特征向量维度等。这里的附带的代码只贴出了核心相关代码,即CInput, CHidden, COutput, CAlgothrim的核心代码

网络手动设定的参数在macroDefinition.h里面,定义为宏,初始设置是按照论文中设置的:
//以下是各个变量的宏定义,留做接口,方便调试  
  
#define M 100       //一个单词对应的向量的维度数为M  
#define N 3     //输入层的单词个数,第N+1个是预测单词  
#define HN 60       //Hidden Number隐层神经元的个数   
#define EPSILON 0.001       //神经网络的学习率  
#define CONVERGE_THRESHOLD -4       //手动设定的累加对数概率收敛值  
#define FOREWORD_NUM 5  //模型预测时的输出概率最高的前5个词语

在Input.h文件里面,类的结构:

//输入层的结构定义   
class  CInput    
{  
public :  
     bool  LoadCorpusfile( char  *corpusfile);       //将语料库文件读入   
     bool  Computex( int  k);                        //计算一个句子输入单词的x向量   
    string GetWordByID(unsigned  long  id);        //根据ID返回单词   
    unsigned  long  GetIDByWord(string word);      //根据单词返回其ID    
     bool  NextSentence( int  i);            //从语料库文件中读入下一个句子   
    CInput();                        //生成词典、二维矩阵   
     virtual  ~CInput();           //释放单词映射矩阵,释放词典   
  
    CLex *pChnLex;       //指向中文词典的指针   
     float  **vec;         //输入单词对应的映射矩阵   
    vector<string> sentence;       //一行句子   
    vector<string> corpus;         //语料库   
     float  *x;        //保存输入层单词的特征向量   
     long  unsigned expectedID;        //训练句子时下一个输出单词ID   
};

类的实现在Input.cpp里面:

CInput::CInput()  
{  
    //构造函数  
    //生成词典、二维矩阵  
  
    pChnLex = new CLex;     //动态分配词典对象  
    if (NULL == pChnLex)        //分配失败  
    {  
        printf("动态分配词典失败!\n");  
        exit(1);          
    }  
              
    if (!pChnLex->LoadLexicon_Null("output.voc"))        //将指向中文词典的指针与词典文本库连接起来  
    {  
        printf("载入中文词典失败!\n");      //载入失败输出错误信息到屏幕  
    }  
  
    unsigned long sizeV = pChnLex->ulVocSizeC;       //记录词典的大小  
    srand(time(NULL));                                  //随机数种子  
  
    vec = new float *[sizeV];       //开始分配单词映射的二维矩阵  
    if (NULL == vec)        //分配失败  
    {  
        printf("分配单词映射矩阵失败!\n");  
        exit(1);  
    }  
    for (unsigned long i=1; i<sizeV; i++)        //初始化二维矩阵  
    {  
        vec[i] = new float[M];      //分配满足每个单词对应M维  
        if (NULL == vec[i])       
        {  
            printf("分配单词映射向量失败!\n");  
            exit(1);  
        }  
        for (int j=0; j<M; j++)          //赋值-0.5-0.5的小数  
        {  
            vec[i][j] = (float)(((rand()/32767.0)*2-1)/2);  
        }  
    }  
      
    x = new float[M*N];     //输入层单词的特征向量  
    if (NULL == x)  
    {  
        cerr << "输入层单词的特征向量分配失败" << endl;  
        exit(1);  
    }  
    memset(x, 0, M*N*sizeof(float));        //将x向量清0  
                                                                  
}  
  
CInput::~CInput()  
{  
    //析构函数  
    //释放单词映射矩阵  
    //释放中文词典  
  
    unsigned long sizeV = pChnLex->ulVocSizeC;       //记录词典的大小  
    for (unsigned long i=1; i<sizeV; i++)            //释放单词映射矩阵  
    {  
        delete [] vec[i];  
        vec[i] = NULL;  
    }  
    delete []vec;  
    vec = NULL;  
  
    delete pChnLex;     //释放中文词典  
    pChnLex = NULL;       
  
    delete [] x;        //释放x  
    x = NULL;  
  
}  
  
bool CInput::NextSentence(int i)  
{  
    //从预料中读取第i个句子  
    //并且将该句子中的单词以空格分隔存入容器  
  
    string line;          
    string word;  
      
    if (i >= corpus.size())      //错误  
    {  
        cerr << "!!!!!error 下标出界" << endl;  
        return false;  
    }  
    line = corpus[i];       //第i个句子  
  
    stringstream instring(line);        //字符流与该句子关联  
    sentence.clear();       //清空之前的句子  
      
    while (instring >> word)  
    {  
        sentence.push_back(word);       //把句子中的单词以空格隔开存入sentence
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值