ex◯の実行結果はあってるはずなのに提出時に合格点にならない・・・
Courseraのプログラミング課題で、テストコードを実行した際には期待通りの結果がでているが、
課題提出の際にscoreが加算されていないことがありました。
フォーラムをみたり、テストケースを実行してみたりして原因究明をしてみたところ、
sum
の第2引数を指定していなかったのが原因でした。
sumを使った勾配計算の実装
線形回帰において、勾配は以下の式で求める。
\frac{\partial J(\theta)}{\partial \theta_{0}} = \frac{1}{m}\sum_{i=1}^{m}(h_{\theta}(x^{(i)}) - y^{(i)})x_{j}^{(i)} \qquad for \quad j > 0 \\
\frac{\partial J(\theta)}{\partial \theta_{j}} = \Bigl( \frac{1}{m}\sum_{i=1}^{m}(h_{\theta}(x^{(i)}) - y^{(i)})x_{j}^{(i)} \Bigr) + \frac{\lambda}{m} \theta_{j} \qquad for \quad j \geq 1
以下のような訓練データ_X_、ラベルデータ_y_、θが与えられるとする。
X =
\begin{bmatrix}
x_1^{(1)} & x_2^{(1)} & \cdots & x_n^{(1)} \\
x_1^{(2)} & x_2^{(2)} & \cdots & x_n^{(2)} \\
\vdots & \vdots & \ddots & \vdots \\
x_1^{(m)} & x_2^{(m)} & \cdots & x_n^{(m)}
\end{bmatrix}
\\
y =
\begin{bmatrix}
y^{(1)} \\
y^{(2)} \\
\vdots \\
y^{(m)}
\end{bmatrix}
\\
\Theta =
\begin{bmatrix}
\theta_1 \\
\theta_2 \\
\vdots \\
\theta_n
\end{bmatrix}
正規化なしの項を以下のように実装してみる。
grad = (1 / m) * sum(((X * theta) - y) .* X)';
適当なデータを作成して計算させてみると、問題なさそうに見える。
octave:1> m = 5;
octave:2> X = rand(m, 3)
X =
0.719964 0.384009 0.471899
0.254826 0.660515 0.465894
0.188693 0.822077 0.075419
0.604758 0.614742 0.231738
0.730915 0.114709 0.894736
octave:3> y = rand(m, 1)
y =
0.312361
0.106697
0.524671
0.493868
0.063764
octave:5> theta = rand(size(X, 2), 1)
theta =
0.57806
0.13361
0.78240
octave:6> grad = (1 / m) * sum(((X * theta) - y) .* X)'
grad =
0.26277
0.10417
0.28947
しかし訓練データが1つのときに、スカラー値が返る。
octave:7> x1 = X(1, :)
x1 =
0.71996 0.38401 0.47190
octave:8> y1 = y(1)
y1 = 0.31236
octave:9> grad = (1 / 1) * sum(((x1 * theta) - y1) .* x1)'
grad = 0.82630
これはsumしているものが前者が行列、後者がベクトルであるためである。
octave:12> ((X * theta) - y) .* X
ans =
0.377508 0.201353 0.247437
0.125725 0.325882 0.229860
-0.046560 -0.202848 -0.018610
0.072067 0.073256 0.027615
0.785089 0.123211 0.961052
octave:13> ((x1 * theta) - y1) .* x1
ans =
0.37751 0.20135 0.24744
sumの挙動について以下の通り。
Built-in Function: sum (x, dim)
次元dim方向の和を計算する。 dimが省略されたときは,1を指定した(列方向に和をとる)とみなす。
例外として,xがベクトルでdimを省略したとき,要素の和を返す。
第2引数の指定がなかったため、ベクトルの要素をsumしてしまっていました。
これを防ぐためにsumの第2引数に1
を指定しましょう。
octave:17> grad = (1 / m) * sum(((X * theta) - y) .* X, 1)'
grad =
0.26277
0.10417
0.28947
まとめ
sum関数を使うときは第2引数を指定しましょう。
プログラミング課題は対象の週のディスカッションフォーラムを見たり、テストケースを実行してデバッグすると原因がわかるかもしれません。