2010-02-10 394 views
24

我正在爲計算機視覺的論文寫一個相當複雜的機器學習程序。它工作得很好,但我需要不斷嘗試新事物並添加新功能。這是有問題的,因爲我在擴展代碼或試圖簡化算法時有時會引入錯誤。單元測試機學習代碼

顯然,正確的做法是添加單元測試,但不清楚如何執行此操作。我的程序的許多組件產生了一個有點主觀的答案,我不能自動執行完整性檢查。

例如,我有一些代碼使用較低分辨率的曲線來近似曲線,這樣我就可以在較低分辨率曲線上進行計算密集型工作。我意外地在這段代碼中引入了一個bug,並且只有在我的整個程序的結果稍微惡化的時候才發現它是一個艱苦的搜索。

但是,當我試圖爲它編寫一個單元測試時,我不清楚該怎麼做。如果我製作了一個簡單的曲線,它有一個明確正確的低分辨率版本,那麼我並沒有真正測試出所有可能出錯的東西。如果我製作一個簡單的曲線,然後稍微擾動這些點,我的代碼就開始產生不同的答案,即使這段代碼現在看起來確實很好。

回答

8

你可能不會感激這個諷刺,但基本上你有什麼是遺留代碼:一大塊沒有任何單元測試的軟件。當然你不知道從哪裏開始。因此,您可能會發現閱讀處理遺留代碼很有幫助。

關於此問題的權威性思想是Michael Feather的書,與遺產代碼有效地工作。過去在ObjectMentor網站上有一個有用的總結,但可惜的是,該網站已經走過了公司的道路。但是WELC在評論和其他文章中留下了遺產。 Check them out (or just buy the book),雖然關鍵的經驗教訓是S.Lott和tvanfosson在他們的回覆中提到的。

+0

這實際上是最有用的建議。我所有成功的調試都是通過使用這樣的技術手工完成的。但是這個PDF爲自動化過程提供了一些很好的建議。 您的PDF鏈接不適用於我,但一個簡單的谷歌找到它。 – forefinger 2010-02-10 21:28:27

+0

@forefinger - 我現在已經修復了這個鏈接。但我很高興你找到了這篇文章,並發現它很有用。 – APC 2010-02-10 21:38:55

+2

該PDF的作者有一本關於同一主題的出色書籍:http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052 – TrueWill 2010-02-10 21:42:51

11

沒有看到您的代碼,很難說,但我懷疑您正在嘗試編寫太高級別的測試。您可能想考慮將您的方法分解爲確定性較小的組件並對其進行測試。然後通過提供從基礎方法(可能位於不同對象上)返回可預測值的模擬實現來測試使用這些方法的方法。然後,您可以撰寫涵蓋各種方法領域的測試,確保您覆蓋全部可能的結果。對於通過提供代表輸入域的值的小型方法。對於依賴於這些方法的方法,通過提供模擬實現來返回依賴關係的結果範圍。

+0

這條建議很有幫助。在這個例子中,我正在通過一個動態程序來進行逼近。這可以被分解爲確定性的幾個分量: 1.計算特定部分近似的誤差。我可以通過一些特定的曲線手工完成。 2.確保總體目標函數是正確的。再次,我可以手工完成。 3.確保動態程序是正確的。 (這是錯誤發生的地方。) – forefinger 2010-02-10 21:23:30

+1

如果我知道總體目標函數是正確的,我可以通過提供簡單的可分解曲線進行測試。只要答案給了我比我想要的答案更好的分數,動態程序可能正常工作。 – forefinger 2010-02-10 21:24:01

11

「那麼我並沒有真正測試出所有可能出錯的東西。」

正確。

的單元測試工作是測試一切可能出錯。

單元測試的工作是測試你有什麼權利事情,給出具體的輸入和具體的預期結果。這裏的重要部分是具體的可見的,外部要求通過特定的測試用例來滿足。不是說每一件可能出錯的事情都會被阻止。

沒什麼可以測試一切都可能出錯。你可以寫一個證明,但你很難寫的一切的測試。

明智地選擇你的測試用例。另外,單元測試的工作就是測試整個應用程序的每個小部分都是正確的 - 孤立地進行測試。

例如,您的「用較低分辨率曲線近似曲線的代碼」可能有幾個小部件可以作爲單獨的單位進行測試。處於隔離狀態。整體整體也可以進行測試,以確保它的工作。

例如,「在較低分辨率曲線上的計算密集型工作」可能有幾個小部件可以作爲單獨的單位進行測試。處於隔離狀態。

單元測試的要點是創建稍後組裝的小的,正確的單元。

+0

這似乎是合理的建議,但它不像其他一些迴應那樣幫助解決我的具體問題。 – forefinger 2010-02-10 22:31:23

+0

「具體問題」?這並不容易理解,因爲你的問題似乎沒有列出任何具體問題。如果您需要更多信息,請隨時更新您的問題。 – 2010-02-10 22:38:57

1

一般來說,對於統計測量,你可以在你的答案中建立一個epsilon。 I.E.你的積分的均方差將是< 0.01或其他。另一種選擇是運行多次,如果「太頻繁」失敗,那麼你有問題。

6

您的單元測試需要使用某種模糊因子,要麼通過接受近似值,要麼使用某種概率檢查。

例如,如果您有一些函數返回浮點結果,那麼編寫可在所有平臺上正確運行的測試幾乎是不可能的。您的支票需要執行近似值。

TEST_ALMOST_EQ(result, 4.0); 

以上TEST_ALMOST_EQ可能驗證result是3.9和4.1(例如)之間。或者,如果您的機器學習算法是概率性的,那麼您的測試需要通過取多次運行的平均值並期望它在某個範圍內來適應它。

x = 0; 
for (100 times) { 
    x += result_probabilistic_test(); 
} 

avg = x/100; 
TEST_RANGE(avg, 10.0, 15.0); 

Ofcourse,測試是不確定的,所以你需要對其進行調整,這樣你可以得到一個高概率的非片狀的測試。 (例如,增加試驗次數或增加誤差範圍)。

您也可以使用模擬(例如,用於您的概率算法的模擬隨機數生成器),它們通常有助於確定性地測試特定的代碼路徑,但它們需要很多努力來維護。理想情況下,您可以使用模糊測試和mocks的組合。

HTH。

+0

這是一個很好的建議,但它並不能真正解決我的問題,因爲我需要檢查的許多事情都是離散的,所以不能爲他們計算錯誤,而且他們不能被有意義地平均。 – forefinger 2010-02-10 21:25:44

0
  1. 找一個合適的測試數據集
  2. 計算這個數據集的一些指標(也許您通常使用的是什麼的一個子集)(例如,精度)
  3. 記下獲得的(交叉驗證)的值
  4. 這應該是在修改代碼時給出如何設置爲

當然門檻的跡象,如果可以的數據集的性能會增加一點,但是如果它減少了很多,這可能表明出現了問題。