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

本文来自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里面,定义为宏,初始设置是按照论文中设置的:

<span style="font-family:Microsoft YaHei;font-size:14px;">//以下是各个变量的宏定义,留做接口,方便调试

#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个词语</span>

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

<span style="font-family:Microsoft YaHei;font-size:14px;">//输入层的结构定义
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
};</span>

类的实现在Input.cpp里面:

<span style="font-family:Microsoft YaHei;font-size:14px;">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
	}

	return true;
}

unsigned long CInput::GetIDByWord(string word)
{
	//根据单词返回其ID
	return pChnLex->findword(word);
}

string CInput::GetWordByID(unsigned long id)
{
	//根据ID返回单词
	return pChnLex->GetLexiconByID(id);
}

bool CInput::Computex(int k)
{
	//计算一个句子输入单词的x向量
	//k用来控制多次训练一个句子

	long unsigned id;
	long unsigned Vsize = pChnLex->ulVocSizeC;		//词典大小
	int i, j, t;
	for (i=k,t=0; i<N+k; i++,t++)
	{
		if (i >= sentence.size())		//该句子训练完毕
		{
			return false;
		}
		id = GetIDByWord(sentence[i]);		//得到输入层第i个单词id
		if (id >= Vsize)
		{
			cerr << "输入句子有误(可能是由于当前训练语料库过小,词库太少导致)" << endl;
			exit(1);
		}
		for (j=0; j<M; j++)
		{
			x[M*t+j] = vec[id][j];
		}
	}

	if (k+N >= sentence.size())		//该句子训练完毕
	{
		expectedID = 0;		//不会出现的ID号码标注
		return false;
	}
	expectedID = GetIDByWord(sentence[k+N]);		//得到训练句子的输出单词ID
}

bool CInput::LoadCorpusfile(char *corpusfile)
{
	//将语料库文件读入内存

	ifstream infile(corpusfile);		//关联欲读入的文件
	if (!infile)		//读入失败
	{
		return false;
	}

	string line;
	string word;

	while (getline(infile, line))		//从语料库读入一行句子到容器
	{
		corpus.push_back(line);
	}

	infile.close();		//关闭文件	

	return true;

}</span>

隐层的结构定义在Hidden.h里面:

<span style="font-family:Microsoft YaHei;font-size:14px;">//隐层的结构定义
class CHidden
{
public:
	CHidden();					//生成输入层到隐层的权值矩阵,隐层神经元的输出向量,偏置向量
	virtual ~CHidden();			//释放权值矩阵H、向量a,d
	void OutHidden(float *x);		//计算隐层的输出

	float **H;		//由输入层到隐层的权值矩阵(变量名按照论文中,方便对照)
	float *a;		//隐层神经元的输出向量
	float *d;		//隐层的偏置向量

};</span>

隐层的实现在Hidden.cpp:

<span style="font-family:Microsoft YaHei;font-size:14px;">CHidden::CHidden()
{
	//构造函数
	//生成输入层到隐层的权值矩阵
	//生成隐层神经元的输出向量
	//生成隐层的偏置向量

	H = new float *[HN];		//输入层到隐层的权值矩阵H
	if (NULL == H)
	{
		cerr << "输入层到隐层的权值矩阵分配失败!" << endl;
		exit(0);
	}
	int i, j;
	for (i=0; i<HN; i++)
	{
		H[i] = new float [M*N];
		if (NULL == H[i])
		{
			cerr << "输入层到隐层的权值矩阵分配失败!" << endl;
			exit(0);
		}
	}	

	for (i=0; i<HN; i++)		//初始化矩阵H
	{
		for (j=0; j<M*N; j++)
		{
			H[i][j] = (float)(((rand()/32767.0)*2-1)/2);		//赋值-0.5-0.5的小数
		}
	}

	d = new float[HN];		//隐层偏置向量
	if (NULL == d)
	{
		cerr << "隐层偏置向量分配失败" << endl;
		exit(1);
	}
	a = new float[HN];		//隐层输出向量
	if (NULL == a)
	{
		cerr << "隐层输出向量分配失败" << endl;
		exit(1);
	}
	for (i=0; i<HN; i++)
	{
		d[i] = (float)(((rand()/32767.0)*2-1)/2);		//赋值-0.5-0.5的小数
		a[i] = 0;
	}

}

CHidden::~CHidden()
{
	//释放权值矩阵H、向量a,d

	int i;
	for (i=0; i<HN; i++)		//释放H
	{
		delete [] H[i];
		H[i] = NULL;
	}
	delete []H;
	H = NULL;

	delete []d;		//释放d
	delete []a;		//释放a
	d = NULL;
	a = NULL;
}

void CHidden::OutHidden(float *x)
{
	//计算隐层输出
	//x是由输入层传过来的输入层特征向量

	int i, j;
	float zigma, o;
	for (i=0; i<HN; i++)		//根据o<-d + Hx  a<-tanh(o)计算a
	{
		zigma = 0.0;
		for (j=0; j<M*N; j++)
		{
			zigma += x[j] * H[i][j];
		}
		o = d[i] + zigma;
		a[i] = tanh(o);
	}

}</span>

输出层的结构定义在Output.h:

<span style="font-family:Microsoft YaHei;font-size:14px;">//输出层的结构定义
class COutput
{
public:
	void Initialize(long unsigned lexiconSize);		//生成隐层到输出层的权值矩阵,偏置向量、输出向量、输出单词概率向量
	void SoftMax(void);								//SotfMax回归层,进行归一化,计算概率
	void Output(float *a, long unsigned expectedID);		//计算输出层的输出
	COutput();
	virtual ~COutput();				//释放权值矩阵U、向量b,y,p

	float **U;		//隐层到输出层的权值矩阵
	float *y;		//输出层的输出
	float *b;		//输出层神经元的偏置向量
	float *p;		//输出单词概率向量
	long unsigned VSize;		//语料库词典的大小
	float L;		//累加的对数概率
};</span>

输出层的实现在Output.cpp文件里面:

<span style="font-family:Microsoft YaHei;font-size:14px;">COutput::COutput()
{
	//do nothing
}

COutput::~COutput()
{
	//释放权值矩阵U、向量b,y,p

	long unsigned i;
	for (i=1; i<VSize; i++)		//释放H
	{
		delete [] U[i];
		U[i] = NULL;
	}
	delete []U;
	U = NULL;

	delete []b;		//释放d
	delete []y;		//释放a
	delete []p;		//释放p
	b = NULL;
	y = NULL;
	p = NULL;
}

void COutput::Output(float *a, long unsigned expectedID)
{
	//计算输出层的输出
	//a,expectedID分别是隐层传的输出向量,句子的输出单词ID

	long unsigned i;
	int j;
	float zigma;
	for (i=1; i<VSize; i++)		//根据y<-b + Ua
	{
		zigma = 0.0;
		for (j=0; j<HN; j++)
		{
			zigma += a[j] * U[i][j];
		}
		y[i] = b[i] + zigma;
		p[i] = exp(y[i]);		//即计算e^yi
	}

	SoftMax();		//SotfMax回归计算概率

	L += log(p[expectedID]);		//返回以e为底的对数值
}

void COutput::SoftMax()
{
	//SotfMax回归层,进行归一化,计算概率

	float sum = 0;
	long unsigned i;
	for (i=1; i<VSize; i++)		//计算SoftMax分母
	{
		sum += p[i];
	}
	for (i=1; i<VSize; i++)		//计算每个单词的概率
	{
		p[i] /= sum;
	}
}

void COutput::Initialize(unsigned long lexiconSize)
{
	//初始化输出层函数,为了程序构架好看方便,没放在构造函数里面
	//生成隐层到输出层的权值矩阵
	//输出层偏置向量、输出向量、输出单词概率向量

	VSize = lexiconSize;		//保存语料库词典大小
	U = new float *[lexiconSize];		//隐层到输出层的权值矩阵U,让其下标从1开始与词典ID对应
	if (NULL == U)
	{
		cerr << "隐层到输出层的权值矩阵U分配失败!" << endl;
		exit(0);
	}
	long unsigned int i, j;		//i尽量为lVsizeg型,与词典类型大小对应
	for (i=1; i<lexiconSize; i++)
	{
		U[i] = new float[HN];
		if (NULL == U[i])
		{
			cerr << "隐层到输出层的权值矩阵U分配失败!" << endl;
			exit(0);
		}
	}

	for (i=1; i<lexiconSize; i++)		//初始化矩阵U
	{
		for (j=0; j<HN; j++)
		{
			U[i][j] = (float)(((rand()/32767.0)*2-1)/2);		//赋值-0.5-0.5的小数
		}
	}

	b = new float[lexiconSize];		//输出层偏置向量,让其下标从1开始与词典ID对应
	if (NULL == b)
	{
		cerr << "输出层偏置向量分配失败" << endl;
		exit(1);
	}
	y = new float[lexiconSize];		//输出层输出向量,让其下标从1开始与词典ID对应
	if (NULL == y)
	{
		cerr << "输出层输出向量分配失败" << endl;
		exit(1);
	}
	p = new float[lexiconSize];		//输出层输出向量,让其下标从1开始与词典ID对应
	if (NULL == p)
	{
		cerr << "输出层概率向量分配失败" << endl;
		exit(1);
	}
	for (i=1; i<lexiconSize; i++)		//初始化输出矩阵偏置向量、输出向量、概率向量
	{
		b[i] = (float)(((rand()/32767.0)*2-1)/2);		//赋值-0.5-0.5的小数
		p[i] = 0;
		y[i] = 0;
	}

	p[0] = 0;		//对后续排序起作用
	L = 0;		//累加对数概率清0
}</span>

