⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 train.cpp

📁 网页分类器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
       // 返回类型	  : int 
       // 函数参数	  : int i1 拉格朗日乘子
       // 函数参数	  : int i2 拉格朗日乘子
********************************************************************/
int CTrain::TakeStep(int i1,int i2)
{
	int y1, y2;	//标记
	int s;		//临时变量,值等于y1*y2
	double alph1, alph2;//旧的α值
	double a1, a2;		//新的α值
	double E1, E2;		//错误率
	double H, L;		//第i2个Lagrange乘子的上、下限
	double k11, k22, k12;//应用核函数求得的值
	double eta;			
	double lobj, hobj;	//当第i2个Lagrange值为L,H时的目标函数值

	//当待优化的两个Lagrange乘子为同一个时,则不会进行操作
	if( i1 == i2 )
		return 0;

	//将alph1,y1,E1赋初值
	alph1 = dAlph[i1];
	y1 = nType[i1];

	if( alph1 > 0 && alph1 < dPenalty )
		E1 = dErrorCache[i1];
	else
		E1 = ObjectFunc(i1) - y1;

	//将alph2,y2,E2赋初值
	alph2 = dAlph[i2];
	y2 = nType[i2];

	if( alph2 > 0 && alph2 < dPenalty )
		E2 = dErrorCache[i2];
	else
		E2 = ObjectFunc(i2) - y2;
	
	s = y1 * y2;//设置s的初值
	
	if( y1 == y2 )//当待优化的两个Lagrange乘子都为同一类
	{
		double dGamma = alph1 + alph2;//dGamma,临时变量
	
		if( dGamma > dPenalty )	//根据dGamma的值,设置L,H的值
		{
			L = dGamma - dPenalty;
			H = dPenalty;
		}
		else
		{
			L = 0;
			H = dGamma;
		}
	}
	else		//当待优化的两个Lagrange乘子不为同一类时
	{
		double dGamma = alph1 - alph2;//dGamma,临时变量
		
		if( dGamma > 0 )//根据dGamma的值,设置L,H的值
		{
			L = 0;
			H = dPenalty - dGamma;
		}
		else
		{
			L = -dGamma;
			H = dPenalty;
		}
	}
	
	if( L == H )//当Lagrange乘子的上下限一样时,不需要操作
		return 0;
	
	k11 = Kernel(i1,i1);
	k12 = Kernel(i1,i2);
	k22 = Kernel(i2,i2);

	//设置临时变量eta的初始值
	eta = 2 * k12 - k11 - k22;

	//依据核函数的形式,eta只能有小于或等于零两种状态
	if( eta < 0 )		//小于0
	{
		//依据推导求得a2,然后根据限制条件取的a2
		a2 = alph2 + y2 * ( E2 - E1 ) / eta;
		if( a2 < L )
			a2 = L;
		else if( a2 > H )
			a2 = H;
	}
	else				//等于0
	{
		double c1 = eta / 2;
		double c2 = y2 * ( E1 - E2 ) - eta * alph2;
		lobj = c1 * L * L + c2 * L;
		hobj = c1 * H * H + c2 * H;
	
		if( lobj > hobj + eps )
			a2 = L;
		else if( lobj < hobj - eps )
			a2 = H;
		else
			a2 = alph2;
	}

	if( fabs( a2 - alph2 ) < eps * ( a2 + alph2 + eps ) )
		return 0;

	a1 = alph1 - s * ( a2 - alph2 );//依据a2,求得a1
	
	if( a1 < 0 )//a1也不能超出边界
	{
		a2 += s * a1;
		a1 = 0;
	}
	else if( a1 > dPenalty )
	{
		double t = a1 - dPenalty;
		a2 += s * t;
		a1 = dPenalty;
	}
	//更新阈值b 
	{
		double b1,b2,bnew;
		if( a1 > 0 && a1 < dPenalty )
			bnew = b + E1 + y1 * ( a1 - alph1 ) * k11 + y2 * ( a2 - alph2 ) * k12;
		else
		{
			if( a2 > 0 && a2 < dPenalty )
				bnew = b + E2 + y1 * ( a1 - alph1 ) * k12 + y2 * ( a2 - alph2 ) * k22;
			else
			{
				b1 = b + E1 + y1 * ( a1 - alph1 ) * k11 + y2 * ( a2 - alph2 ) * k12;
				b2 = b + E2 + y1 * ( a1 - alph1 ) * k12 + y2 * ( a2 - alph2 ) * k22;
				bnew = ( b1 + b2 ) / 2;
			}
		}
		delta_b = bnew - b;
		b = bnew;
	}
	//更新错误率 
	{
		double t1 = y1 * ( a1 - alph1 );
		double t2 = y2 * ( a2 - alph2 );
		for( int i = 0; i < nPageNumber; i++ )
			if( 0 < dAlph[i] && dAlph[i] < dPenalty )
				dErrorCache[i] += t1 * Kernel(i1,i) + t2 * Kernel(i2,i) - delta_b;
		dErrorCache[i1] = 0;
		dErrorCache[i2] = 0;
	}
	dAlph[i1] = a1;
	dAlph[i2] = a2;

	return 1;
}

