機械学習の設計パターン(マクロ&ミクロ)
機械学習で参考になった情報
機械学習を勉強するにあたって参照した情報源の自分用メモです。 (手を付けたが完了できなかった項目への自戒もこめて)
履修済みで役にたっている情報
- www.coursera.org ご存知Stanford大のAndrew Ng先生の講座。演習用の言語がMatlab互換のOctaveなのがつらかった。
- 作者:岡谷 貴之
- 発売日: 2015/04/08
- メディア: 単行本(ソフトカバー)
[第2版]Python 機械学習プログラミング 達人データサイエンティストによる理論と実践 (impress top gear)
- 作者:Sebastian Raschka,Vahid Mirjalili
- 発売日: 2018/03/16
- メディア: 単行本(ソフトカバー)
ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装
- 作者:斎藤 康毅
- 発売日: 2016/09/24
- メディア: 単行本(ソフトカバー)
- 作者:Francois Chollet
- 発売日: 2018/05/28
- メディア: 単行本(ソフトカバー)
イラストで学ぶ ディープラーニング 改訂第2版 (KS情報科学専門書)
- 作者:山下 隆義
- 発売日: 2018/11/19
- メディア: 単行本(ソフトカバー)
Pythonデータサイエンスハンドブック ―Jupyter、NumPy、pandas、Matplotlib、scikit-learnを使ったデータ分析、機械学習
- 作者:Jake VanderPlas
- 発売日: 2018/05/26
- メディア: 単行本(ソフトカバー)
scikit-learnとTensorFlowによる実践機械学習
- 作者:Aurélien Géron
- 発売日: 2018/04/26
- メディア: 単行本(ソフトカバー)
実践チュートリアル 決定木とランダムフォレスト student.codexa.net 決定木をなんとなくしか理解していなかったので。
実践チュートリアル XGBoost student.codexa.net KaggleでXGBoostがよく使われるということなので勉強してみた。
courses.edx.org IBMの講座。内容は難しくないが機械学習全体のフローを再確認するのに役立った。
着手したが未完了で役にたちそうな本
- 作者:C.M. ビショップ
- 発売日: 2012/04/05
- メディア: 単行本(ソフトカバー)
- 作者:C.M. ビショップ
- 発売日: 2012/02/29
- メディア: 単行本
パターン認識と機械学習の学習―ベイズ理論に負けないための数学
- 作者:滋生, 光成
- 発売日: 2017/07/01
- メディア: 単行本
統計的機械学習の数理100問 with Python (機械学習の数理100問シリーズ)
- 作者:讓, 鈴木
- 発売日: 2020/04/27
- メディア: 単行本
- 作者:Ian Goodfellow,Yoshua Bengio,Aaron Courville
- 発売日: 2018/03/07
- メディア: 単行本
www.coursera.org Kaggleでの勝ち方。自分にはまだレベルが高くて挫折。Kaggleをある程度やってから受けた方がよさそう。
Lecture 1 - Welcome | Stanford CS229: Machine Learning (Autumn 2018)
ご存知Stanford大のAndrew Ng先生の2018年の講座の動画。
www.udemy.com www.udemy.com www.udemy.com www.udemy.com 日本語だし、内容は分かりやすいのですが、自分が欲張っていくつも登録した結果、消化できていない。
未着手だがよく紹介されているのできっと参考になる
- 作者:平井 有三
- 発売日: 2012/07/31
- メディア: 単行本(ソフトカバー)
- 作者:Trevor Hastie,Robert Tibshirani,Jerome Friedman
- 発売日: 2014/06/25
- メディア: 単行本
あんまり自分には合わなかったが参考になる人もいるはず
(この情報を見た時の自分の実力や求めるものと合わなかっただけで、フィットする人もいるはずです。)
機械学習のための特徴量エンジニアリング ―その原理とPythonによる実践 (オライリー・ジャパン)
- 作者:Alice Zheng,Amanda Casari
- 発売日: 2019/02/23
- メディア: 単行本(ソフトカバー)
直感 Deep Learning ―Python×Kerasでアイデアを形にするレシピ
- 作者:Antonio Gulli,Sujit Pal
- 発売日: 2018/08/17
- メディア: 単行本(ソフトカバー)
Anacondaで作成した環境をJupyter Notebookで選択する
anacondaで環境作成後に下記コマンドを実行する
conda install notebook ipykernel pip install environment_kernels jupyter ipython kernel install --user --name <vir_env>
<vir_env> はAnacondaで作成した環境名
FreeRTOS Code Reading (Arduino編, #3)
今回は予定通り vTaskStartScheduler() から呼ばれる xTaskCreate() を読んでいく。
vTaskStartScheduler()
からの の呼び出し。
- variantHooks.cpp: void vTaskStartScheduler( void )
/* The Idle task is being created using dynamically allocated RAM. */ xReturn = xTaskCreate( prvIdleTask, configIDLE_TASK_NAME, configMINIMAL_STACK_SIZE, ( void * ) NULL, portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */ &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
- tack.h: 関数宣言
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ const configSTACK_DEPTH_TYPE usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION;
- 関数引数
引数型 | 名前 | 内容、意味 |
---|---|---|
TaskFunction_t | pxTaskCode | PRiVate アイドルタスク(関数)、 |
const char * const | pcName | タスク名。configIDLE_TASK_NAME, "IDLE"。 |
const configSTACK_DEPTH_TYPE | usStackDepth | タスクのスタックサイズ。configMINIMAL_STACK_SIZE, 192byte |
void * const | pvParameters | タスクへの引数。null pointer |
UBaseType_t | uxPriority | 0x00。portPRIVILEGE_BIT |
TaskHandle_t * const | pxCreatedTask | NULL。xIdleTaskHandle |
次はxTaskCreate()
の実装。
- tack.c
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ const configSTACK_DEPTH_TYPE usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask { ... #if( portSTACK_GROWTH > 0 ) ... #else /* portSTACK_GROWTH */ { StackType_t *pxStack; /* Allocate space for the stack used by the task being created. */ pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */ if( pxStack != NULL ) { /* Allocate space for the TCB. */ pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */ if( pxNewTCB != NULL ) { /* Store the stack location in the TCB. */ pxNewTCB->pxStack = pxStack; } else { ... } } else { ... } } #endif /* portSTACK_GROWTH *
順にみていくが、pvPortMalloc()はヒープからメモリを確保していると思うので詳細は後で見る。
pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) );
タスクのためのスタックメモリ領域を確保。サイズは StackType_t を usStackDepth個 だけ。
次にタスク制御バッファ(Tack Control Buffer。TCB_t
)の領域を確保する。
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
#defineを辿るとTCB_t
の実体は下記のようである。
- tack.c:
typedef struct TaskControlBlock_t { volatile StackType_t *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */ ListItem_t xStateListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */ ListItem_t xEventListItem; /*< Used to reference a task from an event list. */ UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */ StackType_t *pxStack; /*< Points to the start of the stack. */ char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ }
メンバの型 | メンバ変数名 | 内容、意味 |
---|---|---|
volatile StackType_t | *pxTopOfStack | タスクのスタックの最後のアイテムのアドレスへのポインタ。TCB構造体のメンバの最初に置く必要がある |
ListItem_t | xStateListItem | ステート(状態)リスト。Ready, Blocked, Suspended |
ListItem_t | xEventListItem | イベントリストからタスクを参照するのに使われる |
UBaseType_t | uxPriority | 優先度。0が最低。 |
StackType_t | *pxStack | スタックの先頭アドレスへのポインタ |
char | pcTaskName[ configMAX_TASK_NAME_LEN ] | デバッグ用 |
xStateListItem、xEventListItem の使われ方がまだよくわからない。
pxNewTCB->pxStack = pxStack;
タスク用のスタック領域(pxStack )と、タスク制御用のバッファ(pxNewTCB )が確保出来たら、タスク制御用のバッファのスタック領域に割り当てる。
後回しにしていたpvPortMalloc()
を詳細にみてみる。
- heap_3.c
void *pvPortMalloc( size_t xWantedSize ) { void *pvReturn; vTaskSuspendAll(); { pvReturn = malloc( xWantedSize ); traceMALLOC( pvReturn, xWantedSize ); } ( void ) xTaskResumeAll(); #if( configUSE_MALLOC_FAILED_HOOK == 1 ) { if( pvReturn == NULL ) { ... } } #endif return pvReturn; }
メモリをヒープから確保する。下記順に実行されている
- タスクを全部サスペンドする(
vTaskSuspendAll()
) - malloc してヒープからメモリをxWantedSize [byte] 確保する。
- サスペンドしたタスクをレジュームする(
xTaskResumeAll()
)
まず、1. の全タスクのサスペンドする処理を読んでみる。
- tasks.c:
void vTaskSuspendAll( void ) { /* A critical section is not required as the variable is of type BaseType_t. Please read Richard Barry's reply in the following link to a post in the FreeRTOS support forum before reporting this as a bug! - http://goo.gl/wu4acr */ ++uxSchedulerSuspended; }
コードは1行しかないけど、コメントが何やら書いてあるので辿ってみる。 goo.gl
要約すると、最初にこの記述は問題があるのでは?という質問に対して、問題ない、と回答している。 質問者が下記質問を投げかけている。
AVR(Arduino UNOとか), ARM Cortex M ではこの操作(++uxSchedulerSuspended; のこと)をコンパイラーが以下のように処理する
- (メモリから)uxSchedulerSuspendeded をCPUレジスタにロードする
- レジスタ値をインクリメントする
- レジスタ値を (メモリ上の)uxSchedulerSuspendeded にストアする
これは 明らかに NOT ATOMIC じゃない。(訳注:3命令の途中でタスク切り替えが発生し得る etc.) だから、アトミックなインクリメント機械語命令がないすべてのプラットフォームに対してportATOMIC_INCREMENT()マクロを実装することを提案する。
それに対する richardbarry さん(中の人?)の答えがこれ。
各タスクは自分自身のコンテキストを管理していて、かつコンテキストスイッチはこの値(
uxSchedulerSuspended
)がゼロでないときは発生しない。 従って、レジスタバックからメモリーへの書き込みはアトミックであり、問題にならない。
さらに丁寧に例を挙げて説明してくれている。
uxSchedulerSuspended がゼロから始まるシナリオを考えてみる。
- (メモリから)uxSchedulerSuspendeded をCPUレジスタにロードする
さて、コンテキストスイッチは他のタスクが実行することを発生させる。そのタスクが同じ変数を使用する。そのタスクはその変数をゼロとしてみる。なぜなら、その変数はオリジナルタスクから更新されていないから。
ここまでは理解できる。
そのあとで、オリジナルタスクが再度実行したとする。これは以下のときのみ発生する
- uxSchedulerSuspended が再度ゼロに設定された
- かつ、オリジナルタスクがCPUレジスタの内容、これらはコンテキストスイッチアウトされた時のまま保持された内容であり、これを再度実行した
従って、レジスタにリードされた値はまだ(メモリ上の)
xuSchedulerSuspended
の値と同じである。
うーん。この条件がよくわからない。
さらにこの後に続く質問者のコメントをみると、
uxSchedulerSuspended
はカウンターではなくバイナリ(1 or 0)で扱われているから問題ないね。
と納得しているのでなんかそういうことなんだと思うけど、あとでもう一度考えてみます。
malloc() は stdlib.h で宣言されている。malloc実装はあとでみる。 mallocを解説した動画www.youtube.comも参考になる。
traceMALLOC()
は、traceMALLOC
が定義されておらずArduino UNO版では実態はないようだ。
- Arduino_FreeRTOS.h
#ifndef traceMALLOC #define traceMALLOC( pvAddress, uiSize ) #end
最後にxTaskResumeAll()
を読もうと思ったけど、長いので次回に持ち越し。
従って、次回はvTaskStartScheduler() -> xTaskCreate() -> pvPortMalloc()
から呼ばれた `xTaskResumeAll()' から続きを読んでいきます。
今回はいろいろ積み残しがありました。
FreeRTOS Code Reading (Arduino編, #2)
xTaskCreate()
関数を読む前に予定を変えてWindows環境でAruduino IDEでのビルドについて確認します。
Arduino IDEのメニューから、ファイル->環境設定->より詳細な情報を表示する->コンパイル にチェックを入れると、 下記にようにビルド時の詳細情報が表示されるようになります。
"C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10809 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino" "-IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\standard" "-IC:\Users\hogehoge\Documents\Arduino\libraries\FreeRTOS\src" "C:\Users\hogehoge\AppData\Local\Temp\arduino_build_353041\sketch\arduino_freertos_sample.ino.cpp" -o "C:\Users\hogehoge\AppData\Local\Temp\arduino_build_353041\sketch\arduino_freertos_sample.ino.cpp.o"
上の例では、下記フォルダでビルドが実行され、ファイルが生成されています
"C:\Users\hogehoge\AppData\Local\Temp\arduino_build_353041
上記フォルダで、avr-objdump.exe
を実行することで、生成されたアセンブリ言語を見ることもできます
必要に応じて利用していきたいと思います。
次回こそxTaskCreate()
関数を読み進めます。
FreeRTOS Code Reading (Arduino編, #1)
興味があるのでFreeRTOSのソースコードを読んでみる。 あとで修正するかもしれませんが、しばらくは体裁が整っていない自分用のメモです。
なぜ読むか?
RTOSの実装に興味があり、Arduino版ならコード量の少なく読みやすそうだったので。
ソースコードはここ。github.com MPU(atmega328p)のdatasheetはここ。https://avr.jp/user/DS/PDF/mega328P.pdf
もしくはここ。http://akizukidenshi.com/download/ds/microchip/atmega328.pdf
読み方、ソースコード引用の方針
どこから読み始めるか
161204_Mastering_the_FreeRTOS_Real_Time_Kernel-A_Hands-On_Tutorial_Guide.pdf に variantHook.cpp から読めと書いてあるのでそこから始める。 (↑は昔書いたメモだけど、見当たらないorz)
読む
- Arduino_FreeRTOS_Library\src\variantHooks.cpp
extern void setup(void); extern void loop(void); /*-----------------------------------------------------------*/ void initVariant(void) __attribute__ ((OS_main)); void initVariant(void) { #if defined(USBCON) USBDevice.attach(); #endif setup(); // the normal Arduino setup() function is run here. vTaskStartScheduler(); // initialise and run the freeRTOS scheduler. Execution should never return here. }
setup(), loop()はexternされていて、実体は Arduinoのsketchが参照される。
- task.c
void vTaskStartScheduler( void ) { BaseType_t xReturn; /* Add the idle task at the lowest priority. */ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) { ... } #else { /* The Idle task is being created using dynamically allocated RAM. */ xReturn = xTaskCreate( prvIdleTask, configIDLE_TASK_NAME, configMINIMAL_STACK_SIZE, ( void * ) NULL, portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */ &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ } #endif /* configSUPPORT_STATIC_ALLOCATION */
configSUPPORT_STATIC_ALLOCATION は, config次第だが多分0(要確認)。
- Arduino_FreeRTOS.h
#ifndef configSUPPORT_STATIC_ALLOCATION /* Defaults to 0 for backward compatibility. */ #define configSUPPORT_STATIC_ALLOCATION 0 #endi
スケジューラをタスクの1つとして登録する。
/* The Idle task is being created using dynamically allocated RAM. */ xReturn = xTaskCreate( prvIdleTask, configIDLE_TASK_NAME, configMINIMAL_STACK_SIZE, ( void * ) NULL, portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */ &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
if( xReturn == pdPASS ) { ... /* Interrupts are turned off here, to ensure a tick does not occur before or during the call to xPortStartScheduler(). The stacks of the created tasks contain a status word with interrupts switched on so interrupts will automatically get re-enabled when the first task starts to run. */ portDISABLE_INTERRUPTS(); #if ( configUSE_NEWLIB_REENTRANT == 1 ) { /* Switch Newlib's _impure_ptr variable to point to the _reent structure specific to the task that will run first. */ _impure_ptr = &( pxCurrentTCB->xNewLib_reent ); } #endif /* configUSE_NEWLIB_REENTRANT */ xNextTaskUnblockTime = portMAX_DELAY; xSchedulerRunning = pdTRUE; xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT; /* If configGENERATE_RUN_TIME_STATS is defined then the following macro must be defined to configure the timer/counter used to generate the run time counter time base. NOTE: If configGENERATE_RUN_TIME_STATS is set to 0 and the following line fails to build then ensure you do not have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your FreeRTOSConfig.h file. */ portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(); traceTASK_SWITCHED_IN(); /* Setting up the timer tick is hardware specific and thus in the portable interface. */ if( xPortStartScheduler() != pdFALSE ) { /* Should not reach here as if the scheduler is running the function will not return. */ } else { /* Should only reach here if a task calls xTaskEndScheduler(). */ } } else { ... }
- スケジューラのタスクの生成に成功したか(xReturn == pdPASS)を確認する
- xPortStartScheduler() を呼ぶまで割り込み禁止にする
xNextTaskUnblockTime = portMAX_DELAY; xSchedulerRunning = pdTRUE; xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
xNextTaskUnblockTime
は、...xSchedulerRunning
は、スケジューラが動作中はpdTRUE
、void vTaskEndScheduler( void )
が呼ばれるとpdFALSE
に設定されるxTickCount
は、次のスケジュールのタスクの割り込みまでの時間。
portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(); traceTASK_SWITCHED_IN();
この2つのマクロはdefaultはカラ。
if( xPortStartScheduler() != pdFALSE )
- port.c
BaseType_t xPortStartScheduler( void ) { /* Setup the relevant timer hardware to generate the tick. */ prvSetupTimerInterrupt(); /* Restore the context of the first task that is going to run. */ portRESTORE_CONTEXT(); /* Simulate a function call end as generated by the compiler. We will now jump to the start of the task the context of which we have just restored. */ __asm__ __volatile__ ( "ret" ); /* Should not get here. */ return pdTRUE; }
//initialize watchdog void prvSetupTimerInterrupt( void ) { //reset watchdog wdt_reset(); //set up WDT Interrupt (rather than the WDT Reset). wdt_interrupt_enable( portUSE_WDTO ); }
prvSetupTimerInterrupt()
は、WDT(Watch Dog Timer)をリセットし、WDT割り込みを有効にしている。 ** `wdt_rest(), wdt_interrupt_enable()' は要確認portRESTORE_CONTEXT()
は、CPUレジスタを戻して(pop)、xPortStartScheduler()
が呼ばれる前の状態(context)に戻している。ret
を発行して関数から戻る。
ここまででスケジューラタスクの登録し、実行した状態になった。
次回は、少し戻ってスケジューラタスクの生成処理を読み解いてみる。
/* The Idle task is being created using dynamically allocated RAM. */ xReturn = xTaskCreate( prvIdleTask, configIDLE_TASK_NAME, configMINIMAL_STACK_SIZE, ( void * ) NULL, portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */ &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
Googleカレンダーをスマホと同期させる
改めていうことじゃないですが、Googleカレンダー便利ですね。 スマホとも同期できるので一元管理できていいですね。
でも、自分の環境では問題が・・・
用途毎に複数のカレンダーを作ったり、公開されているカレンダーを登録したりして、 複数のカレンダがーが場合にブラウザでは全てのカレンダーが見れるけど、 同期設定しているつもりのスマホのカレンダーアプリでは見れるカレンダーと見れないカレンダーがありました。 以前に軽く調べたときはよくわからなかったけど、 もう一度調べ直しても見たら解決したのでφ(..)
そのような内容なので、スマホのカレンダーアプリでGoogleカレンダーと"全く"同期できない場合は 他の記事を検索した方がよいです。
iPhone/iPad編
iPhone/iPadはこの記事で紹介されている同期設定のページが ビンゴでした。 weekly.ascii.jp
…ただ、自分でGoogleカレンダーのヘルプからたどろうとすると スマートフォンまたはタブレットでのカレンダーの同期 - カレンダー ヘルプ→Apple カレンダーとの同期→他のカレンダーの同期→カレンダーの同期 となかなかたどり着けないページにある。
Android編
Androidスマホではカレンダーアプリとして ジョルテを使っていますが、 このアプリからでは設定できないようだ。 Googleカレンダーでないと同期するカレンダーを選択できないようだ。Googleカレンダー"アプリ"は全く使ってなかったので気づかなかったけど… 具体的にはGoogleカレンダーアプリを開いて以下の手順を実行すれば、ジョルテでも同期されるようになりました。 メニュー → 設定 → 同期させたいカレンダーを選択 → 同期をONに変更