吴恩达课后编程作业】神经网络和深度学习第二周作业logistic回归(个人小结)

    科技2023-10-02  91

    本 文 是 对 这 篇 文 章 的 总 结 以 及 个 人 理 解 \color{Red}本文是对这篇文章的总结以及个人理解

    有神经网络思维的Logistic回归

    我觉得这位大佬写的非常好,因此在这里做个笔记,方便自己日后参考

    后续有很多话是引用大佬的,所以也算半个转载吧!!


    任 务 梳 理 ( 概 述 ) \color{Red}任务梳理(概述) ()

    w w w b b b是计算系数,也就是我们要不断训练计算的值

    i i i表示第 i i i张样本图片,所以 x i x_i xi是一个包含了图片的颜色信息的矩阵

    z i = w T x i + b z^i=w^Tx^i+b zi=wTxi+b

    我们先用 0 0 0初始化 w w w系数矩阵和 b b b来计算图片对应的 z i z^i zi

    但是因为 z i z^i zi不是一个 [ 0 , 1 ] [0,1] [0,1]的数,所以我们使用函数来映射

    y ^ i = s i g m o i d ( z i ) \hat{y}^i=sigmoid(z^i) y^i=sigmoid(zi)

    通过 s i g m o i d sigmoid sigmoid函数把预测值转化为一个 [ 0 , 1 ] [0,1] [0,1]的数,这就是我们对图片的预测值

    越接近 1 1 1代表预测是猫,越接近 0 0 0代表系数不是猫

    为了衡量预测的精度,我们准备了一个损失函数来计算误差

    其中 y i y^i yi是真实值, y ^ i \hat{y}^i y^i是预测值

    L ( y ^ i , y i ) = − y i l o g ( y ^ i ) − ( 1 − y i ) l o g ( 1 − y ^ i ) L(\hat{y}^i,y^i)=-y^ilog(\hat{y}^i)-(1-y^i)log(1-\hat{y}^i) L(y^i,yi)=yilog(y^i)(1yi)log(1y^i)

    当然,我们训练的是 m m m张图片,所以对损失求平均值

    J = 1 m ∑ i = 1 m L ( y ^ i , y i ) J=\frac{1}{m}\sum\limits_{i=1}^mL(\hat{y}^i,y^i) J=m1i=1mL(y^i,yi)

    提前备好的资料

    资料下载处提取码2u3w ,在开始之前下载好所需资料,然后将文件解压到你的代码文件同一级目录下,请确保你的代码那里有lr_utils.py和datasets文件夹。

    需要的库

    不需要知道这些库是什么,照着敲就理解了,只需要知道 l o a d _ d a t a s e t load\_dataset load_dataset可以返回图片信息

    from lr_utils import load_dataset #自己写的加载图片信息的包 import h5py #为了加载图片信息导入的库 import matplotlib.pyplot as plt #绘图的库 import numpy as np #科学计算矩阵的常用库 train_set_x_orig , train_set_y , test_set_x_orig , test_set_y , classes = load_dataset()

    首 先 我 想 详 细 介 绍 一 下 t r a i n _ s e t _ x _ o r i g 变 量 什 么 \color{Red}首先我想详细介绍一下train\_set\_x\_orig变量什么 train_set_x_orig

    train_set_x_orig训练集存放的所有 m m m张图片的信息

    train_set_y训练集存放的所有的 m m m张图片是不是猫,取值 0 0 0 1 1 1

    比如我现在就查看一下第 2 2 2张图片是什么,是不是猫,你也可以把 i n d e x index index换成其他

    index = 2 plt.imshow(train_set_x_orig[index]) plt.show() print("第%d张图片是不是猫呢?->%d"%(index,train_set_y[0][index]))

    测试集test_set_x_orig等同理

    print ("训练集_图片的维数 : " + str(train_set_x_orig.shape))

    结果

    训练集_图片的维数 : (209, 64, 64, 3)

    这告诉我们这是一个四维矩阵,第一维是代表 209 209 209张图片

    每一张图片都是 64 ∗ 64 ∗ 3 64*64*3 64643个点信息组成,为什么呢?

    大概理解下就算长宽各 64 64 64,而且有三层 ( R , G , B ) (R,G,B) (R,G,B),分别表示红绿蓝

    理解了这个,其他的也是同理了,下面的解释自己看一下即可

    train_set_x_orig , train_set_y , test_set_x_orig , test_set_y , classes = load_dataset() m_train = train_set_y.shape[1] #训练集图片数量 m_test = test_set_y.shape[1] #测试集图片数量 m_train = train_set_y.shape[1] #训练集里图片的数量。 m_test = test_set_y.shape[1] #测试集里图片的数量。 num_px = train_set_x_orig.shape[1] #训练、测试集里面的图片的宽度和高度(均为64x64)。 #现在看一看我们加载的东西的具体情况 print ("训练集的数量: m_train = " + str(m_train)) print ("每张图片的宽/高 : num_px = " + str(num_px)) print ("每张图片的大小 : (" + str(num_px) + ", " + str(num_px) + ", 3)") print ("训练集_图片的维数 : " + str(train_set_x_orig.shape)) print ("训练集_标签的维数 : " + str(train_set_y.shape))

    现在每张图片的信息是一个三维矩阵 ( 64 , 64 , 3 ) (64,64,3) (64,64,3)

    很不方便,我们把它转化为一个一列的矩阵

    就是把原本四维的train_set_x_orig变成 ( 64 ∗ 64 ∗ 3 , 图 片 数 ) (64*64*3,图片数) (64643,)的矩阵

    train_set_x_orig.shape[0]就是图片数

    至于reshape的第二维写 − 1 -1 1,这是函数的用法自动计算剩余列,读者可以百度

    .T表示矩阵转置

    R G B RGB RGB颜色矩阵的值是 [ 0 , 255 ] [0,255] [0,255]的,除以一个 255 255 255让所有数变到 [ 0 , 1 ] [0,1] [0,1]区间内

    话说为啥要除以255我也不知道,也许更精确??

    #变换维度,每张图片的信息集中在一列上 train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0],-1).T test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0],-1).T #把颜色通道映射到[0,1]去 train_set_x = train_set_x_flatten / 255 test_set_x = test_set_x_flatten / 255

    所以我们目前得到了train_set_x是 255 255 255列, 64 ∗ 64 ∗ 3 64*64*3 64643行的信息矩阵

    每列表示一张图片的信息,现在我们开始训练来计算 w w w b b b

    看下面这个函数,其中参数 w w w b b b初始化都是 0 0 0

    def propagate(w,b,x,y): #w是(64*64*3,1)的矩阵,x是(64*64*3,训练数量)的矩阵 #y是(1,训练数),非0即1,表示是不是猫 m = x.shape[1] #训练数目 A = sigmoid( np.dot(w.T,x)+b ) #计算值z[i]并利用sigmoid映射到[0,1] cost = (-1/m)*np.sum(y*np.log(A)+(1-y)*np.log(1-A)) #损失函数的计算 dw = ( 1/m )*np.dot( x,(A-y).T ) #损失函数对w的导数 db = ( 1/m )*np.sum(A-y) #损失函数对b的导数 cost = np.squeeze(cost) #squeeze删除为1的维度, grad = { "dw":dw, "db":db} return (grad,cost )

    于是我们得到了 d w , d b dw,db dw,db,就可以轻松的去更新 w , b w,b w,b

    于是下面这个函数就变得很清楚了,因为就只干了一件事

    就是拿当前的 w w w减去 d w dw dw,拿当前的 b b b减去 d b db db

    def optimize( w, b, x, y, circle_num, learning): #其中circle_num是训练(计算)次数,learning是学习率 costs = [] for i in range(circle_num): grads,cost = propagate(w,b,x,y) #得到dw,db dw = grads["dw"] db = grads["db"] w = w-learning*dw b = b-learning*db if i%100 == 0: costs.append(cost)#记录一下误差方便观察 params = { "w": w, "b": b} grads = { "dw":dw, "db":db} return (params,grads,costs)

    现在我们得到了相对精确的参数 w , b w,b w,b,就可以开始预测测试集啦!!

    def predict( w, b, x ): m = x.shape[1]#图片数量 predicy = np.zeros((1,m)) w = w.reshape(x.shape[0],1) A = sigmoid(np.dot(w.T,x)+b ) #计算z[i]并映射到[0,1] for i in range(A.shape[1]): predicy[0,i] = 1 if A[0,i]>0.5 else 0 return predicy

    基本工作都做完了。不妨绘制个图片看看 w w w b b b怎么变化到??

    costs = d['costs'] #取出损失度,这是一个列表 plt.plot(costs) #绘图 plt.ylabel('cost') #y轴标签 plt.xlabel('iterations (per hundreds)') #x轴标签 plt.title("Learning rate =" + str(d["learning"])) #图的标题 plt.show() #展示

    可以看到损失误差值一直在减小,说明算法很成功

    下面是完整的代码,相信除了 p r o p a g a t e propagate propagate函数计算导数很绕之外

    其他部分都容易懂,看不懂 p r o p a g a t e propagate propagate回去刷吴恩达的推导过程即可

    完整代码

    from lr_utils import load_dataset import h5py import matplotlib.pyplot as plt import numpy as np train_set_x_orig , train_set_y , test_set_x_orig , test_set_y , classes = load_dataset() m_train = train_set_y.shape[1] #训练集图片数量 m_test = test_set_y.shape[1] #测试集图片数量 m_train = train_set_y.shape[1] #训练集里图片的数量。 m_test = test_set_y.shape[1] #测试集里图片的数量。 num_px = train_set_x_orig.shape[1] #训练、测试集里面的图片的宽度和高度(均为64x64)。 #现在看一看我们加载的东西的具体情况 #变换维度,每张图片的信息集中在一列上 train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0],-1).T test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0],-1).T #把颜色通道映射到[0,1]去 train_set_x = train_set_x_flatten / 255 test_set_x = test_set_x_flatten / 255 def sigmoid(z):#映射到[0,1]概率的函数 return 1/(1+np.exp(-z)) def init_forwb(dim): #作用是为w创建维度是(dim,1)的0向量,并将b初始化为0 #返回w是(dim,1)的向量,b是初始化的标量 w = np.zeros( shape=(dim,1) ) b = 0 return (w,b) def propagate(w,b,x,y): #w是(num_px*num_py*3,1)的矩阵,x是(num_px*num_py*3,训练数量) m = x.shape[1] #训练数目 A = sigmoid( np.dot(w.T,x)+b ) #计算值 cost = (-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) cost = np.squeeze(cost)#删除为1的维度, grad = { "dw":dw, "db":db} return (grad,cost ) def optimize( w, b, x, y, circle_num, learning, print_cost=False): costs = [] for i in range(circle_num): grads,cost = propagate(w,b,x,y) dw = grads["dw"] db = grads["db"] w = w-learning*dw b = b-learning*db if i%100 == 0: costs.append(cost)#记录一下 if (print_cost) and (i%100==0): print("迭代次数: %d, 误差值: %f"%(i,cost)) params = { "w": w, "b": b} grads = { "dw":dw, "db":db} return (params,grads,costs) def predict( w, b, x ): m = x.shape[1]#图片数量 predicy = 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]): predicy[0,i] = 1 if A[0,i]>0.5 else 0 return predicy def model(x_train,y_train,x_test,y_test,circle_num=2000,learning=0.5,print_cost=False): w , b = init_forwb(x_train.shape[0]) parameters,grads,costs = optimize(w,b,x_train,y_train,circle_num,learning,print_cost) w, b =parameters['w'],parameters['b'] predic_test = predict(w,b,x_test) predic_train = predict(w,b,x_train) print("训练集准确度: ",format(100-np.mean(np.abs(predic_train-y_train))*100),"%" ) print("测试集准确度: ",format(100-np.mean(np.abs(predic_test-y_test))*100),"%" ) d = { "costs":costs, "predicy_test":predic_test, "predic_train":predic_train, "w": w, "b": b, "learning":learning, "circle_num":circle_num } return d print("====================测试model====================") #这里加载的是真实的数据,请参见上面的代码部分。 d = model(train_set_x, train_set_y, test_set_x, test_set_y, circle_num = 2000, learning = 0.005, print_cost = True) #绘制图 costs = d['costs'] plt.plot(costs) plt.ylabel('cost') plt.xlabel('iterations (per hundreds)') plt.title("Learning rate =" + str(d["learning"])) plt.show()

    无注释简介版本

    from lr_utils import load_dataset import h5py import matplotlib.pyplot as plt import numpy as np train_set_x_orig , train_set_y , test_set_x_orig , test_set_y , classes = load_dataset() m_train = train_set_y.shape[1] #训练集图片数量 m_test = test_set_y.shape[1] #测试集图片数量 m_train = train_set_y.shape[1] #训练集里图片的数量。 m_test = test_set_y.shape[1] #测试集里图片的数量。 num_px = train_set_x_orig.shape[1] #训练、测试集里面的图片的宽度和高度(均为64x64)。 train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0],-1).T test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0],-1).T train_set_x = train_set_x_flatten / 255 test_set_x = test_set_x_flatten / 255 def sigmoid(z):#映射到[0,1]概率的函数 return 1/(1+np.exp(-z)) def init_forwb(dim): w = np.zeros( shape=(dim,1) ) b = 0 return (w,b) def propagate(w,b,x,y): m = x.shape[1] #训练数目 A = sigmoid( np.dot(w.T,x)+b ) #计算值 cost = (-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) cost = np.squeeze(cost)#删除为1的维度, grad = { "dw":dw, "db":db} return (grad,cost ) def optimize( w, b, x, y, circle_num, learning, print_cost=False): costs = [] for i in range(circle_num): grads,cost = propagate(w,b,x,y) dw = grads["dw"] db = grads["db"] w = w-learning*dw b = b-learning*db if i%100 == 0: costs.append(cost)#记录一下 if (print_cost) and (i%100==0): print("迭代次数: %d, 误差值: %f"%(i,cost)) params = { "w": w, "b": b} grads = { "dw":dw, "db":db} return (params,grads,costs) def predict( w, b, x ): m = x.shape[1]#图片数量 predicy = 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]): predicy[0,i] = 1 if A[0,i]>0.5 else 0 return predicy def model(x_train,y_train,x_test,y_test,circle_num=2000,learning=0.5,print_cost=False): w , b = init_forwb(x_train.shape[0]) parameters,grads,costs = optimize(w,b,x_train,y_train,circle_num,learning,print_cost) w, b =parameters['w'],parameters['b'] predic_test = predict(w,b,x_test) predic_train = predict(w,b,x_train) print("训练集准确度: ",format(100-np.mean(np.abs(predic_train-y_train))*100),"%" ) print("测试集准确度: ",format(100-np.mean(np.abs(predic_test-y_test))*100),"%" ) d = { "costs":costs } return d print("====================测试model====================") d = model(train_set_x, train_set_y, test_set_x, test_set_y, circle_num = 2000, learning = 0.005, print_cost = True) costs = d['costs'] plt.plot(costs) plt.ylabel('cost') plt.xlabel('iterations (per hundreds)') plt.title("Learning rate =" + str(d["learning"])) plt.show()

    其实还可以自己调整学习率,迭代次数让结果更加准确

    这里不再累赘了

    Processed: 0.012, SQL: 8