3. 吴恩达机器学习课程-作业3-多分类和神经网络
fork了别人的项目,自己重新填写,我的代码如下
https://gitee.com/fakerlove/machine-learning/tree/master/code
代码原链接
文章目录
- 3. 吴恩达机器学习课程-作业3-多分类和神经网络
- 3.1 逻辑回归实现多分类
- 3.1.1 题目介绍
- 3.1.2 数据介绍
- 3.1.3 可视化图片
- 3.1.4 逻辑回归
- One-vs-all Classification
- 3.1.5 代码如下
- 3.2 神经网络
- 3.2.1 题目介绍
- 3.2.2 数据介绍
- 3.2.3 代码介绍
3. 吴恩达机器学习课程-作业3-多分类和神经网络
3.1 逻辑回归实现多分类
假设有一个训练集如下图左部分所示,有3个类别。逻辑回归的方法是将其分成3个二元分类问题。先从类别1开始,创建一个新的“伪”训练集,类别2和类别3定为负类,类别1设定为正类,如图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3bBhmTf6-1645517858350)(picture/sadjklsajkdhquiascbhdcgdashdgiuqw2437893829.png)]
3.1.1 题目介绍
在这个练习中,你将使用逻辑回归和神经网络识别手写数字(从0到9)。自动手写数字识别今天被广泛使用-从识别邮政编码(邮政编码)
在邮件信封上注明银行支票上的金额。这练习会告诉你如何使用你所学到的方法分类任务。
在练习的第一部分中,您将扩展以前的逻辑回归实现,并将其应用于“一对所有”分类。
3.1.2 数据介绍
这里的数据存储变成了.mat的格式,这样的数据选择借助scipy.io.loadmat()实现
通过loadmat方法加载数据后会返回一个Python字典的数据结构,我们可以查看数据关键字,代码如下:
data = sio.loadmat("ex3data1.mat")
print(data.keys())
print(data["X"].shape)
print(data["y"].shape)
结果如下
dict_keys(['__header__', '__version__', '__globals__', 'X', 'y'])
(5000, 400)
(5000, 1)
其中X和y都是numpy数组,X(5000,400),y(5000,1),其中X存储的是5000张20x20pixel的图片,y是图片对应的数字
一行代表一张图片,一共5000张图片
3.1.3 可视化图片
def randomly_select(self, images, numbers):"""从图片中,随机选出numbers张图片:param images: 图片信息:param numbers: 选择的图片的数量:return:"""m = images.shape[0]n = images.shape[1]flags = np.zeros((m,), bool)res = Falsefor i in range(numbers):index = random.randint(0, m - 1)while flags[index]:index = random.randint(0, m)if type(res) == bool:res = images[index].reshape(1, n)else:res = np.concatenate((res, images[index].reshape(1, n)), axis=0)return resdef mapping(self, images, images_dimension):"""将若干张图片组成一张大图片:param images: 图片信息:param images_dimension: 一行放图片的数量:return:"""image_dimension = int(np.sqrt(images.shape[-1]))image = Falseim = Falsefor i in images:if type(image) == bool:image = i.reshape(image_dimension, image_dimension)else:if image.shape[-1] == image_dimension * images_dimension:if type(im) == bool:im = imageelse:im = np.concatenate((im, image), axis=0)image = i.reshape(image_dimension, image_dimension)else:image = np.concatenate((image, i.reshape(image_dimension, image_dimension)), axis=1)return np.concatenate((im, image), axis=0)
使用
def __init__(self):"""初始化数据"""data = sio.loadmat("ex3data1.mat")self.X = np.array(data["X"])self.y = np.array(data["y"])def main(self):X = self.Xim = self.mapping(self.randomly_select(X, 100), 10)plt.imshow(im.T) # 图片是镜像的需要转置让它看起来更更正常plt.axis('off')plt.show()
结果如下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8pR8aavI-1645517858354)(picture/image-20211106110120656.png)]
3.1.4 逻辑回归
使用上一道题目的逻辑回归
def cost(self, theta, X, y, l):"""计算损失函数:param theta: 参数21个:param X: 映射后的X:param y::param l: 为正则化参数,它代表了“惩罚力度”:return:"""m = X.shape[0]hat_y = self.f(x=X, theta=theta)part1 = np.mean(-y * np.log(hat_y) - (1 - y) * np.log(1 - hat_y))part2 = (l / (2 * m)) * np.sum(np.delete((theta * theta), 0, axis=0))return part1 + part2def gradient(self, theta, X, y, l):"""计算梯度:param theta: 带求参数:param X::param y::param l: 为正则化参数,它代表了“惩罚力度”:return:"""m = self.mhat_y = self.f(x=X, theta=theta)part1 = X.T.dot(hat_y - y) / mpart2 = (l / m) * thetapart2[0] = 0return part1 + part2def sigmoid(self, z):"""sigmoid函数实现了将结果从R转化到0-1,用来表示概率。实现sigmoid函数:param z: z值:return:"""return 1 / (1 + np.exp(-z))def f(self, x, theta):"""计算函数值:param theta::param x::return:"""# z=w_1x_1+w_2x_2+b,这里的theta=[b,w_1,w_2]z = x.dot(theta)return self.sigmoid(z)
One-vs-all Classification
实现多分类的方法就是用多个二分类器组合,每个分类器置识别一个数字即可。也就是我们要对0-9这10个数字训练10组分类器。
训练对应与某一个数字的分类器,需要重新构造y,当前的y的存储的是0-9,我们需要把它存储成向量[0,0,…,1,0],对应下标处的内容为1则表示是该数字。这样对应的y,每一列就代表了是否是某个数字。
对利用循环对每个数字进行分类器训练,y[…, i]即为是否为第i个数字
def one_vs_all(self, X, y, l, K):"""实现一对多分类:param X: 带求的X:param y: y:param l: lambda 惩罚力度:param K: 分类的数量,本题是0-9,所以K=10:return: 训练结束的参数"""all_theta = np.zeros((K, X.shape[1])) # (10, 401)for i in range(1, K + 1):theta = np.zeros(X.shape[1])y_i = np.array([1 if label == i else 0 for label in y])# SciPy的较新优化API来最小化每个分类器的代价函数。ret = minimize(fun=self.cost, x0=theta, args=(X, y_i, l), method='TNC',jac=self.gradient, options={'disp': True})all_theta[i - 1, :] = ret.xreturn all_theta
这里的预测函数与之前的不同,需要计算10组,取最大值的就是对应的数字。
为啥需要加1
但是现在是这个样子的
数字y | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 |
---|---|---|---|---|---|---|---|---|---|---|
原本在mat文件中,对应的结果 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
对应的向量下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
加一后效果,和y表达的值 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
所以需要加一,移位一下,
def predict_all(self, X, all_theta):"""进行预测:param X::param all_theta::return: 返回每行中最大值,即每行图片最大的概率"""# 计算每个训练实例上每个类的类概率h = self.f(X, all_theta.T) # 注意的这里的all_theta需要转置# 创建具有最大概率的索引数组# 沿轴返回最大值的索引。h_argmax = np.argmax(h, axis=1)# 因为数组的索引是0,所以需要为真正的标签预测添加1h_argmax = h_argmax + 1return h_argmax
3.1.5 代码如下
import randomimport numpy as np
import matplotlib.pyplot as plt
import scipy.io as sio
from scipy.optimize import minimize
from sklearn.metrics import classification_reportclass Multiclass_Classification:def randomly_select(self, images, numbers):"""从图片中,随机选出numbers张图片:param images: 图片信息:param numbers: 选择的图片的数量:return:"""m = images.shape[0]n = images.shape[1]flags = np.zeros((m,), bool)res = Falsefor i in range(numbers):index = random.randint(0, m - 1)while flags[index]:index = random.randint(0, m)if type(res) == bool:res = images[index].reshape(1, n)else:res = np.concatenate((res, images[index].reshape(1, n)), axis=0)return resdef mapping(self, images, images_dimension):"""将若干张图片组成一张大图片:param images: 图片信息:param images_dimension: 一行放图片的数量:return:"""image_dimension = int(np.sqrt(images.shape[-1]))image = Falseim = Falsefor i in images:if type(image) == bool:image = i.reshape(image_dimension, image_dimension)else:if image.shape[-1] == image_dimension * images_dimension:if type(im) == bool:im = imageelse:im = np.concatenate((im, image), axis=0)image = i.reshape(image_dimension, image_dimension)else:image = np.concatenate((image, i.reshape(image_dimension, image_dimension)), axis=1)return np.concatenate((im, image), axis=0)def cost(self, theta, X, y, l):"""计算损失函数:param theta: 参数共28个:param X: 映射后的X:param y::param l: 为正则化参数,它代表了“惩罚力度”:return:"""m = X.shape[0]hat_y = self.f(x=X, theta=theta)part1 = np.mean(-y * np.log(hat_y) - (1 - y) * np.log(1 - hat_y))part2 = (l / (2 * m)) * np.sum(np.delete((theta * theta), 0, axis=0))return part1 + part2def gradient(self, theta, X, y, l):"""计算梯度:param theta: 带求参数:param X::param y::param l: 为正则化参数,它代表了“惩罚力度”:return:"""m = self.mhat_y = self.f(x=X, theta=theta)part1 = X.T.dot(hat_y - y) / mpart2 = (l / m) * thetapart2[0] = 0return part1 + part2def sigmoid(self, z):"""sigmoid函数实现了将结果从R转化到0-1,用来表示概率。实现sigmoid函数:param z: z值:return:"""return 1 / (1 + np.exp(-z))def f(self, x, theta):"""计算函数值:param theta::param x::return:"""# z=w_1x_1+w_2x_2+b,这里的theta=[b,w_1,w_2]z = x.dot(theta)return self.sigmoid(z)def one_vs_all(self, X, y, l, K):"""实现一对多分类:param X: 带求的X:param y: y:param l: lambda 惩罚力度:param K: 分类的数量,本题是0-9,所以K=10:return: 训练结束的参数"""all_theta = np.zeros((K, X.shape[1])) # (10, 401)for i in range(1, K + 1):theta = np.zeros(X.shape[1])y_i = np.array([1 if label == i else 0 for label in y])# SciPy的较新优化API来最小化每个分类器的代价函数。ret = minimize(fun=self.cost, x0=theta, args=(X, y_i, l), method='TNC',jac=self.gradient, options={'disp': True})all_theta[i - 1, :] = ret.xreturn all_thetadef predict_all(self, X, all_theta):"""进行预测:param X::param all_theta::return: 返回每行中最大值,即每行图片最大的概率"""# 计算每个训练实例上每个类的类概率h = self.f(X, all_theta.T) # 注意的这里的all_theta需要转置# 创建具有最大概率的索引数组# 沿轴返回最大值的索引。h_argmax = np.argmax(h, axis=1)# 因为数组的索引是0,所以需要为真正的标签预测添加1h_argmax = h_argmax + 1return h_argmaxdef main(self):"""主函数:return:"""# 画图im = self.mapping(self.randomly_select(self.X, 100), 10)plt.imshow(im.T) # 图片是镜像的需要转置让它看起来更更正常plt.axis('off')plt.show()# 计算参数X = np.insert(self.X, 0, 1, axis=1) # (5000, 401)方便计算最后一列的by = self.y.flatten() # 这里消除了一个维度,方便后面的计算 or .reshape(-1) (5000,)all_theta = self.one_vs_all(X, y, 1, 10)print(all_theta)print("参数的维度", all_theta.shape)# 开始进行预测,注意的这里的all_theta需要转置print(classification_report(y, self.predict_all(X=X, all_theta=all_theta),target_names=[str(i) for i in range(10)], digits=4))def __init__(self):"""初始化数据"""data = sio.loadmat("ex3data1.mat")self.X = np.array(data["X"])self.y = np.array(data["y"])self.m = self.X.shape[0]if __name__ == '__main__':print("========程序开始============")obj = Multiclass_Classification()obj.main()print("========程序结束============")
3.2 神经网络
3.2.1 题目介绍
在本练习的前一部分中,您实现了多类逻辑回归来识别手写数字。
然而,逻辑回归不能形成更复杂的假设,因为它只是一个线性分类器
在这部分练习中,您将使用与之前相同的训练集实现一个神经网络来识别手写数字。
神经网络将能够表示形成非线性假设的复杂模型。这周,你将使用神经网络的参数我们已经训练过了。
您的目标是实现前馈传播算法使用我们的权值进行预测。
在下周的练习中,你将编写学习神经的反向传播算法网络参数。
3.2.2 数据介绍
def __init__(self):data = sio.loadmat("ex3data1.mat") # (5000,400)theta = sio.loadmat("ex3weights.mat")theta1 = theta["Theta1"] # (25,401)theta2 = theta["Theta2"] # (10,26)X = np.array(data["X"])y = np.array(data["y"]).flatten()X = np.insert(X, 0, 1, axis=1) # 添加一列1,方便计算bprint(y.shape)print(X.shape)
结果是
(5000,)
(5000, 401)
前向传播就是按照网络顺序计算出最后的结果,计算的具体方式,核心思想是上一层的每个节点相对于下一层的某个节点都有对应的权重,所有权重组合起来就是参数theta
3.2.3 代码介绍
y_pred = np.argmax(A3, axis=1) + 1
为啥需要加1
但是现在是这个样子的
数字y | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 |
---|---|---|---|---|---|---|---|---|---|---|
原本在mat文件中,对应的结果 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
对应的向量下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
加一后效果,和y表达的值 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
所以需要加一,移位一下,
代码如下
import scipy.io as sio
import numpy as np
from sklearn.metrics import classification_report, accuracy_scoreclass Neural_Network:def sigmoid(self, z):"""sigmoid函数实现了将结果从R转化到0-1,用来表示概率。实现sigmoid函数:param z: z值:return:"""return 1 / (1 + np.exp(-z))def f(self, x, theta):"""计算函数值:param theta::param x::return:"""# z=w_1x_1+w_2x_2+b,这里的theta=[b,w_1,w_2]z = x.dot(theta)return self.sigmoid(z)def convert(self, y):"""将y的每个值变化为向量,来表示数字parameters:----------y : ndarray表示图片对应额数字"""n = len(np.unique(y))res = Falsefor i in y:temp = np.zeros((1, n))temp[0][i[0] % 10] = 1if type(res) == bool:res = tempelse:res = np.concatenate((res, temp), axis=0)return resdef __init__(self):self.data = sio.loadmat("ex3data1.mat") # (5000,400)theta = sio.loadmat("ex3weights.mat")self.theta1 = theta["Theta1"] # (25,401)self.theta2 = theta["Theta2"] # (10,26)X = np.array(self.data["X"])self.y = np.array(self.data["y"]).flatten()self.X = np.insert(X, 0, 1, axis=1) # 添加一列1,方便计算bdef main(self):# 前馈传播算法,就是简单的矩阵运算。# 先算输入层,隐藏层,输出层# A1 (5000,401)A1 = self.X# self.theta1 (25,401)Z2 = A1.dot(self.theta1.T)# 计算隐藏层,Z2 (5000,25) ,计算完毕后Z2 (5000,26)Z2 = np.insert(Z2, 0, 1, axis=1)# 选择的函数为sigmod函数,一般A2 = self.sigmoid(Z2)# self.theta2 (10,26),,,A2(5000,26)Z3 = A2.dot(self.theta2.T)# A3就是最后的输出值,(5000,10)A3 = self.sigmoid(Z3)# 进行预测,为啥要+1,因为预测的值是1-10,,10代表0,axis=1表示选取的是行。选出每行最y_pred = np.argmax(A3, axis=1) + 1accuracy = np.mean(y_pred == self.y)print('accuracy = {0}%'.format(accuracy * 100)) # accuracy = 97.52%if __name__ == '__main__':print("========程序开始============")obj = Neural_Network()obj.main()print("========程序结束============")
结果如下
========程序开始============
accuracy = 97.52%
========程序结束============
3. 吴恩达机器学习课程-作业3-多分类和神经网络相关推荐
- 8. 吴恩达机器学习课程-作业8-异常检测和推荐系统
fork了别人的项目,自己重新填写,我的代码如下 https://gitee.com/fakerlove/machine-learning/tree/master/code 代码原链接 文章目录 8. ...
- 7. 吴恩达机器学习课程-作业7-Kmeans and PCA
fork了别人的项目,自己重新填写,我的代码如下 https://gitee.com/fakerlove/machine-learning/tree/master/code 代码原链接 文章目录 7. ...
- 6. 吴恩达机器学习课程-作业6-SVM
fork了别人的项目,自己重新填写,我的代码如下 https://gitee.com/fakerlove/machine-learning/tree/master/code 代码原链接 文章目录 6. ...
- 5. 吴恩达机器学习课程-作业5-偏差和方差
fork了别人的项目,自己重新填写,我的代码如下 https://gitee.com/fakerlove/machine-learning/tree/master/code 代码原链接 文章目录 5. ...
- 4. 吴恩达机器学习课程-作业4-神经网络学习
fork了别人的项目,自己重新填写,我的代码如下 https://gitee.com/fakerlove/machine-learning/tree/master/code 代码原链接 文章目录 4. ...
- 2.吴恩达机器学习课程-作业2-逻辑回归
fork了别人的项目,自己重新填写,我的代码如下 https://gitee.com/fakerlove/machine-learning/tree/master/code 代码原链接 文章目录 2. ...
- 1. 吴恩达机器学习课程-作业1-线性回归
fork了别人的项目,自己重新填写,我的代码如下 https://gitee.com/fakerlove/machine-learning/tree/master/code 代码原链接 文章目录 1. ...
- 吴恩达机器学习课程-作业1-线性回归(python实现)
Machine Learning(Andrew) ex1-Linear Regression 椰汁学习笔记 最近刚学习完吴恩达机器学习的课程,现在开始复习和整理一下课程笔记和作业,我将陆续更新. Li ...
- 吴恩达机器学习课程作业(一)基于python实现 详细解析(上篇)
@单变量线性回归 前言 斯坦福大学吴恩达老师的机器学习课程几乎是每位热爱人工智能领域同学的必修课.网上虽然有许多基于python实现的代码,但大多使用python交互模式解释器ipython实例讲解. ...
最新文章
- 【Smart_Point】动态内存与智能指针实战:文本查询程序(设计set,map,智能指针的应用)
- 10自带sftp服务器_一文讲透FTP和SFTP的区别
- 图像检索:几类基于内容的图像分类技术
- Spring Web Application Security
- Eclipse报错:!!MESSAGE Job found still running.......
- c++进阶---IO类的详细介绍(一)
- Android textedit 背景,Android EditText 的使用及值得注意的地方
- 克隆一个 AI 替自己开会,爽吗?
- 大数据分析平台的功能
- 图形学初探(一)图形学基础和基本术语
- CMOS电路中闩锁效应产生的原因、过程以及后果
- 国内免费CMS系统大全
- 小米笔记本bios版本大全_分享BIOS设置IDE兼容模式的方法大全,轻松解决重装系统蓝屏!...
- 七年未必痒:如何营造亲密关系的新鲜感?
- DVM,ART,JVM之间的关系
- 微信小程序通过code去获取微信用户的加密信息
- XMind 8 Update 8 Pro 激活教程(亲测可用) 国外官网下载 破解教程(带离线安装包)
- Long Short Term Memory networks(LSTMs)
- 《物理光学》——光的衍射
- 5、TORCH.RANDOM
热门文章
- 深入剖析Android音频(二)AudioSystem
- C++之printf格式
- pytorch 实现张量tensor,图片,CPU,GPU,数组等的转换
- Educoder Basemap和Seaborn 第一关:Seaborn
- cpu功耗排行_AMD、Intel主流处理器性能、功耗及性价比排行(更新中)
- 你离Python大神就差这课树了!建议收藏|Python技能树测评
- matlab录音函数怎么保存在哪里,利用matlab 录音
- java家谱树_青锋家谱系统-基于springboot+orgtree的青锋家谱树管理系统
- startlogging中设置setstdout=false来禁用这个功能。_无线路由器的安全功能,你知道多少?...
- Idea 新建类 快捷键