编程作业 4 - 神经网络

对于这个练习,我们将再次处理手写数字数据集,这次使用反向传播的前馈神经网络。 我们将通过反向传播算法实现神经网络成本函数和梯度计算的非正则化和正则化版本。 我们还将实现随机权重初始化和使用网络进行预测的方法。

由于我们在练习3中使用的数据集是相同的,所以我们将重新使用代码来加载数据。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.io import loadmat
data = loadmat('ex4data1.mat')
data
{'__header__': b'MATLAB 5.0 MAT-file, Platform: GLNXA64, Created on: Sun Oct 16 13:09:09 2011','__version__': '1.0','__globals__': [],'X': array([[0., 0., 0., ..., 0., 0., 0.],[0., 0., 0., ..., 0., 0., 0.],[0., 0., 0., ..., 0., 0., 0.],...,[0., 0., 0., ..., 0., 0., 0.],[0., 0., 0., ..., 0., 0., 0.],[0., 0., 0., ..., 0., 0., 0.]]),'y': array([[10],[10],[10],...,[ 9],[ 9],[ 9]], dtype=uint8)}

由于我们以后需要这些(并将经常使用它们),我们先来创建一些有用的变量。

X = data['X']
y = data['y']X.shape, y.shape#看下维度
((5000, 400), (5000, 1))

我们也需要对我们的y标签进行一次one-hot 编码。 one-hot 编码将类标签n(k类)转换为长度为k的向量,其中索引n为“hot”(1),而其余为0。 Scikitlearn有一个内置的实用程序,我们可以使用这个。

from sklearn.preprocessing import OneHotEncoder
encoder = OneHotEncoder(sparse=False)
y_onehot = encoder.fit_transform(y)
y_onehot.shape
(5000, 10)
y[0], y_onehot[0,:]
(array([10], dtype=uint8), array([0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]))

我们要为此练习构建的神经网络具有与我们的实例数据(400 +偏置单元)大小匹配的输入层,25个单位的隐藏层(带有偏置单元的26个),以及一个输出层, 10个单位对应我们的一个one-hot编码类标签。 有关网络架构的更多详细信息和图像,请参阅“练习”文件夹中的PDF。

我们需要实现的第一件是评估一组给定的网络参数的损失的代价函数。 源函数在练习文本中(看起来很吓人)。 以下是代价函数的代码。

sigmoid 函数

g 代表一个常用的逻辑函数(logistic function)为S形函数(Sigmoid function),公式为: \[g\left( z \right)=\frac{1}{1+{{e}^{-z}}}\]
合起来,我们得到逻辑回归模型的假设函数:
\[{{h}_{\theta }}\left( x \right)=\frac{1}{1+{{e}^{-{{\theta }^{T}}X}}}\]

def sigmoid(z):return 1 / (1 + np.exp(-z))

前向传播函数

(400 + 1) -> (25 + 1) -> (10)

def forward_propagate(X, theta1, theta2):# INPUT:参数值theta,数据X# OUTPUT:当前参数值下前项传播结果# TODO:根据参数和输入的数据计算前项传播结果# STEP1:获取样本个数# your code here  (appro ~ 1 lines)m = X.shape[0]# STEP2:实现神经网络正向传播# your code here  (appro ~ 5 lines)    a1 =np.insert(X, 0, values=np.ones(m), axis=1) #给X矩阵插入一行1元素z2 =a1 * theta1.Ta2 =np.insert(sigmoid(z2), 0, values=np.ones(m), axis=1)  #注意插入1元素z3 = a2 * theta2.Th = sigmoid(z3)return a1, z2, a2, z3, h

代价函数

Tip:重新定义矩阵维度可以使用reshape函数

def cost(params, input_size, hidden_size, num_labels, X, y, lamda):# INPUT:神经网络参数,输入层维度,隐藏层维度,训练数据及标签,正则化参数# OUTPUT:当前参数值下的代价函数# TODO:根据上面的公式计算代价函数# STEP1:获取样本个数# your code here  (appro ~ 1 lines)m = X.shape[0]# STEP2:将矩阵X,y转换为numpy型矩阵# your code here  (appro ~ 2 lines)X =np.matrix(X)y =np.matrix(y)# STEP3:从params中获取神经网络参数,并按照输入层维度和隐藏层维度重新定义参数的维度# your code here  (appro ~ 2 lines)theta1 =  np.matrix(np.reshape(params[:hidden_size * (input_size + 1)], (hidden_size, (input_size + 1))))theta2 = np.matrix(np.reshape(params[hidden_size * (input_size + 1):], (num_labels, (hidden_size + 1))))# STEP4:调用前面写好的前项传播函数# your code here  (appro ~ 1 lines)a1, z2, a2, z3, h = forward_propagate(X, theta1, theta2)# STEP5:初始化代价函数# your code here  (appro ~ 1 lines)J = 0# STEP6:根据公式计算代价函数for i in range(m):  #遍历每个样本# your code here  (appro ~ 2 lines)first_term =np.multiply(-y[i,:], np.log(h[i,:]))second_term = np.multiply((1 - y[i,:]), np.log(1 - h[i,:]))J += np.sum(first_term - second_term)J = J / m# STEP7:计算代价函数的正则化部分# your code here  (appro ~ 1 lines)J += (float(lamda) / (2 * m)) * (np.sum(np.power(theta1[:,1:], 2)) + np.sum(np.power(theta2[:,1:], 2)))return J

