话会识别分类机器学习源码.7z
(251.07 KB, 售价: 1 E币)
部分源码
- #include <bits/stdc++.h>
- using namespace std;
- const int maxn=155;
- vector<int> v[maxn];
- map<string, int> mp;
- struct Iris
- {
- double prop[4];
- //0_Sepal_Length 1_Sepal_Width
- //2_Petal_Length 3_Petal_Width
- int sum;//原本分类;
- int pv;//预测分类;
- }all[maxn];
- void print(Iris a)
- {
- printf("%12.1f %11.1f %12.1f %11.1f %12d %15d ",a.prop[0],a.prop[1],a.prop[2],a.prop[3],a.sum,a.pv);
- if(a.sum==a.pv) printf("\n");
- else printf(" 预测错误\n");
- }
- void Iris_Division(int t)
- //分层随机分成t份,用于t折交叉验证;
- {
- srand(time(NULL));//重置随机数种子;
- int book[maxn], cnt;
- memset(book, 0, sizeof(book));
- for(int i=1; i<=t; i++)
- {
- for(int j=1; j<=3; j++)
- {
- cnt=0;
- while(cnt<150/(t*3))
- {
- int x=rand()%50+1+50*(j-1);
- if(book[x]==1) continue;
- book[x]=1;
- v[i].push_back(x);
- cnt++;
- }
- }
- }
- }
- struct Tree_Node
- {
- int sum;//-1表示非叶节点, 0、1、2表示该节点划分种类
- int basic;//依据什么划分
- double div;//分界值
- struct Tree_Node* left;//小于等于分界值的儿子节点
- struct Tree_Node* right;//大于分界值的儿子节点
- };
- double log2(double x) { return log(x)/log((double)(2.0)); }
- double Cal_Ent_D(int cnt[], int n, int sum)
- {
- double Ent_D=0;
- for(int i=0; i<n; i++)
- if(cnt[i]!=0)
- {
- double x;
- x=cnt[i]*1.0/sum;
- Ent_D=Ent_D-x*log2(x);
- }
- return Ent_D;
- }
- void Cal_Max_Gain(set<int>train, int* basic, double* div)
- //计算最大的信息增益,选择划分依据;
- {
- int cnt[3]={0};//3种分类结果的数量;
- int sum=train.size();
- //cout<<sum<<endl;
- for(auto x : train) cnt[all[x].sum]++;
- double Ent_D=Cal_Ent_D(cnt, 3, sum);
- vector<double> t;
- double maxx=-1e5;
- for(int i=0; i<4; i++)
- {
- t.clear();
- for(auto x : train) t.push_back(all[x].prop[i]);
- sort(t.begin(), t.end());//连续值排序,用于二分离散化
- for(int j=0; j<(int)(t.size()-1); j++)
- {
- double y=(t[j]+t[j+1])/2.0;
- double ans=Ent_D;
- memset(cnt, 0, sizeof(cnt));
- sum=0;
- for(auto x : train) if(all[x].prop[i]<=y) cnt[all[x].sum]++, sum++;
- if(sum!=0) ans=ans-(double)sum/(double)(t.size())*Cal_Ent_D(cnt, 3, sum);
- memset(cnt, 0, sizeof(cnt));
- sum=0;
- for(auto x : train) if(all[x].prop[i]>y) cnt[all[x].sum]++, sum++;
- if(sum!=0) ans=ans-(double)sum/(double)(t.size())*Cal_Ent_D(cnt, 3, sum);
- if(ans>maxx)
- {
- maxx=ans;
- *basic=i;
- *div=y;
- }
- }
- }
- }
- void Build_Tree(Tree_Node** T, set<int>train)//建立决策树
- {
- *T=(Tree_Node*)malloc(sizeof(Tree_Node));
- ((*T)->sum)=-1; ((*T)->basic)=0; ((*T)->div)=0;
- set<int> s;
- for(auto x : train) s.insert(all[x].sum);
- if(s.size()==1) { ((*T)->sum)=(*s.begin()); s.clear(); return; }
- Cal_Max_Gain(train, &((*T)->basic), &((*T)->div));
- set<int> left_train, right_train;
- for(auto x : train)
- {
- if(all[x].prop[(*T)->basic] <= ((*T)->div)) left_train.insert(x);
- else right_train.insert(x);
- }
- Build_Tree(&(*T)->left, left_train);
- Build_Tree(&(*T)->right, right_train);
- }
- int Test_Data(Tree_Node* T, int x)
- {
- if((T->sum)!=-1) return T->sum;
- if(all[x].prop[T->basic]<=(T->div))
- return Test_Data(T->left, x);
- else return Test_Data(T->right, x);
- }
- int main()
- {
- freopen("iris.txt","r",stdin);
- int cnt=0;
- for(int i=1; i<=150; i++)
- {
- string s;
- scanf("%lf,%lf,%lf,%lf,",&all[i].prop[0],&all[i].prop[1],&all[i].prop[2],&all[i].prop[3]);
- cin>>s;
- if(!mp.count(s)) { mp[s]=cnt; cnt++;}
- all[i].sum=mp[s];
- }
- int t=10;
- Iris_Division(t);//分层随机分成t份,用于t折交叉验证;
- set<int> train, test;
- double Ans=0.0;
- for(int i=1; i<=10; i++)
- {
- train.clear(); test.clear();
- for(int j=1; j<=t; j++)
- {
- if(j==i) for(int k=0; k<(int)v[j].size(); k++) test.insert(v[j][k]);
- else for(int k=0; k<(int)v[j].size(); k++) train.insert(v[j][k]);
- }
- Tree_Node* tree;
- Build_Tree(&tree, train);
- printf("Sepal_Length Sepal_Width Petal_Length Petal_Width Actual_Value Predicted_Value\n");
- int Cor_Num=0, All_Num=0;
- for(auto x: test)
- {
- all[x].pv=Test_Data(tree, x);
- if(all[x].sum==all[x].pv) Cor_Num++;
- All_Num++;
- print(all[x]);
- }
- printf("第%d次 预测正确率:%.3f\n\n", i, (double)Cor_Num/(double)All_Num);
- Ans+=(double)Cor_Num/(double)All_Num;
- }
- printf("平均预测正确率:%.3f\n\n", Ans/(double)t);
- return 0;
- }
复制代码
【必读】版权免责声明
1、本主题所有言论和内容纯属会员个人意见,与本论坛立场无关。2、本站对所发内容真实性、客观性、可用性不做任何保证也不负任何责任,网友之间仅出于学习目的进行交流。3、对提供的数字内容不拥有任何权利,其版权归原著者拥有。请勿将该数字内容进行商业交易、转载等行为,该内容只为学习所提供,使用后发生的一切问题与本站无关。 4、本网站不保证本站提供的下载资源的准确性、安全性和完整性;同时本网站也不承担用户因使用这些下载资源对自己和他人造成任何形式的损失或伤害。 5、本网站所有软件和资料均为网友推荐收集整理而来,仅供学习用途使用,请务必下载后两小时内删除,禁止商用。6、如有侵犯你版权的,请及时联系我们(电子邮箱1370723259@qq.com)指出,本站将立即改正。
|
|