深度学习-吴恩达第一课第二周课程作业

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Bazingaea/article/details/83041262

这周作业是,给出一张图片,判断这张图是不是猫。

这是一个二分类问题,结果是非0即1的,使用逻辑回归(Logic Regression),可以说,了解这个回归方法,有些python基础,会使用jupyter notebook就可以尝试着码一遍代码,走完整个学习流程,能进一步加深对逻辑回归的了解,对下一步的学习也有好处。首先在写代码之前,需要把逻辑回归向量化理解清楚,因为后面代码不是用循环来写的,是直接对矩阵进行操作的,这就要求把回归中的循环求和啊,相乘啊都用矩阵来表示,特别要注意矩阵的维度,不要搞混了,这就不细说了。

1.数据导入

首先需要获取数据集,这里贴一个GITHUB地址,可分别自行下载训练和测试数据集,数据集是后缀为.h5的文件,

要让python文件能读取这类文件,需要引入h5py库。已安装Anaconda的话应该不需要再手动下载这个库了,Anaconda

中包含了很多常用的库文件,如果没有安装Anaconda,可以直接用pip安装:pip install h5py

安装好以后,就可以在notebook上直接导入库,这个案例一共需要用到三个库,这块就一起导入了:

import numpy as np
import matplotlib.pyplot as plt
import h5py

h5py库是用来读取数据集的,有两个数据集需要读取,训练数据集和测试数据集:

train_data = h5py.File('D:\\jupyter\\datasets\\train_catvnoncat.h5','r')
test_data = h5py.File('D:\\jupyter\\datasets\\test_catvnoncat.h5','r')

后面的参数r表示只读模式,这样就把这两个数据集导入到notebook中了,下面就需要对导入的数据进行处理

在此之前,可以先来看看数据集到底是什么样的,.h5文件中存储的数据都是键值对(key-value),可以理解为key就是对一堆数据设定的一个标签,通过这个标签就可以获取这个标签下的所有数据,就拿train集来说:

#获取其中的所有key值
list(train_data.keys())

#这是输出结果,有三个
['list_classes', 'train_set_x', 'train_set_y']

#选其中一个
train_data['train_set_x'].shape

#输出,这表示有209张图,每张图存储格式为(64,64,3)
(209, 64, 64, 3)

图像在计算机中的存储形式,其实就是三个矩阵,这三个矩阵分别表示(red,green,blue)在每一个像素单元格的取值,

因为我们都知道这三色可以组成任何色,这个案例中用到的图像大小都是64*64*3,也就是由三个64*64的矩阵来存储的

矩阵中每个元素的取值为0-255

再介绍一下三个key值,第一个是类别,针对这个问题也就是,是否为猫;第二个是X集,也就是所有的特征值,属性值,这里的X集并不是我们能直接使用的,还需要对它进行处理,下面会讲到;第三个是Y集,0/1 ,这里就要明确一点,train数据集的样本个数,也就是m的值是209

2.数据处理

为了方便操作,先把数据都取出来,X集和Y集分开:

train_data_x=train_data['train_set_x'][:]
train_data_y=train_data['train_set_y'][:]

test_data_x=test_data['test_set_x'][:]
test_data_y=test_data['test_set_y'][:]

下面要做的就是处理X集,相对麻烦,Y集直接重塑成1*209矩阵即可

#处理X集:获取样本个数,将X集转换为209*(64*64*3)形式
m_train=train_data_x.shape[0]
train_data_finalX=train_data_x.reshape(m_train,-1).T

m_test=test_data_x.shape[0]
test_data_finalX=test_data_x.reshape(m_test,-1).T


#处理Y集
train_data_finalY=train_data_y.reshape(1,m_train)
test_data_finalY=test_data_y.reshape(1,m_test)

解释一下这个数据格式转化,我们在向量化的时候,需要的X集是(n*m)的,其中n是特征值或者叫做属性值的个数,m是样本的个数,在这里,样本数是209,属性值的个数就是64*64*3,就是把一个图片的所有存储值都合并在一起。通过reshape得到的是一个m(m=209)*n(n=64*64*3)的矩阵,所以还需要获取它的转置

如果不确定现在操作的矩阵的维数,可以通过X.shape查看维数

最后一步,前面提到过X集中特征值的取值范围在0-255,偏差较大,为使得分类器训练效果更好一些,可以对X集数据进行规范处理,这里可以直接让每一个特征值除以255,让其处于0-1这个范围

train_data_finalX=train_data_finalX/255
test_data_finalX=test_data_finalX/255

3.训练模型

处理完数据以后,终于可以进入正题了,下面分两个阶段来讲,向前传播和反向传播。

向前传播,就是根据X集的特征值,结合W权重,以及b值,经过 Z=W’X+b 得到Z值,然后计算出预测的Y值 a

反向传播,就是求偏倒数,这里的dw只是方便书写,这其实是w对J的偏导数,其他也一样

#先定义sigmoid函数,方便后面调用,这里的a是一个样本数据得到的预测值
def sigmoid(z):
    a=1/(1+np.exp(-z))
    return a


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


