吴恩达深度学习deeplearning.ai学习笔记(一)2.11 2.12 2.13 2.15 2.16 2.17

2.11 向量化

什么是向量化?通过两个例子说明:

例1:计算z=w^Tx+b,w\in \mathbb{R}^{n_x},x\in \mathbb{R}^{n_x}

Non-Vectorized:

         z=0

         for\ i\ in\ range(n_x):

                z+=w[i]\ast x[i]

         z+=b

Vectorized:

         z=np.dot(w,x)+b

注意:np.dot指令对两个一维数组而言,求的是它们的内积;

例2:举一个例子说明向量化使计算速度提升

import\ numpy\ as\ np

a=np.array([1,2,3,4])

print(a)

#按下Shift和enter可执行上述代码,屏幕显示[1,2,3,4];

import\ time

a=np.random.rand(1000000)

b=np.random.rand(1000000)

tic=time.time()

c=np.dot(a,b)

toc=time.time()

print(\text{"}Vectorized\ version:\text{"}+str(1000\times (toc-tic))+\text{"}ms\text{"})

#生成两个百万维度的数组,直接计算内积,耗时约1.5ms;

c=0

tic=time.time()

for\ i\ in\ range(1000000):

        c+=a[i]\ast b[i]

toc=time.time()

print(\text{"}For\ loop:\text{"}+str(1000\times (toc-tic))+\text{"}ms\text{"})

#结果for loop 耗时约450ms,用了接近300倍的时间。

2.12 向量化的更多例子

例3:A是一个m\times n矩阵,v是一个n\times 1向量,试求u=Av

Non-Vectorized:

u=np.zeros((m,1))

for\ i=1\ to\ m:

        for\ j=1\ to\ n:

                u[i]+=A[i][j]\ast v[j]

Vectorized:

u=np.dot(A, v)

注意np.dot指令对两矩阵而言求的是矩阵乘法;

例4:假设内存中已有一个向量v=\begin{bmatrix} v_1\\ v_2\\ \cdots\\ v_n \end{bmatrix},求u=\begin{bmatrix} e^{v_1}\\ e^{v_2}\\ \cdots\\ e^{v_n} \end{bmatrix}

Non-Vectorized:

u=np.zeros((n,1))

for\ i\ in\ range(n):

        u[i]=math.exp(v[i])

Vectorized:

import\ numpy\ as\ np

u=np.exp(v)

例5:修改版本2的程序

对于(1)处,由于可以令dw=\begin{bmatrix} dw_1\\ dw_2\\ \cdots\\ dw_{n_x} \end{bmatrix},因此直接让dw初始化为0矩阵,就相当于初始化了dw_1=0;dw_2=0;\cdots;dw_{n_x}=0,即:

dw=np.zeros((n_x,1))

(2)处则是要实现dw_1+=x_1^{(i)}dz^{(i)};dw_2+=x_2^{(i)}dz^{(i)};\cdots;dw_{n_x}+=x_{n_x}^{(1)}dz^{(i)}n_x个式子,现在已经定义了dw,于是:

dw+=x^{(i)}dz^{(i)}

这一个式子就等效代替了上面n_x个式子,因为:

dw=\begin{bmatrix} dw_1\\ dw_2\\ \cdots\\ dw_{n_x} \end{bmatrix}+=\begin{bmatrix} x_1^{(i)}dz^{(i)}\\ x_2^{(i)}dz^{(i)}\\ \cdots\\ x_{n_x}^{(i)}dz^{(i)} \end{bmatrix}=\begin{bmatrix} x_1^{(i)}\\ x_2^{(i)}\\ \cdots\\ x_{n_x}^{(i)} \end{bmatrix}dz^{(i)}=x^{(i)}dz^{(i)}

(3)处直接改为dw/=m

(4)处直接改为w:=w-\alpha dw

版本3:

dw=np.zeros((n_x,1));db=0

For\ i=1\ to\ m:

         z^{(i)}=w^Tx^{(i)}+b\rightarrow (1)

         a^{(i)}=\sigma(z^{(i)})\rightarrow (2)

         dz^{(i)}=a^{(i)}-y^{(i)}\rightarrow (3)

         dw+=x^{(i)}dz^{(i)}\rightarrow (4)

         db+=dz^{(i)}\rightarrow (5)

dw/=m;db/=m

w:=w-\alpha dw

b:=b-\alpha db

2.13 向量化logistic回归

版本3的(1)处要做z^{(1)}=w^Tx^{(1)}+b;z^{(2)}=w^Tx^{(2)}+b;\cdots;z^{(m)}=w^Tx^{(m)}+bm次操作,因此先定义:

