深度学习入门——利用梯度下降的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 %
**
以下为代码实现:
**
"""
利用神经网络思想实现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