2020年1月24日金曜日

KaggleのTitanicタイタニックの正解率をあげる。

おじさん、やっと暇ができました。
途中までやっていた、正解率78%のKaggleのタイタニックの正解率をとりあえず80%くらいにあげようと思います。

前回まではKaggleをC言語でやるための準備だったので、今回が本当のスタートです。

まず、SVMが線形カーネルだとよくないので、RBFカーネルをサポートしているlibsvmに変えます。まぁRBFカーネルのほうが真ん中取り出せるし。

次に、親兄弟の数と子供の数は足して一つのパラメーターのほうがよさそうなので足します。これだけで1%くらい正解率があがり79%に。

あと港と生存率が関係するので、港の値も入力。
SとCとQとパラメータなしにどの値を割り振るのが良いか16通り試験します。
Sは1、Cは0、Qは-1にマッピングするのがパラメーター的には一番よさそう
これで0.5%あがり。79.49%に。

客室もAかBかCだと船の上の方なので生存率が高そう。
このABだけなのかCまでなのかとかを決めるのが大変ですね。
どうやらABCにいるかいないかで違うっぽい。
これも0.5%あがり。79.9%に。

なんでこう微妙に足りないのかな。
もうチケット名以外の入力は全部使いました。

ここまでは簡単に上がるんですが、ここからがきつい。
とりあえず、SVMの予想がはずれているしている人だけをピックアップしてみます。

