吴恩达机器学习系列作业目录

1 Neural Networks 神经网络

在这个练习中,你将实现反向传播算法来学习神经网络的参数。依旧是上次预测手写数数字的例子。

1.1 Visualizing the data 可视化数据

这部分我们随机选取100个样本并可视化。训练集共有5000个训练样本,每个样本是20*20像素的数字的灰度图像。每个像素代表一个浮点数,表示该位置的灰度强度。20×20的像素网格被展开成一个400维的向量。在我们的数据矩阵X中,每一个样本都变成了一行,这给了我们一个5000×400矩阵X,每一行都是一个手写数字图像的训练样本。

import numpy as np
import matplotlib.pyplot as plt
from scipy.io import loadmat
import scipy.optimize as opt
from sklearn.metrics import classification_report  # 这个包是评价报告
def load_mat(path):'''读取数据'''data = loadmat('ex4data1.mat')  # return a dictX = data['X']y = data['y'].flatten()return X, y
def plot_100_images(X):"""随机画100个数字"""index = np.random.choice(range(5000), 100)images = X[index]fig, ax_array = plt.subplots(10, 10, sharey=True, sharex=True, figsize=(8, 8))for r in range(10):for c in range(10):ax_array[r, c].matshow(images[r*10 + c].reshape(20,20), cmap='gray_r')plt.xticks([])plt.yticks([])plt.show()
X,y = load_mat('ex4data1.mat')
plot_100_images(X)

1.2 Model representation 模型表示

我们的网络有三层,输入层,隐藏层,输出层。我们的输入是数字图像的像素值,因为每个数字的图像大小为20*20,所以我们输入层有400个单元(这里不包括总是输出要加一个偏置单元)。

1.2.1 load train data set 读取数据

首先我们要将标签值(1,2,3,4,…,10)转化成非线性相关的向量,向量对应位置(y[i-1])上的值等于1,例如y[0]=6转化为y[0]=[0,0,0,0,0,1,0,0,0,0]。

from sklearn.preprocessing import OneHotEncoder
def expand_y(y):result = []# 把y中每个类别转化为一个向量,对应的lable值在向量对应位置上置为1for i in y:y_array = np.zeros(10)y_array[i-1] = 1result.append(y_array)'''# 或者用sklearn中OneHotEncoder函数encoder =  OneHotEncoder(sparse=False)  # return a array instead of matrixy_onehot = encoder.fit_transform(y.reshape(-1,1))return y_onehot''' return np.array(result)

获取训练数据集,以及对训练集做相应的处理,得到我们的input X,lables y。

raw_X, raw_y = load_mat('ex4data1.mat')
X = np.insert(raw_X, 0, 1, axis=1)
y = expand_y(raw_y)
X.shape, y.shape
'''
((5000, 401), (5000, 10))
'''

1.2.2 load weight 读取权重

这里我们提供了已经训练好的参数θ1,θ2,存储在ex4weight.mat文件中。这些参数的维度由神经网络的大小决定,第二层有25个单元,输出层有10个单元(对应10个数字类)。

def load_weight(path):data = loadmat(path)return data['Theta1'], data['Theta2']
t1, t2 = load_weight('ex4weights.mat')
t1.shape, t2.shape
# ((25, 401), (10, 26))

1.2.3 展开参数

当我们使用高级优化方法来优化神经网络时,我们需要将多个参数矩阵展开,才能传入优化函数,然后再恢复形状。

def serialize(a, b):'''展开参数'''return np.r_[a.flatten(),b.flatten()]
theta = serialize(t1, t2)  # 扁平化参数,25*401+10*26=10285
theta.shape  # (10285,)
def deserialize(seq):'''提取参数'''return seq[:25*401].reshape(25, 401), seq[25*401:].reshape(10, 26)

1.3 Feedforward and cost function 前馈和代价函数

1.3.1 Feedforward

确保每层的单元数,注意输出时加一个偏置单元,s(1)=400+1,s(2)=25+1,s(3)=10。

def sigmoid(z):return 1 / (1 + np.exp(-z))
def feed_forward(theta, X,):'''得到每层的输入和输出'''t1, t2 = deserialize(theta)# 前面已经插入过偏置单元,这里就不用插入了a1 = Xz2 = a1 @ t1.Ta2 = np.insert(sigmoid(z2), 0, 1, axis=1)z3 = a2 @ t2.Ta3 = sigmoid(z3)return a1, z2, a2, z3, a3
a1, z2, a2, z3, h = feed_forward(theta, X)

