具有神经网络思维的Logistic回归

一、目的

搭建一个能够识别猫的简单的神经网络

二、训练集与测试集

百度网盘,提取码:1234

三、编程

注:本编程未使用提供的py文件——lr_utils.py
本次编程所需的所有模块

import h5py
import numpy as np
import matplotlib.pyplot as plt
from skimage import transform

numpy :是用Python进行科学计算的基本软件包;
h5py:是与H5文件中存储的数据集进行交互的常用软件包;
matplotlib:是一个著名的库,用于在Python中绘制图表;
skimage:在本次编程用来修改图片的维度

1.导入原始数据集进行剖析

将训练集保存到train_dataset,测试集保存到test_dataset

# 导入原始数据集
train_dataset = h5py.File("./datasets/train_catvnoncat.h5", "r")
test_dataset = h5py.File("./datasets/test_catvnoncat.h5", "r")

使用for循环查看训练集中的键:

for key in train_dataset.keys():print(key)

训练集中我们可以得到三个键:
train_set_x :保存的是训练集里面的图像数据;
train_set_y :保存的是训练集的图像对应的分类值(0 | 1,0表示不是猫,1表示是猫);
list_classes : 保存的是以bytes类型保存的两个字符串数据,数据为:b’non-cat’ b’cat’]
测试集中是test_set_xtest_set_ylist_classes
这些数据都可以用print函数打印出来查看

我们单独将训练集和测试集的原始数据和标签导出,使用x代表数据,y代表标签

# 单独导出训练集和测试集的原始数据和标签
train_set_x_orig = np.array(train_dataset["train_set_x"][:])
train_set_y_orig = np.array(train_dataset["train_set_y"][:])
test_set_x_orig = np.array(test_dataset["test_set_x"][:])
test_set_y_orig = np.array(test_dataset["test_set_y"][:])

我们可以选择任意一个样本查看一下是什么样的,以及标签

# 查看第三张图片和标签
plt.imshow(train_set_x_orig[2])
print(train_set_y_orig[2])
plt.show()



我们再查看一下数据的维度

print(train_set_x_orig.shape, train_set_y_orig.shape,test_set_x_orig.shape, test_set_y_orig.shape)


(209, 64, 64, 3)表示训练集有209张rgb图片,每个通道图片的大小是64*64的;(209,)表示标签的形状;也能看到测试集有50张图片

2.处理数据的维度

这一步非常重要,要将数据的维度处理成为神经网络输入的维度,很多问题都是由于维度没有处理好导致的。
现在我们数据的维度是:

数据集 原始维度
train_set_x_orig (209, 64, 64, 3)
train_set_y_orig (209,)
test_set_x_orig (50, 64, 64, 3)
test_set_y_orig (50,)

现在让我们来回顾一下神经网络的前向传播是怎样的:

对于某一个训练样本i输入它的n个特征值,每个特征值乘上权重再加上b,我们将其结果记为z(i)z^{(i)}z(i),即z(i)=xi1w1+xi2w2+...+xinwn+bz^{(i)}=x_{i1}w_1+x_{i2}w_2+...+x_{in}w_n+bz(i)=xi1​w1​+xi2​w2​+...+xin​wn​+b,经过激活函数a,就可以得到预测值,现在我们若有m个样本,每个样本具有n个特征,我们就能得到m个z,则我们需要对其进行向量化,去掉for循环,加快程序运行速度

由公式Z=wTX+bZ=w^TX+bZ=wTX+b得:


那么对于本次数据集我们就可以得到我们需要的维度:

数据集 原始维度 需要的维度
train_set_x_orig=X (209, 64, 64, 3) (12288,209)
train_set_y_orig=y^\hat{y}y^​ (209,) (1, 209)
test_set_x_orig (50, 64, 64, 3) (12288,50)
test_set_y_orig (50,) (1, 50)

原始文档在此
现在我们开始处理数据维度,在此期间可以多次使用shape查看维度是否正确

# 处理数据的维度
m = train_set_x_orig.shape[0]
train_set_x_tran = train_set_x_orig.reshape((m, -1)).T
train_set_y_tran = train_set_y_orig.reshape((m, -1)).T
m = test_set_x_orig.shape[0]
test_set_x_tran = test_set_x_orig.reshape((m, -1)).T
test_set_y_tran = test_set_y_orig.reshape((m, -1)).T

