PLA感知学习算法

1 1 #include <vector> 2 2 #include<iomanip> 3 3 #include <string> 4 4 #include<stdio.h> 5 5 #include<string.h> 6 6 #include <fstream> 7 7 #include <iostream> 8 8 #include<set> 9 9 #include<algorithm> 10 10 #include<cstdio> 11 11 #include<iomanip> 12 12 #include<map> 13 13 #include<cmath> 14 14 #define col 41 15 15 #define row 7000 16 16 17 17 using namespace std; 18 18 double label[8010][80]; //训练集 19 19 double test_label[8010][80]; //测试集 20 20 double valition_label[8010][80]; //验证集 21 21 string s[8010]; 22 22 string ss[8010]; 23 23 string s2[8010]; 24 24 25 25 26 26 //logitic函数,将负无穷到正无穷 转化 -1到 1 27 27 28 28 double logistic(double n){ 29 29 30 30 return 1/(1+exp(-1.0*n)); 31 31 32 32 } 33 33 34 34 double geterror(int n){ 35 35 return 0.001; 36 36 } 37 37 38 38 double cut_t(string s, int t){ 39 39 string str = s; 40 40 int r = 0; 41 41 double count = 0.0; 42 42 bool flag = true; 43 43 double flag1 = 1.0; 44 44 double sum = 0.0; 45 45 for(int i=0;i<str.length();i++){ 46 46 47 47 if(r==t && str[i] == '-'){ 48 48 flag1 = -1; 49 49 continue; 50 50 } 51 51 if(str[i]==','){ 52 52 r++; 53 53 continue; 54 54 } 55 55 if(r==t){ 56 56 if(flag == false){ 57 57 count ++; 58 58 } 59 59 if(str[i] == '.'){ 60 60 flag = false; 61 61 } 62 62 else { 63 63 sum = sum + (str[i] - '0') * 1.0; 64 64 sum = sum * 10; 65 65 } 66 66 67 67 } 68 68 } 69 69 70 70 for(int i=0;i<=count;i++){ 71 71 sum = sum/10; 72 72 } 73 73 return sum*flag1; 74 74 } 75 75 76 76 77 77 78 78 int main() 79 79 { 80 80 81 81 82 82 /*************************************************读文件***********************************************************/ 83 83 84 84 fstream myfile("C:\\AI_data\\lab5\\train.csv"); 85 85 fstream valition("C:\\AI_data\\lab5\\valition.csv"); 86 86 fstream test("C:\\AI_data\\lab5\\test.csv"); 87 87 88 88 89 89 int num=0; 90 90 string temp; 91 91 if(!myfile.is_open()) 92 92 { 93 93 cout << "1未成功打开文件" << endl; 94 94 } 95 95 while(getline(myfile,temp)) //读入文本中的词 96 96 { 97 97 s[num] = temp; 98 98 num++; 99 99 } 100100 101101 102102 int num1 = 0; 103103 string temp1; 104104 if(!test.is_open()) 105105 { 106106 cout << "2未成功打开文件" << endl; 107107 } 108108 while(getline(test,temp1)) //读入文本中的词 109109 { 110110 ss[num1] = temp1; 111111 num1++; 112112 } 113113 114114 115115 int num2 = 0; 116116 string temp2; 117117 if(!valition.is_open()) 118118 { 119119 cout << "3未成功打开文件" << endl; 120120 } 121121 while(getline(valition,temp2)) //读入文本中的词 122122 { 123123 s2[num2] = temp2; 124124 num2++; 125125 } 126126 127127 128128 /***********************************************处理文本********************************************************************/ 129129 for(int i=0; i<num; i++){ 130130 131131 int len = s[i].length(); 132132 string str = s[i]; 133133 char t[8000]=""; 134134 for(int j=0;j<col;j++){ 135135 label[i][0] = 1.0; //需要在每一个样例前面加上一个 1 136136 label[i][j+1] = cut_t(s[i],j); 137137 } 138138 // for(int j=0;j<=col;j++) cout<<label[i][j]<<" "; 139139 //cout<<endl; 140140 for(int w=0;w<len;w++){ 141141 t[w] = str[w]; 142142 } 143143 const char *d = " , \n" ; 144144 char* p = strtok(t,d); 145145 while(p) 146146 { 147147 p=strtok(NULL,d); 148148 } 149149 } 150150 151151 for(int i=0; i<num1; i++){ 152152 153153 int len1 = ss[i].length(); 154154 string str1 = ss[i]; 155155 char tt[8000]=""; 156156 //cout<<ss[i]<<endl; 157157 for(int j=0;j<col-1;j++){ 158158 test_label[i][0] = 1.0; //需要在每一个样例前面加上一个 1 159159 test_label[i][j+1] = cut_t(ss[i],j); 160160 //cout<<test_label[i][j]<<" "; 161161 } 162162 //for(int j=0;j<67;j++) cout<<label[i][j]<<endl; 163163 //cout<<endl; 164164 for(int w=0;w<len1;w++){ 165165 tt[w] = str1[w]; 166166 } 167167 const char *d = " , \n" ; 168168 char* p = strtok(tt,d); 169169 while(p) 170170 { 171171 p=strtok(NULL,d); 172172 } 173173 } 174174 175175 for(int i=0; i<num2; i++){ 176176 177177 int len2 = s2[i].length(); 178178 string str2 = s2[i]; 179179 char t2[8000]=""; 180180 for(int j=0;j<col;j++){ 181181 valition_label[i][0] = 1.0; //需要在每一个样例前面加上一个 1 182182 valition_label[i][j+1] = cut_t(s2[i],j); 183183 } 184184 // for(int j=0;j<=col;j++) cout<<label[i][j]<<" "; 185185 //cout<<endl; 186186 for(int w=0;w<len2;w++){ 187187 t2[w] = str2[w]; 188188 } 189189 const char *d2 = " , \n" ; 190190 char* p2 = strtok(t2,d2); 191191 while(p2) 192192 { 193193 p2=strtok(NULL,d2); 194194 } 195195 } 196196 /***************************************************************** PLA算法执行 ************************************************/ 197197 198198 199199 200200 201201 double w[col]; //初始的 w[] 数组 202202 double new_w[col]; 203203 double zhishu[row]; 204204 for(int j=0;j<col;j++){ 205205 w[j] = 1.0; 206206 } 207207 for(int ui=0;ui<row;ui++){ 208208 zhishu[ui] = 0.0; 209209 } 210210 211211 int a = 6000; //由于不能全部划分,所以设立一个最大次数 212212 double error = 0.5; 213213 while(a--){ 214214 //double error = geterror(a); //调整步长 215215 216216 for(int j=0;j<col;j++){ //初始化数组,用来更新w[]数组 217217 new_w[j] = 0.0; 218218 } 219219 for(int i=0;i<num;i++){ // 遍历所有样本进行一轮迭代 220220 for(int j=0;j<col;j++){ 221221 zhishu[i] += label[i][j]*w[j]; // 对每一个导数进行存储 222222 } 223223 //进行logistic变换 224224 zhishu[i] = logistic(zhishu[i]) - label[i][col]; 225225 } 226226 bool flag = true; //判断是否收敛 227227 for(int jt=0;jt<col;jt++){ 228228 for(int it=0;it<num;it++){ //更新 w[] 229229 new_w[jt] += label[it][jt]*zhishu[it]; 230230 } 231231 new_w[jt] = new_w[jt]*error; 232232 if(new_w[jt] != 0) flag = false; 233233 w[jt] = w[jt] - new_w[jt]; //为下一次迭代 w[] 234234 } 235235 if(flag){ //如果收敛 236236 cout<<a<<endl; 237237 cout<<"完美收敛,提前结束"<<endl; 238238 break; 239239 } 240240 241241 } 242242 243243 //统计各个指标 244244 double TP = 0.0; 245245 double FN = 0.0; 246246 double TN = 0.0; 247247 double FP = 0.0; 248248 double Acc = 0.0; 249249 double Rec = 0.0; 250250 double Pre = 0.0; 251251 double F1 = 0.0; 252252 253253 254254 for(int i=0;i<num2;i++){ 255255 int flag1 = 1; 256256 double sum2 = 0.0; 257257 for(int j=0;j<col;j++){ 258258 sum2 += valition_label[i][j]*w[j]; 259259 } 260260 if(logistic(sum2) < 0.5) flag1 = 0; 261261 else flag1 = 1; 262262 263263 264264 if(flag1 == 1 && valition_label[i][col] == 1) TP++; 265265 else if(flag1 == 0 && valition_label[i][col] == 1) FN++; 266266 else if(flag1 == 0 && valition_label[i][col] == 0) TN++; 267267 else FP++; 268268 } 269269 cout<<"TP = "<<TP<<endl; 270270 cout<<"TN = "<<TN<<endl; 271271 cout<<"FN = "<<FN<<endl; 272272 cout<<"FP = "<<FP<<endl; 273273 Acc = (TP+TN)/(TP+TN+FP+FN); 274274 Rec = TP/(TP+FN); 275275 Pre = TP/(TP+FP); 276276 F1 = 2*Pre*Rec / (Pre+Rec); 277277 278278 cout<<"Acc = "<<Acc<<endl; 279279 cout<<"Rec = "<<Rec<<endl; 280280 cout<<"Pre = "<<Pre<<endl; 281281 cout<<"F1 = "<<F1<<endl; 282282 283283 284284 285285 for(int k=0;k<num1;k++){ 286286 287287 int flag3 = 0; 288288 double sum3 = 0.0; 289289 for(int j=0;j<col;j++){ 290290 sum3 += test_label[k][j]*w[j]; 291291 } 292292 293293 if(logistic(sum3) < 0.5 ) flag3 = 0; 294294 else flag3 = 1; 295295 cout<<flag3<<endl; 296296 } 297297 298298 test.close(); 299299 myfile.close(); 300300 return 0; 301301 }

