它能解决FIND-S若干不足之处,FIND-S输出的假设只是H中能拟合训练的多个样例的多个假设中的一个。而在候选消除算法中,输出的是与训练样例一致的所有假设的集合。候选消除算法在描述这一集合时不需要明确列举其所有成员。这也归功于more_general_than偏序结构。在这里需要维护一个一致假设集合的简洁表示,然后在遇到新的训练样例时逐步精化这一表示。
一、表示
定义:一个假设h与训练样例集合D一致,当且仅当对D中每一个样例<x,c(x)>都有h(x)=c(x)。
Consistent(h,D)≡(∨<x,c(x)>∈D) h(x)=c(x)
定义:关于假设空间H和训练样例集D的变型空间,标记为VSH,D,是H中与训练样例D一致的所有假设构成的子集。
VSH,D≡{h∈H|Consistent(h,D)}
2.列表后消除算法(LIST-THEN-ELIMINATE)
1.变型空间VersionSpace<-包含H中所有假设的列表
2.对每个训练样例<x,c(x)>
从变型空间中移除所有h(x)≠c(x)的假设h
3. 输出VersionSpace中个假设列表
3.变型空间的更简洁表示
定义:关于假设空间H和训练数据D的一般边界(general boundary)G,是在H中与D相一致的极大一般(maximally general)成员的集合。
定义:关于假设空间H和训练数据D的特殊边界(specific boundary)S,是在H中与D相一致的极大特殊(maximally specific)成员的集合。
变型空间的确切组成是:G中包含的假设,S中包含的假设已经G和S直接偏序结果所规定的假设。
定理2.1:变型空间表示定理 令X为任意的实例集合,H为X上定义的布尔假设的集合。另c:X->{0,1}为X上定义的任一个目标概念,并令D为任一训练样例的集合{<x,c(x)>}。对所有的X,H,c,D以及良好定义的S和G:
4.候选消除学习算法
将G集合初始化为H中极大一般假设
将S集合初始化为H中极大特殊假设
对每个训练例d,进行以下操作:
- 如果d是一正例
• 从G中移去所有与d不一致的假设
• 对S中每个与d不一致的假设s
•从S中移去s
• 把s的所有的极小一般化式h加入到S中,其中h满足
•h与d一致,而且G的某个成员比h更一般
• 从S中移去所有这样的假设:它比S中另一假设更一般
- 如果d是一个反例
• 从S中移去所有d不一致的假设
• 对G中每个与d不一致的假设g
•从G中移去g
•把g的所有的极小特殊化式h加入到G中,其中h满足
•h与d一致,而且S的某个成员比h更特殊
•从G中移去所有这样的假设:它比G中另一假设更特殊
5.算法举例
候选消除算法步骤(EnjoySport)
训练样例:
1.<Sunny,Warm,Normal,Strong,Warm,Same>,EnjoySport=Yes
2.<Sunny,Warm,High,Strong,Warm,Same>,EnjoySport=Yes
S0和G0为最初的边界集合,分别对应最特殊和最一般假设。训练样例1和2使得S边界变得更一般,如FIND-S算法中一样,这些样例对G边界没有影响。
训练样例:
3.<Rainy,Cold,High,Strong,Warm,Change>,EnjoySport=No
样例3是一个反例,他把G2边界特殊化为G3。注意在G3中有多个可选的极大一般假设。
训练样例:
4.<Sunny,Warm,High,Storage,Cool,Change>,EnjoySport=Yes
正例是S边界更一般,从S3变为S4。G3的一个成员也必须被删除,因为它不再比S4更一般。
EnjoySprot概念学习问题中的最终的变型空间
#include<iostream>
#include<string>
#include<vector>
#include<set>
using namespace std;
string TestState[4][7]={{"Sunny","Warm","Normal","Strong","Warm","Same","Yes"},{"Sunny","Warm","High","Strong","Warm","Same","Yes"},//测试数据1
{"Rainy","Cold","High","Strong","Warm","Change","No"},{"Sunny","Warm","High","Strong","Cool","Change","Yes"}};
string TestState2[4][7]={{"Sunny","Warm","High","Strong","Warm","Same","Yes"},{"Sunny","Warm","Normal","Strong","Warm","Same","No"},//测试数据2
{"Rainy","Cold","High","Strong","Warm","Change","No"},{"Sunny","Warm","High","Strong","Cool","Change","Yes"}};
class Candidate
{
private:
int TestNum,AttributeNum;
vector<string> S;
set<vector<string>>G;
vector<vector<string>>TestInstance;
public:
Candidate(int Test,int Attribute,string test[][7])
{
TestNum=Test;
AttributeNum=Attribute;
vector<string> G0;
for(int i=0;i<Attribute-1;i++)
{
S.push_back("0");
G0.push_back("?");
}
G.insert(G0);
TestInstance=vector<vector<string>>(Test,vector<string>(Attribute));
for(int i=0;i<Test;i++)
{
for(int j=0;j<Attribute;j++)
{
TestInstance[i][j]=test[i][j];
}
}
}
void CandidateAlgriothm()
{
int i,j;
for(i=0;i<TestNum;i++)
{
if(TestInstance[i][AttributeNum-1].compare("Yes")==0)
{
for(j=0;j<AttributeNum-1;j++)
{
if(S[j]=="0")S[j]=TestInstance[i][j];
if(S[j].compare(TestInstance[i][j]))
{
S[j]="?";
}
}
set<vector<string>>::iterator it;
for(it=G.begin();it!=G.end();it++)
{
for(j=0;j<AttributeNum-1;j++)
{
if(S[j]=="?"&&(*it)[j]!=S[j])
{
G.erase(it);
it=G.begin();
}
}
}
}
else
{
set<vector<string>>::iterator it;
for(it=G.begin();it!=G.end();)
{
vector<string> temp;
for(j=0;j<AttributeNum-1;j++)
{
temp.push_back((*it)[j]);
}
if(IsRight(temp,TestInstance[i]))
{
for(j=0;j<AttributeNum-1;j++)
{
if(S[j]!="?"&&S[j]!=TestInstance[i][j]&&temp[j]=="?")
{
temp[j]=S[j];
G.insert(G.begin(),temp);
temp[j]="?";
}
}
G.erase(it);
it=G.begin();
}
else it++;
temp.clear();
}
}
}
}
bool IsRight(vector<string> a,vector<string> b)
{
for(int i=0;i<AttributeNum-1;i++)
{
if(a[i]!="?"&&a[i]!=b[i])return false;
}
return true;
}
void Show()
{
/*for(int i=0;i<TestNum;i++)
{
for(int j=0;j<AttributeNum;j++)
{
cout<<TestInstance[i][j]<<' ';
}
}*/
cout<<"S:"<<endl;
for(int i=0;i<AttributeNum-1;i++)
{
cout<<S[i]<<' ';
}
cout<<endl;
set<vector<string>>::iterator it,temp;
cout<<"G:"<<endl;
for(it=G.begin();it!=G.end();it++)
{
temp=it;
for(int j=0;j<AttributeNum-1;j++)
{
cout<<(*it)[j]<<' ';
}
if(!(++temp==G.end()))
{
cout<<',';
}
}
cout<<endl;
}
};
int main()
{
Candidate Candi(4,7,TestState);
Candi.CandidateAlgriothm();
Candi.Show();
Candidate Candi2(4,7,TestState2);
Candi2.CandidateAlgriothm();
Candi2.Show();
system("pause");
return 0;
}