简单神经网络的搭建(原创) @water
用于分类猫的图片,数据集有209张图片,每张图片分辨率64643。
本文所使用的资料已上传到百度网盘【点击下载】,请在开始之前下载好所需资料,然后将文件解压到你的代码文件同一级目录下,请确保你的代码那里有lr_utils.py和datasets文件夹。
操作系统:ubuntu18.04
显卡:GTX1080ti
python版本:2.7(3.7)
QQ群:加入深度学习交流群 获取更多环境配置细节和学习资料(147960154)
# -*- coding: utf-8 -*-
from __future__ import division
第一行是可以进行中文编码
第二行是python2可以整除一个数,且保留小数
我们要做的事是搭建一个能够【识别猫】 的简单的神经网络,你可以跟随我的步骤在Jupyter Notebook中一步步地把代码填进去,也可以直接复制完整代码,在完整代码在本文最底部。
在开始之前,我们有需要引入的库:
import numpy as np
import matplotlib.pyplot as plt
from lr_utils import load_dataset
- numpy :是用Python进行科学计算的基本软件包。
- h5py:是与H5文件中存储的数据集进行交互的常用软件包。
- matplotlib:是一个著名的库,用于在Python中绘制图表。
- lr_utils:在本文的资料包里,一个加载资料包里面的数据的简单功能的库。
一、加载数据集
from lr_utils import load_dataset
train_set_x_orig , train_set_y , test_set_x_orig , test_set_y , classes = load_dataset()#(209, 64, 64, 3)
train_y = train_set_y #(1.209)
index = 25
plt.imshow(train_set_x_orig[index])
plt.title( classes[np.squeeze(train_set_y[:,index])])
plt.show()
现在我们可以结合一下训练集里面的数据来看一下我到底都加载了一些什么东西。
train_x = train_set_x_orig.reshape(train_set_x_orig.shape[0],-1).T/ 255 #(12288, 209)
test_x = test_set_x_orig.reshape(test_set_x_orig.shape[0], -1).T/ 255
- 为了方便,我们要把维度为(64,64,3)的numpy数组重新构造为(64 x 64 x 3,1)的数组,要乘以3的原因是每张图片是由64x64像素构成的,而每个像素点由(R,G,B)三原色构成的,所以要乘以3。
- 这一段意思是指把数组变为209行的矩阵(因为训练集里有209张图片),但是我懒得算列有多少,于是我就用-1告诉程序你帮我算,最后程序算出来时12288列,我再最后用一个T表示转置,这就变成了12288行,209列。测试集亦如此。
- 为了表示彩色图像,必须为每个像素指定红色,绿色和蓝色通道(RGB),因此像素值实际上是从0到255范围内的三个数 - 字的向量。机器学习中一个常见的预处理步骤是对数据集进行居中和标准化,这意味着可以减去每个示例中整个numpy数组的平均值,然后将每个示例除以整个numpy数组的标准偏差。但对于图片数据集,它更简单,更方便,几乎可以将数据集的每一行除以255(像素通道的最大值),因为在RGB中不存在比255大的数据,所以我们可以放心的除以255,让标准化的数据位于[0,1]之间
数据集这样就处理#### 一、加载数据集好了,下一步我们来创建神经网络模型
二、创建网络模型
建立神经网络的主要步骤是:
- 定义模型结构(例如输入特征的数量)
- 初始化模型的参数
- 循环:
- 3.1 计算当前损失(正向传播)
- 3.2 计算当前梯度(反向传播)
- 3.3 更新参数(梯度下降)
def initialize_with_zeros(X):
'''
build a model structure
z = w1x1 + w2x2 + w3x3 +...+w(n)x(n) + b
:param:
nx - the numble of features
:return:
parameters - 一个包含W1,B1,W2和B2的字典类型的变量
'''
np.random.seed(2)
nx = X.shape[0]
W = np.random.randn(nx, 1) * 0.01
b = 0
parameters = {'W':W,'b':b}
return parameters
def sigmoid(z):
'''
activation function
s(z) = 1/(1+e**(-z)))
:param:
z - z = w1x1 + w2x2 + w3x3 +...+w(n)x(n) + b
:return:
a - sigmoid(z)
'''
a = 1/(1+np.exp(-z))
return a
def forward_propagation( X , parameters ):
"""
forward_propagation
a = sigmoid(WX+b)
:param X:(12288, 209)
:param parameters = {'W':W,'b':b}
"""
W = parameters["W"]
b = parameters["b"]
z = np.dot(W.T,X) + b
a = sigmoid(z)
return a
def compute_cost(a,y):
'''
calculate the cost function between a and y
:param y:(1,209)
:param b:
:return:cost
'''
m = y.shape[1]
cost = (- 1 / m) * np.sum(y * np.log(a) + (1 - y) * (np.log(1 - a)))
return cost
def backward_propagation(a,X,y):
'''
backward_propagation
:param parameters: {'W':W,'b':b}
:param X: (12288, 209)
:param Y: (1,209)
:return:gard:{"dW": dW,
"db": db }
'''
m = X.shape[1]
dZ = a - y
dW = (1 / m) * np.dot(X,dZ.T)
db = (1 / m) * np.sum(dZ)
grads = {"dW": dW,
"db": db}
return grads
测试一下propagate
打印出来的结果
====================测试propagate====================
2
dw = [[0.99993216]
[1.99980262]]
db = 0.49993523062470574
cost = 6.000064773192205
初始化参数的函数已经构建好了,现在就可以执行“前向”和“后向”传播步骤来学习参数。
我们现在要实现一个计算成本函数及其渐变的函数propagate()。
现在,我要使用渐变下降更新参数。
目标是通过最小化成本函数 JJ 来学习 ww和bb 。对于参数 θθ ,更新规则是 θ=θ−α dθθ=θ−α dθ,其中 αα 是学习率。
def update_parameters(parameters,grads,learning_rate=1.2):
'''
This function optimizes W and B by running gradient descent algorithm
:param parameters:
:param grads:
:param learning_rate:
:return:
'''
W = parameters["W"]
b = parameters["b"]
dW , db = grads["dW"], grads["db"]
W = W - learning_rate * dW
b = b - learning_rate * db
parameters = {'W': W, 'b': b}
return parameters
def predict(W , b , X ):
"""
使用学习逻辑回归参数logistic (w,b)预测标签是0还是1,
参数:
w - 权重,大小不等的数组(num_px * num_px * 3,1)
b - 偏差,一个标量
X - 维度为(num_px * num_px * 3,训练数据的数量)的数据
返回:
Y_prediction - 包含X中所有图片的所有预测【0 | 1】的一个numpy数组(向量)
"""
m = X.shape[1] #图片的数量
Y_prediction = np.zeros((1,m))
W = W.reshape(X.shape[0],1)
#计预测猫在图片中出现的概率
A = sigmoid(np.dot(W.T , X) + b)
for i in range(A.shape[1]):
#将概率a [0,i]转换为实际预测p [0,i]
Y_prediction[0,i] = 1 if A[0,i] > 0.5 else 0
#使用断言
assert(Y_prediction.shape == (1,m))
return Y_prediction
def model(X_train , y_train , X_test , Y_test , num_iterations = 2000 , learning_rate = 0.5 , print_cost = False):
"""
通过调用之前实现的函数来构建逻辑回归模型
参数:
X_train - numpy的数组,维度为(num_px * num_px * 3,m_train)的训练集
Y_train - numpy的数组,维度为(1,m_train)(矢量)的训练标签集
X_test - numpy的数组,维度为(num_px * num_px * 3,m_test)的测试集
Y_test - numpy的数组,维度为(1,m_test)的(向量)的测试标签集
num_iterations - 表示用于优化参数的迭代次数的超参数
learning_rate - 表示optimize()更新规则中使用的学习速率的超参数
print_cost - 设置为true以每100次迭代打印成本
返回:
d - 包含有关模型信息的字典。
"""
costs = []
parameters = initialize_with_zeros(X_train)
for i in range(num_iterations):
a = forward_propagation(X_train, parameters)
cost = compute_cost(a, y_train)
grads = backward_propagation(a, X_train, y_train)
parameters = update_parameters(parameters, grads, learning_rate)
if print_cost:
if i % 100 == 0:
costs.append(cost)
print "i= ", i, " cost = :" + str(cost)
#从字典“参数”中检索参数w和b
W , b = parameters['W'] , parameters['b']
#预测测试/训练集的例子
Y_prediction_test = predict(W , b, X_test)
Y_prediction_train = predict(W , b, X_train)
#打印训练后的准确性
print"训练集准确性:" , format(100 - np.mean(np.abs(Y_prediction_train - y_train)) * 100) ,"%"
print"测试集准确性:" , format(100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100) ,"%"
print costs
d = {
"costs" : costs,
"Y_prediction_test" : Y_prediction_test,
"Y_prediciton_train" : Y_prediction_train,
"w" : W,
"b" : b,
"learning_rate" : learning_rate,
"num_iterations" : num_iterations }
return d
print("====================测试model====================")
#这里加载的是真实的数据,请参见上面的代码部分。
d = model(train_x, train_set_y, test_x, test_set_y, num_iterations = 2000, learning_rate = 0.005, print_cost = True)
print type(d)
plt.figure(0)
costs = np.squeeze(d["costs"])
print costs
plt.plot(costs)
plt.ylabel('cost')
plt.xlabel('iterations (per hundreds)')
plt.title("Learning rate =" + str(d["learning_rate"]))
plt.figure(1)
learning_rates = [0.01, 0.001, 0.0001]
models = {}
for i in learning_rates:
print ("learning rate is: " + str(i))
models[str(i)] = model(train_x, train_set_y, test_x, test_set_y, num_iterations = 1500, learning_rate = i, print_cost = False)
print ('\n' + "-------------------------------------------------------" + '\n')
for i in learning_rates:
plt.plot(np.squeeze(models[str(i)]["costs"]), label= str(models[str(i)]["learning_rate"]))
plt.ylabel('cost')
plt.xlabel('iterations')
legend = plt.legend(loc='upper center', shadow=True)
frame = legend.get_frame()
frame.set_facecolor('0.90')
plt.show()
代码结果如下:
====================测试model====================
i= 0 cost = :0.6414754756603139
i= 100 cost = :0.6281406675614425
i= 200 cost = :0.474221970271689
i= 300 cost = :0.3717508764545704
i= 400 cost = :0.32858869707055666
i= 500 cost = :0.30070713233054913
i= 600 cost = :0.27757184087303255
i= 700 cost = :0.2579579762006669
i= 800 cost = :0.24105309384034423
i= 900 cost = :0.2262907681287754
i= 1000 cost = :0.21326099794194806
i= 1100 cost = :0.20165793957178563
i= 1200 cost = :0.19124769554664245
i= 1300 cost = :0.1818475894042285
i= 1400 cost = :0.17331235253802288
i= 1500 cost = :0.16552464253865398
i= 1600 cost = :0.15838836923173807
i= 1700 cost = :0.15182389346621317
i= 1800 cost = :0.14576450599340313
i= 1900 cost = :0.14015380013602247
训练集准确性: 99.043062201 %
测试集准确性: 70.0 %
[0.6414754756603139, 0.6281406675614425, 0.474221970271689, 0.3717508764545704, 0.32858869707055666, 0.30070713233054913, 0.27757184087303255, 0.2579579762006669, 0.24105309384034423, 0.2262907681287754, 0.21326099794194806, 0.20165793957178563, 0.19124769554664245, 0.1818475894042285, 0.17331235253802288, 0.16552464253865398, 0.15838836923173807, 0.15182389346621317, 0.14576450599340313, 0.14015380013602247]
<type 'dict'>
[0.64147548 0.62814067 0.47422197 0.37175088 0.3285887 0.30070713
0.27757184 0.25795798 0.24105309 0.22629077 0.213261 0.20165794
0.1912477 0.18184759 0.17331235 0.16552464 0.15838837 0.15182389
0.14576451 0.1401538 ]
learning rate is: 0.01
训练集准确性: 99.5215311005 %
测试集准确性: 70.0 %
[]
-------------------------------------------------------
learning rate is: 0.001
训练集准确性: 89.4736842105 %
测试集准确性: 62.0 %
[]
-------------------------------------------------------
learning rate is: 0.0001
训练集准确性: 70.8133971292 %
测试集准确性: 40.0 %
[]
-------------------------------------------------------
Process finished with exit code 0