#完成一次迭代
def propagate(w,b,x,y):

    #向前传播,z(1*m),A(1*m)
    z=np.dot(w.T,x)+b
    A=sigmoid(z)
    
    m=x.shape[1]

    #损失函数
    J=-1/m*np.sum(y*np.log(A)+(1-y)*np.log(1-A))
    
    #反向传播,其实就是求偏导
    #dz(1*m),dw(n*1),db常数
    dz=A-y
    dw=1/m*np.dot(x,dz.T)
    db=1/m*np.sum(dz)
    

    #将返回值封装在dict中,比较方便获取
    grands={'dw':dw,'db':db}
    
    return grands,J

当然一次迭代是无效的,需要多次迭代:

#多次迭代寻找最优解(w,b)
def optimize(w,b,x,y,alphs,n_iters,flag=True):

    #每一百次获取一个代价值,保存在这个list中
    costs=[]

    #开始迭代,每次迭代之前先获取dw,db,用来更新w,b的值
    for i in range(n_iters):
        grands,J=propagate(w,b,x,y)
        dw=grands['dw']
        db=grands['db']
        
        w=w-dw*alphs
        b=b-db*alphs
        
        #打印代价值,后期可以用来绘制cost图像
        if i % 100 == 0:
            costs.append(J)
            if flag:
                print('iters is ',i,' cost is ',J)
    

   #返回得到的w,b
    params={'w':w,'b':b}
    
    return params,costs

迭代完成以后,模型就训练好了,其实训练模型,说白了在这个案例中就是获得w和b

4.检验模型

那么这么训练出来的模型怎么样呢,就需要用我们刚才处理过的测试集数据进行预测,也就是输入X集,看得到的Y值是否正确,

从而可以知道我们这个模型的精确度是多少,也就是给出100张图片,能有效判断出几张有猫在内的

def predict(w,b,X_test):

    #这个步骤是不是很熟悉,这就是前面训练模型时的向前传播啊!
    z=np.dot(w.T,X_test)+b
    A=sigmoid(z)
   

    #初始化Y值
    m=X_test.shape[1]
    y_pred = np.zeros([1,m])
    
    #得到测试集预测到的Y值
    for i in range(m):
        if A[:,i] > 0.5:
            y_pred[:,i]=1
        else:
            y_pred[:,i]=0
    return y_pred

5.整体实现

把模型训练和预测比较整合在一起:

def model(w,b,x_train,y_train,x_test,y_test,alpha,n_iters,flag):
    #训练模型
    params,costs=optimize(w,b,x_train,y_train,alpha,n_iters,flag)
    
    #获取模型的中w,b
    w=params['w']
    b=params['b']
    
    #为了判断模型对数据的拟合程度,这里添加了对训练集的预测
    y_pred_train=predict(w,b,x_train)
    y_pred_test=predict(w,b,x_test)
    
    #预测值和真实值做出比较,输出相似程度百分比,也就是精确度
    print('train acc is ' ,np.mean(y_pred_train == y_train)*100,'%')
    print('test acc is ' ,np.mean(y_pred_test == y_test)*100,'%')
    

    b={'w':w,'b':b,'alpha':alpha,'costs':costs}
    
    return b

接下来就万事具备只欠东风了,这风就是把训练数据喂给模型,然后拿测试数据检验

这里用了两个相差较大的学习因子训练模型,比较效果更加明显:

 b1=model(w,b,train_data_finalX,train_data_finalY,test_data_finalX,test_data_finalY,alpha=0.002,n_iters=2000,flag=True)
 b2=model(w,b,train_data_finalX,train_data_finalY,test_data_finalX,test_data_finalY,alpha=0.03,n_iters=2000,flag=False)

输出结果如下,注意b2模型没有打印cost值

iters is  0  cost is  0.6931471805599453
iters is  100  cost is  0.5557515010876188
iters is  200  cost is  0.5068465769831775
iters is  300  cost is  0.47107861667750084
iters is  400  cost is  0.4423236413210922
iters is  500  cost is  0.41813940491641477
iters is  600  cost is  0.39724674562566165
iters is  700  cost is  0.37886680661383465
iters is  800  cost is  0.3624799165374718
iters is  900  cost is  0.3477178030467021
iters is  1000  cost is  0.33430809895082164
iters is  1100  cost is  0.322042799907918
iters is  1200  cost is  0.31075900404024404
iters is  1300  cost is  0.30032649931928485
iters is  1400  cost is  0.29063942055667524
iters is  1500  cost is  0.2816104491476511
iters is  1600  cost is  0.27316666681904955
iters is  1700  cost is  0.2652465214170832
iters is  1800  cost is  0.25779756133061105
iters is  1900  cost is  0.25077471388028166
train acc is  95.69377990430623 %
test acc is  74.0 %
train acc is  100.0 %
test acc is  68.0 %

下面我们绘制出cost图像,更加直观的看我们模型的训练过程:

plt.plot(b1['costs'],label=b1['alpha'])
plt.plot(b2['costs'],label=b2['alpha'])
plt.xlabel('per 100 iters')
plt.ylabel('cost')
plt.legend()

从图像中可以看到,学习因子选择不当导致模型梯度下降时幅度太大,走了很多弯路,0.03是故意选了一个不靠谱的学习因子,

可以看到在学习因子为0.002时针对测试集准确率为74%,这个结果可能是有些不尽如人意,后面学习了更复杂的模型,再来试试会不会提高准确度。

猜你喜欢

转载自blog.csdn.net/Bazingaea/article/details/83041262