/* 第一步:从文档中读取训练样本集 ;假设一个有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()之后输出不了距离,其他也有问题,我调试不过
你好,我帮你找到一个错误,把 ifstream fin("D:\训练样本集文件.txt");这行代码改成 ifstream fin("D:\\训练样本集文件.txt");
希望能帮助你
另外,我看了这一整篇代码,我想如果想要这篇代码执行成功的话,还有两个地方要改,就是把void Input(structTrainSet v)和void DistanceALL(struct TrainSet v)这两个函数的参数去掉改成void Input()和void DistanceALL()就行了,
希望能帮助你
@kevinGao: 你好,参数去和不去都一样喔,读文件路径更对后可以输出距离了,但是分类那里错了,无论输入什么数据都是输出待分类的样本类型为0
@爱嘉牛LA: 我想这是因为你的参数是按值传递的,导致参数作用域出问题了,既然你用的是全局的V和trainset[n],所以我建议你去掉参数列表试试看,
希望能帮助你
@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:
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 }
试试这样可以么