查看数据的维度是否处理的正确

print(train_set_x_tran.shape, train_set_y_tran.shape, test_set_x_tran.shape, test_set_y_tran.shape)

3.标准化数据

对数据进行标准化,因为在图片中,一个数据的大小在0-255之间,我们可以选第一个样本的部分数据来看一下

print(train_set_x_tran[:9, :9])


这会导致不同的特征的权重差别比较大,通常会将数据处理在一个比较小的范围内,如0-1之间,防止不同特征之间权重比例失衡;我们对样本每个特征都除(max-min)=255即可

# 标准化数据
train_set_x_stan = train_set_x_tran / 255
test_set_x_stan = test_set_x_tran / 255

再看一下处理过后的数据

4.定义激活函数,初始化w和b

这里激活函数我们选用sigmoid函数,函数定义为:
A=sig(Z)=g(Z)=11+e−ZA=sig(Z)=g(Z)=\frac{1}{1+e^{-Z}}A=sig(Z)=g(Z)=1+e−Z1​

# 定义sigmoid函数
def sigmoid(Z):s = 1 / (1 + np.exp(-Z))return s

初始化w和b

# 初始化w和b,w为n*1的数组,b为常数
n_dim = train_set_x_stan.shape[0]
w = np.zeros((n_dim, 1))
b = 0

5.定义前向传播函数、代价函数以及反向传播函数

我们再来看一下神经网络的反向传播,就是利用我们得到的代价损失函数L返回去去推导w和b

损失函数L和代价函数J

想看如何推导的,链接在此:001_wz_sf_逻辑回归(Logistic Regression)
使用梯度下降法推导dw和db


再对其向量化,最后就可以得到w和b以及损失函数J的迭代公式

原始文档在此

5.1 前向传播函数

Z=wTX+bZ = w^TX+bZ=wTX+bA=sigmoid(Z)A = sigmoid(Z)A=sigmoid(Z)

5.2 代价函数

J=−1m∑i=1m(y∗logA+(1−y)∗log(1−A))J=-\frac{1}{m}\sum{^{m}_{i=1}}(y*logA+(1-y)*log(1-A))J=−m1​∑i=1m​(y∗logA+(1−y)∗log(1−A))

5.3 反向传播函数

dw=1mX(A−y)dw=\frac{1}{m}X(A-y)dw=m1​X(A−y)db=1m∑i=1m(A−y)db=\frac{1}{m}\sum{^m_{i=1}}(A-y)db=m1​∑i=1m​(A−y)

# 定义前向传播函数、代价函数以及反向传播函数
def propagate(w, b, X, y, alpha):# 1.前向传播函数Z = np.dot(w.T, X) + bA = sigmoid(Z)# 2.代价函数m = train_set_x_stan.shape[1]J = -1 / m * np.sum((y * np.log(A)) + (1 - y) * np.log(1 - A))# 反向传播函数dw = 1 / m * np.dot(X, (A - y).T)db = 1 / m * np.sum(A - y)grands = {"dw": dw,"db": db}return grands, J

最后将dw,db,J返回

6.进行优化

迭代公式
w:=w−αdww := w-\alpha dww:=w−αdwb:=b−αdbb:=b-\alpha dbb:=b−αdb
设计一个成本列表,用于储存损失函数的数值,后面用于绘图,然后返回各个需要用到的参数
注:形参print_cost是一个控制间隔100次打印成本的布尔类型参数

# 优化部分
def optimize(w, b, X, y, alpha, n_iters, print_cost):costs = []for i in range(n_iters):grands, J = propagate(w, b, y, X)dw = grands["dw"]db = grands["db"]w = w - alpha * dwb = b - alpha * dbif i % 100 == 0:costs.append(J)if print_cost:print("n_iters is", i, "cost is", J)grands = {"dw": dw, "db": db}params = {"w": w, "b": b}return grands, params, costs

7.进行预测

传入测试集X_test,进行预测输出预测结果y_pred