1.3.2 Cost function

回顾下神经网络的代价函数(不带正则化项)

输出层输出的是对样本的预测,包含5000个数据,每个数据对应了一个包含10个元素的向量,代表了结果有10类。在公式中,每个元素与log项对应相乘。

最后我们使用提供训练好的参数θ,算出的cost应该为0.287629

def cost(theta, X, y):a1, z2, a2, z3, h = feed_forward(theta, X)J = 0for i in range(len(X)):first = - y[i] * np.log(h[i])second = (1 - y[i]) * np.log(1 - h[i])J = J + np.sum(first - second)J = J / len(X)return J
'''# or just use verctorizationJ = - y * np.log(h) - (1 - y) * np.log(1 - h)return J.sum() / len(X)
'''
cost(theta, X, y)  # 0.2876291651613189

1.4 Regularized cost function 正则化代价函数

注意不要将每层的偏置项正则化。

最后You should see that the cost is about 0.383770

def regularized_cost(theta, X, y, l=1):'''正则化时忽略每层的偏置项,也就是参数矩阵的第一列'''t1, t2 = deserialize(theta)reg = np.sum(t1[:,1:] ** 2) + np.sum(t2[:,1:] ** 2)  # or use np.power(a, 2)return l / (2 * len(X)) * reg + cost(theta, X, y)
regularized_cost(theta, X, y, 1)  # 0.38376985909092354

2 Backpropagation 反向传播

2.1 Sigmoid gradient S函数导数

这里可以手动推导,并不难。

def sigmoid_gradient(z):return sigmoid(z) * (1 - sigmoid(z))

2.2 Random initialization 随机初始化

当我们训练神经网络时,随机初始化参数是很重要的,可以打破数据的对称性。一个有效的策略是在均匀分布(−e,e)中随机选择值,我们可以选择 e = 0.12 这个范围的值来确保参数足够小,使得训练更有效率。

def random_init(size):'''从服从的均匀分布的范围中随机返回size大小的值'''return np.random.uniform(-0.12, 0.12, size)

2.3 Backpropagation 反向传播

目标:获取整个网络代价函数的梯度。以便在优化算法中求解。

这里面一定要理解正向传播和反向传播的过程,才能弄清楚各种参数在网络中的维度,切记。比如手写出每次传播的式子。

print('a1', a1.shape,'t1', t1.shape)
print('z2', z2.shape)
print('a2', a2.shape, 't2', t2.shape)
print('z3', z3.shape)
print('a3', h.shape)
'''
a1 (5000, 401) t1 (25, 401)
z2 (5000, 25)
a2 (5000, 26) t2 (10, 26)
z3 (5000, 10)
a3 (5000, 10)
'''
def gradient(theta, X, y):'''unregularized gradient, notice no d1 since the input layer has no error return 所有参数theta的梯度,故梯度D(i)和参数theta(i)同shape,重要。'''t1, t2 = deserialize(theta)a1, z2, a2, z3, h = feed_forward(theta, X)d3 = h - y # (5000, 10)d2 = d3 @ t2[:,1:] * sigmoid_gradient(z2)  # (5000, 25)D2 = d3.T @ a2  # (10, 26)D1 = d2.T @ a1 # (25, 401)D = (1 / len(X)) * serialize(D1, D2)  # (10285,)return D

2.4 Gradient checking 梯度检测

在你的神经网络,你是最小化代价函数J(Θ)。执行梯度检查你的参数,你可以想象展开参数Θ(1)Θ(2)成一个长向量θ。通过这样做,你能使用以下梯度检查过程。

