我試圖運行(隨機或批量)梯度下降,當一個使用標準交叉熵(SOFTMAX虧損):在使用softmax損耗時,如何調試和矢量化徑向基函數網絡的偏導數?
使用作爲模型的Radial Basis Function (RBF)網絡時,(你可以觀看講座的形式caltech here),當擴展到多類分類時(通過簡單地將RBF網絡的輸出饋送到softmax層來容易地擴展)。注意,P(y=l|x)
僅通過將RBF網絡的輸出通過每個標記的softmax層來計算l
如下:
其中\theta_l
索引負責做標籤預測的參數l
。
在這方面,我想通過計算關於參數的導數來優化我的模型。回想一下,在徑向基函數網絡中優化的參數是最後一層的權重c
以及第一層的權重t
。我已經實現並調試瞭如何計算權重c
的導數。該代碼按預期工作,因爲偏導數與數值導數匹配。你可以找到單元測試代碼是here。
我也試過編寫相對於中心來實現派生的代碼,但我似乎無法讓我實現派生匹配的數值導數。損失J
相對於中心t_k
我試圖實現的導數的計算公式如下:
其中h_{\theta_l}
對應於負責預測標籤l
的RBF輸出。事實上,h_{\theta_l}
是表達很簡單:
我的主要問題是與相對於t_k
(上面的方程)計算的J
的衍生物。對於這一點,我已經實施了天真地計算它的following function沒有向量化它:
function [ dJ_dt ] = compute_dJ_dt(z,x,y,t,c)
%Computes dJ_dc
% Input:
% z = (K x 1)
% x = data point (D, 1)
% y = labels (1 x 1)
% t = centers (D x K)
% c = weights (K x L)
% Output:
% dJ_dc = (D x K)
[D,K] = size(t);
[~, L] = size(c);
dJ_dt = zeros(D, K);
for k=1:K
dJ_dt_k = zeros(D, 1);
for l=1:L
c_l = c(:,l);
dh_dt_l = compute_dh_dt(z,x,t,c_l); %(D x K)
delta = (y==l);
dJ_dt_k = dJ_dt_k + dh_dt_l(:,k) * delta;
end
dJ_dt(:,k) = -dJ_dt_k;
end
end
和不匹配the numerical derivatives code。
我試過不同的東西來檢查它是否有效,我會在這裏解釋它們。如果任何人有更多的想法,隨時分享,我覺得我用完了新的想法來嘗試調試。
- 首先一個很好的自然問題是,我的數學推導導數是否正確?儘管我沒有明確地檢查過某個人的數學推導,但我有很高的信心,因爲對於模型中的
c
和t
偏導數的推導是相同的,並且您只將符號\theta
更改爲您擁有的任何參數有問題。由於我已經實施了關於c
的衍生工具,並且它通過了我所有的衍生工具測試,所以我會假設衍生工具相對於t
或任何參數\theta
的派生都應該是正確的。可以在math.stack exchange here中看到我對這個公式的推導。 - 一個選項可能是
compute_dJ_dt
實際上並未實現我期待的等式。這確實可能是這種情況,並檢查我是否獨立實施了更多vectorized version of that code以查看我是否實際實施了我在紙面上記錄的公式。由於這個方程的兩個版本輸出相同的微分值,我有很高的信心,他們正在計算,實際上我懷疑的方程(如果有人有進一步矢量化這個方程的方法,那真是太棒了!我添加的矢量化是如此微不足道,以至於它看起來並沒有那麼有趣,或者說在性能上有很大的提升,但它確實會去除一個循環)。
由於我在紙上的方程式(具有高概率)是正確的,並且方程式的實現似乎是正確的,因爲它的兩個版本輸出相同的值,所以它導致我可以得出結論:數值派生代碼有一個錯誤。
- numerical derivative code太簡單了,以至於很難檢查地球上會出現什麼問題。我發現的唯一可能是錯誤的是,可能是我的softmax cost J的實現是錯誤的,但我非常懷疑它,因爲......我已經爲它寫了一個單元測試!另外,我用它來檢查數值衍生物相對於
c
和c
總是通過,所以我無法想象J
是錯誤的。 - 要檢查的最後一件不平凡的事是
compute_dh_dt
正在計算正確。我寫了units tests for dh_dt,並且由於它們在每次運行中都匹配其相應的數值衍生物,所以我會懷疑代碼是正確的。
在這一點上,我不是100%肯定還有什麼其他嘗試我希望也許有人有一個好主意,或者指出我正在做的愚蠢的事情?我不知道現在該怎麼想。感謝幫助和時間社區!