2022年2月22日火曜日

株価指数を計算する。

 おじさん、今週は株価指数を計算するライブラリを作成しています。


株価指数って、まずTOPIXが基本らしい。

株系のWebページって結構みんな読まれるためか、いろいろな人がいろいろなことを書いているのですが、結構適当な記事が多いです。


ある経済ライターさんのページには以下のように書かれています。

https://seikeidenron.jp/articles/584

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

景気を知るためにもう一つ覚えておきたいのが「TOPIX(東証株価指数)」。

こちらは、東証一部に上場しているすべての銘柄の時価総額(株価×発行済株式数)を足して、銘柄数で割ったものだ。

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


平均だから銘柄数で割ったら平均になりそうだけどね。

うそつきー。うそのこと書くなよ!

景気を知る前に株価指数のこと知れよ!!!!



おじさんがプログラムで計算した式は、


(今の浮遊株時価総額)÷(昔の浮遊株時価総額)×(100または1000)

(浮遊株時価総額)=(浮遊株数)×(終値)


だぞ!


おじさんも二週間、朝から晩までプログラム書いて株価指数の計算方法がわかったので、こういう嘘のことを書いているのがわかるようになりました。

おじさんの勉強では平均株価ってだいたい「浮動株基準時価総額加重平均型株価」って方法で計算するらしい。


https://ja.wikipedia.org/wiki/%E6%99%82%E4%BE%A1%E7%B7%8F%E9%A1%8D%E5%8A%A0%E9%87%8D%E5%B9%B3%E5%9D%87%E5%9E%8B%E6%A0%AA%E4%BE%A1%E6%8C%87%E6%95%B0


でもこの株価指数の計算ってなかなか大変。

浮遊株数とか基準時時価総額とかの具体的な計算例や一覧データはどこにもフリーのデータがありません。

東証から月3300円で入手しないといけないっぽいです。

10年分とると40万円いるじゃないか!

うそ書いてるやると金とるやつしかいない・・・・。

なんという厳しい世界。


TOPIXでさえ、株価指数の計算の仕方が正確に書かれていないので、おじさんきちんとTOPIXを求めてみました。

浮遊株数ってどうやって計算するんだろ?

おじさん頑張ってフリーのデータから基準時時価総額と浮遊株数を計算する方法を見つけました。



まず、東京証券取引所からTOPIXの銘柄別のウェイト情報を入手

https://www.jpx.co.jp/markets/indices/topix/index.html

構成銘柄別ウエイト一覧


つぎに、年末の浮遊株時価総額と基準時時価総額を入手。

https://www.jpx.co.jp/markets/indices/related/value/index.html

2021年12月末現在



上記の二個のファイルから、TOPIX時価総額にウェイトをかけて各銘柄の浮遊株時価総額を計算。

浮遊株時価総額をその日の終値で割って、浮遊株式数を逆計算で取得。

浮遊株式数から株価指数を計算。


さらに実際には、銘柄変更、上場廃止、一時取引停止、株式分割などいろいろなイベントが毎週あるので、これらのイベントに対応し計算しないといけないためかなりめんどくさい。


でもこの方法で業種別の株価指数を計算できるようになりました。

これでただで業種別株価指数を使ってAIで株価分析してやる。



ソースはこちら。

https://github.com/yomei-o/Protra_cpp





2022年2月16日水曜日

33業種データベースを作る。

 おじさん、以下のサイトで株価はマーケットや業種ごとに傾向がことなることを勉強しました。

https://qiita.com/blog_UKI/items/25dc1c2559c61890a449

なるほど、ウイリアム・シャープっていうノーベル賞を受賞したおちゃんが言っているのね。

https://ja.wikipedia.org/wiki/%E8%B3%87%E6%9C%AC%E8%B3%87%E7%94%A3%E4%BE%A1%E6%A0%BC%E3%83%A2%E3%83%87%E3%83%AB


何言ってるのかよくわからん。

けど、機械学習とかって論文や資料が全部英語なんだけど、金融経済分野って資料が全部日本語に翻訳されている・・・。

きっとこの分野、お金が有り余ってるに違いない。


株のリターンを計算するには、上場企業の「業種」やどのマーケットに上場しているのかのデータが必要らしいです。

Protraの上場企業データベースには、上場しているマーケット情報はあるのですが、業種のデータベースがありません。なので、本日は上場企業の業種のデータベースを作ろうと思ういます。


上場企業の業種の一覧ってどこにあるんだろ?

調べてみると、東京証券取引所にあるみたい。



https://www.jpx.co.jp/markets/statistics-equities/misc/01.html

ここにいろんな企業の株に関するデータがありました。

ここの東証上場銘柄一覧というエクセルの中に業種があるのね。


しかしこのエクセル、「食品    」のように業種の文字のあとにスペースが入ってる・・・。

たしかに見た感じわかんないひっかけだけど、微妙に間違ってるのね。

金融とか証券ってこういうの間違っちゃいけないと思うんだけど・・・。

きっと誰もこのエクセル使っていないのね。


エクセルを見ると、「17業種コード」と「33業種コード」があるらしい。

「17業種コード」は1から連番なのですが、「33業種コード」は7250とか意味不明な数字が・・・

図書館の本の分類の日本十進分類だって連番なのに、Kaggleのようにあちこちにいろんな罠があります。

https://ja.wikipedia.org/wiki/%E6%97%A5%E6%9C%AC%E5%8D%81%E9%80%B2%E5%88%86%E9%A1%9E%E6%B3%95


こういう不連続なデータをきちんと機械学習できるように連番にしていきます。

データを正確に分類するのって結構大変なのね。


ということで、いろいろ罠があり時間がかかってしまいましたが、上場企業の業種のライブラリができた!


https://github.com/yomei-o/Protra_cpp/blob/main/src/Industory.h




2022年2月14日月曜日

ローソク足を表示する

 おじさん、今日はどうやってJavaScriptで株価のローソク足を描画するのか調べています。

日経平均株価のリアルタイム表示サイトとかで使われている赤と緑のグラフのやつね。

デフォルトのChart.jsだとローソク足表示はできないらしい。

だけど、なかなかあれと同じようなちょうどいいライブラリがないねぇ。


いろいろ試してみると、このライブラリが一番きれいにローソク足が表示できそう。

https://github.com/chartjs/chartjs-chart-financial/tree/master/docs

Chart.jsのプラグインになっているようです。



思う通りの日経平均株価のローソク足表示ができた。
おじさんシステムトレードのプログラム作るより、証券会社のWebページを作った方が儲かるんじゃないかと思えてきました。
自分で作って分かったのですが、証券会社のWebページって結構製作難易度高いように思ういます。
みんなどのように作っているのでしょうね?

ソースコードはこちら

2022年2月10日木曜日

残差プロットをする。

おじさん、先日作ったlightgbmの住宅価格の予想プログラムを任意のCSVファイルを読めるように少し改造してました。

あとモデルデータの保存と読み込みもできるようにしました。

でもどうしても学習の結果が正しいかどうかなかなかわからない。

プログラムにバグがないことを確認することはほんと至難の業。


いろいろ考えた結果、よく知られているデータの学習結果を残差プロット表示すればわかるんじゃないかと思いつきました。

PandasやR言語でグラフ表示すると結局別のプログラムしないといけないし。

よく考えて、今週は機械学習のデータのグラフ表示のJavascriptライブラリを作ってみました。

いつものようにC++からJavaScriptを生成。

全部C++で行います。


JavaScriptで計算すると遅いのかと思ったのですが、ChromeのJavaScriptってめちゃくちゃ高速なのね。

あまりの速さにびっくり。

相関係数とか行列操作のJavaScriptrの統計ライブラリも作ったので、ブラウザでさくさくCSVファイルを読み込んで相関行列とか残差プロットとかが表示できるようになりました。



先日作った、おじさんのlightgbmのプログラムの、ボストンの住宅価格の残差プロットを作ってみました。
おー、ネットに落っこちている図と同じになった。
右下の部分にある謎の直線上の点が同じ。

ということは、先日作ったおじさんのlightgbmのプログラムや今週作ったJavaScriptの統計ライブラリは正しいっぽい。
モデルデータの保存と読み込みやCSVファイルの処理もあってそう。
しかもおじさんの方が右下部分の点の数が少ないからある意味正確??
おじさんのデータだと10以上外したの二つしかないし。

学習アルゴリズムが多少違っても、どちらもある程度正しく学習できていれば、残差プロットの特徴ってだいたい一致するのね。


残差プロットってこういう具合にプログラムにバグがないかを判断するのにも使えるのね。

勉強になるねぇ。

これで、いろんな株価の特徴データのCSVファイルを作れば、ブラウザベースで株価のAIデータ解析ができて、学習が正しいかわかるはず。

ソースコードはこちら

https://github.com/yomei-o/Protra_cpp/tree/main/server/scatter_plot

2022年2月6日日曜日

c++でデータマイニングをする。

 おじさん、先週は勾配ブーストの機械学習ライブラリの使い方がわかったので、今週はデータマイニングのやり方を勉強します。


データマイニングって意味がよくわからないし。日本語で言うと統計解析?

統計解析とデータマイニングは違うといってる人もいるし。

データマイニングとは、上の図のように相関行列を求めたりしてデータの中から意味のある情報を取りだすことらしいです。

そしてその手法が統計解析っぽいです。

PythonのPandasなどの統計解析のライブラリを使うと上の図のような相関行列を簡単に作り出せます。

なんかデータマイニングしてる感じが出てかっこいいね。


そもそも統計解析はR言語やPythonを使って行うのが一般的なのですが、R言語とかでやると遅いらしく、海外ではC++で高速に行ったりもしています。

でもC++で統計解析を行っている日本語の記事が一つもない。

どうやってC++で統計解析をやるのか日本語で正しく書かれているサイトがひとつもないのです。

さみしいなぁ。

日本の金融業界とか証券業界ってどうやって統計解析をやっているのでしょうか?

きっと外部に丸投げ?

ということで、今日はC++で統計解析を行って相関係数を求めてみたいと思います。


C++で統計解析を行うには、DataFrameというライブラリを使用します。

https://github.com/hosseinmoein/DataFrame

これ名前がよくなくて、DetaFrameなんていう一般的によく使われる単語の組み合わせなので、なかなか検索で出てきません。

でもこれを使うと簡単に相関係数を求めることができます。


統計解析のライブラリってどれもだいぶ癖が強めです。

というかDetaFrameという概念に癖がありますね。

普通、データをCSVファイルとかで読むときとかは、まず行を読んでそのあと列に分割して処理するのですが、行を中心に行います。

しかし、統計解析って列選択して統計処理を行うので行と列が逆なのです。。

そもそも英語でcolとrowどっちがどっちかわからないし。

年を取ってくると頭が固くなってこういう柔軟な思考に頭が瞬時に追いつかない。

でもDetaFrameの使い方がわかれば、ついでにR言語やPandasの使い方もわかります。


いろいろ書きましたが、C++でDetaFrameのライブラリを使ってボストンの住宅価格の相関行列を求めてみました。



ソースコード

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

#include <stdio.h>

#include <iostream>

#include <stdexcept>


#include <DataFrame_DataFrame.h>


using namespace hmdf;

using MyDataFrame = StdDataFrame<int>;


template<class T> inline std::vector<std::string> split(const std::string& s, const T& separator, bool ignore_empty = 0, bool split_empty = 0) {

struct {

auto len(const std::string& s) { return s.length(); }

auto len(const std::string::value_type* p) { return p ? std::char_traits<std::string::value_type>::length(p) : 0; }

auto len(const std::string::value_type  c) { return c == std::string::value_type() ? 0 : 1; /*return 1;*/ }

} util;


if (s.empty()) { /// empty string ///

if (!split_empty || util.len(separator)) return { "" };

return {};

}


auto v = std::vector<std::string>();

auto n = static_cast<std::string::size_type>(util.len(separator));

if (n == 0) {    /// empty separator ///

if (!split_empty) return { s };

for (auto&& c : s) v.emplace_back(1, c);

return v;

}


auto p = std::string::size_type(0);

while (1) {      /// split with separator ///

auto pos = s.find(separator, p);

if (pos == std::string::npos) {

if (ignore_empty && p - n + 1 == s.size()) break;

v.emplace_back(s.begin() + p, s.end());

break;

}

if (!ignore_empty || p != pos)

v.emplace_back(s.begin() + p, s.begin() + pos);

p = pos + n;

}

return v;

}


struct datapair {

float* data;

float* label;

int rows;

int cols;

};


struct datapair* readboston(const char* fn)

{

FILE* fp;

struct datapair* ret = NULL;

char buf[256];

std::string str;

std::vector<std::string> rows;

std::vector<std::string> cols;

fp = fopen(fn, "rt");

if (fp == NULL)return ret;

while (1) {

buf[0] = 0;

fgets(buf, sizeof(buf), fp);

if (buf[0] == 0)break;

str = buf;

rows.push_back(str);

}

ret = new(struct  datapair);

ret->cols = 13;

ret->rows = rows.size();

ret->data = new float[13 * rows.size()];

ret->label = new float[rows.size()];


for (int i = 0; i < rows.size(); i++) {

cols = split(rows[i], " ", 1, 1);

if (cols.size() < 14)continue;

for (int j = 0; j < 13; j++) {

ret->data[13 * i + j] = std::stod(cols[j]);

}

ret->label[i] = std::stod(cols[13]);

}

return ret;

}


void freedata(struct datapair* d)

{

if (d == nullptr)return;

delete[] d->data;

delete[] d->label;

delete d;

}



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

{

    MyDataFrame df;

    std::vector<int> index;

    std::vector<float> tmp;

    StatsVisitor<float>    stats_visitor;

std::vector<std::string> col_lbl;

char col_name[256];

struct datapair* dp;

int ret;


dp = readboston("housing.data");

for (int j = 0; j < dp->rows; j++) {

index.push_back(j);

}

df.load_index(std::move(index));


for (int j = 0; j < dp->cols; j++) {

sprintf(col_name, "col_%d", j);

tmp.clear();

for (int i = 0; i < dp->rows; i++) {

tmp.push_back(dp->data[j+i*dp->cols]);

}

col_lbl.push_back(col_name);

df.load_column<float>(col_name, std::move(tmp));

}


sprintf(col_name, "col_%d", 24);

tmp.clear();

for (int j = 0; j < dp->rows; j++) {

tmp.push_back(dp->label[j]);

}

df.load_column<float>(col_name, std::move(tmp));

col_lbl.push_back(col_name);


CorrVisitor<float> corr_visitor;

for (int j = 0; j < dp->cols + 1; j++) {

for (int i = 0; i < dp->cols + 1; i++) {

printf("+-----");

}

printf("+\n");

for (int i = 0; i < dp->cols + 1; i++) {

auto fut10 = df.visit<float, float>(col_lbl[i].c_str(), col_lbl[j].c_str(), corr_visitor);

float res = corr_visitor.get_result();

printf("|%5.2f", res);

}

printf("|\n");

}

for (int i = 0; i < dp->cols + 1; i++) {

printf("+-----");

}

printf("+\n");

return 0;

}


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


結果


これでC++を使ってプログラムで自動でデータマイニングができそう。


2022年2月4日金曜日

lightGBMで回帰分析をする。

 おじさん、毎日システムトレードに向けてプログラムを勉強しています。

株価の予想ってたぶん回帰分析なので、本日はlightGBMで回帰分析をしてみます。


回帰分析と言えば、ボストンの住宅価格予想!

アメリカのボストンの住宅のデータをもとにその価格を予想する定番のやつです。

これを住宅データの代わりに株のデータにすれば、株価の予想ができるはず。



むかし、このブログでもタイタニックの生存者の判定とかマンションの価格推定とかをやりました。

混同行列の図を見ればわかりますが、このふざけた複雑な相関関係。

いかにも普通のプログラムでは難しそう。でも原理は全く同じです。


作ってみてわかったのですが、先日作ったlightGBMのMNISTのソースコードをほんの少し直すだけで、住宅価格の回帰分析ができます。

学習の関数に渡すパラメーターを変えるだけでいろんなタイプの学習ができるんですね。

これはすごい。

たぶん、株価の予想もこれを少し直すだけできっとできるようになるんですね。


ネットでも書かれている通り、回帰分析って作ったプログラムの結果が正しいかどうか結果の数値だけからはなかなかわからない。

解けた感が全くありません。

むしろこれが本当に正しいのかという猜疑心が常にわいてきます。

同じデータを別のプログラムでもう一つ作らないと正しいことがわからないのです。

おじさんもネットに落ちていたPythonのlightGBMのボストンの住宅価格のプログラムの結果と比較して自分のプログラムが正しいことを確かめました。

いろいろ勉強になるね。


ソースコード

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

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <string>

#include <vector>

#include "LightGBM/c_api.h"



template<class T> inline std::vector<std::string> split(const std::string& s, const T& separator, bool ignore_empty = 0, bool split_empty = 0) {

struct {

auto len(const std::string& s) { return s.length(); }

auto len(const std::string::value_type* p) { return p ? std::char_traits<std::string::value_type>::length(p) : 0; }

auto len(const std::string::value_type  c) { return c == std::string::value_type() ? 0 : 1; /*return 1;*/ }

} util;


if (s.empty()) { /// empty string ///

if (!split_empty || util.len(separator)) return { "" };

return {};

}


auto v = std::vector<std::string>();

auto n = static_cast<std::string::size_type>(util.len(separator));

if (n == 0) {    /// empty separator ///

if (!split_empty) return { s };

for (auto&& c : s) v.emplace_back(1, c);

return v;

}


auto p = std::string::size_type(0);

while (1) {      /// split with separator ///

auto pos = s.find(separator, p);

if (pos == std::string::npos) {

if (ignore_empty && p - n + 1 == s.size()) break;

v.emplace_back(s.begin() + p, s.end());

break;

}

if (!ignore_empty || p != pos)

v.emplace_back(s.begin() + p, s.begin() + pos);

p = pos + n;

}

return v;

}


struct datapair {

float* data;

float* label;

int rows;

int cols;

};


struct datapair* readboston(const char* fn)

{

FILE* fp;

struct datapair * ret = NULL;

char buf[256];

std::string str;

std::vector<std::string> rows;

std::vector<std::string> cols;

fp = fopen(fn, "rt");

if (fp == NULL)return ret;

while (1) {

buf[0] = 0;

fgets(buf, sizeof(buf), fp);

if (buf[0] == 0)break;

str = buf;

rows.push_back(str);

}

ret = new(struct  datapair);

ret->cols = 13;

ret->rows = rows.size();

ret->data = new float[13*rows.size()];

ret->label = new float[rows.size()];


for(int i=0;i<rows.size();i++){

cols=split(rows[i], " ", 1, 1);

if (cols.size() < 14)continue;

for (int j = 0; j < 13; j++) {

ret->data[13*i+j]=std::stod(cols[j]);

}

ret->label[i]= std::stod(cols[13]);

}

return ret;

}


void freedata(struct datapair*d)

{

if (d == nullptr)return;

delete[] d->data;

delete[] d->label;

delete d;

}


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

{

int ret;


DatasetHandle hx_train, hx_test;

struct datapair* dp;



dp=readboston("housing.data");

int pos = dp->rows * 0.8;

int n = dp->rows - pos;


#if 0

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

printf("%d ",i);

for (int j = 0; j < 13; j++)printf("%f ",dp->data[i*13+j]);

printf(">>%f\n",dp->label[i]);

}

#endif


ret = LGBM_DatasetCreateFromMat(dp->data, C_API_DTYPE_FLOAT32, pos,

dp->cols, 1, "", nullptr, &hx_train);

if (ret) {

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

return 1;

}

ret = LGBM_DatasetSetField(hx_train, "label", dp->label, pos, C_API_DTYPE_FLOAT32);

if (ret) {

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

return 1;

}


ret = LGBM_DatasetCreateFromMat(&dp->data[dp->cols*pos], C_API_DTYPE_FLOAT32, n,

dp->cols, 1, "", hx_train, &hx_test);

if (ret) {

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

return 1;

}

ret = LGBM_DatasetSetField(hx_test, "label", &dp->label[pos], n, C_API_DTYPE_FLOAT32);

if (ret) {

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

return 1;

}


printf("Create Data OK!!\n");


BoosterHandle bh;

ret = LGBM_BoosterCreate(hx_train, "objective=regression "

"metric=rmse", &bh);

if (ret) {

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

return 1;

}


ret = LGBM_BoosterAddValidData(bh, hx_test);

if (ret) {

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

return 1;

}


int is_finished = 0;

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

double d = 0;

ret = LGBM_BoosterUpdateOneIter(bh, &is_finished);

if (ret) {

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

return 1;

}

int out_len = 10;

ret = LGBM_BoosterGetEval(bh, 1, &out_len, &d);

if (ret) {

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

return 1;

}

printf("%d %f\n",i,d);

}


printf("Update OK!!\n");


long long d_len = 1;

double d;


ret = LGBM_BoosterPredictForMat(bh, &dp->data[dp->cols * pos], C_API_DTYPE_FLOAT32, 1, 13,

1, C_API_PREDICT_NORMAL, 0, -1, "", &d_len, &d);

if (ret) {

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

return 1;

}

printf("input\n");

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

printf("%d  %f\n",i, dp->data[dp->cols * pos+i]);

}

printf("predict\n");

printf("d=%f\n", d);


LGBM_BoosterFree(bh);

LGBM_DatasetFree(hx_train);

LGBM_DatasetFree(hx_test);


freedata(dp);


return 0;

}

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



結果

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

Create Data OK!!
[LightGBM] [Warning] Auto-choosing row-wise multi-threading, the overhead of testing was 0.000566 seconds.
You can set `force_row_wise=true` to remove the overhead.
And if memory is not enough, you can set `force_col_wise=true`.
[LightGBM] [Info] Total Bins 1028
[LightGBM] [Info] Number of data points in the train set: 404, number of used features: 13
[LightGBM] [Info] Start training from score 24.175743
[LightGBM] [Warning] No further splits with positive gain, best gain: -inf
0 8.902198
[LightGBM] [Warning] No further splits with positive gain, best gain: -inf
1 8.128168
...
[LightGBM] [Warning] No further splits with positive gain, best gain: -inf
99 5.225559
Update OK!!
input
0  41.529202
1  0.000000
2  18.100000
3  0.000000
4  0.693000
5  5.531000
6  85.400002
7  1.607400
8  24.000000
9  666.000000
10  20.200001
11  329.459991
12  27.379999
predict
d=9.342857

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



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

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


2022年2月1日火曜日

lightGBMでMNISTをする。

おじさん、今月はシステムトレードの計算ができるようにするため、lightGBMの使い方を勉強し始めました。

ネットの情報ではlightGBMでMNISTができるらしい。

決定木でニューラルネットワークのようなことができるのね。

これは面白そう。

ということで、lightGBMの最初のプログラムでMNISTをやってみました。



しかし、Pythonのコードはたくさん落っこちているのですが、c++のサンプルコードはどこにも落ちていません。

マイクロソフトの公式サイトにもC++のサンプルがありません。

これ本当にC++でできんの?


一日中いろいろ試して、どうにか学習と予測のところまでC++でできました。

だけれど、C++だと学習がちょうどいいところで自動で終わってくれない。

このハイパーパラメータを自分で計算しないといけないっぽいです。

どうやって計算するんだ?


でもとりあえずできた。

