机器学习 花卉识别分类C++例程

[复制链接]
查看22 | 回复0 | 2020-6-4 00:51:56 | 显示全部楼层 |阅读模式
话会识别分类机器学习源码.7z (251.07 KB, 售价: 1 工控币)
1.png
部分源码
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int maxn=155;
  4. vector<int> v[maxn];
  5. map<string, int> mp;
  6. struct Iris
  7. {
  8.     double prop[4];
  9.     //0_Sepal_Length 1_Sepal_Width
  10.     //2_Petal_Length 3_Petal_Width
  11.     int sum;//原本分类;
  12.     int pv;//预测分类;
  13. }all[maxn];
  14. void print(Iris a)
  15. {
  16.     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);
  17.     if(a.sum==a.pv) printf("\n");
  18.     else printf(" 预测错误\n");
  19. }
  20. void Iris_Division(int t)
  21. //分层随机分成t份,用于t折交叉验证;
  22. {
  23.     srand(time(NULL));//重置随机数种子;
  24.     int book[maxn], cnt;
  25.     memset(book, 0, sizeof(book));
  26.     for(int i=1; i<=t; i++)
  27.     {
  28.         for(int j=1; j<=3; j++)
  29.         {
  30.             cnt=0;
  31.             while(cnt<150/(t*3))
  32.             {
  33.                 int x=rand()%50+1+50*(j-1);
  34.                 if(book[x]==1) continue;
  35.                 book[x]=1;
  36.                 v[i].push_back(x);
  37.                 cnt++;
  38.             }
  39.         }
  40.     }
  41. }
  42. struct Tree_Node
  43. {
  44.     int sum;//-1表示非叶节点, 0、1、2表示该节点划分种类
  45.     int basic;//依据什么划分
  46.     double div;//分界值
  47.     struct Tree_Node* left;//小于等于分界值的儿子节点
  48.     struct Tree_Node* right;//大于分界值的儿子节点
  49. };
  50. double log2(double x) { return log(x)/log((double)(2.0)); }
  51. double Cal_Ent_D(int cnt[], int n, int sum)
  52. {
  53.     double Ent_D=0;
  54.     for(int i=0; i<n; i++)
  55.         if(cnt[i]!=0)
  56.         {
  57.             double x;
  58.             x=cnt[i]*1.0/sum;
  59.             Ent_D=Ent_D-x*log2(x);
  60.         }
  61.     return Ent_D;
  62. }
  63. void Cal_Max_Gain(set<int>train, int* basic, double* div)
  64. //计算最大的信息增益,选择划分依据;
  65. {
  66.     int cnt[3]={0};//3种分类结果的数量;
  67.     int sum=train.size();
  68.     //cout<<sum<<endl;
  69.     for(auto x : train) cnt[all[x].sum]++;

  70.     double Ent_D=Cal_Ent_D(cnt, 3, sum);

  71.     vector<double> t;
  72.     double maxx=-1e5;
  73.     for(int i=0; i<4; i++)
  74.     {
  75.         t.clear();
  76.         for(auto x : train) t.push_back(all[x].prop[i]);
  77.         sort(t.begin(), t.end());//连续值排序,用于二分离散化
  78.         for(int j=0; j<(int)(t.size()-1); j++)
  79.         {
  80.             double y=(t[j]+t[j+1])/2.0;
  81.             double ans=Ent_D;
  82.             memset(cnt, 0, sizeof(cnt));
  83.             sum=0;
  84.             for(auto x : train) if(all[x].prop[i]<=y) cnt[all[x].sum]++, sum++;
  85.             if(sum!=0) ans=ans-(double)sum/(double)(t.size())*Cal_Ent_D(cnt, 3, sum);

  86.             memset(cnt, 0, sizeof(cnt));
  87.             sum=0;
  88.             for(auto x : train) if(all[x].prop[i]>y) cnt[all[x].sum]++, sum++;
  89.             if(sum!=0) ans=ans-(double)sum/(double)(t.size())*Cal_Ent_D(cnt, 3, sum);

  90.             if(ans>maxx)
  91.             {
  92.                 maxx=ans;
  93.                 *basic=i;
  94.                 *div=y;
  95.             }
  96.         }
  97.     }
  98. }
  99. void Build_Tree(Tree_Node** T, set<int>train)//建立决策树
  100. {
  101.     *T=(Tree_Node*)malloc(sizeof(Tree_Node));
  102.     ((*T)->sum)=-1; ((*T)->basic)=0; ((*T)->div)=0;
  103.     set<int> s;
  104.     for(auto x : train) s.insert(all[x].sum);
  105.     if(s.size()==1) { ((*T)->sum)=(*s.begin()); s.clear(); return; }

  106.     Cal_Max_Gain(train, &((*T)->basic), &((*T)->div));

  107.     set<int> left_train, right_train;
  108.     for(auto x : train)
  109.     {
  110.         if(all[x].prop[(*T)->basic] <= ((*T)->div)) left_train.insert(x);
  111.         else right_train.insert(x);
  112.     }
  113.     Build_Tree(&(*T)->left, left_train);
  114.     Build_Tree(&(*T)->right, right_train);
  115. }

  116. int Test_Data(Tree_Node* T, int x)
  117. {
  118.     if((T->sum)!=-1) return T->sum;
  119.     if(all[x].prop[T->basic]<=(T->div))
  120.         return Test_Data(T->left, x);
  121.     else return Test_Data(T->right, x);
  122. }
  123. int main()
  124. {
  125.     freopen("iris.txt","r",stdin);
  126.     int cnt=0;
  127.     for(int i=1; i<=150; i++)
  128.     {
  129.         string s;
  130.         scanf("%lf,%lf,%lf,%lf,",&all[i].prop[0],&all[i].prop[1],&all[i].prop[2],&all[i].prop[3]);
  131.         cin>>s;
  132.         if(!mp.count(s)) { mp[s]=cnt; cnt++;}
  133.         all[i].sum=mp[s];
  134.     }
  135.     int t=10;
  136.     Iris_Division(t);//分层随机分成t份,用于t折交叉验证;
  137.     set<int> train, test;
  138.     double Ans=0.0;
  139.     for(int i=1; i<=10; i++)
  140.     {
  141.         train.clear();  test.clear();
  142.         for(int j=1; j<=t; j++)
  143.         {
  144.             if(j==i) for(int k=0; k<(int)v[j].size(); k++) test.insert(v[j][k]);
  145.             else for(int k=0; k<(int)v[j].size(); k++) train.insert(v[j][k]);
  146.         }
  147.         Tree_Node* tree;
  148.         Build_Tree(&tree, train);
  149.         printf("Sepal_Length Sepal_Width Petal_Length Petal_Width Actual_Value Predicted_Value\n");
  150.         int Cor_Num=0, All_Num=0;
  151.         for(auto x: test)
  152.         {
  153.             all[x].pv=Test_Data(tree, x);
  154.             if(all[x].sum==all[x].pv) Cor_Num++;
  155.             All_Num++;
  156.             print(all[x]);
  157.         }
  158.         printf("第%d次 预测正确率:%.3f\n\n", i, (double)Cor_Num/(double)All_Num);
  159.         Ans+=(double)Cor_Num/(double)All_Num;
  160.     }
  161.     printf("平均预测正确率:%.3f\n\n", Ans/(double)t);
  162.     return 0;
  163. }
复制代码

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则