2008年1月25日 星期五

減少操作實驗浪費的時間

分享一下之前做實驗時發展出的小技巧,我這裡指的是跑程式的實驗。花點時間研究一些工具,可以剩下不少重覆執行的動作。

首先,畫圖方面 gnuplot 是最好的選擇,用法很簡單,google一下學個基本,之後要用什麼特殊指令,去 Demos and Screenshots 裡找符合的圖,將範例code抓下來試一試,改一改就會用了。看到常用的指令或參數,就到 DocumentsIndex 裡找詳細說明(比方查 xrange 的用法),減少試誤的時間。

gnuplot 最大的好處在於批次處理,初期費些工夫寫出滿意格式的 gnuplot code,接著就可以把所有圖表套用一樣的格式,想變更格式時,比方加格線或放大字型,只要改一份 code,所有圖表可以一同更新,這是 Excel 難以做到的,也許 VBScript可以,但學習代價應該會比 gnuplot 高。若會寫 shell script或scripting language如Perl、Python、Ruby、PHP,可以配合script和寫好的gnuplot code,執行一個程式讀入不同的資料檔,即可重畫所有圖表,這點 Excel 更不方便達成。配合 script 還可以自動轉成 LaTeX 用的圖檔格式。若不滿意 gnuplot 預設 EPS 的風格,像我較喜歡預設 PNG 的話,可以配合圖檔轉檔軟體,可以輕易地批次處理,像 Linux、FreeBSD上可以用 convert。做實驗時常要重畫圖表,很少能一次搞定,初期投資些時間在 gnuplot 和批次處理程式上,絕對會回本的。

若想再進一步自動化的話,可以將實驗結果存到資料庫裡,不要存到普通檔案裡。花點時間研究如何用 scripting language 或自己慣用的程式語言操作DBMS(如MySQL),看要在實驗結束時程式直接將結果寫入資料庫,或是先寫入暫存檔再另用別的語言 (例如直接用 MySQL script)將結果寫入資料庫。於是,透過 DBMS 網頁介面的軟體(如phpMyAdmin),可以輕易地觀察實驗結果,像是依時間排序資料、依數據大小排序,或要算平均、標準差等,都輕而易舉;要輸出成 gnuplot 或其它程式的輸入格式,也是非常容易。

最後,跑實驗的程式最好寫成從命令列讀參數,或讀一個設定檔設定參數,減少重新編譯的動作,也方便批次實驗不同參數。

總結一下,我自己的做法是:

  1. 實驗用的程式從命令列讀參數。
  2. 其中一個參數決定要將實驗結果直接輸出(STDOUT) 或寫入 MySQL。有時候做些小更動想看看實驗有什麼差別,不想塞太多資料進資料庫弄亂原有資料,可以下參數讓程式不要寫入資料庫。
  3. 用 shell script 寫好測試用的批次檔,會輸入不同參數給實驗用的程式,產生所有要的結果。
  4. 裝 phpMyAdmin,方便分析實驗情形,以及輸出 gnuplot 要求的輸入格式(用TAB分隔)。
  5. 寫好 gnuplot 的 code,我不知道怎麼在 gnuplot 裡使用變數,讓它能配合shell script對畫圖作細部調整(如更改輸出檔檔名),所以我改用笨一點的做法,將gnuplot code存成字串,用Ruby配合不同變數產生有點不同的 gnuplot code 到文字檔裡,再執行 gnuplot 讀入新產生的 code 以符合細部調整。
  6. 寫個簡單網頁顯示 gnuplot 輸出的 PNG 檔,方便用圖形觀察各組數據的差異。再寫個 script 利用 convert 把所有 PNG 檔轉成 EPS,確保論文裡的圖檔和我想要的樣子一致,但會犠牲向量圖檔任意放大的優點。

上述的方式我試過幾次,幫我省下不少時間,第一次試用時間投資就有回本,更不用說第二次之後的收益了。舉例來說,我其中一個實驗要求是記錄演算法各段落執行的時間,想配合各種不同資料量,判斷演算法的子項目平均時間差多少。但用 profiler 會拖慢執行速度,我只想記錄幾個主要步驟而已。這時輸入到 MySQL 變得相當順手,執行一次批次檔,上床睡覺,隔天早上下個 SQL 做平均,就可以看出差異。找出關鍵的部份後,再下 SQL 選出關鍵資料的細項,看看資料分佈的情況,有助於了解情況。想想看,若不用自動化實驗和資料庫來呈現數據,前述動作有多麼冗長無味,你會想重覆幾次這樣的事?更不用說集中精神分析結果和思考改進方式了。

沒有留言:

張貼留言