上面是原始的PLA实现,下面是PLA基于口袋算法的优化:

1 1 #include <vector> 2 2 #include<iomanip> 3 3 #include <string> 4 4 #include<stdio.h> 5 5 #include<string.h> 6 6 #include <fstream> 7 7 #include <iostream> 8 8 #include<set> 9 9 #include<algorithm> 10 10 #include<cstdio> 11 11 #include<iomanip> 12 12 #include<map> 13 13 #include<cmath> 14 14 using namespace std; 15 15 double label[4010][80]; 16 16 string s[4010]; 17 17 18 18 double cut_t(string s, int t){ 19 19 string str = s; 20 20 int r = 0; 21 21 double count = 0.0; 22 22 bool flag = true; 23 23 double flag1 = 1.0; 24 24 double sum = 0.0; 25 25 for(int i=0;i<str.length();i++){ 26 26 27 27 if(r==t && str[i] == '-'){ 28 28 flag1 = -1; 29 29 continue; 30 30 } 31 31 if(str[i]==','){ 32 32 r++; 33 33 continue; 34 34 } 35 35 if(r==t){ 36 36 if(flag == false){ 37 37 count ++; 38 38 } 39 39 if(str[i] == '.'){ 40 40 flag = false; 41 41 } 42 42 else { 43 43 sum = sum + (str[i] - '0') * 1.0; 44 44 sum = sum * 10; 45 45 } 46 46 47 47 } 48 48 } 49 49 50 50 for(int i=0;i<=count;i++){ 51 51 sum = sum/10; 52 52 } 53 53 return sum*flag1; 54 54 } 55 55 56 56 57 57 58 58 int main() 59 59 { 60 60 61 61 62 62 /*************************************************读文件***********************************************************/ 63 63 64 64 fstream myfile("F:\\AI_data\\lab3\\train.txt"); 65 65 int num=0; 66 66 string temp; 67 67 if (!myfile.is_open()) 68 68 { 69 69 cout << "未成功打开文件" << endl; 70 70 } 71 71 while(getline(myfile,temp)) //读入文本中的词 72 72 { 73 73 s[num] = temp; 74 74 num++; 75 75 } 76 76 77 77 78 78 /***********************************************处理文本********************************************************************/ 79 79 for(int i=0; i<num; i++){ 80 80 81 81 int len = s[i].length(); 82 82 string str = s[i]; 83 83 char t[8000]=""; 84 84 for(int j=0;j<66;j++){ 85 85 label[i][0] = 1.0; //需要在每一个样例前面加上一个 1 86 86 label[i][j+1] = cut_t(s[i],j); 87 87 } 88 88 //for(int j=0;j<67;j++) cout<<label[i][j]<<endl; 89 89 // cout<<endl; 90 90 for(int w=0;w<len;w++){ 91 91 t[w] = str[w]; 92 92 } 93 93 const char *d = " , \n" ; 94 94 char* p = strtok(t,d); 95 95 while(p) 96 96 { 97 97 p=strtok(NULL,d); 98 98 } 99 99 } 100100 101101 /***************************************************************** PLA算法执行 ************************************************/ 102102 103103 double w[66]; //初始的 w[] 数组 104104 double change_w[66]; 105105 //double w[7]; 106106 double store[4010]; 107107 double sum = 0.0; 108108 for(int j=0;j<66;j++){ 109109 w[j] = 1.0; 110110 change_w[j] = 1.0; 111111 } 112112 int a = 2000; 113113 114114 115115 while(a--){ //规定迭代次数 116116 117117 bool flag2 = true; 118118 long double counter_right1 = 0; //两次的正确的数目统计 119119 long double counter_right2 = 0; 120120 int dex = 0; 121121 122122 for(int i=0;i<num;i++){ //遍历所有数据 123123 124124 sum = 0.0; 125125 126126 for(int j=0;j<66;j++){ //进行计算 127127 128128 sum += label[i][j]*w[j]; 129129 //cout<< i << " "<<j<<endl; 130130 } 131131 //cout<<"sum= "<<sum<<endl; 132132 int flag = 0; 133133 134134 if(sum > 0.0){ //对结果的符号进行判断 135135 flag = 1; 136136 } 137137 else{ 138138 flag = -1; 139139 } 140140 141141 //cout<<flag << " "<<label[i][66]<<endl; 142142 if(flag != label[i][66] ){ //判断结果是否是正确的,不正确需要考虑这个w[] 143143 if(flag2){ 144144 for(int k=0;k<66;k++){ 145145 change_w[k] = w[k] + label[i][k]*label[i][66]; 146146 dex = i; 147147 //cout<<w[k]<<endl; 148148 } 149149 } 150150 flag2 = false; //一次只考虑第一个不正确的 w[] 151151 } 152152 else counter_right1++; //记录第一个 w[] 的正确率 153153 } 154154 155155 156156 for(int i=0;i<num;i++){ //遍历所有数据 157157 158158 sum = 0.0; 159159 160160 for(int j=0;j<66;j++){ //用第二个w[]进行迭代 161161 162162 sum += label[i][j]*change_w[j]; 163163 //cout<< i << " "<<j<<endl; 164164 } 165165 //cout<<"sum= "<<sum<<endl; 166166 int flag = 0; 167167 168168 if(sum > 0.0){ //算出结果的符号 169169 flag = 1; 170170 } 171171 else{ 172172 flag = -1; 173173 } 174174 //记录正确率 175175 //cout<<flag << " "<<label[i][66]<<endl; 176176 if(flag == label[i][66] ) counter_right2++; 177177 } 178178 179179 180180 //两个w[]数组正确率比较 ,第一个正确率高则返回原来的w[],否则w[] 替换为更新后的,进入下一轮迭代 181181 if(counter_right1 > counter_right2){ 182182 for(int j=0;j<66;j++){ 183183 w[j] = change_w[j] - label[dex][j]*label[dex][66]; 184184 } 185185 } 186186 else{ 187187 for(int j=0;j<66;j++){ 188188 w[j] = change_w[j] ; 189189 } 190190 } 191191 192192 } 193193 194194 195195 double TP = 0.0; 196196 double FN = 0.0; 197197 double TN = 0.0; 198198 double FP = 0.0; 199199 double Acc = 0.0; 200200 double Rec = 0.0; 201201 double Pre = 0.0; 202202 double F1 = 0.0; 203203 204204 for(int i=0;i<num;i++){ 205205 int flag1 = 1; 206206 double sum1 = 0.0; 207207 for(int j=0;j<66;j++){ 208208 sum1 += label[i][j]*w[j]; 209209 //cout<<" w[] = "<<w[j]<<endl; 210210 } 211211 cout<<sum1<<endl; 212212 213213 if(sum1 >= 0 ) flag1 = 1; 214214 else flag1 = -1; 215215 216216 cout<<flag1<<" "; 217217 cout<<label[i][66]<<endl; 218218 if(flag1 == 1 && label[i][66] == 1) TP++; 219219 else if(flag1 == -1 && label[i][66] == 1) FN++; 220220 else if(flag1 == -1 && label[i][66] == -1) TN++; 221221 else if(flag1 == 1 && label[i][66] == -1)FP++; 222222 223223 } 224224 cout<<TP<<endl; 225225 cout<<TN<<endl; 226226 cout<<FN<<endl; 227227 cout<<TN<<endl; 228228 Acc = (TP+TN)/(TP+TN+FP+FN); 229229 Rec = TP/(TP+FN); 230230 Pre = TP/(TP+FP); 231231 F1 = 2*Pre*Rec / (Pre+Rec); 232232 233233 cout<<"Acc = "<<Acc<<endl; 234234 cout<<"Rec = "<<Rec<<endl; 235235 cout<<"Pre = "<<Pre<<endl; 236236 cout<<"F1 = "<<F1<<endl; 237237 for(int k=0;k<66;k++){ 238238 cout<< w[k] <<endl; 239239 } 240240 241241 myfile.close(); 242242 return 0; 243243 }
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )