📄 train.cpp
字号:
// 返回类型 : 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 + -