おじさん、毎日システムトレードに向けてプログラムを勉強しています。
株価の予想ってたぶん回帰分析なので、本日は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;
}
---------------------------------
---------------------------------
---------------------------------
0 件のコメント:
コメントを投稿