这个Sigmoid函数我们以前使用过。 前向传播函数计算给定当前参数的每个训练实例的假设。 它的输出形状应该与y的一个one-hot编码相同。

# 初始化设置
input_size = 400
hidden_size = 25
num_labels = 10
lamda = 1# 随机初始化完整网络参数大小的参数数组
params = (np.random.random(size=hidden_size * (input_size + 1) + num_labels * (hidden_size + 1)) - 0.5) * 0.25m = X.shape[0]
X = np.matrix(X)
y = np.matrix(y)# 将参数数组解开为每个层的参数矩阵
theta1 = np.matrix(np.reshape(params[:hidden_size * (input_size + 1)], (hidden_size, (input_size + 1))))
theta2 = np.matrix(np.reshape(params[hidden_size * (input_size + 1):], (num_labels, (hidden_size + 1))))theta1.shape, theta2.shape
((25, 401), (10, 26))

如果你的程序正确,这里的输出应该是:((25, 401), (10, 26))

a1, z2, a2, z3, h = forward_propagate(X, theta1, theta2)
a1.shape, z2.shape, a2.shape, z3.shape, h.shape
((5000, 401), (5000, 25), (5000, 26), (5000, 10), (5000, 10))

如果你的程序正确,这里的输出应该是:((5000, 401), (5000, 25), (5000, 26), (5000, 10), (5000, 10))

代价函数在计算假设矩阵h之后,应用代价函数来计算y和h之间的总误差。

cost(params, input_size, hidden_size, num_labels, X, y_onehot, lamda)
7.189709282447219
##error case 6.7329429719363878  & 6.8604869039403171
#当用python进行数组运算,出现RuntimeWarning: invalid value encountered的报错,往往是因为数组中存在0元素
#RuntimeWarning: invalid value encountered in multiply 溢出

如果你的程序正确,这里的输出应该是:7.1170579556373621

接下来是反向传播算法。 反向传播参数更新计算将减少训练数据上的网络误差。 我们需要的第一件事是计算我们之前创建的Sigmoid函数的梯度的函数。

def sigmoid_gradient(z):return np.multiply(sigmoid(z), (1 - sigmoid(z)))

现在我们准备好实施反向传播来计算梯度。 由于反向传播所需的计算是代价函数中所需的计算过程,我们实际上将扩展代价函数以执行反向传播并返回代价和梯度。

def backprop(params, input_size, hidden_size, num_labels, X, y, lamda):# INPUT:神经网络参数,输入层维度,隐藏层维度,训练数据及标签,正则化参数# OUTPUT:当前参数值下的代价函数# TODO:根据上面的公式计算代价函数# STEP1:获取样本个数# your code here  (appro ~ 1 lines)m = X.shape[0]# STEP2:将矩阵X,y转换为numpy型矩阵# your code here  (appro ~ 2 lines)X = np.matrix(X)y = np.matrix(y)# STEP3:从params中获取神经网络参数,并按照输入层维度和隐藏层维度重新定义参数的维度# your code here  (appro ~ 2 lines)theta1 = np.matrix(np.reshape(params[:hidden_size * (input_size + 1)], (hidden_size, (input_size + 1))))theta2 = np.matrix(np.reshape(params[hidden_size * (input_size + 1):], (num_labels, (hidden_size + 1))))# STEP4:调用前面写好的前项传播函数# your code here  (appro ~ 1 lines)a1, z2, a2, z3, h =forward_propagate(X, theta1, theta2)# STEP5:初始化# your code here  (appro ~ 3 lines)J = 0delta1 = np.zeros(theta1.shape)  # (25, 401)delta2 = np.zeros(theta2.shape)  # (10, 26)# STEP6:计算代价函数(调用函数)# your code here  (appro ~ 1 lines)for i in range(m):first_term = np.multiply(-y[i,:], np.log(h[i,:]))second_term = np.multiply((1 - y[i,:]), np.log(1 - h[i,:]))J += np.sum(first_term - second_term)J = J / m# STEP7:实现反向传播(这里用到的公式请参考原版作业PDF的第5页)for t in range(m):  #遍历每个样本a1t = a1[t,:]  # (1, 401)z2t = z2[t,:]  # (1, 25)a2t = a2[t,:]  # (1, 26)ht = h[t,:]  # (1, 10)yt = y[t,:]  # (1, 10)# your code here  (appro ~ 5 lines)d3t = ht - ytz2t = np.insert(z2t, 0, values=np.ones(1)) # (1, 26) d2t = np.multiply((theta2.T * d3t.T).T, sigmoid_gradient(z2t))  # (1, 26)delta1 = delta1 + (d2t[:,1:]).T * a1tdelta2 = delta2 + d3t.T * a2t# STEP8:加入正则化# your code here  (appro ~ 1 lines)delta1[:,1:] = delta1[:,1:] + (theta1[:,1:] * lamda) / mdelta2[:,1:] =  delta2[:,1:] + (theta2[:,1:] * lamda) / m# STEP9:将梯度矩阵转换为单个数组grad = np.concatenate((np.ravel(delta1), np.ravel(delta2)))return J, grad