Z=\begin{bmatrix} z^{(1)} &z^{(2)} &\cdots & z^{(m)} \end{bmatrix}

X=\begin{bmatrix} x^{(1)} &x^{(2)} &\cdots & x^{(m)} \end{bmatrix}

(1)处的这m次操作可以由一行代码代替:

Z=np.dot(w.T,X)+b

原因如下:

首先:w^TX=w^T\begin{bmatrix} x^{(1)} &x^{(2)} &\cdots & x^{(m)} \end{bmatrix}

\because w^T是一个n_x维行向量,x^{(1)},x^{(2)} ,\cdots , x^{(m)}都是n_x维列向量,由矩阵乘法可知w^T和任何一个x^{(i)},i=1,2,\cdots,m相乘都将是一个数,且w^TX矩阵相乘出来是一个1\times m的矩阵

\therefore w^TX=\begin{bmatrix} w^Tx^{(1)} &w^Tx^{(2)} &\cdots & w^Tx^{(m)} \end{bmatrix}

更加详细、严谨的证明是:

w^TX=\begin{bmatrix} w_1 &w_2 &\cdots & w_{n_x} \end{bmatrix}\begin{bmatrix} x_1^{(1)} & x_1^{(2)} & \cdots & x_1^{(m)}\\ x_2^{(1)}& x_2^{(2)} & \cdots & x_2^{(m)}\\ \vdots & \vdots & & \vdots\\ x_{n_x}^{(1)}&x_{n_x}^{(2)} & \cdots & x_{n_x}^{(m)} \end{bmatrix}

=\begin{bmatrix} w_1x_1^{(1)}+w_2x_2^{(1)}+\cdots+w_{n_x}x_{n_x}^{(1)} &\cdots & w_1x_1^{(m)}+w_2x_2^{(m)}+\cdots+w_{n_x}x_{n_x}^{(m)} \end{bmatrix}

w^Tx^{(1)}=\begin{bmatrix} w_1 &w_2 &\cdots & w_{n_x} \end{bmatrix}\begin{bmatrix} x_1^{(1)}\\ x_2^{(1)}\\ \vdots\\ x_{n_x}^{(1)} \end{bmatrix}=w_1x_1^{(1)}+w_2x_2^{(1)}+\cdots+w_{n_x}x_{n_x}^{(1)}

\cdots

w^Tx^{(m)}=\begin{bmatrix} w_1 &w_2 &\cdots & w_{n_x} \end{bmatrix}\begin{bmatrix} x_1^{(m)}\\ x_2^{(m)}\\ \vdots\\ x_{n_x}^{(m)} \end{bmatrix}=w_1x_1^{(m)}+\cdots+w_{n_x}x_{n_x}^{(m)}

\therefore w^TX=\begin{bmatrix} w^Tx^{(1)} &w^Tx^{(2)} &\cdots & w^Tx^{(m)} \end{bmatrix}

其次:

w^TX+b在Python中会通过广播自动地将实数b扩展为1\times m矩阵\begin{bmatrix} b & \cdots & b \end{bmatrix},即:

w^TX+b=\begin{bmatrix} w^Tx^{(1)}+b &w^Tx^{(2)}+b &\cdots & w^Tx^{(m)} +b\end{bmatrix}

最后:

Z=\begin{bmatrix} z^{(1)} &z^{(2)} &\cdots & z^{(m)} \end{bmatrix}=\begin{bmatrix} w^Tx^{(1)}+b &w^Tx^{(2)}+b &\cdots & w^Tx^{(m)} +b\end{bmatrix}\\=w^TX+b

就相当于完成了所需的m次操作;

w^TX编程时,用w.T表示w转置后的矩阵,用np.dot(w.T,X)表示两矩阵相乘;

(2)处定义A=\begin{bmatrix} a^{(1)} &a^{(2)} &\cdots & a^{(m)} \end{bmatrix},即可用一行式子代替:

A=\sigma(Z)

因为:

A=\begin{bmatrix} a^{(1)} &a^{(2)} &\cdots & a^{(m)} \end{bmatrix}=\begin{bmatrix} \sigma(z^{(1)}) &\sigma(z^{(2)}) &\cdots & \sigma(z^{(m)}) \end{bmatrix}\\=\sigma(\begin{bmatrix} z^{(1)} &z^{(2)} &\cdots & z^{(m)} \end{bmatrix})=\sigma(Z)

(3)处要做dz^{(1)}=a^{(1)}-y^{(1)};dz^{(2)}=a^{(2)}-y^{(2)};\cdots;dz^{(m)}=a^{(m)}-y^{(m)}m次操作,定义矩阵:

dZ=\begin{bmatrix} dz^{(1)} &dz^{(2)} &\cdots & dz^{(m)} \end{bmatrix}

Y=\begin{bmatrix} y^{(1)} &y^{(2)} &\cdots & y^{(m)} \end{bmatrix}

于是用一行代码就可以代替上面m次操作:

dZ=A-Y

因为:

dZ=\begin{bmatrix} dz^{(1)} &dz^{(2)} &\cdots & dz^{(m)} \end{bmatrix}\\=\begin{bmatrix} a^{(1)}-y^{(1)} & a^{(2)}-y^{(2)} & \cdots & a^{(m)}-y^{(m)} \end{bmatrix}\\ =\begin{bmatrix} a^{(1)} &a^{(2)} &\cdots & a^{(m)} \end{bmatrix}-\begin{bmatrix} y^{(1)} &y^{(2)} &\cdots & y^{(m)} \end{bmatrix}=A-Y

(4)处要做dw+=x^{(1)}dz^{(1)};dw+=x^{(2)}dz^{(2)};\cdots;dw+=x^{(m)}dz^{(m)}共m次相加操作,且考虑后面要进行dw/=m,可用一行式子代替:

dw=\frac{1}{m}XdZ^T

因为:

dw=x^{(1)}dz^{(1)}+x^{(2)}dz^{(2)}+\cdots+x^{(m)}dz^{(m)}

并且dz^{(1)},dz^{(2)},\cdots,dz^{(m)}都是数;

\because x^{(1)}dz^{(1)}=\begin{bmatrix} x_1^{(1)}\\ x_2^{(1)}\\ \vdots\\ x_{n_x}^{(1)} \end{bmatrix}dz^{(1)}=\begin{bmatrix} x_1^{(1)}dz^{(1)}\\ x_2^{(1)}dz^{(1)}\\ \vdots\\ x_{n_x}^{(1)}dz^{(1)} \end{bmatrix}

\cdots

x^{(m)}dz^{(m)}=\begin{bmatrix} x_1^{(m)}dz^{(m)}\\ x_2^{(m)}dz^{(m)}\\ \vdots\\ x_{n_x}^{(m)}dz^{(m)} \end{bmatrix}

\therefore dw=\begin{bmatrix} x_1^{(1)}dz^{(1)}+x_1^{(2)}dz^{(2)}+\cdots+x_1^{(m)}dz^{(m)}\\ x_2^{(1)}dz^{(1)}+x_2^{(2)}dz^{(2)}+\cdots+x_2^{(m)}dz^{(m)}\\ \vdots \\ x_{n_x}^{(1)}dz^{(1)}+x_{n_x}^{(2)}dz^{(2)}+\cdots+x_{n_x}^{(m)}dz^{(m)} \end{bmatrix}

\because XdZ^T=\begin{bmatrix} x_1^{(1)} & x_1^{(2)} & \cdots & x_1^{(m)}\\ x_2^{(1)}& x_2^{(2)} & \cdots & x_2^{(m)}\\ \vdots & \vdots & & \vdots\\ x_{n_x}^{(1)}&x_{n_x}^{(2)} & \cdots & x_{n_x}^{(m)} \end{bmatrix}\begin{bmatrix} dz^{(1)}\\ dz^{(2)}\\ \vdots\\ dz^{(m)} \end{bmatrix}\\=\begin{bmatrix} x_1^{(1)}dz^{(1)}+x_1^{(2)}dz^{(2)}+\cdots+x_1^{(m)}dz^{(m)}\\ x_2^{(1)}dz^{(1)}+x_2^{(2)}dz^{(2)}+\cdots+x_2^{(m)}dz^{(m)}\\ \vdots \\ x_{n_x}^{(1)}dz^{(1)}+x_{n_x}^{(2)}dz^{(2)}+\cdots+x_{n_x}^{(m)}dz^{(m)} \end{bmatrix}

\therefore dw=XdZ^T

最后结合上dw/=m就变为dw=\frac{1}{m}XdZ^T

(5)处要做db+=dz^{(1)},db+=dz^{(2)},\cdots,db+=dz^{(m)}共m次相加,即:

db=dz^{(1)}+dz^{(2)}+\cdots+dz^{(m)}=\sum_{i=1}^{m}dz^{(i)}

实际上,对于矩阵dZ=\begin{bmatrix} dz^{(1)} &dz^{(2)} &\cdots & dz^{(m)} \end{bmatrix}而言,使用元素求和指令np.sum(dZ)就可以实现对这m个数求和,结合db/=m,用一行代码就可以替代:

