60908


「ゼロから作るDeep Learning」でP.104の勾配を求める関数 `numerical_gradient` に関してです。

[code]

    def f2(x):
        return x[0]**2 + x[1]**2
    
    
    def numerical_gradient(f, x):
        h = 1e-4 
        grad = np.zeros_like(x)
    
        for idx in range(x.size):
            tmp_val = x[idx]
            x[idx] = tmp_val + h
            fxh1 = f(x)
    
            x[idx] = tmp_val - h
            fxh2 = f(x)
    
            grad[idx] = (fxh1 - fxh2)/(2*h)
            x[idx] = tmp_val
    
        return grad
    
[/code]

f2の勾配をnumerical_gradientで求めたいのですが、

[code]

    numerical_gradient(f2, np.array([3.0, 4.0]))
    numerical_gradient(f2, np.array([3, 4]))
    
[/code]

この２つで結果が変わる理由がわかりません。  
なぜ下の方法だとうまくいかないのか、どなたかわかる方がいらっしゃれば教えてください。  
よろしくおねがいします。


CC BY-SA 4.0
2019-11-28T05:29:55.287
60906
2019-11-28T10:14:17.480
2019-11-28T05:52:17.687
3060
36826
question
python numpy 深層学習
ゼロから作るDeep Learning


ndarrayは内部に「型」をもちます。

[code]

    print(np.array([3.0, 4.0]).dtype)
    # float64
    print(np.array([3, 4]).dtype)
    # int32
    
[/code]

今回のような浮動小数点数の計算をしたい場合に、`int`系の型のndarrayを渡すと、結果がintに丸められてしまいます。

[code]

    x = np.array([3, 4])
    x[0] += 0.1
    print(x)
    # [3 4]
    
[/code]

次のようにすれば、`[3.0,4.0]`と同じ結果を得るはずです:

[code]

    numerical_gradient(f2, np.array([3, 4]).astype(np.float))
    
[/code]

参考:

  * <https://docs.scipy.org/doc/numpy/reference/generated/numpy.dtype.html#numpy.dtype>
  * <https://docs.scipy.org/doc/numpy/user/basics.types.html>


CC BY-SA 4.0
2019-11-28T06:07:29.963
60908
2019-11-28T06:14:56.753
2019-11-28T06:14:56.753
36828
36828
60906
answer


user36828さんの回答ですでに決着していますが、整数を渡した場合と小数を渡した場合で具体的にどのような違いが出るのか興味が出てきましたので調べてみました。

ケース１

[code]

    numerical_gradient(f2, np.array([3.0, 4.0]))
    
[/code]

と  
ケース２

[code]

    numerical_gradient(f2, np.array([3, 4]))
    
[/code]

で、次の計算結果が変わりました。

[code]

    x[idx] = tmp_val - h
    
[/code]

ケース１のとき、`x[idx]`はtmp_valよりhだけ小さい小数になりますが、  
ケース２のときは`tmp_val - h`の計算結果の小数部が切り捨てられた整数が`x[idx]`に格納されます。

私も少し前「ゼロから作るDeep
Learning」の３章から５章のソースコードを勉強のため写経(※)してみたのですが、整数を渡すとき`numerical_gradient`の振る舞いが変わるなんて思いもよりませんでした。※コピーペーストではなく手打ち

整数でも小数でも、どちらでも対応可能なコードを考えてみようと思いました。  
実はちょっと試してみたのですが、うまくいかず、宿題になりました。


CC BY-SA 4.0
2019-11-28T10:14:17.480
60917
2019-11-28T10:14:17.480
35558
60906
answer