它能解决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,进行以下操作:
• 从G中移去所有与d不一致的假设
• 对S中每个与d不一致的假设s
•从S中移去s
• 把s的所有的极小一般化式h加入到S中,其中h满足
•h与d一致,而且G的某个成员比h更一般
• 从S中移去所有这样的假设:它比S中另一假设更一般
• 从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; }