def gradient_checking(theta, X, y, e):def a_numeric_grad(plus, minus):"""对每个参数theta_i计算数值梯度,即理论梯度。"""return (regularized_cost(plus, X, y) - regularized_cost(minus, X, y)) / (e * 2)numeric_grad = [] for i in range(len(theta)):plus = theta.copy()  # deep copy otherwise you will change the raw thetaminus = theta.copy()plus[i] = plus[i] + eminus[i] = minus[i] - egrad_i = a_numeric_grad(plus, minus)numeric_grad.append(grad_i)numeric_grad = np.array(numeric_grad)analytic_grad = regularized_gradient(theta, X, y)diff = np.linalg.norm(numeric_grad - analytic_grad) / np.linalg.norm(numeric_grad + analytic_grad)print('If your backpropagation implementation is correct,\nthe relative difference will be smaller than 10e-9 (assume epsilon=0.0001).\nRelative Difference: {}\n'.format(diff))
gradient_checking(theta, X, y, epsilon= 0.0001)#这个运行很慢,谨慎运行

2.5 Regularized Neural Networks 正则化神经网络

def regularized_gradient(theta, X, y, l=1):"""不惩罚偏置单元的参数"""a1, z2, a2, z3, h = feed_forward(theta, X)D1, D2 = deserialize(gradient(theta, X, y))t1[:,0] = 0t2[:,0] = 0reg_D1 = D1 + (l / len(X)) * t1reg_D2 = D2 + (l / len(X)) * t2return serialize(reg_D1, reg_D2)

2.6 Learning parameters using fmincg 优化参数

def nn_training(X, y):init_theta = random_init(10285)  # 25*401 + 10*26res = opt.minimize(fun=regularized_cost,x0=init_theta,args=(X, y, 1),method='TNC',jac=regularized_gradient,options={'maxiter': 400})return res
res = nn_training(X, y)#慢
res
'''fun: 0.5156784004838036jac: array([-2.51032294e-04, -2.11248326e-12,  4.38829369e-13, ...,9.88299811e-05, -2.59923586e-03, -8.52351187e-04])message: 'Converged (|f_n-f_(n-1)| ~= 0)'nfev: 271nit: 17status: 1success: Truex: array([ 0.58440213, -0.02013683,  0.1118854 , ..., -2.8959637 ,1.85893941, -2.78756836])
'''
def accuracy(theta, X, y):_, _, _, _, h = feed_forward(res.x, X)y_pred = np.argmax(h, axis=1) + 1print(classification_report(y, y_pred))
accuracy(res.x, X, raw_y)
'''precision    recall  f1-score   support1       0.97      0.99      0.98       5002       0.98      0.97      0.98       5003       0.98      0.95      0.96       5004       0.98      0.97      0.97       5005       0.97      0.98      0.97       5006       0.99      0.98      0.98       5007       0.99      0.97      0.98       5008       0.96      0.98      0.97       5009       0.97      0.98      0.97       50010       0.99      0.99      0.99       500avg / total       0.98      0.98      0.98      5000
'''

3 Visualizing the hidden layer 可视化隐藏层

理解神经网络是如何学习的一个很好的办法是,可视化隐藏层单元所捕获的内容。通俗的说,给定一个的隐藏层单元,可视化它所计算的内容的方法是找到一个输入x,x可以激活这个单元(也就是说有一个激活值 ai(l)a^{(l)}_iai(l)​ 接近与1)。对于我们所训练的网络,注意到θ1中每一行都是一个401维的向量,代表每个隐藏层单元的参数。如果我们忽略偏置项,我们就能得到400维的向量,这个向量代表每个样本输入到每个隐层单元的像素的权重。因此可视化的一个方法是,reshape这个400维的向量为(20,20)的图像然后输出。

注:
It turns out that this is equivalent to finding the input that gives the highest activation for the hidden unit, given a norm constraint on the input.

这相当于找到了一个输入,给了隐层单元最高的激活值,给定了一个输入的标准限制。例如( ∣∣x∣∣2≤1||x||_2 \leq 1∣∣x∣∣2​≤1)

(这部分暂时不太理解)

def plot_hidden(theta):t1, _ = deserialize(theta)t1 = t1[:, 1:]fig,ax_array = plt.subplots(5, 5, sharex=True, sharey=True, figsize=(6,6))for r in range(5):for c in range(5):ax_array[r, c].matshow(t1[r * 5 + c].reshape(20, 20), cmap='gray_r')plt.xticks([])plt.yticks([])plt.show()
plot_hidden(res.x)

在我们经过训练的网络中,你应该发现隐藏的单元大致对应于在输入中寻找笔画和其他模式的检测器。