------------------------
1179,NG,1.000000,-1.000000,-0.400,1,2,Snyder, Mr. John Pillsbury,21228,B45
1182,NG,1.000000,-1.000000,-0.258,1,1,Rheims, Mr. George Alexander Lucien,PC 17607,
1192,NG,1.000000,-1.000000,-0.200,3,1,Olsson, Mr. Oscar Wilhelm,347079,
1201,NG,1.000000,-1.000000,0.125,3,2,Hansen, Mrs. Claus Peter (Jennie L Howard),350026,
1203,NG,1.000000,-1.000000,-0.450,3,1,Vartanian, Mr. David,2658,
1205,NG,-1.000000,1.000000,-0.075,3,1,Carr, Miss. Jeannie,368364,
1207,NG,-1.000000,1.000000,-0.575,3,1,Hagardon, Miss. Kate,AQ/3. 30631,
1213,NG,1.000000,-1.000000,-0.375,3,1,Krekorian, Mr. Neshan,2654,F E57
1233,NG,1.000000,-1.000000,-0.200,3,1,Lundstrom, Mr. Thure Edvin,350403,
1246,NG,1.000000,-1.000000,-1.000,3,4,Dean, Miss. Elizabeth Gladys Millvina"""",C.A. 2315,
1250,NG,1.000000,-1.000000,-0.258,3,1,O'Keefe, Mr. Patrick,368402,
1261,NG,1.000000,-1.000000,-0.275,2,1,Pallas y Castello, Mr. Emilio,SC/PARIS 2147,
------------------------

どうも、傾向として3等室で港とか年齢とか客室とか欠損データが多い人が予想をはずしているのね。それ以外はほぼランダム。
この3等室で生きている人を当てるのが難しい。

なので3等室でかつSVMが予想を外している人のリストを眺めます。
SVMが予想を外している人の特徴を特徴ベクトルとして入れる作戦。
おじさんにデータ解析ツールなんていらない。
おじさんはC言語とコンソールだけでいいもん。
おじさん、リストの文字と数値を眺めるだけで分析してやる。

リストを眺めると3等室でチケットの名前がPPで始まっている人と番号が1から始まている人が生存率が高そうなのでその人にフラグを立てます。

80.382775%

やったー、これで目標の80%越え達成です。
そうかぁ全項目使わないとだめなのね。
こんな感じで勝手な予想をたててKaggleは正解率を上げていくようです。

もうちょっと頑張ればもっと上がりそうだけど、とりあえず本日はここまで。
これをタイタニック以外の問題でやれば銅メダルがもらえるのね。
おじさんとりあえずは銅メダルはもらえそうなことはわかった。


------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


static char *strtokrev(char *s1, int s2) {
static char *str = 0;
int f = 0;

if (s1)str = s1;
else s1 = str;

if (!s1)return NULL;

while (1) {
if (!*str) {
str = 0;
return(s1);
}
if (*str == '\r' || *str == '\n') {
*str = 0;
str = 0;
return(s1);
}
if (*str == '\"' && f == 0) {
str++;
s1 = str;
f = 1;
continue;
}
if (*str == '\"' && f == 1 && *(str + 1) == '\"') {
str += 2;
continue;
}
if (*str == '\"' && f == 1) {
*str++ = 0;
f = 0;
continue;
}
if (*str == s2 && f == 0) {
*str++ = 0;
return(s1);
}
str++;
}
}


struct person{
int id;
int survive;
int cls;
char name[64];
int sex;
int age;
double s_age;
int sib;
int per;
int f_mr;
int f_mas;
char ticket[64];
char cabin[64];
double fare;
int emb;
int f_oth1;
int f_oth2;
int f_oth3;
};

struct person pli[1024];
struct person pli2[1024];

char* firstnum(const char* a)
{
if (a == NULL)return a;
while (*a) {
if (*a < '0') { a++; continue; }
if (*a > '9') { a++; continue; }
if (*(a+1) < '0') { a++; continue; }
if (*(a+1) > '9') { a++; continue; }
break;
}
return a;
}
void store(struct person* plist,int pos, int n, const char* str)
{
char buf[256];
char*p;
switch (n)
{
case 0:
sscanf(str, "%d", &(plist[pos].id));
break;
case 1:
sscanf(str, "%d", &(plist[pos].survive));
if (plist[pos].survive == 0)plist[pos].survive = -1;
break;
case 2:
sscanf(str, "%d", &(plist[pos].cls));
break;
case 3:
plist[pos].f_mr = 0;
if (strlen(str) < 64 - 1)strcpy(plist[pos].name, str);
if (strstr(plist[pos].name, "Mr."))plist[pos].f_mr = 1;
break;
case 4:
buf[0] = 0;
plist[pos].sex = -1;
if (strlen(str) < 64 - 1)strcpy(buf, str);
if(strstr(buf,"female"))plist[pos].sex = 1;
else if (strstr(buf, "male"))plist[pos].sex = -1;
break;
case 5:
plist[pos].age = -1;
sscanf(str, "%d", &(plist[pos].age));
break;
case 6:
sscanf(str, "%d", &(plist[pos].sib));
break;
case 7:
sscanf(str, "%d", &(plist[pos].per));
break;
case 8:
if (strlen(str) < 64 - 1)strcpy(plist[pos].ticket, str);
if (plist[pos].cls == 3) {
p = firstnum(plist[pos].ticket);
if (*p == '1') {
plist[pos].f_oth1 = 1;
}
if (plist[pos].ticket[0]=='P') {
plist[pos].f_oth1 = 1;
}
}

break;
case 9:
sscanf(str, "%lf", &(plist[pos].fare));
break;
case 10:
if (strlen(str) < 64 - 1)strcpy(plist[pos].cabin, str);
plist[pos].f_mas = 0;
if (strchr(str, 'A'))plist[pos].f_mas = 1;
if (strchr(str, 'B'))plist[pos].f_mas = 1;
if (strchr(str, 'C'))plist[pos].f_mas = 1;
break;
case 11:
plist[pos].emb = 1;
if (strchr(str, 'S'))plist[pos].emb = 1;
if (strchr(str, 'C'))plist[pos].emb = 0;
if (strchr(str, 'Q'))plist[pos].emb = -1;
break;
default:
break;
}
}
int read_plist(struct person* plist,const char* fn,int ff)
{
FILE *fp=NULL;
char buf[256];
int i, f, id, re, ct = 0;
char *p,*q;

int ct2=0;
static double ave,dmax = 0, dmin = 1000,sub=0;

fp = fopen(fn,"rb");
if (fp == NULL)goto end;
fgets(buf, sizeof(buf), fp);
while (1) {
buf[0] = 0;
fgets(buf, sizeof(buf), fp);
if (buf[0] == 0)break;
for (i = 0; i < 14; i++) {
p = buf;
if (i != 0)p = NULL;
if (ff && i == 1)continue;
q = strtokrev(p, ',');
if (q == NULL)q = "";
store(plist,ct,i, q);
}
ct++;
}
if (ff == 0) {
for (i = 0; i < ct; i++) {
if (plist[i].age == -1)continue;
ct2++;
sub += plist[i].age;
if (plist[i].age > dmax)dmax = plist[i].age;
if (plist[i].age < dmin)dmin = plist[i].age;
}
ave = sub; ave /= ct2;
}
//printf("ave=%f\n",ave);
for (i = 0; i < ct; i++) {
if (plist[i].age == -1) {
plist[i].s_age = ave;
}
else plist[i].s_age = plist[i].age;

plist[i].s_age = (plist[i].s_age - dmin)*2/dmax-1;
}

end:
if(fp)fclose(fp);
return 0;
}

void print_plist(struct person* plist,FILE* fd)
{
int i;
if (fd == NULL)return;
for (i = 0; i < 1024; i++) {
if (plist[i].id == 0)break;
fprintf(fd, "%d 1:%d 2:%d 3:%d 4:%f 5:%d 6:%d 7:%f 8:%d 9:%d\n",
plist[i].survive, plist[i].cls, plist[i].f_mr, plist[i].sex, plist[i].s_age,
plist[i].sib + plist[i].per + 1, plist[i].f_mas, plist[i].fare, plist[i].emb,plist[i].f_oth1);
}
}

void comp(const char* fn1,const char* fn2)
{
FILE *f1 = NULL, *f2 = NULL;
char buf1[256];
char buf2[256];
int ct = 0;
int ok = 0;
double d1, d2;
int id, f;
double per;
f1 = fopen(fn1, "rt");
f2 = fopen(fn2, "rt");
if (f1 == NULL || f2 == NULL)goto err;

fgets(buf1, sizeof(buf1), f1);
while (1) {
buf1[0] = 0;
buf2[0] = 0;
d1 = 0;
d2 = 0;
f = 0;
fgets(buf1, sizeof(buf1), f1);
fgets(buf2, sizeof(buf2), f2);
if (buf1[0] == 0 || buf2[0] == 0)break;
sscanf(buf1, "%d,%lf", &id, &d1);
sscanf(buf2, "%lf", &d2);
if (d1 == 0)d1 = -1;

if (d1 > 0 && d2 > 0)f = 1;
if (d1 < 0 && d2 < 0)f = 1;
if (f)ok++;
if (f == 0) {
printf("%d,%s,%1lf,%1lf,%0.3lf,%d,%d,%s,%s,%s\n", 892 + ct, f ? "OK" : "NG",d1, d2,
pli2[ct].s_age,pli2[ct].cls, pli2[ct].sib+pli2[ct].per+1,
pli2[ct].name,pli2[ct].ticket, pli2[ct].cabin);
}
ct++;
}
per = ok * 100;
per /= ct;
printf("ct=%d  ok=%d  %f%%\n", ct, ok, per);
err:
if (f1)fclose(f1);
if (f2)fclose(f2);
}



int main()
{
FILE* fp;
read_plist(pli,"train.csv",0);
read_plist(pli2,"test.csv",1);
fp = fopen("yomei_train.csv","wb");
print_plist(pli,fp);
if (fp)fclose(fp);
fp = fopen("yomei_test.csv", "wb");
print_plist(pli2, fp);
if (fp)fclose(fp);
//printf("----------pli\n");
//print_plist(pli, stdout);
//printf("----------pli2\n");
//print_plist(pli2, stdout);
system("svm-scale -s yomei_scale.txt yomei_train.csv  > yomei_train_scale.csv");
system("svm-scale -r yomei_scale.txt yomei_test.csv > yomei_test_scale.csv");
system("svm-train yomei_train_scale.csv yomei_model.txt");
system("svm-predict yomei_test_scale.csv yomei_model.txt yomei_predict.csv");

comp("gender_submission2.csv", "yomei_predict.csv");
return 0;
}
------------------------



0 件のコメント:

コメントを投稿