首页 新闻 搜索 专区 学院

请教大牛帮我看看自己学的knn算法,哪里错了

0
悬赏园豆:10 [已解决问题] 解决于 2012-05-12 08:36
/*
第一步:从文档中读取训练样本集 ;假设一个有5用类型
                            文件中格式:                        
                                      1 A00,A01...A0(n-1);           
                                      2 .                                        
                                      3 .                                        
                                      1 .                                        
                                      5 A(m-1)0,A(m-1)1...A(m-1)(n-1);T(m-1)()  
                          当在程序中定义数组时,定义为trainingspeciemens[n][m+1]
                          每个样本的倒数第一个数为改数据所属的类型,
                          
                           
第二步:输入K,和待分类样本 R
第三步:计算R与一个训练样本的欧几里得距离
第四步:选出与 样本 R 的K个最小样本
第五步:选出包含 K个最邻近样本中最多样本的类别
第六步:把样本R归于k个样本最大类别    

*/


#include<iostream>
#include<cmath>
#include<fstream>
using namespace std;
#define k 4//选出k个样本 
#define n 5//文档中样本数 
#define m 4//样本维数
#define maxclass 5//规定最大类别数 
int classnumber[maxclass];
struct TrainSet{
    int tab; 
    double distancetov;
    double classlabel;
    double samples[m];
};
TrainSet trainset[n];//从文档中读取的样本放在这里 
TrainSet v;//用户输入的样本 

struct Ksample{
    double classlabel;
}K[k];//选出来的k个最近样本放在这里
 
//第一步: 从文件中读取数据
void read(){
    ifstream fin("D:\训练样本集文件.txt");
    for(int i=0;i<n;i++){
        fin>>trainset[i].classlabel;
        for(int j=0;j<m;j++)
          fin>>trainset[i].samples[j];
    } 
    fin.close();
    
    //cin.get();
}
//第二步:输入K,和待分类样本 v 
void Input(struct TrainSet v){
    //struct TrainSet v;
    cout<<"please input the "<<m<<" specimen of v:";
    for(int i=0;i<m;i++)
       cin>>v.samples[i]; 
  /*
  for(int i=0;i<m;i++)
       cout<<v.samples[i]<<" ";*/
}
//第三步:计算样本v与训练集中每个样本的欧几里得距离
void DistanceALL(struct TrainSet v){
    double squaresum=0.0,temp=0.0;
    for(int j=0;j<n;j++){
        for(int i=0;i<m;i++){
        temp=v.samples[i]-trainset[j].samples[i];
        temp=temp*temp;
        squaresum+=temp;
      }
      trainset[j].distancetov=sqrt(squaresum);
    }
    for(int i=0;i<n;i++)
        cout<<trainset[i].distancetov<<"  ";
}
//第四步:选出与样本 v 的K个最小样本
void ChooseK(){
    int min;
    for(int i=0;i<n;i++)
       trainset[i].tab=0;
    for(int i=0;i<n;i++){
        min=i;
        for(int j=i+1;j<n;j++){
            if(trainset[i].tab==0&&trainset[min].distancetov<trainset[j].distancetov)
            min=j;
        }
        K[i].classlabel=trainset[min].classlabel;
        trainset[min].tab=1;
    }
}
//第五步:选出包含 K个最邻近样本中最多样本的类别作为代分类类别 
int ChooseMax(){
    
    for(int i=0;i<k;i++){
        for(int j=0;j<maxclass;j++)
          if(K[i].classlabel==j)
          classnumber[j]++;
    } 
    int max=0;
       for(int j=1;j<maxclass;j++)
           if(classnumber[max]<classnumber[j])
             max=j;
             
    return max;
}
//第六步:更新训练样本集                 
int main(){
    for(int i=0;i<maxclass;i++)
        classnumber[i]=0;
    
    read();
    
    Input(v);
        for(int i=0;i<n;i++){
        cout<<trainset[i].classlabel<<endl;
        for(int j=0;j<m;j++){
            cout<<trainset[i].samples[j]<<" ";
        }
        cout<<endl;
    }
    DistanceALL(v);
/*
    for(int i=0;i<n;i++)
        cout<<trainset[i].distance<<"  ";*/
    ChooseK();
    cout<<"The sample v belong to "<<ChooseMax()<<endl; 
    return 0;
    
}

为什么read()之后输出不了距离,其他也有问题,我调试不过

C++
爱嘉牛LA的主页 爱嘉牛LA | 初学一级 | 园豆:190
提问于:2012-05-06 09:27
< >
分享
最佳答案
1

你好,我帮你找到一个错误,把 ifstream fin("D:\训练样本集文件.txt");这行代码改成 ifstream fin("D:\\训练样本集文件.txt");

希望能帮助你

收获园豆:10
NLP新手 | 菜鸟二级 |园豆:204 | 2012-05-06 22:37

另外,我看了这一整篇代码,我想如果想要这篇代码执行成功的话,还有两个地方要改,就是把void Input(structTrainSet v)和void DistanceALL(struct TrainSet v)这两个函数的参数去掉改成void Input()和void DistanceALL()就行了,

希望能帮助你

NLP新手 | 园豆:204 (菜鸟二级) | 2012-05-06 23:25

@kevinGao: 你好,参数去和不去都一样喔,读文件路径更对后可以输出距离了,但是分类那里错了,无论输入什么数据都是输出待分类的样本类型为0

爱嘉牛LA | 园豆:190 (初学一级) | 2012-05-07 08:41

@爱嘉牛LA: 我想这是因为你的参数是按值传递的,导致参数作用域出问题了,既然你用的是全局的V和trainset[n],所以我建议你去掉参数列表试试看,

希望能帮助你

NLP新手 | 园豆:204 (菜鸟二级) | 2012-05-07 08:57

@kevinGao: 真的麻烦你了,我按照你的做法发程序改了。自己还发觉了void DistanceALL的错误,并改进了。通过调试,发觉void ChooseK()函数错了!你改后的代码如下,请帮我改下,麻烦了

 

/*
第一步:从文档中读取训练样本集 ;假设一个有5用类型
                            文件中格式:                       
                                      1 A00,A01...A0(n-1);          
           2 .                                       
           3 .                                       
           1 .                                       
                          5 A(m-1)0,A(m-1)1...A(m-1)(n-1);T(m-1)() 
                          当在程序中定义数组时,定义为trainingspeciemens[n][m+1]
        每个样本的倒数第一个数为改数据所属的类型,
       
        
第二步:输入K,和待分类样本 R
第三步:计算R与一个训练样本的欧几里得距离
第四步:选出与 样本 R 的K个最小样本
第五步:选出包含 K个最邻近样本中最多样本的类别
第六步:把样本R归于k个样本最大类别   

*/


#include<iostream>
#include<cmath>
#include<fstream>
using namespace std;
#define k 4//选出k个样本
#define n 5//文档中样本数
#define m 4//样本维数
#define maxclass 5//规定最大类别数
int classnumber[maxclass];
struct TrainSet{
 int tab;
 double distancetov;
 double classlabel;
 double samples[m];
};
TrainSet trainset[n];//从文档中读取的样本放在这里
TrainSet v;//用户输入的样本

struct Ksample{
 double distance;
 double classlabel;
};//选出来的k个最近样本放在这里
Ksample K[k];
//第一步: 从文件中读取数据
void read(){
    ifstream fin("D:\\训练样本集文件.txt");
 for(int i=0;i<n;i++){
  fin>>trainset[i].classlabel;
  for(int j=0;j<m;j++)
    fin>>trainset[i].samples[j];
 }
 fin.close();
   
 //cin.get();
}
//第二步:输入K,和待分类样本 v
void Input(){
 //struct TrainSet v;
 cout<<"please input the "<<m<<" specimen of v:";
 for(int i=0;i<m;i++)
    cin>>v.samples[i];
  /*
  for(int i=0;i<m;i++)
       cout<<v.samples[i]<<" ";*/
}
//第三步:计算样本v与训练集中每个样本的欧几里得距离如果类型数都相等
 
void DistanceALL(){
 double squaresum,temp=0.0;
 for(int j=0;j<n;j++){
  squaresum=0.0;
  for(int i=0;i<m;i++){
  temp=v.samples[i]-trainset[j].samples[i];
  temp=temp*temp;
  squaresum+=temp;
   }
   trainset[j].distancetov=sqrt(squaresum);
 }
 cout<<"The all distance:"<<endl;

}
//第四步:选出与样本 v 的K个最小样本
void ChooseK(){
 int min;
 for(int i=0;i<n;i++)
    trainset[i].tab=0;
 for(int i=0;i<k;i++){
  for(int t=0;t<n;t++)
   if(trainset[t].tab==0){
    min=t;
    break;
      }
  for(int j=0;j<n;j++){
   if((trainset[i].tab==0)&&(trainset[min].distancetov<trainset[j].distancetov))
        min=j;
  }
  trainset[min].tab=1;
  K[i].classlabel=trainset[min].classlabel;
     K[i].distance=trainset[min].distancetov;
  cout<<K[i].distance<<"  \t"<<K[i].classlabel<<endl;
       
 }
 cout<<"The "<<k<<"is:"<<endl;
 /*
for(int i=0;i<k;i++)
     cout<<"Distance:"<<K[i].distance<"  "<<"Class:"<<K[i].classlabel<<endl;
 */
}
//第五步:选出包含 K个最邻近样本中最多样本的类别作为代分类类别 ,那么选择最近的那个作为他的类型
int ChooseMax(){
 
    for(int i=0;i<k;i++){
     for(int j=0;j<maxclass;j++)
       if(K[i].classlabel==j)
       classnumber[j]++;
    }
    int max=0;
    for(int j=1;j<maxclass;j++)
        if(classnumber[max]<classnumber[j])
          max=j;
         
    return max;
}
//第六步:更新训练样本集       
int main(){
 for(int i=0;i<maxclass;i++)
     classnumber[i]=0;
   
 read();
 
 Input();
  for(int i=0;i<n;i++){
  cout<<trainset[i].classlabel<<endl;
  for(int j=0;j<m;j++){
   cout<<trainset[i].samples[j]<<" ";
  }
  cout<<endl;
 }
 DistanceALL();
  for(int i=0;i<n;i++)
   cout<<"Distance:"<<trainset[i].distancetov<<"  "<<"\tClass:"<<trainset[i].classlabel<<endl;
/*
 for(int i=0;i<n;i++)
     cout<<trainset[i].distance<<"  ";*/
 ChooseK();
/*
 for(int i=0;i<k;i++)
     cout<<"distance:"<<K[i].distance<"  "<<"Class:"<<K[i].classlabel<<endl;*/
 cout<<"The sample v belong to "<<ChooseMax()<<endl;
 return 0;
 
}

爱嘉牛LA | 园豆:190 (初学一级) | 2012-05-07 21:30

@爱嘉牛LA: 

 1 int ChooseMax()
 2 {
 3     for(int i=0;i<k;i++)
 4     {
 5         for(int j=0;j<maxclass;j++)
 6           if(K[i].classlabel==j)
 7             classnumber[j]++;
 8     } 
 9     int max=0;
10     for(int j=0;j<maxclass;j++)
11        if(classnumber[max]<classnumber[j])
12           max=j;         
13     return max+1;
14 }

试试这样可以么

NLP新手 | 园豆:204 (菜鸟二级) | 2012-05-11 20:29
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册