本文是参考了 这篇文章
一、 准备工作
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()