/********************************************************************
       // 创建日期   :  2008-5-19 21:07:12
	   // 作    者	  : 祝美莲<zml123818@163.com> 
       // 函数名称	  : CTrain::GetNormalVector
       // 函数功能	  : 求超平面的法向量
       // 返回类型	  : void 
********************************************************************/
void CTrain::GetNormalVector( )
{
	for( int i = 0; i < VECTORITEMNUMBER; i++ )
		Plane.dNormalVector[i] = 0;

	//按照求ω的公式,求解所有训练网页的ω
	for( i = 0; i < nPageNumber; i++ )
	{
		double dX[VECTORITEMNUMBER];
		Transform( i,dX );
		for( int j = 0; j < nVectorItemNumber; j++ )
		{
			//求ω的公式
			Plane.dNormalVector[j] += Plane.dAlph[i] * nType[i] * dX[j];
		}
	}
}

/********************************************************************
       // 创建日期   :  2008-5-19 21:07:23
	   // 作    者	  : 祝美莲<zml123818@163.com> 
       // 函数名称	  : CTrain::Training
       // 函数功能	  : 训练向量机
       // 返回类型	  : void 
       // 函数参数	  : int t
       // 函数参数	  : int times
********************************************************************/
void CTrain::Training(int t,int times)
{
	int nNumChanged = 0;//训练集的各个网页的Lagrange乘子是否有改变的
	int nExamineAll = 1;//是否要查询全部的训练网页
	int nNums = 0;//迭代的次数

	//初始化
	Plane.dThreValue = 0;
	b = 0;
	for( int i = 0; i < nPageNumber; i++ )
	{
		Plane.dAlph[i] = 0;
		dAlph[i] = 0;
	}

	for( i = 0; i < nVectorItemNumber; i++ )
	{
		Plane.dNormalVector[i] = 0;
	}

	SetKind(t);//设置y的值

	while(( nNumChanged > 0 || nExamineAll ) && nNums < 200 )// 
	{
		nNumChanged = 0;//赋为0,表示重新开始,则所有的Lagrange乘子都未变

		if( nExamineAll )//查询全部的特征向量
		{
			for( int j = 0; j < nPageNumber ; j++ )
				nNumChanged += ExamineExample(j);//若有网页的Lagrange乘子
												//改变,则将nNumChanged加1,以改变其值
		}
		else			//只查询Lagrange值不为0且不为dPenalty的特征向量,即非边界样本
		{
			for( int j = 0;j < nPageNumber;j++ )
				if( dAlph[j] != 0 && dAlph[j] != dPenalty )
					nNumChanged += ExamineExample(j);
		}

		//重新设置nExamineAll和nNumChanged的值,以进行下一次的循环
		if( nExamineAll == 1 )
		{
			nExamineAll = 0;
			nNums++;//迭代次数增1
		}
		else if( nNumChanged == 0 )
		{
			nExamineAll = 1;
			nNums++;//迭代次数增1
		}
	}

	//将计算得到的值,赋给超平面相应的值
	for( i = 0; i < nPageNumber; i++ )
	{
		Plane.dAlph[i] = dAlph[i];
	}

	Plane.dThreValue = b;
	GetNormalVector();

	//创建文件夹
	CString   strFolderPath;//文件夹的路径

	//设置路径
	strFolderPath = pPath;
	strFolderPath += "\\向量机模型";

	CreateDirectory(strFolderPath,NULL);//创建文件夹

	CString strName;//文件的完整路径

	//设置文件的文件名和存放路径
	strName.Format("%d.txt ", times);
	strName = "\\向量机模型\\" + strName;
	strName = pPath + strName;

	CFile mFile; //文件操作
	mFile.Open(strName,CFile::modeCreate|CFile::modeWrite);
	
	//准备设备
	CArchive ar(&mFile,CArchive::store); 
	for( i = 0; i < nVectorItemNumber; i++ )
	{
		ar << Plane.dNormalVector[i];//写入文件
	}
	ar << Plane.dThreValue;
	ar.Close();

	mFile.Close();//关闭文件

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -