Weather casting with Machine Learning (SVM and SRNN).
Dependencies: EthernetInterface GraphicHandler NTPClient SRNN SVM SensorModule mbed-rtos mbed
Revision 5:b61f3f5b0fc8, committed 2015-02-19
- Comitter:
- yukari_hinata
- Date:
- Thu Feb 19 19:21:16 2015 +0000
- Parent:
- 4:00da8e8c7e2a
- Child:
- 6:29d393d430d0
- Commit message:
- Have a bug. This program CANNOT operate permanentry
Changed in this revision
--- a/GraphicHandler.lib Thu Feb 19 13:53:12 2015 +0000 +++ b/GraphicHandler.lib Thu Feb 19 19:21:16 2015 +0000 @@ -1,1 +1,1 @@ -GraphicHandler#4aacf35455da +http://developer.mbed.org/users/yukari_hinata/code/GraphicHandler/#4aacf35455da
--- a/SRNN.lib Thu Feb 19 13:53:12 2015 +0000 +++ b/SRNN.lib Thu Feb 19 19:21:16 2015 +0000 @@ -1,1 +1,1 @@ -SRNN#e97ccc643bf1 +http://developer.mbed.org/users/yukari_hinata/code/SRNN/#92ea6cefc6a5
--- a/SVM.lib Thu Feb 19 13:53:12 2015 +0000 +++ b/SVM.lib Thu Feb 19 19:21:16 2015 +0000 @@ -1,1 +1,1 @@ -SVM#792afbb0bcf3 +http://developer.mbed.org/users/yukari_hinata/code/SVM/#e7aa8d270f8b
--- a/SensorModule.lib Thu Feb 19 13:53:12 2015 +0000 +++ b/SensorModule.lib Thu Feb 19 19:21:16 2015 +0000 @@ -1,1 +1,1 @@ -SensorModule#c1c2c7c5fe82 +http://developer.mbed.org/users/yukari_hinata/code/SensorModule/#f37a8d2673cc
--- a/main.cpp Thu Feb 19 13:53:12 2015 +0000 +++ b/main.cpp Thu Feb 19 19:21:16 2015 +0000 @@ -1,6 +1,6 @@ #include "main.hpp" -LocalFileSystem *local_fs; // マウントポイントを定義(ディレクトリパスになる) +LocalFileSystem *local_fs; // マウントポイント // Pointer to Class instance (global) SRNN *srnn; @@ -16,8 +16,7 @@ float* new_predict_data; // 現在の予測結果 int* new_predict_weather; // 現在の予測天気 float* new_predict_probability; // 現在の予測天気の確率(厳密には,確率ではない...) -FILE* seqence_data_fp; // 系列データのファイルポインタ(SRNNと計器の記録に使う) -FILE* predict_data_fp; // 予測データ +float* srnn_sample_queue; // SRNNのサンプルキュー(サンキューキュー). volatile int ml_flag; time_t now_time; @@ -27,15 +26,15 @@ DigitalOut live_led(LED1); volatile int thread_count = 0; -int open_count = 0; +int num_data_line = 0; // 計器タスク void read_task(void const *arg) { - // char str_buf[BUF_SIZE]; + FILE* seqence_data_fp; - // データ更新 + // データ読み出し sensor_module->read_all_sensor(); new_seqence_data[TEMPERATURE] = sensor_module->get_temperture(); new_seqence_data[AIR_PRESSURE] = sensor_module->get_pressure(); @@ -43,6 +42,10 @@ printf("T:%f P:%f H:%f \r\n", new_seqence_data[TEMPERATURE], new_seqence_data[AIR_PRESSURE], new_seqence_data[HUMIDITY]); graphic_handler->set_now_data(new_seqence_data); + // サンプルのアップデート + update_srnn_sample(srnn_sample_queue, new_seqence_data); + + // ログの追加 seqence_data_fp = fopen( SEQUENCE_DATA_NAME, "a"); check_file_open( seqence_data_fp, SEQUENCE_DATA_NAME); @@ -52,115 +55,44 @@ new_seqence_data[TEMPERATURE], new_seqence_data[AIR_PRESSURE], new_seqence_data[HUMIDITY]); fclose( seqence_data_fp ); + // ログファイルの切り詰め + num_data_line++; + if ( num_data_line > SUITABLE_LOG_LENGTH ) { + // コメント:この関数はファイルポインタの開け閉めが激しい為, 頻繁に使うと落ちる可能性あり + truncate_data_file(SUITABLE_LOG_LENGTH); + } + } // 機械学習タスク void ml_task(void const *arg) { - // ローカル変数 - int line = 0, diff_line; - //float* srnn_sample = new float[LEN_DATA_SEQUENCE * DIM_SIGNAL]; // SRNNのサンプル - float srnn_sample[LEN_DATA_SEQUENCE * DIM_SIGNAL]; - // 読み込みバッファ - float buf_data[DIM_SIGNAL]; - char str_buf[BUF_SIZE], str_dummy[50], str_dum1[10], str_dum2[10], str_dum3[10]; - - printf("[%d] M.L.S.T.A.R.T \r\n", thread_count++); - - // 3. SRNNに学習データを読み込ませる. - printf("Set SRNN sample... %02d:%02d \r\n", local_time_p->tm_hour, local_time_p->tm_min); - seqence_data_fp = fopen( SEQUENCE_DATA_NAME, "r"); - check_file_open( seqence_data_fp, SEQUENCE_DATA_NAME); - // まず、行数を数える - line = 0; - while( fgets( str_buf, BUF_SIZE, seqence_data_fp) != NULL ) { - line++; - } - printf(" line : %d \r\n", line); - // 差分行の計算 - diff_line = (line - LEN_DATA_SEQUENCE); - rewind( seqence_data_fp ); - printf(" go to line : %d \r\n", diff_line); - line = 0; - // 差分行までfpを移動 - fflush( seqence_data_fp ); - while( fgets( str_buf, BUF_SIZE, seqence_data_fp) != NULL ) { - line++; - if ( line == diff_line ) break; - } - // 最新LEN_DATA_SEQUENCE個のデータを読み込む. - line = 0; - /* - while( ( ret = fscanf( seqence_data_fp, " %[^\n,],%f,%f,%f", str_buf, &(buf_data[0]), &(buf_data[1]), &(buf_data[2])) ) != EOF ) { - if (line == LEN_DATA_SEQUENCE) break; - memcpy(&(srnn_sample[line * DIM_SIGNAL]), buf_data, sizeof(float) * DIM_SIGNAL); - printf("sample %d : %s %f %f %f \r\n", diff_line + line, str_buf, MATRIX_AT(srnn_sample,DIM_SIGNAL,line,0), MATRIX_AT(srnn_sample,DIM_SIGNAL,line,1), MATRIX_AT(srnn_sample,DIM_SIGNAL,line,2)); - line++; - } - */ + // キューからサンプルセット + srnn->set_sample(srnn_sample_queue); - while( fgets( str_buf, BUF_SIZE, seqence_data_fp) != NULL ) { - if (line == LEN_DATA_SEQUENCE) break; - if (open_count > 20) - printf("%d %s \r", line, str_buf); - - //sscanf( str_buf, " %[^\n,],%f,%f,%f", str_buf, &(buf_data[0]), &(buf_data[1]), &(buf_data[2])) ) - sscanf( str_buf, "%[^,],%[^,],%[^,],%[^,]", str_dummy - , str_dum1 - , str_dum2 - , str_dum3); - - // エラーハンドル... 仕様か過失かわからないが, 19回目以降に開いたファイルはおかしい. - buf_data[0] = float(atof(str_dum1)); - buf_data[1] = float(atof(str_dum2)); - buf_data[2] = float(atof(str_dum3)); - // 直前の結果+乱数 - if ( line >= 1 ) { - if (fabsf(buf_data[TEMPERATURE] - srnn_sample[(line-1) * DIM_SIGNAL]) > 30) - buf_data[TEMPERATURE] = (srnn_sample[(line-1) * DIM_SIGNAL + TEMPERATURE] + uniform_rand(1)); - if (fabsf(buf_data[AIR_PRESSURE] - srnn_sample[(line-1) * DIM_SIGNAL + AIR_PRESSURE]) > 30) - buf_data[AIR_PRESSURE] = (srnn_sample[(line-1) * DIM_SIGNAL + 1] + uniform_rand(1)); - if (fabsf(buf_data[HUMIDITY] - srnn_sample[(line-1) * DIM_SIGNAL + 2]) > 30) - buf_data[HUMIDITY] = (srnn_sample[(line-1) * DIM_SIGNAL + HUMIDITY] + uniform_rand(1)); - } - - memcpy(&(srnn_sample[line * DIM_SIGNAL]), buf_data, sizeof(float) * DIM_SIGNAL); - /* - srnn_sample[line * DIM_SIGNAL] = buf_data[0]; - srnn_sample[line * DIM_SIGNAL + 1] = buf_data[1]; - srnn_sample[line * DIM_SIGNAL + 2] = buf_data[2]; - */ - - if (open_count > 20) - printf(" %d str : %s , f0 : %f , f1 : %f , f2 : %f \r\n", line, str_dummy - , srnn_sample[line * DIM_SIGNAL] - , srnn_sample[line * DIM_SIGNAL + 1] - , srnn_sample[line * DIM_SIGNAL + 2]); - // memcpy(&(srnn_sample[line * DIM_SIGNAL]), buf_data, sizeof(float) * DIM_SIGNAL); - line++; - } - - fclose( seqence_data_fp ); - srnn->set_sample(srnn_sample); - - // 4. SRNNの学習/予測結果から, MCSVMで天気識別 - printf("Learning... %02d:%02d \r\n", local_time_p->tm_hour, local_time_p->tm_min); + // SRNNの学習/予測結果から, MCSVMで天気識別 + // printf("Learning... %02d:%02d \r\n", local_time_p->tm_hour, local_time_p->tm_min); srnn->learning(); srnn->predict(new_seqence_data); memcpy(new_predict_data, srnn->predict_signal, sizeof(float) * DIM_SIGNAL * PREDICT_LENGTH); // MCSVMによる天候識別 for (int i_predict = 0; i_predict < PREDICT_LENGTH; i_predict++) { - // printf("predict_data[%d] : %f %f %f \r\n", i_predict, new_predict_data[i_predict * DIM_SIGNAL], new_predict_data[i_predict * DIM_SIGNAL + 1], new_predict_data[i_predict * DIM_SIGNAL + 2]); new_predict_weather[i_predict] = mcsvm->predict_label(&(new_predict_data[i_predict * DIM_SIGNAL])); new_predict_probability[i_predict] = mcsvm->predict_probability(&(new_predict_data[i_predict * DIM_SIGNAL])); - // printf("P_W : %d P_P : %f \r\n", new_predict_weather[i_predict], new_predict_probability[i_predict]); } - printf("SVM predict finished \r\n"); + // printf("SVM predict finished \r\n"); +} - // 5. 予測結果の書き込み +// 予測結果の書き込み +void write_predict_task(void const* arg) +{ + + FILE* predict_data_fp; + char str_buf[BUF_SIZE]; printf("Write out predict... %02d:%02d \r\n", local_time_p->tm_hour, local_time_p->tm_min); predict_data_fp = fopen( PREDICT_DATA_NAME, "w"); check_file_open( predict_data_fp, PREDICT_DATA_NAME); + for (int i_predict = 0; i_predict < PREDICT_LENGTH; i_predict++) { // 予測時刻へ変換 now_time += PREDICT_INTERVAL_TIME; @@ -191,14 +123,12 @@ new_predict_data[i_predict * DIM_SIGNAL + AIR_PRESSURE], new_predict_data[i_predict * DIM_SIGNAL + HUMIDITY]); } + fclose( predict_data_fp ); // GraphicHandlerの現在予測データのセット graphic_handler->set_predict_data(new_predict_data, new_predict_weather, new_predict_probability); - // delete [] srnn_sample; - // delete local_time_p; <- してはいけない(戒め) - } // 描画スレッド : 優先度低め @@ -209,6 +139,7 @@ if (ml_flag) { Thread::signal_wait(0x2, osWaitForever); } + //printf("sp : %d, pc : %d \r\n", __current_sp(), __current_pc()); // printf("draw thread start. \r\n"); if (time(NULL) % 60 == 0) { @@ -249,6 +180,8 @@ if (ml_flag) { Thread::signal_wait(0x1, osWaitForever); } + // printf("sp : %d, pc : %d \r\n", __current_sp(), __current_pc()); + live_led = !live_led; Thread::wait(1000); } @@ -259,28 +192,32 @@ { set_new_handler(no_memory); local_fs = new LocalFileSystem("local"); - + setup(); - // graphic_handler->draw_log("setup finish"); + // 擬似的なロックをかける(他のスレッドを待ち状態に) ml_flag = 1; - Thread draw_thread(draw_task, NULL, osPriorityNormal, 2000); + Thread draw_thread(draw_task, NULL, osPriorityNormal, 800); Thread liveled_thread(liveled_task, NULL, osPriorityLow, 200); - + osThreadSetPriority(Thread::gettid() ,osPriorityHigh); while (true) { ml_flag = 1; + // 現在時刻取得(ロギングに用いる) now_time = time(NULL); local_time_p = localtime(&now_time); + // センサ読み込み, 機械学習, 予測データセット read_task(NULL); ml_task(NULL); + write_predict_task(NULL); ml_flag = 0; + // シグナルにより他スレッドの再開 liveled_thread.signal_set(0x1); draw_thread.signal_set(0x2); - Thread::wait(2 * 1000); + Thread::wait(PREDICT_INTERVAL_TIME); } - + error("unreachable here"); }
--- a/main.hpp Thu Feb 19 13:53:12 2015 +0000 +++ b/main.hpp Thu Feb 19 19:21:16 2015 +0000 @@ -33,7 +33,6 @@ extern float* new_predict_data; // 現在の予測結果 extern int* new_predict_weather; // 現在の予測天気 extern float* new_predict_probability; // 現在の予測天気の確率(厳密には,確率ではない...) - -extern int open_count; +extern float* srnn_sample_queue; // SRNNのサンプルキュー #endif /* MAIN_H_INCLUDED */ \ No newline at end of file
--- a/main_util.cpp Thu Feb 19 13:53:12 2015 +0000 +++ b/main_util.cpp Thu Feb 19 19:21:16 2015 +0000 @@ -1,8 +1,22 @@ #include "main_util.hpp" +void update_srnn_sample(float* sample_queue, float* new_data) +{ + // 古いデータの消去, データのシフト + for (int i = 0; i < DIM_SIGNAL * LEN_DATA_SEQUENCE; i++) { + if ( i < DIM_SIGNAL * (LEN_DATA_SEQUENCE-1) ) + sample_queue[i] = sample_queue[i+DIM_SIGNAL]; + } + + // 末尾に新データを追加 + memcpy(&(sample_queue[DIM_SIGNAL * (LEN_DATA_SEQUENCE-1)]), new_data, sizeof(float) * DIM_SIGNAL); +} + +// ファイルのオープンチェック(いや、fopenをラップしろよサーセン) void check_file_open(FILE* file_p, const char* file_name) { - printf("[cnt:%d] %s : %p \r\n", open_count++, file_name, file_p); + // static int open_count; + // printf("[cnt:%d] %s : %p \r\n", open_count++, file_name, file_p); if ( file_p == NULL ) { fprintf( stderr, "Error : file %s open faild. \r\n", file_name ); fflush( stderr ); @@ -10,8 +24,8 @@ } } -// データ系列ファイルの行数をLEN_DATA_SEQUENCEまで切り詰める -void truncate_data_file(void) +// データ系列ファイルの行数をmaxlineまで切り詰める +void truncate_data_file(int maxline) { FILE* dat_file_fp; const char tmp_file_name[] = "/local/TMP_DAT.CSV"; @@ -23,15 +37,13 @@ line = 0; while(fgets(trunc_buf_str, BUF_SIZE, dat_file_fp) != NULL) { line++; - // printf("line %d : %s\r\n", line, trunc_buf_str); } - // printf("current num of line : %d \r\n", line); fclose( dat_file_fp ); // 切り詰め開始 - if ( line > LEN_DATA_SEQUENCE ) { + if ( line > maxline ) { FILE* tmp_fp; - diff_line = (line - LEN_DATA_SEQUENCE); + diff_line = (line - maxline); dat_file_fp = fopen(SEQUENCE_DATA_NAME, "r"); // rewind( dat_file_fp ); check_file_open( dat_file_fp, SEQUENCE_DATA_NAME ); @@ -66,7 +78,5 @@ // テンポラリの削除 remove( tmp_file_name ); - // free( tmp_fp ); } - // free( dat_file_fp ); } \ No newline at end of file
--- a/main_util.hpp Thu Feb 19 13:53:12 2015 +0000 +++ b/main_util.hpp Thu Feb 19 19:21:16 2015 +0000 @@ -11,7 +11,8 @@ extern void check_file_open(FILE*, const char*); // ファイルのオープンチェック.第一引数はファイルポインタ, 第二引数はファイル名 // ホントはdebugだけど, オープン失敗はよく起こるので... -extern void truncate_data_file(void); // 系列データの行数をLEN_DATA_SEQUENCEに切り詰める.(先頭から削除) +extern void truncate_data_file(int); // 系列データの行数をLEN_DATA_SEQUENCEに切り詰める.(先頭から削除) extern void print_status(const char*,...); +extern void update_srnn_sample(float*, float*); // サンプルキューの更新. 第一引数にサンプルキュー, 第二引数に新しいサンプル #endif /* MAIN_UTIL_H_INCLUDED */ \ No newline at end of file
--- a/ml_util/ml_util.hpp Thu Feb 19 13:53:12 2015 +0000 +++ b/ml_util/ml_util.hpp Thu Feb 19 19:21:16 2015 +0000 @@ -3,7 +3,7 @@ #include "mbed.h" -/* float.h がないので, FLT_MAXをここで */ +/* float.h がないので, FLT_MAXをここで...と思ったらあるみたいなことを誰かが言ってた */ #ifndef FLT_MAX #define FLT_MAX (0x1.fffffeP127F) // float max #endif
--- a/setup.cpp Thu Feb 19 13:53:12 2015 +0000 +++ b/setup.cpp Thu Feb 19 19:21:16 2015 +0000 @@ -74,9 +74,11 @@ FILE* srnn_setup_fp; int ret; float buf_data[DIM_SIGNAL]; - float sample[LEN_DATA_SEQUENCE * DIM_SIGNAL]; float sample_maxmin[DIM_SIGNAL * 2]; char buf_str[20]; + + // グローバルなサンプルキューを**ここで**アロケート + srnn_sample_queue = new float[DIM_SIGNAL * LEN_DATA_SEQUENCE]; // 信号の正規化のために, 信号の最大値と最小値を決めてやる必要がある. sample_maxmin[0] = 50; @@ -95,18 +97,15 @@ int line = 0; while( ( ret = fscanf( srnn_setup_fp, " %[^\n,],%f,%f,%f", buf_str, &(buf_data[0]), &(buf_data[1]), &(buf_data[2])) ) != EOF ) { if ( line == LEN_DATA_SEQUENCE ) break; - memcpy(&(sample[line * DIM_SIGNAL]), buf_data, sizeof(float) * DIM_SIGNAL); - // printf("sample %d : %f %f %f \r\n", line, MATRIX_AT(sample,DIM_SIGNAL,line,0), MATRIX_AT(sample,DIM_SIGNAL,line,1), MATRIX_AT(sample,DIM_SIGNAL,line,2)); + memcpy(&(srnn_sample_queue[line * DIM_SIGNAL]), buf_data, sizeof(float) * DIM_SIGNAL); + // printf("sample %d : %f %f %f \r\n", line, MATRIX_AT(srnn_sample_queue,DIM_SIGNAL,line,0),MATRIX_AT(srnn_sample_queue,DIM_SIGNAL,line,1), MATRIX_AT(srnn_sample_queue,DIM_SIGNAL,line,2)); line++; } fclose( srnn_setup_fp ); /* アドバイス:RNNにおいては,ダイナミクス(中間層のニューロン数)は多いほど良い */ - srnn = new SRNN(DIM_SIGNAL, 20, LEN_DATA_SEQUENCE, PREDICT_LENGTH, sample, sample_maxmin); - - // delete [] sample; - // delete [] sample_maxmin; + srnn = new SRNN(DIM_SIGNAL, 20, LEN_DATA_SEQUENCE, PREDICT_LENGTH, srnn_sample_queue, sample_maxmin); } @@ -116,7 +115,7 @@ sensor_module = new SensorModule(5); } -/* // ネットワークのセットアップ +// ネットワークのセットアップ static void network_setup(void) { // セットアップ, 最初の時間取得 @@ -131,8 +130,8 @@ if ( eth_if.connect() < 0 ) { // (offlineが確定する -> offline modeへ). - fprintf( stderr, "%s Ethernet connect failed. \r\n", prefix_net_str); - exit(1); + fprintf( stderr, "%s Ethernet connect failed. Go To offline \r\n", prefix_net_str); + return; } // init time @@ -149,10 +148,8 @@ // http_server = new HTTPServer(80, "/local/"); printf("%s IP Address : %s \r\n", prefix_net_str, eth_if.getIPAddress()); - printf("%s Network setup finished! \r\n", prefix_net_str); } -*/ // グラフィックハンドラの初期化 static void graphic_handler_setup(void) @@ -173,7 +170,6 @@ static void jst_setup(int year, int month, int day, int hour, int min) { // setup time structure - if ( time(NULL) == 0 ) { struct tm t; t.tm_sec = 0; // 0-59 t.tm_min = min; // 0-59 @@ -185,7 +181,6 @@ // convert to timestamp and set time_t seconds = mktime(&t); set_time(seconds); - } } // セットアップ. @@ -200,8 +195,8 @@ sensor_setup(); printf("SENSOR ...OK \r\n"); // network_setup(); - jst_setup(2015, 2, 19, 21, 30); - // printf("NETWORK ...NO(offline) \r\n"); + jst_setup(2015, 2, 20, 4, 0); + printf("NETWORK ...NO(offline) \r\n"); graphic_handler_setup(); printf("GRAPHIC ...OK \r\n"); data_setup();
--- a/share.hpp Thu Feb 19 13:53:12 2015 +0000 +++ b/share.hpp Thu Feb 19 19:21:16 2015 +0000 @@ -5,19 +5,30 @@ /* 共通のパラメタ類をマクロで定義 */ -#define PREDICT_LENGTH (3) // 予測系列長 -#define PREDICT_INTERVAL_TIME (1 * 60 * 60) // 予測間隔 : 1h +#define PREDICT_LENGTH (4) // 予測系列長 +#define PREDICT_INTERVAL_TIME (1 * 60 * 60 * 1000) // 予測間隔 : 1h #define LEN_DATA_SEQUENCE (50) // 観測データの履歴長 #define NUM_WEATHERS (4) // 気候の種類 #define DIM_SIGNAL (3) // 信号の次元(=センサの数) #define MCSVM_NUM_SAMPLES (120) // MCSVMのサンプル数 +#define MAX_LOG_LENGTH (1000) // 観測データファイルの最大行数(これをこえるとやばい値) +#define SUITABLE_LOG_LENGTH (500) // 切り詰め後の最適なデータファイルの行数 -#define BUF_SIZE (150) // fprintfの時などに使われる文字列バッファの長さ +#define BUF_SIZE (100) // fprintfの時などに使われる文字列バッファの長さ +/* #ifdef DEFAULT_STACK_SIZE #undef DEFAULT_STACK_SIZE -#define DEFAULT_STACK_SIZE ((WORDS_STACK_SIZE*4) * 8) -#endif /* DEFAULT_STACK_SIZE */ +#define DEFAULT_STACK_SIZE ((WORDS_STACK_SIZE*4) * 2.25) +#endif */ /* DEFAULT_STACK_SIZE */ + + +#ifdef OS_MAINSTKSIZE +#undef OS_MAINSTKSIZE +#define OS_MAINSTKSIZE (DEFAULT_STACK_SIZE*8) +#endif /* OS_STKSIZE */ + +#define OS_STKCHECK // スタックオーバーフローの監視 #ifdef BUFSIZ #undef BUFSIZ @@ -27,12 +38,12 @@ #define SEQUENCE_DATA_NAME "/local/SEQ_DAT.CSV" // 系列データのファイル名 #define PREDICT_DATA_NAME "/local/PRE_DAT.CSV" // 予測データのファイル名 -// 信号のインデックス +// 気候のインデックス typedef enum { TEMPERATURE = 0, // 気温 AIR_PRESSURE = 1, // 気圧 HUMIDITY = 2, // 湿度 -} SIGNAL_ID; +} WEATHER_ID; // 天候を表す列挙型 typedef enum {