実際にやってみてわかったのですが、lightGBMは他の機械学習のライブラリと比べてビルド時間や学習にかかる時間が圧倒的に速い。

調べてみると、MNISTもニューラルネットワークと比べて8倍くらい早いらしいです。

しかもMNISTのようにたくさんの次元をいれても高速。

これくらいさくさく学習できると、ストレスなくいろんな特徴量をいれることができますね。

Kaglleとかでみんなが使う理由がよくわかります。



ソースコード

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


#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "LightGBM/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[])

{

int ret;


DatasetHandle hx_train, hx_test;


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);



ret = LGBM_DatasetCreateFromMat(x_train->data, C_API_DTYPE_FLOAT32, x_train->rows,

x_train->cols, 1, "", nullptr, &hx_train);

if (ret) {

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

return 1;

}

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

if (ret) {

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

return 1;

}


ret = LGBM_DatasetCreateFromMat(x_test->data, C_API_DTYPE_FLOAT32, x_test->rows,

x_test->cols, 1, "", hx_train, &hx_test);

if (ret) {

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

return 1;

}

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

if (ret) {

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

return 1;

}


printf("Create Data OK!!\n");


BoosterHandle bh;

ret = LGBM_BoosterCreate(hx_train, "objective=multiclass "

"num_class=10 num_boost_round=300 "

"early_stopping_round=5", &bh);

if (ret) {

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

return 1;

}


ret = LGBM_BoosterAddValidData(bh, hx_test);

if (ret) {

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

return 1;

}


int is_finished = 0;

double d_min = 10;

int ct_min=0;

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

double d = 0;

ret = LGBM_BoosterUpdateOneIter(bh, &is_finished);

if (ret) {

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

return 1;

}

int out_len = 10;

ret = LGBM_BoosterGetEval(bh, 1, &out_len, &d);

if (ret) {

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

return 1;

}

printf("%d %f\n",i,d);

if (d < d_min) {

d_min = d;

ct_min = 0;

}

else {

ct_min++;

if (ct_min >= 5)break;

}

}


printf("Update OK!!\n");


long long d_len = 10;

double d[10];

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

data[j] = data[j] * 255;

}

ret = LGBM_BoosterPredictForMat(bh, data, C_API_DTYPE_FLOAT32, 1, 784,

1, C_API_PREDICT_NORMAL, 0, -1, "", &d_len, d);

if (ret) {

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

return 1;

}

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

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

}


LGBM_BoosterFree(bh);

LGBM_DatasetFree(hx_train);

LGBM_DatasetFree(hx_test);

        free_tensor(x_train); free_tensor(y_train);

free_tensor(x_test); free_tensor(y_test);

return 0;

}

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


結果

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

[LightGBM] [Info] Load from binary file x_train

Create Data OK!!

[LightGBM] [Warning] Auto-choosing col-wise multi-threading, the overhead of testing was 1.095544 seconds.

You can set `force_col_wise=true` to remove the overhead.

[LightGBM] [Info] Total Bins 109606

[LightGBM] [Info] Number of data points in the train set: 60000, number of used features: 629

[LightGBM] [Info] Start training from score -2.315501

[LightGBM] [Info] Start training from score -2.185988

[LightGBM] [Info] Start training from score -2.309610

[LightGBM] [Info] Start training from score -2.280987

[LightGBM] [Info] Start training from score -2.329271

[LightGBM] [Info] Start training from score -2.404064

[LightGBM] [Info] Start training from score -2.316346

[LightGBM] [Info] Start training from score -2.259366

[LightGBM] [Info] Start training from score -2.327732

[LightGBM] [Info] Start training from score -2.311121

0 1.679374

1 1.373263

2 1.159687

...

...

149 0.000824


Update OK!!


d[0]=0.000818

d[1]=0.000104

d[2]=0.236144

d[3]=0.014695

d[4]=0.573232

d[5]=0.003431

d[6]=0.016848

d[7]=0.002404

d[8]=0.142658

d[9]=0.009667

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


おー、なんかあってる。
でもCPPでlightGBMつかうの大変ね。