2019年2月26日 星期二

一個奇怪的夢

夢的開頭是,我醒了,在一個周圍都是樹的有庭院的日式房子裡面。全身是傷,有個女生在照顧我的傷勢,我不知道自己為什麼會搞成這樣,什麼記憶都沒有。每天因為全身都痛,也不能動,我就是躺在地板上看著周圍的樹木,隨著風搖動。那個女生話不多,她白天都要去旁邊的田裡面工作,所以除了照顧我以外幾乎都在忙,要砍柴,要種田,要維修房子,因為是木頭的其實很需要修理。夢裡面我是話很少的人,她話也很少,我們都很少講話。

周圍似乎都沒有別的人家,就她自己一個人住在這裡,不知道為什麼。也不知道被照顧了多久,後來身體能動了。我沒地方去,因為我什麼記憶都沒有了,從哪裡來的也不知道。就幫她一起下田、作家事、砍柴、修房子,還有一個我有幫助的,就是我很擅長沒有聲息的移動,所以打獵很成功,以前她很難吃到的肉,現在也都有的吃了。我體格很好,這些事情我作起來超拿手的。

就一起生活,她話不多,也很少講自己的事情,我也沒有問,我只是覺得生活就是這樣一天一天,好像也很好。就這麼過了不知道多久,也許是幾個月,感覺習慣了,這就是我的人生了。雖然不知道我本來是怎樣的人過怎樣的人生,但現在的人生很好,很幸福。我們兩個每天都過得很開心,她也很常笑,我也是。

有一天晚上睡覺睡一半,我頭好痛好痛,越痛越來有很多奇怪的畫面閃過眼前,好痛好痛好痛!阿阿阿阿好痛好痛好痛!我好像想到很多東西,我好像想起來發生什麼事了……

我是一個組織的殺手,類似忍者之類的東西,因為背叛組織,所以被追殺。我逃了好久,但是最後還是被派出來追殺我的殺手們找到了。在被追殺的過程,我把來追殺我的那一票殺手全部幹掉了,但是自己也受了重傷。最後在樹林裡面逃啊逃,逃到這棟房子以後氣力也放盡,一放鬆就昏過去了。(怪不得我體格這麼好,種田劈柴幹嘛的都超順手 XD)

醒過來了 @@ 看著天花板,所有的事情都想起來了。完了,根據我對組織的了解,他們不可能放過我,那些人全部被我幹掉了,他們沒有回去回報任務成功,組織一定會再派出人來找我。找到我只是時間的問…

我聽到了…周圍的樹林裡面有人…天花板上也有人…他們已經找到我了…他們正在慢慢靠近,有很多人,很多人……如果她現在醒過來,她一定會死,如果我留在這邊,她一定會死…我沒有辦法跟她說再見了……

我沒有聲息的起來,小心的看著她的臉,確定她沒有被我吵醒。我聽得很清楚,他們正在慢慢的靠近,我穿好衣服,拿起受傷時落在身邊的刀現在被收好的刀,跑進周圍的樹林,一直往前跑,一直往前跑,離房子越遠越好。我聽到後面有好多聲音跟來了……那我就放心了……

2017年7月12日 星期三

Boost.Python 小記

建構子

沒有建構子的 class 要在宣告 mapping 的時候給建構子的 prototype

std::vector<>

跟 python 對接的陣列,要用  boost::python::list 

Overloading function

使用「明確轉型」來指定特定的 overloading 版本

import_array()

使用 numpy 要  import_array()  ,不然執行期用  PyArray_SimpleNewFromData()  建立陣列的時候會 segmentation fault。特別注意的是  import_array()  其實是一個陣列,他會去初始化一個 static variable 叫做  PyArray_APIPyArray_API  是一個 compile unit static variable,所以每一個 .cpp 檔自己都要  import_array() ,但重複 import 又會錯,所以呼叫前要先檢查  PyArray_API  這個變數是否已經被設定。

if (PyArray_API == NULL) {
    import_array();
}


2017年6月28日 星期三

tf.slim deploy trained model

用 tf.slim train 好了 model 以後,要拿來做 inference 才發現腦袋不大清楚不知道怎麼弄,查了一下,看到這邊,原來 tensorflow 本身就有提供 freeze 的工具,slim 也有 script 讓使用者可以方便的 export model。

照著註解裡面步驟做就可以了,兩步,橫簡單,連我都會。

昨天浪費了我幾個小時在那邊摸索,真的很笨。不知道昨天為什麼突然忘記「開始動手做之前先看看別人怎麼做」我的天哪...

[0] https://github.com/tensorflow/models/blob/master/slim/export_inference_graph.py

2017年6月22日 星期四

TF.slim 吃自訂格式的 data

Tensorflow.slim 預設是吃他 TFRecord。但我的圖很多,我不想全部轉成 TFRecord,這樣會吃掉很多硬碟,我想要保留 .jpg 的檔案在硬碟裡,然後有一個文字檔,裡面描述了哪些檔案有哪些 label。

0.jpg -1:* 1:0,7  
1.jpg -1:* 1:1,2,4...

表示 0.jpg 這張圖,有第 0 個 label 跟第 7 個 label。這兩個 label 是 1,其他都是 0。然後 1.jpg 這張圖,有第 1 第 2 第 4 個 label,其他都沒有。至於總共有多少 label,在描述 dataset 的 .py 檔會有寫。

