2022年2月3日木曜日

XGBoostでMNISTをする。

 おじさん、lightGBMでMNISTができたので、今度はもう一つの勾配ブースト木ライブラリのxgboostも試してみたくなりました。

ということで、今日はXGBoostでMNISTをします。



昨日の深夜にXGBoostがビルドできたので、今日は朝5時からXGBoostの使い方を勉強。

朝8時ごろにXGBoostのMNISTができました。

その後学習をしている時間にこのブログを書いています。


XGBoostは入門者やC言語のドキュメントがしっかりしているので、ほとんど何も問題なくMNISTを作ることができました。

はじめにlightGBMよりこっちを勉強すればよかった。


だけれど、やっぱりネットに書かてれいる通り、学習が遅い。

数分で終わるlightGBMに比べてこちらは1/3のイテレーションでも学習に30分以上かかります。

最初止まっているんじゃないないかと思ったくらい。

とても150回イテレーションを回す気がしない。

50回だと判別間違ってるし。

これでは、遅すぎて耐えられない。

プログラムやデータ分析をする気がなくなる。



ソースコード

-------------------------------

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "xgboost_c_api.h"


#define TRAIN_IMAGE "train-images-idx3-ubyte"

#define TRAIN_LABEL "train-labels-idx1-ubyte"

#define TEST_IMAGE "t10k-images-idx3-ubyte"

#define TEST_LABEL "t10k-labels-idx1-ubyte"


float data[] = {


0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,


0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,


0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,


0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,


};




struct tensor {

float* data;

int cols;

int rows;

};


static struct tensor* create_tensor(int rows, int cols) {

struct tensor* ret;

ret = (struct tensor*)malloc(sizeof(struct tensor));

ret->data = (float*)malloc(sizeof(float) * rows * cols);

memset(ret->data, 0, sizeof(float) * rows * cols);

ret->cols = cols; ret->rows = rows;

return ret;

}

static void free_tensor(struct tensor* t)

{

if (t && t->data)free(t->data);

if (t)free(t);

}




static int buf2int(char* buf_) {

int ret;

unsigned char* buf = (unsigned char*)buf_;


ret = buf[0]; ret <<= 8; ret |= buf[1]; ret <<= 8;

ret |= buf[2]; ret <<= 8; ret |= buf[3];

return ret;

}

static struct tensor* load_image_file(const char* fn)

{

struct tensor* ret = NULL;

FILE* fp;

int sz, t, w, h, n, i, j;

char buf[4];


fp = fopen(fn, "rb");

if (fp == NULL)goto end;

fseek(fp, 0, SEEK_END);

sz = ftell(fp);

fseek(fp, 0, SEEK_SET);


fread(buf, 1, 4, fp);

t = buf2int(buf);

if (t != 0x803)goto end;


fread(buf, 1, 4, fp);

n = buf2int(buf);

fread(buf, 1, 4, fp);

w = buf2int(buf);

fread(buf, 1, 4, fp);

h = buf2int(buf);

if (h * w != 784)goto end;


ret = create_tensor(n, 784);

for (i = 0; i < n; i++) {

for (j = 0; j < 784; j++) {

fread(buf, 1, 1, fp);

ret->data[i * 784 + j] = (float)(buf[0] & 255);

}

}

end:

if (fp)fclose(fp);

return ret;

}



static struct tensor* load_label_file(const char* fn)

{

struct tensor* ret = NULL;

FILE* fp;

int sz, t, n, i, j;

char buf[4];


fp = fopen(fn, "rb");

if (fp == NULL)goto end;

fseek(fp, 0, SEEK_END);

sz = ftell(fp);

fseek(fp, 0, SEEK_SET);


fread(buf, 1, 4, fp);

t = buf2int(buf);

if (t != 0x801)goto end;


fread(buf, 1, 4, fp);

n = buf2int(buf);

ret = create_tensor(n, 1);

for (i = 0; i < n; i++) {

fread(buf, 1, 1, fp);

ret->data[i] = (float)buf[0];

}

end:

if (fp)fclose(fp);

return ret;

}




int main(int argc, char *argv[])

{

struct tensor* x_train, * x_test;

struct tensor* y_train, * y_test;


x_train = load_image_file(TRAIN_IMAGE);

y_train = load_label_file(TRAIN_LABEL);

x_test = load_image_file(TEST_IMAGE);

y_test = load_label_file(TEST_LABEL);


int ret;

DMatrixHandle hx_train;

DMatrixHandle hx_test;

DMatrixHandle h_test;

BoosterHandle booster;


ret = XGDMatrixCreateFromMat(x_train->data, x_train->rows, x_train->cols, -1, &hx_train);

if (ret) {

printf("Error: XGDMatrixCreateFromMat()\n");

return 1;

}

ret = XGDMatrixSetFloatInfo(hx_train, "label", y_train->data, y_train->rows);

if (ret) {

printf("Error: XGDMatrixSetFloatInfo()\n");

return 1;

}


ret = XGDMatrixCreateFromMat(x_test->data, x_test->rows, x_test->cols, -1, &hx_test);

if (ret) {

printf("Error: XGDMatrixCreateFromMat()\n");

return 1;

}

ret = XGDMatrixSetFloatInfo(hx_test, "label", y_test->data, y_test->rows);

if (ret) {

printf("Error: XGDMatrixSetFloatInfo()\n");

return 1;

}

ret = XGDMatrixCreateFromMat(data, 1,784, -1, &h_test);

if (ret) {

printf("Error: XGDMatrixCreateFromMat()\n");

return 1;

}


const int eval_dmats_size = 2;

DMatrixHandle eval_dmats[eval_dmats_size] = { hx_train, hx_test };

ret=XGBoosterCreate(eval_dmats, eval_dmats_size, &booster);

if (ret) {

printf("Error: XGBoosterCreate()\n");

return 1;

}

ret = XGBoosterSetParam(booster, "objective", "multi:softprob");

if (ret) {

printf("Error: XGBoosterSetParam()\n");

return 1;

}

ret = XGBoosterSetParam(booster, "num_class", "10");

if (ret) {

printf("Error: XGBoosterSetParam()\n");

return 1;

}


int num_of_iterations = 50;

const char* eval_names[eval_dmats_size] = { "train", "test" };

const char* eval_result = NULL;

for (int i = 0; i < num_of_iterations; ++i) {

ret=XGBoosterUpdateOneIter(booster, i, hx_train);

if (ret) {

printf("Error: XGBoosterUpdateOneIter()\n");

return 1;

}

ret=XGBoosterEvalOneIter(booster, i, eval_dmats, eval_names, eval_dmats_size, &eval_result);

if (ret) {

printf("Error: XGBoosterEvalOneIter()\n");

return 1;

}

printf("%s\n", eval_result);

}


bst_ulong output_length=0;

const float* output_result=NULL;

ret=XGBoosterPredict(booster, h_test, 0, 0,0, &output_length, &output_result);

for (unsigned int i = 0; i < output_length; i++) {

printf("prediction[%i] = %f \n", i, output_result[i]);

}


XGBoosterFree(booster);

XGDMatrixFree(hx_train);

XGDMatrixFree(hx_test);

free_tensor(x_train); free_tensor(y_train);

free_tensor(x_test); free_tensor(y_test);


return 0;

}

-------------------------------



結果

-------------------------------

[07:53:35] WARNING: C:\trash\lightgbm\xgboost_mnist\src\learner.cc:1115: Starting in XGBoost 1.3.0, the default evaluation metric used with the objective 'multi:softprob' was changed from 'merror' to 'mlogloss'. Explicitly set eval_metric if you'd like to restore the old behavior.

[0]     train-mlogloss:1.356904 test-mlogloss:1.367719

[1]     train-mlogloss:1.026020 test-mlogloss:1.046251

...

[19]    train-mlogloss:0.089134 test-mlogloss:0.156737


prediction[0] = 0.027325

prediction[1] = 0.038958

prediction[2] = 0.124319

prediction[3] = 0.109822

prediction[4] = 0.223622

prediction[5] = 0.294601

prediction[6] = 0.042664

prediction[7] = 0.056748

prediction[8] = 0.043369

prediction[9] = 0.038572

-------------------------------


0 件のコメント:

コメントを投稿