# 预测部分
def predict(w, b, X_test):Z = np.dot(w.T, X_test)A = sigmoid(Z)m = X_test.shape[1]y_pred = np.zeros((1, m))for i in range(m):if A[:, i] > 0.5:y_pred[:, i] = 1else:y_pred[:, i] = 0return y_pred

8.模型整合

模型的整合,方面后面模型的调整

# 模型的整合
def model(w, b, X_train, y_train, X_test, y_test, alpha, n_iters, print_cost):grands, params, costs = optimize(w, b, X_train, y_train, alpha, n_iters, print_cost)w = params["w"]b = params["b"]y_train_pred = predict(w, b, X_train)y_test_pred = predict(w, b, X_test)print("alpha is", alpha)print("the train acc is", np.mean(y_train_pred == y_train) * 100, "%")print("the test acc is", np.mean(y_test_pred == y_test) * 100, "%")print("==============================")b = {"w": w,"b": b,"y_train_pred": y_train_pred,"y_test_pred": y_test_pred,"costs": costs,"alpha":alpha}return b

9.运行与结果分析

取学习速率(步长)α\alphaα=0.005,迭代次数n_iters=2000次,运行结果为在训练集上正确率99%,测试集上70%

d = model(w, b, train_set_x_stan, train_set_y_tran, test_set_x_stan, test_set_y_tran, alpha=0.005, n_iters=2000, print_cost=False)


学习成本的变化如下图

对于学习速率α\alphaα的取值,α\alphaα决定了我们更新参数w和b的速度,如果α\alphaα取值过大,我们得到的值可能会“超过”最优值;若α\alphaα取值过小,我们需要迭代太多次才能熟练到最优值,所以α\alphaα的取值至关重要,下面我们来看一下不同α\alphaα值的成本曲线:

# alpha的不同取值
alphas = [0.01, 0.001, 0.0001]
for alpha in alphas:d = model(w, b, train_set_x_stan, train_set_y_tran, test_set_x_stan, test_set_y_tran,alpha=alpha, n_iters=2000, print_cost=False)plt.plot(d["costs"], label=str(alpha))plt.xlabel("per hundred iters")plt.ylabel("cost")plt.legend()
plt.show()



在相同的迭代次数下,可以明显看到在学习速率比较小时,整个成本下降的速度是越来越慢的,收敛到最优值是比较慢的;而对于比较大的学习速率,可见其收敛的速度很快,但是其在前面错过了一些局部最优值,所有前期曲线会有一部分上升,但是总体是在下降的。
可以参见文章:机器学习算法:梯度下降法——原理篇

10.测试

我们可以自己选择一张图片测试

读入要预测的图片,查看维度,将其改为我们所需要的维度,使用预测函数预测

# 读入图片
fname = "E:\py\DL\datasets\img1.jpg"
img_org = plt.imread(fname)
# print(img_org.shape)
# 修改维度
img_tran = transform.resize(img_org, (64, 64, 3)).reshape(64*64*3, 1)
#print(img_tran.shape)
# 进行预测
pred = predict(d["w"], d["b"], img_tran)
print(int(pred))
plt.imshow(img_org)
plt.show()


可以看到预测结果是1,预测成功了

11.源码

源码在此

四、总结

整个神经网络的架构如下

在整个过程中,要搞清楚这里面每一步做的都是为了什么,以及参数w和b在循环:计算当前损失(正向传播)–>计算当前梯度(反向传播)–>更新参数(梯度下降)中是如何求得的,这是比较关键的,还有一个是一定要计算好数据的维度,到哪一步得到的数据应该是什么维度。

五、参考文章

【中文】【吴恩达课后编程作业】Course 1 - 神经网络和深度学习 - 第二周作业
机器学习算法:梯度下降法——原理篇
特别感谢:B站UP主ladykaka007的视频

