【问题标题】:Backward Propagation - Gradient error [Python]反向传播 - 梯度误差 [Python]
【发布时间】:2017-08-15 11:49:29
【问题描述】:

我正在学习 Andrew Ng 新的深度学习 Coursera 课程,第 2 周。

我们应该实现逻辑回归算法。
我卡在渐变代码 (dw) - 给我一个语法错误。

算法如下:

import numpy as np

def propagate(w, b, X, Y):
    m = X.shape[1]

    A = sigmoid(np.dot(w.T,X) + b )  # compute activation
    cost = -(1/m)*(np.sum(np.multiply(Y,np.log(A)) + np.multiply((1-Y),np.log(1-A)), axis=1)    

    dw =(1/m)*np.dot(X,(A-Y).T)
    db = (1/m)*(np.sum(A-Y))
    assert(dw.shape == w.shape)
    assert(db.dtype == float)
    cost = np.squeeze(cost)
    assert(cost.shape == ())

    grads = {"dw": dw,
             "db": db}

    return grads, cost

任何想法为什么我不断收到此语法错误?

File "<ipython-input-1-d104f7763626>", line 32
    dw =(1/m)*np.dot(X,(A-Y).T)
     ^
SyntaxError: invalid syntax

【问题讨论】:

  • 请将您的代码粘贴到 StackOverflow 中。
  • 你的意思是与图像?
  • .T 看起来很可疑...
  • @kyttcar 是的,始终将您的代码作为文本粘贴到 SO 中。

标签: python machine-learning deep-learning gradient


【解决方案1】:

Andrew NG 很有启发性,这是毫无疑问的
但是可以通过几个步骤来获得更好的代码设计:

提示 1
如果认真维护更大的代码库,请开始使用更好的 IDE,其中两个
(a) 括号匹配支持 GUI 突出显示和
(b) 跳转到匹配括号 KBD 快捷方式

    cost = - ( 1 / m ) * ( np.sum(   np.multiply(       Y,   np.log(     A ) )
                                   + np.multiply( ( 1 - Y ), np.log( 1 - A ) ),
                                   axis = 1
                                   )
                           ) # missing-parenthesis

提示 2:
在所有教学大纲任务都自动评分之后,尝试提高您的代码性能 - 并非所有步骤都经过性能优化,这对于小规模的学习任务是宽容的,而一旦扩展到更大的学习任务,这可能会扼杀您的方法 @987654323 @O( N^k ) 在两个 [PTIME,PSPACE] 维度中。

对于 1E+3 来说似乎可以正常工作,但无法为 1E+6 或 1E+9 示例提供训练,如果某些 ML 管道在 ML 模型的 HyperPARAMETERs 上迭代,则更少[EXPTIME,EXPSPACE] -搜索域。那很痛。然后,一旦[PSPACE]-问题的大小不适合计算基础架构的内存处理,就会开始更仔细地编写代码以进行权衡,付出过多的[PTIME][EXPTIME]-成本。

在哪里?

--避免重复计算同一事物,如果考虑到数组则越多
(在所有迭代方法中,ML-pipelines + ML-model-HyperPARAMETERs 的巨大,确实 VAST SPACE 搜索
每个浪费的 [ns] 很快就会变成累积的 [us],如果不是 [ms],
每个浪费的 [ms] 很快就会变成累积的 [s],如果不是几十 [min],
每个 浪费的 [min] 很快就会变成累积的 [hrs],如果不是 [days] .. . 是的, 糟糕的代码设计可能会让日子不好过)

示例:

# here, A[] is .ALLOC'd + .SET -----------------------------[PTIME]
A = sigmoid( np.dot( w.T, X )
           + b
             )  # compute activations, .SET in A[]
# ----------------------------------------------------------[PTIME]-cost was paid
cost = -( 1 / m ) * ( np.sum(   np.multiply(      Y,   np.log(     A ) )
                              + np.multiply( (1 - Y ), np.log( 1 - A ) ),
                                axis = 1
                                )
                      )
# ----------------------------------------------------------[PTIME]-cost again?
dw =  ( 1 / m ) *   np.dot( X, ( A - Y ).T )    # consumes ( A - Y )
db =  ( 1 / m ) * ( np.sum(      A - Y )   )    # consumes ( A - Y ) again
# ----------------------------------------------# last but not least,
#                                               # A[] is not consumed
#                                               #     till EoFun/return
# a better approach is to use powerful + faster [PTIME] numpy in-place operations
# that also avoid additional dynamic allocation [PSPACE] -> saving more [PTIME]
DIV_byM = 1 / m                                 # re-use O(N^2) times
A      -= Y                                     # way faster in-place + re-used
# ----------------------------------------------# [PTIME]-cost avoided 2x
dw      = np.dot( X, A.T )                      #        +1st re-use
dw     *= DIV_byM                               # way faster in-place

assert( dw.shape == w.shape and "INF: a schoolbook assert()-ion test, "
                            and "of not much value in PRODUCTION-code"
                            )
return { 'dw': dw,                              
         'db': DIV_byM * np.sum( A )            #        +2nd re-use
          }                                     # MUCH better to design
#                                               # the whole as in-place mods
#                                               # of static .ALLOC'd np.view-s,
#                                               # instead of new dict()-s

[TEST-ME] 是一个很好的设计实践,但是
[PERF-ME] 扩展对于成熟代码更重要 - 一个评估的好实践:

一个好的工程实践是将自己的代码与一些实际的操作状态/条件进行基准测试。

鉴于使用了,可以假设一组缩放范围——大约 20 M 神经元,大约 30 M 神经元——来对代码执行时间进行基准测试和自我记录:

        """                                                            __doc__
        USAGE:      ...
        PARAMETERS: ...
        ...
        EXAMPLE:    nnFeedFORWARD( X_example, nnMAP, thetaVEC, stateOfZ, stateOfA )

        [TEST-ME]   ...
        [PERF-ME]   *DO NOT* numba.jit( nnFeedFORWARD, nogil = True ) as it performs worse than with plain numpy-OPs

                        ~ 500 .. 1200 [us / 1E6 theta-s .dot() ] on pre-prepared np.view()-s
                        ~ 500 .. 1200 [us / 1E6 theta-s *= 0.  ] on pre-prepared np.view()-s
            ############################################################
            #
            # as-is:    ~   9 [ms / 21M Theta-s .dot() ] on pre-prepared np.view()-s for MAT + INCL. np.random/rand( 1000 ) ~~ 40 [us]
                              [  /  10k NEURONs tanh() ] in  5 LAYERs
                        ~  14 [ms / 30M Theta-s .dot() ]
                              [  /  17k NEURONs tanh() ] in 10 LAYERs
                        >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> * ~ 1E6 iterations in { .minimize() | .fmin_l_bfgs_b() }
                        ~   4 [hrs / 1E6 iterations ] w/o backprop

【讨论】:

    【解决方案2】:

    cost = ... 行最后少了一个括号,或者删除* 后面的括号:

    # ...
    cost = -(1/m)*np.sum(np.multiply(Y,np.log(A)) + np.multiply((1-Y),np.log(1-A)), axis=1)
    # ...
    

    【讨论】:

    • 这解决了我的问题,但仍然不明白 np.sum(v1 + v2) 函数是如何工作的。
    • @RidaIftikhar np.sum 只是添加给定数组中的所有值。如果你做np.sum(v1 + v2),那么你首先计算v1 + v2,它给你一个新数组,np.sum 将把这个新数组的所有值相加。
    【解决方案3】:

    “成本”行中缺少一个右括号“)”,这会在下一行中产生语法错误。

    试试这个 -

    cost = -(1/m) * sum(np.multiply(Y, np.log(A)) + np.multiply((1 - Y), np.log(1 - A)))
    

    【讨论】:

      猜你喜欢
      • 2018-01-02
      • 1970-01-01
      • 2020-01-07
      • 1970-01-01
      • 2018-05-23
      • 2016-05-09
      • 2017-07-27
      • 2021-01-15
      • 1970-01-01
      相关资源
      最近更新 更多