吴恩达机器学习作业Python实现(四):神经网络(反向传播)相关推荐

  1. 吴恩达机器学习作业Python实现(八):异常检测和推荐系统

    吴恩达机器学习系列作业目录 1 Anomaly detection 这部分,您将实现一个异常检测算法来检测服务器计算机中的异常行为.他的特征是测量每个服务器的响应速度(mb/s)和延迟(ms).当你的 ...

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

    吴恩达机器学习系列作业目录 1 K-means Clustering 在这个练习中,您将实现K-means算法并将其用于图像压缩.通过减少图像中出现的颜色的数量,只剩下那些在图像中最常见的颜色. 1. ...

  3. 吴恩达机器学习作业Python实现(六):SVM支持向量机

    吴恩达机器学习系列作业目录 1 Support Vector Machines 1.1 Example Dataset 1 %matplotlib inline import numpy as np ...

  4. 吴恩达机器学习作业Python实现(五):偏差和方差

    吴恩达机器学习系列作业目录 在本练习中,您将实现正则化的线性回归和多项式回归,并使用它来研究具有不同偏差-方差属性的模型 1 Regularized Linear Regression 正则线性回归 ...

  5. 吴恩达机器学习作业Python实现(三):多类分类和前馈神经网络

    吴恩达机器学习系列作业目录 1 多类分类(多个logistic回归) 我们将扩展我们在练习2中写的logistic回归的实现,并将其应用于一对多的分类(不止两个类别). import numpy as ...

  6. 吴恩达机器学习作业Python实现(二):logistic回归

    吴恩达机器学习系列作业目录 1 Logistic regression 在这部分的练习中,你将建立一个逻辑回归模型来预测一个学生是否能进入大学.假设你是一所大学的行政管理人员,你想根据两门考试的结果, ...

  7. 吴恩达|机器学习作业3.1前馈神经网络

    3.1.前馈神经网络 1)题目: 在本次练习中,你将使用前馈神经网络来识别手写数字(从0到9).数据依然是MNIST手写体数据集,这里包含了5000个训练样本.之前用了逻辑回归进行多元分类,这次用前馈 ...

  8. k均值算法python实现(吴恩达机器学习作业)

    k均值算法python实现(吴恩达机器学习作业) 题目要求 数据集 读取mat文件 K-means 实现 结果 问题 题目要求 采用K均值算法对样本进行聚类. 编写K均值算法源代码,对ex7data2 ...

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

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

最新文章

  1. Maya2022基础入门学习教程
  2. Python一键转Java?“Google翻译”你别闹
  3. python提取图像的每一帧
  4. 接口中定义变量必须为public static final的原因
  5. boost::process::cmd相关的测试程序
  6. linux atom 升级,Github更新Atom,主要集中在Windows
  7. centos7 和centos 6的一些区别
  8. webrtc笔记(1): 基于coturn项目的stun/turn服务器搭建
  9. 盘点世界上最奇怪的6种编程语言
  10. LINUX 第六章 Open WebMail完全安装手册
  11. 用欧拉角表示旋转(方位)heading pitch bank 含义,形象的图示
  12. Java中的反射机制
  13. 微信指纹锁原理及安全性分析
  14. ECU软件开发介绍篇
  15. 在网站中添加QQ、旺旺的方法
  16. 自定义8583模板,打包解包,使用j8583包有改动
  17. oppoa57升级android版本,OPPO A57刷机教程_OPPO A57升级更新官方系统包
  18. (五)不只是 huohuo 的 JS 面试题
  19. b站尚硅谷springmvc学习视频:springmvc文档
  20. ToolsOh第6批收录

热门文章

  1. PHP __FILE__
  2. pku1189 钉子和小球
  3. .net生成缩略图,支持等比例缩放,加水印
  4. C++中的内存分配new()
  5. Django学习笔记之二
  6. 跨域请求/SpringMVC拦截器
  7. BZOJ.3990.[SDOI2015]排序(DFS)
  8. 世界摩天大楼2009年排名
  9. 使用layer的弹窗时,出现layer引入成功,触发成功,控制台无报错,但是页面无变化或者仅出现遮罩层的问题的解决思路
  10. CSocket,CAsyncSocket多线程退出时的一些注意事项(解决关闭WinSoket崩溃的问题)