db=\frac{1}{m}np.sum(dZ)

版本4:(一次梯度下降的最终版本)

dW=np.zeros((n_x,1));db=0

Z=np.dot(w.T,X)+b

A=\sigma(Z)

dZ=A-Y

dw=\frac{1}{m}XdZ^T

db=\frac{1}{m}np.sum(dZ)

w:=w-\alpha dw

b:=b-\alpha db

这仅仅完成了一次梯度下降,要实现多次梯度下降应该在最外层加上一个不可省略的for loop来进行一定次数的梯度下降:

for\ inter\ in\ range(1000)

         \cdots

就是执行1000次这样的梯度下降。

2.15 Python中的广播

Python对两个矩阵(也可以是实数)做加减乘除时,遇到尺寸不一样的情况,会自动成行成列copy形成一样尺寸的矩阵,然后再逐元素进行加减乘除。

\begin{bmatrix} 1\\ 2\\ 3\\ 4 \end{bmatrix}+100=\begin{bmatrix} 1\\ 2\\ 3\\ 4 \end{bmatrix}+\begin{bmatrix} 100\\ 100\\ 100\\ 100\end{bmatrix}

\begin{bmatrix} 1 &2 & 3 & 4 \end{bmatrix}+100=\begin{bmatrix} 1 &2 & 3 & 4 \end{bmatrix}+\begin{bmatrix} 100 &100 & 100 & 100 \end{bmatrix}

\begin{bmatrix} 1 & 2 & 3\\ 4 & 5& 6 \end{bmatrix}+\begin{bmatrix} 100 &200 &300 \end{bmatrix}=\begin{bmatrix} 1 & 2 & 3\\ 4 & 5& 6 \end{bmatrix}+\begin{bmatrix} 100 & 200 & 300\\ 100 & 200 & 300 \end{bmatrix}

\begin{bmatrix} 1 & 2 & 3\\ 4 & 5& 6 \end{bmatrix}+\begin{bmatrix} 100\\ 200\end{bmatrix}=\begin{bmatrix} 1 & 2 & 3\\ 4 & 5& 6 \end{bmatrix}+\begin{bmatrix} 100 & 100& 100\\ 200& 200 & 200\end{bmatrix}

2.16 关于Python_numpy向量的说明

不要使用a=np.random.randn(5)去生成一个向量,因为当你用a.shape查看它时会发现:

a.shape=(5,)

这就是说它是一个秩为1的数组,既不是行向量,也不是列向量,无法准确地对它进行转置、求外积、求内积……

应该使用以下两种:

a=np.random.randn(5,1)生成一个5维的列向量;

a=np.random.randn(1,5)生成一个5维的行向量;

如果不确定一个向量的维度,可以用assert函数,运行很快,多用就好:

assert(a.shape==(5,1))

它会计算表达式,如果其值为假(即0),那么它会先向stderr打印出一条出错信息,然后调用abort来终止程序的运行;

如果不可避免地得到一个数组,可以用a=a.reshape((5,1))来把它转为5维列向量,行向量的转法也是类似的。

2.17 logistic损失函数的解释

对于损失函数如何解释?

\because \hat{y}=P\{y=1|x\}

1-\hat{y}=P\{y=0|x\}

If\ y=1:P\{y|x\}=\hat{y}

If\ y=0:P\{y|x\}=1-\hat{y}

\therefore P\{y|x\}=\hat{y}^y \cdot(1-\hat{y})^{(1-y)}

\therefore lnP\{y|x\}=yln\hat{y}+(1-y)ln(1-\hat{y})

希望P\{y|x\}尽量大且能最小化L(\hat{y},y),故定义:

L(\hat{y},y)=-lnP\{y|x\}=-[yln\hat{y}+(1-y)ln(1-\hat{y})]

而对于成本函数如何解释?

\because P(labels\ in\ training\ set)= ^{iid}=\prod_{i=1}^{m}P\{y^{(i)}|x^{(i)}\}

\therefore lnP(labels\ in\ training\ set)= \sum_{i=1}^{m}P\{y^{(i)}|x^{(i)}\}\\=-\sum_{i=1}^{m}L(\hat{y}^{(i)},y^{(i)})

要使P(labels\ in\ training\ set)最大且能最小化J(w,b),故定义:

J(w,b)=-\frac{1}{m}lnP(labels\ in\ training\ set)=\frac{1}{m}\sum_{i=1}^{m}L(\hat{y}^{(i)},y^{(i)})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值