算法类的结构定义在Algothrim.h:

<span style="font-family:Microsoft YaHei;font-size:14px;">//算法层的结构定义
class CAlgothrim
{
public:
	bool SaveParameters();		//保存网络全部参数到文件weight.txt中
	void PrintOverInfo(long unsigned count, int sentNum);		//提示训练结束
	void PrintStartInfo(char *corpusfile);		//打印该神经网络版本训练的相关信息
	bool WriteResult();		//将输出层的概率向量结果输出到文件
	bool Run(char *corpusFile);		//模型训练框架函数
	void Initialize();		//生成中间梯度向量
	void UpdateAll();		//反向算法更新网络所有参数
	void PrintParametersAfterUpate();		//在反向更新参数后打印网络所有参数
	void UpdateInput();		//更新输入层vec
	void UpdateHidden();		//更新隐层的H,d
	void PrintParametersBeforeUpdate();		//在反向更新之前输出整个网络的所有参数
	void UpdateOut();		//更新输出层的参数U,b
	CAlgothrim(CInput *pIn, CHidden *pHi, COutput *pOu);		//3个参数分别表示输入层、隐层、输出层的指针
	virtual ~CAlgothrim();		//释放偏导向量

	CInput *pInput;		//指向输入层的指针
	CHidden *pHidden;		//指向隐层的指针
	COutput *pOut;		//指向输出层的指针
	float *Lpa;		//L对a的偏导向量
	float *Lpx;		//L对x的偏导向量
	float *Lpy;		//L对y的偏导向量

};</span>

算法类的实现在Algothrim.cpp,这里是程序的核心部分:

<span style="font-family:Microsoft YaHei;font-size:14px;"><pre name="code" class="cpp">CAlgothrim::CAlgothrim(CInput *pIn, CHidden *pHi, COutput *pOu)
{
	//构造函数
	//3个参数分别表示输入层、隐层、输出层的指针	

	//获得各层指针
	pInput = pIn;
	pHidden = pHi;
	pOut = pOu;	

}

CAlgothrim::~CAlgothrim()
{
	//释放偏导向量

	delete []Lpa;		//释放Lpa
	Lpa = NULL;

	delete []Lpx;		//释放Lpx
	Lpx = NULL;

	delete []Lpy;		//释放Lpy
	Lpy = NULL;
}

