当前位置: 首页 > >

深度学*| 用神经网络思想实现Logistic回归

发布时间:

吴恩达《深度学*》L1W2作业1
本文是跟着参考资料的博主梳理一遍,化为内功!
我使用的编译环境是天池的notebook。


1 使用numpy构建基本函数
1.1 sigmoid function 和np.exp()

什么是sigmoid函数?
也称为逻辑函数,它是一种非线性函数,可以用来解决二分类问题。
它的优点是函数处处可导;函数范围在[0,1]之间(可以用来压缩数据)。

用math.exp()实现sigmoid函数:


import math

def basic_sigmoid(x):
s=1/(1+math.exp(-x))
return s

basic_sigmoid(3)

输出结果为:
但是在深度学*中主要使用的是矩阵和向量,如果用math的话会报错,比如:


x = [1, 2, 3]
basic_sigmoid(x)


所以用numpy更为合适,例如输入x行向量,求:

import numpy as np

x=np.array([1,2,3])
print(np.exp(x))# result is (exp(1), exp(2), exp(3))


如果x是向量,则s=x+3或s=1/x之类的Python运算将输出与x维度大小相同的向量s:

import numpy as np

x=np.array([1,2,3])
print(x+3)


用numpy实现sigmoid函数,其中x可能是是实数,向量或者矩阵:

import numpy as np

def sigmoid(x):
s=1/(1+np.exp(-x))
return s

x=np.array([1,2,3])
sigmoid(x)


1.2 sigmoid gradient
需要计算梯度来使用反向传播优化损失函数,创建函数sigmoid_grad()计算sigmoid函数相对于其输入x的梯度。 公式为:
一般分为两步编写此代码:
1 将s设为x的sigmoid2 计算

import numpy as np

def sigmoid(x):
s=1/(1+np.exp(-x))
return s

def sigmoid_derivative(x):
s=sigmoid(x)
ds=s*(1-s)
return ds

x=np.array([1,2,3])
print("sigmoid_derivative(x)="+str(sigmoid_derivative(x)))


1.3 重塑函数
深度学*中两个常用的numpy函数是np.shape和np.reshape()。
X.shape用于获取矩阵/向量X的shape(维度)。X.reshape(…)用于将X重塑为其他尺寸。 比如在读取图像作为算法输入时,需要将(length,height,depth=3)转换成(length*height*3,1)
实现image2vector() ,该输入采用维度为(length, height, 3)的输入,并返回维度为(length*height*3, 1)的向量。
例如,如果你想将形为(a,b,c)的数组v重塑为维度为(a*b, 3)的向量,则可以执行以下操作:

v = v.reshape((v.shape[0]*v.shape[1], v.shape[2])) # v.shape[0] = a ; v.shape[1] = b ; v.shape[2] = c

不要将图像的尺寸硬编码为常数。而是通过image.shape [0]等来查找所需的数量。

def image2vector(image):
v=image.reshape(image.shape[0]*image.shape[1]*image.shape[2],1)
return v
image = np.array([[[ 0.67826139, 0.29380381],
[ 0.90714982, 0.52835647],
[ 0.4215251 , 0.45017551]],

[[ 0.92814219, 0.96677647],
[ 0.85304703, 0.52351845],
[ 0.19981397, 0.27417313]],

[[ 0.60659855, 0.00533165],
[ 0.10820313, 0.49978937],
[ 0.34144279, 0.94630077]]])

print("image2vector(image)="+str(image2vector(image)))


1.4 行标准化
由于归一化后梯度下降的收敛速度更快,通常会表现出更好的效果。归一化,也就是将x的每个向量除以其范数。


执行 normalizeRows()来标准化矩阵的行。 将此函数应用于输入矩阵x之后,x的每一行应为单位长度(即长度为1)向量。

def normalizeRows(x):
x_norm=np.linalg.norm(x,axis=1,keepdims=True)
x=x/x_norm
return x
x = np.array([
[0, 3, 4],
[1, 6, 4]])
print("normalizeRows(x) = " + str(normalizeRows(x)))


