【深度学习】学习记录:搭建一个‘识别猫‘的简单神经网络

【深度学习】学习记录:搭建一个“识别猫”的简单神经网络


本文是参考了 这篇文章

一、 准备工作

1、训练环境

我是在百度的AI Studio上进行网络搭建和训练的,在上面创建项目后使用jupter notebook进行编写练习十分方便。

2、数据准备

训练所需要的数据:百度网盘链接
提取码:oi8g
下载下来后,将文件上传到自己的项目里,注意2个h5文件需要新建一个’datasets’文件并上传进去。

二、数据载入及处理

首先导入需要的一些库

#导入所需要的库
import numpy as np
import matplotlib.pyplot as plt
from lr_utils import load_dataset
import h5py

载入数据使用的是提供的提供好的函数load_dataset()
将数据载入并打印训练集和测试集的信息

#载入数据
print('---------------------正在载入数据---------------------')
train_set_x_orig , train_set_y_orig , test_set_x_orig , test_set_y_orig , classes = load_dataset()
print('载入完成,原始数据信息如下:')
#打印原始数据信息
print('训练集 : ')
print('    样本数量 : ' + str(train_set_y_orig.shape[1]))
print('    图片维度 : ' + str(train_set_x_orig.shape))
print('    标签维度 : ' + str(train_set_y_orig.shape))
print('测试集 : ')
print('    样本数量 : ' + str(test_set_y_orig.shape[1]))
print('    图片维度 : '  + str(test_set_x_orig.shape))
print('    标签维度 : '  + str(test_set_y_orig.shape))

train_set_x_orig : 原始训练集图片
train_set_y_orig : 原始训练集标签,是一个行向量,存储0和1,分别对应‘non-cat’和‘cat’
test_set_x_orig : 原始测试集图片
test_set_y_orig : 原始测试集标签
运行效果如下:

---------------------正在载入数据---------------------
载入完成,原始数据信息如下:
训练集 : 
    样本数量 : 209
    图片维度 : (209, 64, 64, 3)
    标签维度 : (1, 209)
测试集 : 
    样本数量 : 50
    图片维度 : (50, 64, 64, 3)
    标签维度 : (1, 50)

三 、 模型建立

这里使用的是最简单的逻辑回归,通过向前传播计算激活值和成本函数,然后通过向后传播得到成本函数对训练参数的偏导数,再利用偏导数进行梯度下降从而更新训练参数,不断地减小误差。

在计算激活值时需要用到sigmoid函数,它的作用是使激活后的值落在0和1之间

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

初始化训练参数w,b

#定义初始化训练参数的函数
def initialize_params(dim):
    #初始化w为(dim,1)的列向量
    w = np.zeros(shape = (dim,1))
    #初始化b
    b = 0

    #使用断言确保数据正确
    #w的维度是(dim,1)
    assert(w.shape == (dim,1))
    #b的类型是float或int
    assert(isinstance(b,float) or isinstance(b,int))

    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)

    #使用断言确保我的数据是正确的
    assert(dw.shape == w.shape)
    assert(db.dtype == float)
    cost = np.squeeze(cost)
    assert(cost.shape == ())

    #创建一个字典保存dw,db
    grads = {
        'dw' : dw,
        'db' : db
    }

    return (grads,cost)

定义梯度下降函数

#更新参数
def optimize(w , b , X , Y , num_iterations  , learning_rate ):

    #创建一个列表用于存储成本
    costs = []

    print('=================开始训练==============')

    for i in range(num_iterations):
        #调用传播函数获取梯度值和成本函数
        grads , cost = propagate(w , b , X , Y)
        dw = grads['dw']
        db = grads['db']

        #更新参数
        w = w - learning_rate * dw
        b = b - learning_rate * db

        #记录成本,每下降100次记录一次
        if i % 100 == 0:
            costs.append(cost)

        #打印迭代次数及误差
        if i % 100 == 0:
            print('迭代%d次,误差为%f' %(i,cost))

    print('=================训练完毕==============')

    #训练得到的参数
    params = {
        'w' : w,
        'b' : b
    }

    #最后一次迭代后的梯度
    grads = {
        'dw' : dw,
        'db' : db
    }

    return (params,grads,costs)

定义预测函数

#定义预测函数
def predict(w , b , X):
    
    #图片数量
    m = X.shape[1]
    
    #生成存放标签的数组
    Y_prediction = np.zeros((1,m))
    
    #计算概率
    A = sigmoid(np.dot(w.T,X) + b)
   
    #将概率转化为标签
    for i in range(m):
        Y_prediction[0,i] = 1 if A[0,i] > 0.5 else 0
    
    #使用断言
    assert(Y_prediction.shape == (1,m))

    return Y_prediction

编写model函数,供进行训练时调用

#定义model函数
def model(train_x , train_y , test_x , test_y , num_iterations = 2000 , learning_rate = 0.05):


    #调用初始化训练参数函数
    w , b = initialize_params(train_x.shape[0])

    #调用优化函数
    params,grads,costs = optimize(w , b , train_x , train_y , num_iterations , learning_rate)

    #得到训练后的参数
    w = params['w']
    b = params['b']

    #预测训练集和测试集
    Y_prediction_train = predict(w , b , train_x)
    Y_prediction_test = predict(w , b , test_x)

    #打印预测准确性
    print('训练集准确性 : ',format((1 - np.mean(np.abs(Y_prediction_train - train_y))) * 100),'%')
    print('测试集准确性 : ',format((1 - np.mean(np.abs(Y_prediction_test - test_y))) * 100),'%')

    d = {
            "costs" : costs,
            "Y_prediction_test" : Y_prediction_test,
            "Y_prediciton_train" : Y_prediction_train,
            "w" : w,
            "b" : b,
            "learning_rate" : learning_rate,
            "num_iterations" : num_iterations }
    
    return d

将所有流程放进main()函数里,方便整体调用

def main():
    #载入数据
    print('---------------------正在载入数据---------------------')
    train_set_x_orig , train_set_y_orig , test_set_x_orig , test_set_y_orig , classes = load_dataset()
    print('载入完成,原始数据信息如下:')
    #打印原始数据信息
    print('训练集 : ')
    print('    样本数量 : ' + str(train_set_y_orig.shape[1]))
    print('    图片维度 : ' + str(train_set_x_orig.shape))
    print('    标签维度 : ' + str(train_set_y_orig.shape))
    print('测试集 : ')
    print('    样本数量 : ' + str(test_set_y_orig.shape[1]))
    print('    图片维度 : '  + str(test_set_x_orig.shape))
    print('    标签维度 : '  + str(test_set_y_orig.shape))

    #处理数据
    print('-------------------正在处理数据---------------')
    #将训练集的图片平铺并转置
    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
    train_set_y = train_set_y_orig
    test_set_y = test_set_y_orig

    #看一下处理后的图片维度
    print('训练集图片处理后维度 : train_set_x.shape = ' + str(train_set_x_flatten.shape))
    print('训练集标签维度 : train_set_y.shape = ' + str(train_set_y.shape))
    print('测试集图片平铺后维度 : test_set_x.shape = ' + str(test_set_x_flatten.shape))
    print('测试集标签维度 : test_set_y.shape = ' + str(test_set_y.shape))

    print('\n')
    print('数据处理完毕!')

    d = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 2000, learning_rate = 0.005 )
    
    #绘制图
    costs = np.squeeze(d['costs'])
    plt.plot(costs)
    plt.ylabel('cost')
    plt.xlabel('iterations (per hundreds)')
    plt.title("Learning rate =" + str(d["learning_rate"]))
    plt.show()

调用main函数进行训练得到结果并绘图

if '__name__' == '__name__':
    main()

运行效果

---------------------正在载入数据---------------------
载入完成,原始数据信息如下:
训练集 : 
    样本数量 : 209
    图片维度 : (209, 64, 64, 3)
    标签维度 : (1, 209)
测试集 : 
    样本数量 : 50
    图片维度 : (50, 64, 64, 3)
    标签维度 : (1, 50)
-------------------正在处理数据---------------
训练集图片处理后维度 : train_set_x.shape = (12288, 209)
训练集标签维度 : train_set_y.shape = (1, 209)
测试集图片平铺后维度 : test_set_x.shape = (12288, 50)
测试集标签维度 : test_set_y.shape = (1, 50)


数据处理完毕!
=================开始训练==============
迭代0次,误差为0.693147
迭代100次,误差为0.584508
迭代200次,误差为0.466949
迭代300次,误差为0.376007
迭代400次,误差为0.331463
迭代500次,误差为0.303273
迭代600次,误差为0.279880
迭代700次,误差为0.260042
迭代800次,误差为0.242941
迭代900次,误差为0.228004
迭代1000次,误差为0.214820
迭代1100次,误差为0.203078
迭代1200次,误差为0.192544
迭代1300次,误差为0.183033
迭代1400次,误差为0.174399
迭代1500次,误差为0.166521
迭代1600次,误差为0.159305
迭代1700次,误差为0.152667
迭代1800次,误差为0.146542
迭代1900次,误差为0.140872
=================训练完毕==============
训练集准确性 :  99.04306220095694 %
测试集准确性 :  70.0 %

在这里插入图片描述
完整代码:

# -*- coding: utf-8 -*-

#导入所需要的库
import numpy as np
import matplotlib.pyplot as plt
from lr_utils import load_dataset
import h5py

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

#定义初始化训练参数的函数
def initialize_params(dim):
    #初始化w为(dim,1)的列向量
    w = np.zeros(shape = (dim,1))
    #初始化b
    b = 0

    #使用断言确保数据正确
    #w的维度是(dim,1)
    assert(w.shape == (dim,1))
    #b的类型是float或int
    assert(isinstance(b,float) or isinstance(b,int))

    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)

    #使用断言确保我的数据是正确的
    assert(dw.shape == w.shape)
    assert(db.dtype == float)
    cost = np.squeeze(cost)
    assert(cost.shape == ())

    #创建一个字典保存dw,db
    grads = {
        'dw' : dw,
        'db' : db
    }

    return (grads,cost)

#更新参数
def optimize(w , b , X , Y , num_iterations  , learning_rate ):

    #创建一个列表用于存储成本
    costs = []

    print('=================开始训练==============')

    for i in range(num_iterations):
        #调用传播函数获取梯度值和成本函数
        grads , cost = propagate(w , b , X , Y)
        dw = grads['dw']
        db = grads['db']

        #更新参数
        w = w - learning_rate * dw
        b = b - learning_rate * db

        #记录成本,每下降100次记录一次
        if i % 100 == 0:
            costs.append(cost)

        #打印迭代次数及误差
        if i % 100 == 0:
            print('迭代%d次,误差为%f' %(i,cost))

    print('=================训练完毕==============')

    #训练得到的参数
    params = {
        'w' : w,
        'b' : b
    }

    #最后一次迭代后的梯度
    grads = {
        'dw' : dw,
        'db' : db
    }

    return (params,grads,costs)

#定义预测函数
def predict(w , b , X):
    
    #图片数量
    m = X.shape[1]
    
    #生成存放标签的数组
    Y_prediction = np.zeros((1,m))
    
    #计算概率
    A = sigmoid(np.dot(w.T,X) + b)
   
    #将概率转化为标签
    for i in range(m):
        Y_prediction[0,i] = 1 if A[0,i] > 0.5 else 0
    
    #使用断言
    assert(Y_prediction.shape == (1,m))

    return Y_prediction

#定义model函数
def model(train_x , train_y , test_x , test_y , num_iterations = 2000 , learning_rate = 0.05):


    #调用初始化训练参数函数
    w , b = initialize_params(train_x.shape[0])

    #调用优化函数
    params,grads,costs = optimize(w , b , train_x , train_y , num_iterations , learning_rate)

    #得到训练后的参数
    w = params['w']
    b = params['b']

    #预测训练集和测试集
    Y_prediction_train = predict(w , b , train_x)
    Y_prediction_test = predict(w , b , test_x)

    #打印预测准确性
    print('训练集准确性 : ',format((1 - np.mean(np.abs(Y_prediction_train - train_y))) * 100),'%')
    print('测试集准确性 : ',format((1 - np.mean(np.abs(Y_prediction_test - test_y))) * 100),'%')

    d = {
            "costs" : costs,
            "Y_prediction_test" : Y_prediction_test,
            "Y_prediciton_train" : Y_prediction_train,
            "w" : w,
            "b" : b,
            "learning_rate" : learning_rate,
            "num_iterations" : num_iterations }
    
    return d

def main():
    #载入数据
    print('---------------------正在载入数据---------------------')
    train_set_x_orig , train_set_y_orig , test_set_x_orig , test_set_y_orig , classes = load_dataset()
    print('载入完成,原始数据信息如下:')
    #打印原始数据信息
    print('训练集 : ')
    print('    样本数量 : ' + str(train_set_y_orig.shape[1]))
    print('    图片维度 : ' + str(train_set_x_orig.shape))
    print('    标签维度 : ' + str(train_set_y_orig.shape))
    print('测试集 : ')
    print('    样本数量 : ' + str(test_set_y_orig.shape[1]))
    print('    图片维度 : '  + str(test_set_x_orig.shape))
    print('    标签维度 : '  + str(test_set_y_orig.shape))

    #处理数据
    print('-------------------正在处理数据---------------')
    #将训练集的图片平铺并转置
    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
    train_set_y = train_set_y_orig
    test_set_y = test_set_y_orig

    #看一下处理后的图片维度
    print('训练集图片处理后维度 : train_set_x.shape = ' + str(train_set_x_flatten.shape))
    print('训练集标签维度 : train_set_y.shape = ' + str(train_set_y.shape))
    print('测试集图片平铺后维度 : test_set_x.shape = ' + str(test_set_x_flatten.shape))
    print('测试集标签维度 : test_set_y.shape = ' + str(test_set_y.shape))

    print('\n')
    print('数据处理完毕!')

    d = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 2000, learning_rate = 0.005 )
    
    #绘制图
    costs = np.squeeze(d['costs'])
    plt.plot(costs)
    plt.ylabel('cost')
    plt.xlabel('iterations (per hundreds)')
    plt.title("Learning rate =" + str(d["learning_rate"]))
    plt.show()

if '__name__' == '__name__':
    main()
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端corner

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值