void CAlgothrim::UpdateOut()
{
	//更新输出层的参数U,b

	//计算Lpy
	long unsigned Vsize = pInput->pChnLex->ulVocSizeC;		//词典大小
	long unsigned j;
	long unsigned wt = pInput->expectedID;		//期望单词ID
	int k;

	memset(Lpa, 0, HN*sizeof(float));		//Lpa置0

	for (j=1; j<Vsize; j++)		//进行更新
	{
		if (j == wt)		//根据Lpy<-1(j==wt) - pj 计算Lpy
		{
			Lpy[j] = 1 - pOut->p[j];
		}
		else
		{
			Lpy[j] = 0 - pOut->p[j];
		}

		pOut->b[j] += EPSILON*Lpy[j];		//根据bj <- bj + ε*Lpy更新b

		for (k=0; k<HN; k++)		//计算Lpa(累加),根据Lpa<-Lpa+Uj*Lpyj
		{
			Lpa[k] += Lpy[j]*pOut->U[j][k];
		}

		for (k=0; k<HN; k++)		//根据Uj<-Uj+ε*Lpy*a更新U
		{
			pOut->U[j][k] += EPSILON*Lpy[j]*pHidden->a[k];
		}
	}

}
void CAlgothrim::UpdateHidden()
{
	//更新隐层的H,d

	float Lpo[HN] = {0.0};		//L对o的偏导向量
	int k;
	for (k=0; k<HN; k++)		//计算Lpo 根据lpo <- (1-ak2)lpak
	{
		Lpo[k] = (1 - pHidden->a[k]*pHidden->a[k]) * Lpa[k];
	}

	//累加计算Lpx
	memset(Lpx, 0, N*M*sizeof(float));		//置0
	int i;
	float temp;
	for (i=0; i<M*N; i++)		//根据Lpx -< Lpx + H(转置)*Lpo 累加计算Lpx
	{
		temp = 0.0;
		for (k=0; k<HN; k++)
		{
			temp += pHidden->H[k][i] * Lpo[k];
		}
		Lpx[i] = temp;
	}

	//更新d
	for (k=0; k<HN; k++)		//根据d <- d + ε*Lpo更新d
	{
		pHidden->d[k] += EPSILON * Lpo[k];
	}

	//更新H
	for (i=0; i<HN; i++)		//根据H <- H + ε*Lpo*x(转置)
	{
		for (k=0; k<M*N; k++)
		{
			pHidden->H[i][k] += EPSILON*Lpo[i]*pInput->x[k];
		}
	}

}

void CAlgothrim::UpdateInput()
{
	//更新输入层vec

	int k, i;
	long unsigned id;

	for (i=0; i<N; i++)
	{
		id = pInput->GetIDByWord(pInput->sentence[i]);		//得到训练句子的第i个单词ID
		for (k=0; k<M; k++)
		{
			pInput->vec[id][k] += EPSILON * Lpx[i*M+k];
		}
	}
}
void CAlgothrim::UpdateAll()
{
	//反向算法更新网络所有参数

	UpdateOut();		//更新输出层
	UpdateHidden();		//更新隐层
	UpdateInput();		//更新输入层
}

void CAlgothrim::Initialize()
{
	//生成中间梯度向量

	long unsigned Vsize = pInput->pChnLex->ulVocSizeC;		//得到词典大小

	Lpa = new float[HN];		//L对a的偏导向量
	if (NULL == Lpa)
	{
		cerr << "L对a的偏导向量分配失败!" << endl;
		exit(1);
	}
	memset(Lpa, 0, HN*sizeof(float));		//置0

	Lpx = new float[N*M];		//L对x的偏导向量
	if (NULL == Lpx)
	{
		cerr << "L对x的偏导向量分配失败!" << endl;
		exit(1);
	}
	memset(Lpx, 0, N*M*sizeof(float));		//置0

	Lpy = new float[Vsize];		//L对y的偏导向量,下标从1开始与id对应
	if (NULL == Lpy)
	{
		cerr << "L对y的偏导向量分配失败!" << endl;
		exit(1);
	}
	memset(Lpy, 0, (Vsize)*sizeof(float));		//置0
}

bool CAlgothrim::Run(char *corpusFile)
{
	//模型训练框架函数
	//参数为语料库文件名

	int i = 0;		//控制语料库句子的循环训练
	int k = 0;		//控制一个句子中循环训练
	unsigned int t = 0;		//控制整个语料库的训练次数
	int len;		//记录要训练句子的长度
	long unsigned count = 0;		//记录网络更新次数		

	PrintStartInfo(corpusFile);		//打印网络功能信息

	pInput->LoadCorpusfile(corpusFile);		//载入语料库文件	

	pOut->Initialize(pInput->pChnLex->ulVocSizeC);		//初始化输出层

	Initialize();		//生成中间梯度向量

	while (true)
	{
		t++;		//记录对语料库训练次数
		pOut->L = 0;		//loge(Pwt) L是累加的对数概率

		for (i=0; i<pInput->corpus.size(); i++)		//遍历语料库的句子进行训练
		{
			//神经网络前馈运算
			pInput->NextSentence(i);		//从语料库中读取第i个句子做训练
			len = pInput->sentence.size();		//读入的句子长度

			for (k=0; k+N<len; k++)		//对一个句子反复训练N-len次
			{
				pInput->Computex(k);		//计算输入层的x的特征向量

				pHidden->OutHidden(pInput->x);		//计算隐层输出

				pOut->Output(pHidden->a, pInput->expectedID);		//计算输出层

				//	PrintParametersBeforeUpdate();		//打印未更新前的参数				

				//反向算法更新参数
				UpdateOut();		//更新输出层参数	

				UpdateHidden();		//更新隐层参数

				UpdateInput();		//更新输入层参数

				//	PrintParametersAfterUpate();		//打印更新后的参数
				count++;
			}
		}
		cout << t << "次训练,累加对数和概率: " << pOut->L << endl;
		if (pOut->L > CONVERGE_THRESHOLD)		//大于手动设定的收敛阈值后退出循环
		{
			break;
		}
	}

	SaveParameters();		//保存参数
	PrintOverInfo(count, pInput->corpus.size());

	return true;
}</span>
时间: 2024-09-29 03:09:16

Feedforward Neural Network Language Model(NNLM)c++核心代码实现的相关文章

Recurrent neural network language modeling toolkit 源码走读(五)

系列前言 参考文献: RNNLM - Recurrent Neural Network  Language Modeling Toolkit(点此阅读) Recurrent neural network based language model(点此阅读) EXTENSIONS OF RECURRENT NEURAL NETWORK LANGUAGE MODEL(点此阅读) Strategies for Training Large Scale Neural Network  Language

Recurrent neural network language modeling toolkit 源码深入剖析系列(一)

系列前言 参考文献: RNNLM - Recurrent Neural Network  Language Modeling Toolkit(点此阅读) Recurrent neural network based language model(点此阅读) EXTENSIONS OF RECURRENT NEURAL NETWORK LANGUAGE MODEL(点此阅读) Strategies for Training Large Scale Neural Network  Language

Recurrent neural network language modeling toolkit 源码深入剖析系列(二)

系列前言 参考文献: RNNLM - Recurrent Neural Network  Language Modeling Toolkit(点此阅读) Recurrent neural network based language model(点此阅读) EXTENSIONS OF RECURRENT NEURAL NETWORK LANGUAGE MODEL(点此阅读) Strategies for Training Large Scale Neural Network  Language

Recurrent neural network language modeling toolkit 源码走读(六)

系列前言 参考文献: RNNLM - Recurrent Neural Network  Language Modeling Toolkit(点此阅读) Recurrent neural network based language model(点此阅读) EXTENSIONS OF RECURRENT NEURAL NETWORK LANGUAGE MODEL(点此阅读) Strategies for Training Large Scale Neural Network  Language

Recurrent neural network language modeling toolkit 源码走读(八)

系列前言 参考文献: RNNLM - Recurrent Neural Network  Language Modeling Toolkit(点此阅读) Recurrent neural network based language model(点此阅读) EXTENSIONS OF RECURRENT NEURAL NETWORK LANGUAGE MODEL(点此阅读) Strategies for Training Large Scale Neural Network  Language

Recurrent neural network language modeling toolkit 源码走读(七)

系列前言 参考文献: RNNLM - Recurrent Neural Network  Language Modeling Toolkit(点此阅读) Recurrent neural network based language model(点此阅读) EXTENSIONS OF RECURRENT NEURAL NETWORK LANGUAGE MODEL(点此阅读) Strategies for Training Large Scale Neural Network  Language

Recurrent neural network language modeling toolkit 源码剖析(三)

系列前言 参考文献: RNNLM - Recurrent Neural Network  Language Modeling Toolkit(点此阅读) Recurrent neural network based language model(点此阅读) EXTENSIONS OF RECURRENT NEURAL NETWORK LANGUAGE MODEL(点此阅读) Strategies for Training Large Scale Neural Network  Language

Recurrent neural network language modeling toolkit 源码剖析(四)

系列前言 参考文献: RNNLM - Recurrent Neural Network  Language Modeling Toolkit(点此阅读) Recurrent neural network based language model(点此阅读) EXTENSIONS OF RECURRENT NEURAL NETWORK LANGUAGE MODEL(点此阅读) Strategies for Training Large Scale Neural Network  Language

Recurrent Neural Network Language Modeling Toolkit by Tomas Mikolov使用示例

递归神经网络语言模型工具地址:http://www.fit.vutbr.cz/~imikolov/rnnlm/ 1. 工具的简单使用 工具为:rnnlm-0.3e step1. 文件解压,解压后的文件为: 图1.rnnlm-0.3e解压后的文件 step2. 编译工具 命令: make clean make 可能报错 说这个x86_64-linux-g++-4.6 命令找不到 如果出现上述错误,简单的将makefile文件的第一行CC = x86_64-linux-g++-4.6 改为 CC =