反向传播计算的最难的部分(除了理解为什么我们正在做所有这些计算)是获得正确矩阵维度。 顺便说一下,你容易混淆了A * B与np.multiply(A,B)使用。 基本上前者是矩阵乘法,后者是元素乘法(除非A或B是标量值,在这种情况下没关系)。
无论如何,让我们测试一下,以确保函数返回我们期望的。

J, grad = backprop(params, input_size, hidden_size, num_labels, X, y_onehot, lamda)
J, grad.shape
(7.184458705259231, (10285,))

如果你的程序正确,这里的输出应该是:(7.3264766401720607, (10285,))

我们终于准备好训练我们的网络,并用它进行预测。 这与以往的具有多类逻辑回归的练习大致相似。

from scipy.optimize import minimize# minimize the objective function
fmin = minimize(fun=backprop, x0=params, args=(input_size, hidden_size, num_labels, X, y_onehot, lamda), method='TNC', jac=True, options={'maxiter': 250})
fmin
D:\sofewore\anaconda\lib\site-packages\ipykernel_launcher.py:34: RuntimeWarning: divide by zero encountered in log
D:\sofewore\anaconda\lib\site-packages\ipykernel_launcher.py:34: RuntimeWarning: invalid value encountered in multiplyfun: 0.36223489551718385jac: array([-2.37751129e+01, -6.52893193e-06, -4.08905647e-06, ...,1.22569704e+00, -7.10083281e+00, -6.25293206e-01])message: 'Linear search failed'nfev: 218nit: 13status: 4success: Falsex: array([-0.29594079, -0.03264466, -0.02044528, ..., -1.35811354,2.59361744, -0.90221032])

如果你的程序正确,这里的输出应该是:

fun: 0.34648873971573946

jac: array([ 3.45137403e-04, 2.31929337e-06, -2.41850602e-06, …,
-2.66641069e-04, 2.12514869e-04, -4.37669150e-04])

message: ‘Max. number of function evaluations reached’

nfev: 250

nit: 19

status: 3

success: False
x: array([-0.92927497, 0.01159647, -0.01209253, …, -3.70653505,
-0.59870645, 0.43449445])

由于目标函数不太可能完全收敛,我们对迭代次数进行了限制。 我们的总代价已经下降到0.5以下,这是算法正常工作的一个很好的指标。 让我们使用它发现的参数,并通过网络转发,以获得一些预测。

让我们使用它找到的参数,并通过网络前向传播以获得预测。

X = np.matrix(X)
theta1 = np.matrix(np.reshape(fmin.x[:hidden_size * (input_size + 1)], (hidden_size, (input_size + 1))))
theta2 = np.matrix(np.reshape(fmin.x[hidden_size * (input_size + 1):], (num_labels, (hidden_size + 1))))a1, z2, a2, z3, h = forward_propagate(X, theta1, theta2)
y_pred = np.array(np.argmax(h, axis=1) + 1)
y_pred
array([[10],[10],[10],...,[ 9],[ 9],[ 9]], dtype=int64)

最后,我们可以计算准确度,看看我们训练完毕的神经网络效果怎么样。

correct = [1 if a == b else 0 for (a, b) in zip(y_pred, y)]
accuracy = (sum(map(int, correct)) / float(len(correct)))
print ('accuracy = {0}%'.format(accuracy * 100))
accuracy = 96.14%

我们已经成功地实施了一个基本的反向传播神经网络,并用它来分类手写数字图像。 在下一个练习中,我们将介绍另一个强大的监督学习算法,支持向量机。

机器学习作业班_python神经网络搭建相关推荐

  1. 吴恩达|机器学习作业4.0神经网络反向传播(BP算法)

    4.0.神经网络学习 1)题目: 在本练习中,您将实现神经网络的反向传播算法,并将其应用于手写数字识别任务.在之前的练习中,已经实现了神经网络的前馈传播,并使用Andrew Ng他们提供的权值来预测手 ...

  2. 吴恩达机器学习作业3.2神经网络

    # neural network(神经网络) import matplotlib.pyplot as plt import numpy as np import scipy.io as sio imp ...

  3. python线性回归预测pm2.5_线性回归预测PM2.5----台大李宏毅机器学习作业1(HW1)

    一.作业说明 给定训练集train.csv,要求根据前9个小时的空气监测情况预测第10个小时的PM2.5含量. 训练集介绍: (1).CSV文件,包含台湾丰原地区240天的气象观测资料(取每个月前20 ...

  4. 机器学习 | MATLAB实现BP神经网络newff参数设定(下)

    机器学习 | MATLAB实现BP神经网络newff参数设定(下) 目录 机器学习 | MATLAB实现BP神经网络newff参数设定(下) 基本介绍 程序设计 参考资料 致谢 基本介绍 newff搭 ...

  5. 机器学习 | MATLAB实现BP神经网络newff参数设定(上)

    机器学习 | MATLAB实现BP神经网络newff参数设定(上) 目录 机器学习 | MATLAB实现BP神经网络newff参数设定(上) 基本介绍 程序设计 参考资料 致谢 基本介绍 newff搭 ...

  6. 机器学习 | MATLAB实现BP神经网络newff参数设定(中)

    机器学习 | MATLAB实现BP神经网络newff参数设定(中) 目录 机器学习 | MATLAB实现BP神经网络newff参数设定(中) 基本介绍 程序设计 参考资料 致谢 基本介绍 newff搭 ...

  7. 由宏观到细节谈谈BP神经网络搭建

    文章目录 序言 引言 模型解读 我们的神经网络要实现的目标: 具体实现 正式开始我们的搭建BP神经网络之旅 1. 设置神经元基本结构 2.正向传播 3.反向传播 4.迭代训练 总结 序言 自从最近十几 ...

  8. 吴恩达机器学习作业7 - K-means和PCA主成分分析(Python实现)

    吴恩达机器学习作业7 - K-means和PCA主成分分析(Python实现) Introduction 在本实验中,将实现K-means聚类算法,并将其应用于图像压缩.在第二部分实验中,将使用主成分 ...

  9. 【深度学习】基于Torch的Python开源机器学习库PyTorch卷积神经网络

    [深度学习]基于Torch的Python开源机器学习库PyTorch卷积神经网络 文章目录 1 CNN概述 2 PyTorch实现步骤2.1 加载数据2.2 CNN模型2.3 训练2.4 可视化训练 ...

  10. 斯坦福大学机器学习第八课“神经网络的表示(Neural Networks: Representation)”

    斯坦福大学机器学习第八课"神经网络的表示(Neural Networks: Representation)" 斯坦福大学机器学习第八课"神经网络的表示(Neural Ne ...

最新文章

  1. 八个开源的 Spring Boot 学习资源,你值得拥有
  2. AI入门:通俗讲解熵、交叉熵和 KL 散度
  3. android+busybox+编译,Android版busybox编译
  4. 计算机专业刚毕业本科生,计算机专业应届本科毕业生自我鉴定
  5. 【转载】作者苗晓平介绍的飞鸽传书
  6. VUE自学日志05-计算属性和侦听器
  7. STM32F205通过SDIO和SPI读写SD卡文件
  8. 手机卫星定位系统_真的可以通过手机号码,准确定位对方信息吗?
  9. 按GB 11643标准对大陆身份证号码分析验证
  10. Twitter首席科学家离职 高层动荡仍持续
  11. 蓝桥杯刷题冲刺 | 倒计时14天
  12. 考虑体积重量的装箱问题(箱子装载平衡)— 基于遗传算法
  13. STM32—ADC和DMA的应用之电流检测(第二部分:电流检测电路与数据处理)
  14. Ubuntu 18.04 安装RealSense D435教程
  15. 一、C语言的具体结构
  16. ps笔刷管理扩展面板:Brusherator for Mac
  17. Android基础入门教程——7.6.1 Socket学习网络基础准备
  18. 魔方(15)二、三、四、五阶棋盘魔方
  19. HDU-1276 士兵队列训练问题
  20. 赛门铁克警告Switch模拟器下载链接实为垃圾站点

热门文章

  1. Sprig 面试中 问及 DI,IOC, AOP
  2. C# 数组转换为DataTable 的三个方法
  3. 一、tkinter简介
  4. mysql的数据类型5---enum与set类型
  5. ASP.NET MVC Action返回结果类型【转】
  6. E4/EAS/Eventing System 事件系统
  7. [收藏]深入浅出的《网络socket编程指南》4
  8. (AnyWhere-)安卓版“捷径”
  9. TX2Ubuntu16.04远程登录
  10. monkey 查找闪退页面的方法