1.5 广播和softmax 函数

numpy中一个很重要的概念是广播,详细信息见官方文档

softmax可以理解为算法需要对两个或多个类进行分类时使用的标准化函数

使用numpy实现softmax函数:


def softmax(x):
x_exp=np.exp(x)
x_sum=np.sum(x_exp,axis=1,keepdims=True)
s=x_exp/x_sum
return s

x = np.array([
[9, 2, 5, 0, 0],
[7, 5, 0, 0 ,0]])
print("softmax(x) = " + str(softmax(x)))


这一节的重点内容:
np.exp(x)适用于任何np.array x并将指数函数应用于每个坐标sigmoid函数及其梯度image2vector通常用于深度学*np.reshape被广泛使用。 保持矩阵/向量尺寸不变有助于我们消除许多错误。numpy具有高效的内置功能broadcasting非常有用
2 向量化
2.1 区分 点/外部/元素乘积之间的区别

import time

x1 = [9, 2, 5, 0, 0, 7, 5, 0, 0, 0, 9, 2, 5, 0, 0]
x2 = [9, 2, 2, 9, 0, 9, 2, 5, 0, 0, 9, 2, 5, 0, 0]

### CLASSIC DOT PRODUCT OF VECTORS IMPLEMENTATION ###
tic = time.process_time()
dot = 0
for i in range(len(x1)):
dot+= x1[i]*x2[i]
toc = time.process_time()
print ("dot = " + str(dot) + "
----- Computation time = " + str(1000*(toc - tic)) + "ms")

### CLASSIC OUTER PRODUCT IMPLEMENTATION ###
tic = time.process_time()
outer = np.zeros((len(x1),len(x2))) # we create a len(x1)*len(x2) matrix with only zeros
for i in range(len(x1)):
for j in range(len(x2)):
outer[i,j] = x1[i]*x2[j]
toc = time.process_time()
print ("outer = " + str(outer) + "
----- Computation time = " + str(1000*(toc - tic)) + "ms")

### CLASSIC ELEMENTWISE IMPLEMENTATION ###
tic = time.process_time()
mul = np.zeros(len(x1))
for i in range(len(x1)):
mul[i] = x1[i]*x2[i]
toc = time.process_time()
print ("elementwise multiplication = " + str(mul) + "
----- Computation time = " + str(1000*(toc - tic)) + "ms")

### CLASSIC GENERAL DOT PRODUCT IMPLEMENTATION ###
W = np.random.rand(3,len(x1)) # Random 3*len(x1) numpy array
tic = time.process_time()
gdot = np.zeros(W.shape[0])
for i in range(W.shape[0]):
for j in range(len(x1)):
gdot[i] += W[i,j]*x1[j]
toc = time.process_time()
print ("gdot = " + str(gdot) + "
----- Computation time = " + str(1000*(toc - tic)) + "ms")


注意 不同于np.multiply()* 操作符(相当于Matlab / Octave中的 .*)执行逐元素的乘法,np.dot()执行的是矩阵-矩阵或矩阵向量乘法,
2.2 实现 L1和L2损失函数
实现L1损失函数的Numpy向量化版本

def L1(yhat,y):
loss=np.sum(np.abs(y-yhat))
return loss
yhat=np.array([.9,0.2,0.1,.4,.9])
y=np.array([1,0,0,1,1])
print("L1="+str(L1(yhat,y)))


实现L2损失函数的Numpy向量化版本。

def L2(yhat,y):
loss=np.dot((y-yhat),(y-yhat).T)
return loss

yhat = np.array([.9, 0.2, 0.1, .4, .9])
y = np.array([1, 0, 0, 1, 1])
print("L2 = " + str(L2(yhat,y)))


这一节的重点内容:
向量化在深度学*中非常重要, 它保证了计算的效率和清晰度。了解L1和L2损失函数。掌握诸多numpy函数,例如np.sum,np.dot,np.multiply,np.maximum等

参考资料:吴恩达《深度学*》L1W2作业1



友情链接: