基于logistic回归构造神经网络进行图像识别

深度学习入门——利用梯度下降的logistic回归进行图像识别

学习搬运自:deeplearning.ai-andrewNG-master

算法的数学表达式

正向传播(损失函数计算):

在这里插入图片描述
反向传播(梯度计算):
在这里插入图片描述

算法框架

在这里插入图片描述
其中参数更新依赖于优化函数,目标是通过最小化损失函数J来学习w和b。
参数更新规则如下: θ= θ- αdθ 其中α为学习率。

样本集训练

关于logistic参数w和b,实验采用梯度下降的方法,参数学习率(更新率)为0.005,得到了迭代次数和损失函数的关系图如下:
在这里插入图片描述
通过对样本数据集和测试样本数据集进行预测,发现本模型的预测准确率并不高,最优大概在70%左右。
在这里插入图片描述
通过调整学习率,实验发现:如果学习率太大(0.01),则成本可能会上下波动。 它甚至可能会发散。在本实验中虽然使用0.01最终仍会以较高的损失值获得收益,但是较低的损失并不意味着模型效果很好。当训练精度比测试精度高很多时,就会发生过拟合情况。
在这里插入图片描述
另外本实验又在学习率为0.01左右进行了探索,最后发现学习率为0.015左右时,能使损失值降到最小,同时它的预测准确率也达到了70%。
在这里插入图片描述
本实验中的模型训练后得到的参数w(12288个)如下图所示:
在这里插入图片描述

其中对测试集(50个)和样本集(209个)又分别进行了预测,预测结果条状图如下图所示,图中黄色部分表示预测正确,紫色部分表示预测错误。
注:以下为Python代码运行结果(预测准确率)  train accuracy: 99.52%test accuracy: 70.0 %
注:以下为Python代码运行结果(预测准确率) train accuracy: 99.52%test accuracy: 70.0 %

**

以下为代码实现:

**

"""
   利用神经网络思想实现logistic回归  
   建立分类器  分类猫
   时间:01/27/2021
"""

"""
   算法框架:
            初始化参数  
            计算损失函数及其梯度
            使用优化算法(梯度下降)
"""
#导入所需要的包

import numpy as np
import matplotlib.pyplot as plt       #Python图形库 matplotlib
import h5py                 #读取处理  HDF5 格式文件(H5)
import scipy
from PIL import Image       #读取图片 处理图片  Image
from scipy import ndimage   #处理n维图像  ndimage
from lr_utils import load_dataset    #初始数据读取函数

#首先 加载数据集
train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()

#得到初始样本训练数据 train_x_orig   得到测试数据集 test_x_orig (未预处理)
#得到样本标签 train_set_y    得到测试数据标签   test_set_y

"""
   接下来进行数组重塑    把维度为(m_train,num_px,num_px,3) 
   重塑为 m_train个 维度为(num_px*num_px*3,1)的数组    
   R G B 值 存在在一列中 
"""
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_flatten (12288, 209)  test_set_x_flatten (12288, 50)

#进行数据标准化
   #这里采用了 数据集的每一行除以255(像素通道的最大值) 效果好
train_set_x = train_set_x_flatten/255  #预处理数据 train_set_x
test_set_x = test_set_x_flatten/255    #预处理后 test_set_y

#辅助激活函数 sigmoid
def sigmoid(x):
    s = 1/(1+np.exp(-x))
    return s

#初始化logistic回归神经网络训练参数 W b
def initialize_with_zeros(dim):
    """
    Returns:
    w -- 初始化维度 (dim, 1)   dim 为训练集样本个数
    b -- 因为Python 广播的存在   初始化 b为0 即可
    """
    w = np.zeros((dim, 1))
    b = 0
    
    #加入assert 语句  防止维度不一致 导致错误
    assert(w.shape == (dim, 1))
    assert(isinstance(b, float) or isinstance(b, int))
    
    return w, b

#向前向后传播  计算 损失函数 以及 梯度
def propagate(w, b, X, Y):
    """

    w -- 参数  维度:(num_px * num_px * 3, 1)
    b -- 参数  标量
    X -- 训练集样本数据  维度:(num_px * num_px * 3, number of examples)
    Y -- 样本标签 ( 0  non-cat, 1  cat) 维度:(1, number of examples)

    Return:
    cost -- negative log-likelihood cost for logistic regression
    dw -- gradient of the loss with respect to w, thus same shape as w
    db -- gradient of the loss with respect to b, thus same shape as b
    
    """
    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)) 

    #np.dot 矩阵相乘
    dw = 1 / m * np.dot(X, (A - Y).T)  #(dw1,dw2,dw3,....,dw_nx)
    db = 1 / m * np.sum(A - Y)  
    
    #加入assert语句  防止矩阵维度不一致 报错
    assert(dw.shape == w.shape)
    assert(db.dtype == float)
    
    #把cost 转换为稚为 1 的数组
    cost = np.squeeze(cost)
    assert(cost.shape == ())
    
    grads = {"dw": dw,
             "db": db}
    
    return grads, cost


#优化学习函数
def optimize(w, b, X, Y, num_iterations, learning_rate, print_cost = False):
    """
    w -- 参数  维度:(num_px * num_px * 3, 1)
    b -- 参数  标量
    X -- 训练集样本数据  维度:(num_px * num_px * 3, number of examples)
    Y -- 样本标签 ( 0  non-cat, 1  cat) 维度:(1, number of examples)
    num_iterations -- 优化循环次数
    learning_rate -- 学习率
    print_cost -- 每训练100次输出 一次结果
    
    Returns:
    params -- dictionary containing the weights w and bias b
    grads -- dictionary containing the gradients of the weights and bias with respect to the cost function
    costs -- list of all the costs computed during the optimization, this will be used to plot the learning curve.

    """
    
    costs = []
    
    for i in range(num_iterations):
        
        #调用 propagate函数 计算第一次训练的dw db cost
        grads, cost = propagate(w, b, X, Y)
        
        # 从梯度中提取导数
        dw = grads["dw"]
        db = grads["db"]
        
        #更新参数
        w = w - learning_rate * dw
        b = b - learning_rate * db
        
        #记录损失值
        if i % 50 == 0:
            costs.append(cost)
        
        #输出损失值  每100次
        if print_cost and i % 100 == 0:
            print ("Cost after iteration %i: %f" %(i, cost))
    
    params = {"w": w,
              "b": b}
    
    grads = {"dw": dw,
             "db": db}
    
    #返回训练后的 参数 w b  、当前dw db  、 损失值 costs
    return params, grads, costs

#预测函数
def predict(w, b, X):
    '''
    w -- 训练到的 w
    b -- 训练到的 b
    X --需要测试的测试集 维度:(num_px * num_px * 3, number of examples)
    
    Returns:
    Y_prediction -- 预测结果 维度:(1,number of examples)
    '''
    
    m = X.shape[1]
    Y_prediction = np.zeros((1,m))
    w = w.reshape(X.shape[0], 1)
    
    #利用训练后的w b  计算激活函数值
    A = sigmoid(np.dot(w.T, X) + b)

    for i in range(A.shape[1]):
        
        #(如果激活值<= 0.5) 则认为预测为0 ; (如果激活> 0.5)  则认为预测为1
        #并将预测结果存储在向量“ Y_prediction”中
        if A[0, i] <= 0.5:
            Y_prediction[0, i] = 0
        else:
            Y_prediction[0, i] = 1
    
    assert(Y_prediction.shape == (1, m))
    
    return Y_prediction

#logitic回归模型   
def model(X_train, Y_train, X_test, Y_test, num_iterations, learning_rate = 0.5, print_cost = False):
    """

    X_train -- 样本训练集   维度:(num_px * num_px * 3, m_train)
    Y_train -- 样本标签集  (矢量) 维度:(1, m_train)
    X_test --  测试样本集   维度:(num_px * num_px * 3, m_test)
    Y_test -- 测试样本标签集  (矢量) 维度:(1, m_test) 
    num_iterations -- 优化参数时的迭代次数
    learning_rate -- 更新参数时的学习率
    print_cost -- 
    
    Returns:
    d -- dictionary containing information about the model.
    """
    
    #初始化参数
    w, b = initialize_with_zeros(X_train.shape[0])

    #利用样本进行训练
    parameters, grads, costs = optimize(w, b, X_train, Y_train, num_iterations, learning_rate, print_cost)
    
    #训练后的参数 w  b 
    w = parameters["w"]
    b = parameters["b"]
    
    #利用参数对   训练集 和 测试集 进行预测 
    Y_prediction_test = predict(w, b, X_test)
    Y_prediction_train = predict(w, b, X_train)

    #输出  预测结果
    print("train accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100))
    print("test accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100))

    #返回训练结果
    d = {"costs": costs,
         "Y_prediction_test": Y_prediction_test, 
         "Y_prediction_train" : Y_prediction_train, 
         "w" : w, 
         "b" : b,
         "learning_rate" : learning_rate,
         "num_iterations": num_iterations}
    
    return d

模块运行

#训练得到参数   装进d 中
d = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 2000, learning_rate = 0.005, print_cost = True)

代码中用到的H5数据读入

# lr_utils 模块
import numpy as np
import h5py
    
    
def load_dataset():
    train_dataset = h5py.File('datasets/train_catvnoncat.h5', "r")
    train_set_x_orig = np.array(train_dataset["train_set_x"][:]) # your train set features
    train_set_y_orig = np.array(train_dataset["train_set_y"][:]) # your train set labels

    test_dataset = h5py.File('datasets/test_catvnoncat.h5', "r")
    test_set_x_orig = np.array(test_dataset["test_set_x"][:]) # your test set features
    test_set_y_orig = np.array(test_dataset["test_set_y"][:]) # your test set labels

    classes = np.array(test_dataset["list_classes"][:]) # the list of classes
    
    train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0]))
    test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0]))
    
    return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes

对数据里的图片进行预测验证

#提取测试集里的图片进行预测验证
index = 1
plt.imshow(test_set_x[:,index].reshape((num_px, num_px, 3)))
print ("y = " + str(test_set_y[0,index]) + ", you predicted that it is a \"" + classes[int(d["Y_prediction_test"][0,index])].decode("utf-8") +  "\" picture.")

其中num_px为图片维度,本实验中维度为64* 64*3
png)

预测实例展示

在这里插入图片描述
输出结果如下:

y = 1, you predicted that it is a “cat” picture.

最后,代码中所用的图片数据为H5文件格式,原数据文件在由此处提取。
链接:H5数据 dataset
提取码:7zn2

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

yasNing

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

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

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

打赏作者

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

抵扣说明:

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

余额充值