您的位置:首页 > 理论基础 > 计算机网络

深度学习与神经网络-吴恩达(Part1Week2)-Logistic Regression编程实现(python)

2017-10-21 10:34 519 查看

一、Logistic Regression 基本网络结构



可以看到 Logistic Regression的网络结构相对比较简单,主要包括:输入层(用于单样本数据x1,x2,x3...的输入)和输出层(单个神经元),输入层和输出层之间是有权重连接的,这里相当于对输入数据做一个线性变换进而得到输出层的输入。值得注意的是,输出层是包含激活函数的,对于Logistic Regression其激活函数一般是sigmoid函数,形式为g(z)=1/(1+exp(-z)),用于对神经元的输入数据进行非线性映射,将最终结果的值映射到合理的范围内。



二、Forward Propagation——损失函数

Logistic Regression一般包括两个过程,正向传播(Forward propagation)和反馈传播(Backward propagation)。
正向传播即根据输入数据逐步计算初始的z1,a1以及衡量最终结果好坏的损失函数L(a1,y)。上图中,x1,x2表示单个样本的特征属性,w1,w2表示每个输入与神经元之间的权重,b表示神经元的偏置(bias),z1表示神经元的输入,a1表示z1经过非线性映射后的结果。
具体过程如下图所示:





根据计算得到的结果,我们可以计算与期望值之间的损失(或者差别),一般通过平方差来定义:



但由于采用上述损失函数,其会存在多个局部极小值,后续的优化算法(梯度下降法)不太适用,因此更多的采用对数形式,这两种损失函数作用其实相同,但后者更容易进行优化。



分析该损失函数可以发现,如果期望值y=1,那么损失函数L=-logy^,我们会让y^足够大这样才能保证L足够小,这样才能让y^接近1。如果期望值y=0,那么损失函数L=-log(1-y^),我们会让y^足够小这样才能保证L足够小,这样才能让y^接近0。
以上损失函数都是基于单个训练样本定义的,只衡量了网络模型在单个训练样本上的表现。因此,我们这里定义了一个成本函数,用于衡量模型在整个训练集上的表现:



三、Backward Propagation——梯度下降法

我们有了上述成本函数,那么对于我们的模型好坏就有了一个衡量标准,那么我们如何根据成本函数去找到我们所需要的模型?换个角度来讲,也就是如何找到最优的模型参数w和b最小化我们的成本函数?



我们首先要做的就是初始化我们的模型参数w和b(如上图中最上方红点所示),对于logistic回归而言,因为其成本函数是凸的,几乎是任意的初始化方法都有效,无论从哪里出发最终都到达同一点。梯度下降法所做的就是,从初始点开始,朝最陡的下坡方向走一步,这就是梯度下降法的一次迭代,经过一定次数的迭代,梯度下降法是极有可能找到全局最小值点的。
梯度下降法最关键的就是求取损失函数关于模型参数的梯度项dw(也就是下降最陡的方向),那么我们先向前一步(也就是后向传播一步),首先计算损失函数关于a的偏导数记为da,然后由链式法则再向前一步计算dz,最后再计算dw和db,具体计算步骤如下:





计算得到dw,db之后我们就可以在每次迭代时对模型参数w和b进行更新,也就实现了损失函数逐步减小。



四、向量化——计算效率提升

以上关于Logistic Regression的推导都是基于单个样本的,但实际给我们的是一个训练样本集,样本数量很庞大,单个样本进行训练计算效率极低。这里先介绍对整个训练集进行训练的基本步骤,分别计算单个样本的梯度项,随后我会引入向量化的概念及优势。我们以成本函数为(注意和单个样本的损失函数进行区分)切入点来介绍m个样本的正向传播和反向传播,随后的求导也都是基于成本函数的。



从上面的计算流程我们可以看出,其首先是通过for循环遍历所有训练样本,然后再对单个样本计算梯度项,这样一个繁琐的过程必然会降低我们得计算效率。
向量化通常是消除代码中显示for循环语句的艺术,在深度学习中训练集数据集是非常大的,因此向量化对于深度学习算法的运行效率是具有巨大意义的。下面以一个简单的例子来说明for循环和向量化的区别:



因为此时我们得输入由单个样本变为所有样本,也就是由列向量变成了矩阵,我们这里都用大写字母表示,表示包含所有样本数据,这里直接给出最终向量化的正向传播和反向传播,有兴趣的可以去验证一下。



五、源代码(按照自己的思路编写的)

代码里面的训练数据是吴恩达老师编程作业里的数据,还包括几个加载数据的函数,需要的可以在评论里留言。

### Code start here
import numpy as np
import matplotlib.pyplot as plt
import h5py
import scipy
from PIL import Image
from scipy import ndimage
from lr_utils import load_dataset

def sigmoid(x):
return 1.0 / (1.0 + np.exp(-x))

# Input data
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()
train_num = train_set_x_orig.shape[0]
test_num = test_set_x_orig.shape[0]
pix_num = train_set_x_orig.shape[1]
chanel_num = train_set_x_orig.shape[3]
print('\n' + '---------------Input information---------------' + '\n')
print('train_set_x_orig.shape = ' + str(train_set_x_orig.shape))
print('train_set_y.shape = ' + str(train_set_y.shape))
print('test_set_x_orig.shape = ' + str(test_set_x_orig.shape))
print('test_set_y.shape = ' + str(test_set_y.shape))
print('train_num = ' + str(train_num))
print('test_num = ' + str(test_num))
print('pix_num = ' + str(pix_num))
print('chanel_num = ' + str(chanel_num))

# Reshape data
train_set_x_flat = train_set_x_orig.reshape(train_num,-1).T
test_set_x_flat = test_set_x_orig.reshape(test_num,-1).T
print('\n' + '---------------After reshaping---------------' + '\n')
print('train_set_x_flat = ' + str(train_set_x_flat.shape))
print('test_set_x_flat = ' + str(train_set_x_flat.shape))

# Standarize data
train_set_x = train_set_x_flat/255.0
test_set_x = test_set_x_flat/255.0
print('\n' + '---------------After Standaring---------------' + '\n')
print('Check for traindata = ' + str(train_set_x[0:5,0]))
print('Check for testdata = ' + str(test_set_x[0:5,0]))

def train(X,y,learning_rate=0.01,num_itr=3000):
nx = X.shape[0]
m = X.shape[1]
# Initialize weights
np.random.seed(3)
W=np.random.randn(nx, 1)*0.01
b = np.zeros((1,1))
costs = []
for i in range(num_itr):
# Forward prapogation
z = np.dot(W.T,X) + b
A = sigmoid(z)
cost = -(1.0/m)*np.sum(y*np.log(A)+(1-y)*np.log(1-A))
# Back prapogation
dz = A -y
dw = np.dot(X,dz.T)/float(m)
db = np.sum(dz)/float(m)

# Update weights
W = W - learning_rate*dw
b  = b - learning_rate*db
if i % 100 == 0:
costs.append(cost)
print ("Cost after iteration %i: %f" %(i, cost))
return W,b

def test(X,y,W,b):
nx = X.shape[0]
m = X.shape[1]
Y_prediction = np.zeros((1,m))
prob = sigmoid(np.dot(W.T,X) + b)
for i in range(m):
if prob[0,i] > 0.5:
Y_prediction[0,i]  = 1
else:
Y_prediction[0,i] = 0
print("accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction - y)) * 100))
return Y_prediction

W,b = train(train_set_x,train_set_y,learning_rate=0.01,num_itr=3000)
y_ = test(test_set_x,test_set_y,W,b)


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