slim 有自己的 reader class,有做了 parallel reader,對於需要大量訓練的時候可以加快 read data 的時間,但是 reader 讀進來之後,decoder 卻只有一個人。如果 decoding 需要很多時間,那這邊就會有問題。為了繞過這個問題,我決定把 reader 跟 decoder 合併在一起。

我根據 slim 的 parallel_reader.py 加了一個 parallel_reader_decoder.py,multi-thread 在讀取檔案以後,同時就會去 decode,之後才放進一個 common queue 讓之後的 node 取用。

這邊註記幾點:
  1. 寫 decoder 的時候,真的要注意效能問題,本來我用很 python 的方法在處理 numpy 陣列,後來發現效能慘不忍睹,改用 numpy style 以後 performance 快了幾百倍。
  2. tf.py_func() 就很好用,不一定要用 C++ 去寫 Op,當然如果真的需要就不要偷懶。
  3. tf.losses 會幫忙把 loss 登錄到 GraphKey.LOSSES,之後會有人去取用,所以不要覺得好奇怪為什麼這個 loss 都沒有人用到
  4. 記得把 slim 的 preprocessing thread 的數量也開到對,不然你會發現 reading 夠快,decoding 夠快,GPU 的 forward computation 跟 backward propagation 也夠快,但是 throughput 就是有夠低。最後發現是死在 preprocessing thread 數量太少。這個數值跟你的 model 所需要的 preprocessing 複雜度有關。mnist 的 preprocessing 很簡單,一個說不定就夠了,inception 可能要 4(或 8?)。
  5. slim 裡面有幾個 queue,queue capacity 記得要改到夠大,pop 以後的 min-size 也要調整(小),不然你會發現他一批一批的做,比方說你 queue capacity 是 16,min-size 卻是 8,但是你有 8 個 clone,這樣他一次要吃掉 8 個,吃完以後這個 queue 的 producer 才會做事,很不方便。這樣這個 queue 等於沒有 buffering 的效果。
    1. Filename Queue (after enumerate files)
    2. Parallel Reading Queue (after read)
    3. Prefetch Queue (after preprocessing)
    4. Batch Queue (after batch packing)
  6. 開太多 preprocessor 的話,tensorboard 秀 graph 會 gg =_=||
  7. sigmoid_cross_entropy 不要亂餵,他的值域就是 0 ~ 1,雖然我自己的 multi-label 標注方法是 1 positive, -1 negative, 0 don't care,但計算的時候,不要去把 logit 轉換到 -1 ~ 1,而是要把 label 從 -1 ~ 1 轉換成 0 ~ 1(但是 label 真的是 0 的時候,要記得 don't care)用tf.abs 跟 tf.maximum 可以做到。不難。
腦子不管用了,剩下的等想到再寫

2017年6月18日 星期日

tensorflow 自訂 operator

考慮開發速度的話,先使用  tf.py_func  [0]
如果遇到限制,或是考慮執行效能的話,再去看 Adding a New Op [1]

雖說 [1] 比 [0] 麻煩,但其實也相當簡單,不用害怕,進去看著照做就可以了,半個小時的事情

[0] https://www.tensorflow.org/api_docs/python/tf/py_func
[1] https://www.tensorflow.org/extend/adding_an_op

2017年5月31日 星期三

undefined symbol: _ZN10tensorflow8internal21CheckOpMessageBuilder9NewStringB5cxx11Ev

解法

編譯的時候加上  -D_GLIBCXX_USE_CXX11_ABI=0  [0]

說明

gcc 5.3 以後導入了新的 ABI,如果你去 link 一個用 5.3 之前的版本編譯的 library,用的還是舊的 ABI,這個時候就會發生錯誤 [1]

參考

[0] https://github.com/tensorflow/tensorflow/issues/1569#issuecomment-200021340
[1] https://stackoverflow.com/questions/34970607/g-new-abi-problems

2017年4月6日 星期四

mysql utf8

原來要 mysql 支援 utf8 不是這麼預設的,好煩 = =||

好吧,歷史因素,可以體諒。

首先看這邊[1]看看怎麼設定(或是變更現有的 database)mysql 支援 unicode

看就好,先不要動手!

注意你要的 collate 是啥。「collate」指的是 DB 用來比對字串的時候所使用的準則,utf8mb4 預設的 collate 是「utf8mb4_general_ci」,這個很有可能不是你要的,因為他會把「ç」跟「c」當作同一個字元,你需要的可能是「utf8mb4_bin」。

然後如果你用的是 docker,不用去寫 my.cnf,run image 的時候直接下命令[2]。

$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci

好,如果你不是用 docker,那現在你可以動手了。去 alter 你的 DB 跟寫你的 my.cnf。
用 docker 的人只要 alter DB 就好,然後 run image 的時候用下指令的。

Note: MySQL 的 utf8 charset 不是真的 utf8,他只支援到 unicode 的一個子集,最多三個 byte。到了 5.5.忘了 版之後才有 utf8mb4 charset 支援整個 unicode codepoint。

[1] https://mathiasbynens.be/notes/mysql-utf8mb4
[2] https://hub.docker.com/_/mysql/