003_wz_wed_DL_课程一第二周编程题(Logistic回归;神经网络思维;)相关推荐

  1. 吴恩达机器学习第二周编程题参考答案

    Andrew Ng机器学习第二周编程题参考答案 https://download.csdn.net/download/yhf2333/10718778 语言:Octave Tips: 1.记得使用si ...

  2. Operations on word vectors-v2 吴恩达老师深度学习课程第五课第二周编程作业1

    吴恩达老师深度学习课程第五课(RNN)第二周编程作业1, 包含答案 Operations on word vectors Welcome to your first assignment of thi ...

  3. 哈工大C语言程序设计精髓 第十一周编程题

    C语言程序设计精髓 第十一周 指针的孪生兄弟 从这一章开始难度才算是真正开始加大了,前面可以说都在过家家. 练兵区--编程题--不计入总分 1找出按字典顺序排在最前面的国名(4分) 题目内容: 输入5 ...

  4. python123第七周测验编程题答案_Python第七周编程题

    Python123第七周编程题 1.打印输出附件文件的平均列数,计算方法如下:‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫ ...

  5. Python123第六周编程题

    Python123中第六周编程题 1.获得用户输入的一个整数N,输出N中所出现不同数字的和.‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬ ...

  6. 中国大学MOOC哈工大C语言程序设计第9周编程题在线测试

    中国大学MOOC哈工大C语言程序设计第9周编程题在线测试 1.重复数字检查(4分) 题目内容: 从键盘输入一个数,检查这个数中是否有重复出现的数字.如果这个数中有重复出现的数字,则显示"Re ...

  7. Emojify - v2 吴恩达老师深度学习第五课第二周编程作业2

    吴恩达老师深度学习第五课第二周编程作业2,包含答案! Emojify! Welcome to the second assignment of Week 2. You are going to use ...

  8. 小学生计算机编程题,真题|小学组倒数第二道编程题,做不出来罚你点赞三遍!...

    原标题:真题|小学组倒数第二道编程题,做不出来罚你点赞三遍! 十年前,当我们还是小学生的时候,碰到电脑你们都会干什么? 是熟练地在网址栏输入www.4399.com,然后一个接一个的点开网页小游戏,还 ...

  9. 面向对象程序设计——Java语言 第3周编程题 查找里程(10分)

    面向对象程序设计--Java语言 第3周编程题 查找里程(10分) 题目内容 下图为国内主要城市之间的公路里程: 你的程序要读入这样的一张表,然后,根据输入的两个城市的名称,给出这两个城市之间的里程. ...

最新文章

  1. 丢包和网络延迟对网络性能的影响
  2. MPLS原理之MPLS基本结构—Vecloud微云
  3. java语言程序设计全国考试题,2019年12月全国计算机等级考试[Java语言程序设计]复习题及答案...
  4. ctfshow-网络迷踪-初学乍练( 离谱! 一张图判断飞机的目的地?)
  5. Bootstrap_导航
  6. mysql如何怎么进行单表的单条数据删除--根据id进行删除
  7. 飞客蠕虫专杀工具_案例-飞客蠕虫攻击
  8. cad快看_对于CAD看图软件,你到底了解多少?
  9. 36氪独家|京东零售宣布多位高管新任命,POP平台部门成整合重点
  10. 2-java面向对象
  11. 面试题系列(三)-socket
  12. 北邮计算机考研专业课分值,北邮计算机考研分数线
  13. echart地图加载中国地图,可切换省市地图
  14. css3的高级特效 2D
  15. 毕业设计-基于深度学习的图像隐写分析
  16. CFileDialog 参数及返回值
  17. 中国十大虚拟主机服务商
  18. 钱包缩水,消费降级,你更需要这款PDF转Word转换器
  19. 华硕ax56u刷机_华硕WiFi6家用路由RT-AX56U初体验
  20. 有多少人等着看百度区块链的笑话?

热门文章

  1. Linux系统之部署Rsyslog 日志服务器
  2. 用html写一个简单课表
  3. QPS和TPS的区别
  4. 【历史上的今天】5 月 29 日:共享软件先驱诞生;ChromeBox 推出;VoodooPC 创始人出生
  5. SASS的概念和使用
  6. docker仓库Repository和harbor仓库
  7. 中国时光之美:旅途中的二十…
  8. 软件工程——成本效益分析
  9. hdu 5435 A serious math problem 数位dp
  10. 将文件复制到ftp服务器时发生错误,请检查是否有权将文件放到该服务器上